From 90659d220c8708bafa4af5130628b42b0b65e3cf Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Wed, 14 Oct 2026 06:56:39 -0400 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=93=9D=20Simplify=20source=20comments?= =?UTF-8?q?=20across=20the=20project?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/acp/src/adapter-snapshots.ts | 97 +++----------- packages/acp/src/checkpoint.ts | 36 ++--- packages/acp/src/native-launch.ts | 38 ++---- packages/acp/src/session-configuration.ts | 48 ++----- packages/acp/src/session-key.ts | 22 +-- packages/acp/src/session-route.ts | 26 +--- packages/acp/tests/acceptance.test.ts | 3 - packages/cli/src/bun-repl.ts | 1 - packages/cli/src/compiled-repl.ts | 1 - packages/cli/src/deno-repl.ts | 1 - packages/cli/src/node-repl.ts | 1 - packages/cli/src/repl/application.ts | 83 +++--------- packages/cli/src/repl/components/rows.ts | 1 - packages/cli/src/repl/layout.ts | 1 - packages/cli/src/repl/presentation-style.ts | 46 ++----- packages/cli/src/repl/terminal-host.ts | 16 +-- packages/code-review-agent/src/categories.ts | 4 +- packages/code-review-agent/src/parse-diff.ts | 12 +- packages/code-review-agent/src/plugin.ts | 57 ++------ .../src/review-components.ts | 125 ++++-------------- .../tests/parse-diff.test.ts | 1 - packages/core/src/components/CodeBlock.ts | 43 ++---- packages/core/src/components/Fail.ts | 61 ++------- packages/core/src/eval-handler.ts | 3 - packages/core/src/eval-interpolate.ts | 3 - packages/core/src/eval-transform.ts | 10 -- packages/core/src/execute.ts | 74 +++++------ packages/core/src/expand.ts | 5 - packages/core/src/modifiers.ts | 2 - packages/core/src/modifiers/daemon.ts | 1 - packages/core/src/output/normalize.ts | 3 - packages/core/src/plugin.ts | 4 +- packages/core/src/scanner.ts | 33 +---- packages/core/tests/daemon.test.ts | 1 - packages/core/tests/eval-durable.test.ts | 2 - packages/core/tests/eval-return.test.ts | 1 - packages/core/tests/execute.test.ts | 6 - packages/core/tests/named-slots.test.ts | 1 - packages/core/tests/sample-component.test.ts | 1 - packages/durable-streams/combinators.ts | 26 +--- packages/durable-streams/divergence.ts | 3 - packages/durable-streams/effect.ts | 7 - packages/durable-streams/ephemeral.ts | 13 +- packages/durable-streams/http-stream.ts | 11 -- packages/durable-streams/position.ts | 33 +---- packages/durable-streams/run.ts | 5 - .../tests/deterministic-id.test.ts | 14 +- .../tests/durable-each.test.ts | 4 - .../durable-streams/tests/durable-run.test.ts | 3 - .../durable-streams/tests/ephemeral.test.ts | 2 - .../tests/replay-index.test.ts | 4 - .../tests/structured-concurrency.test.ts | 3 - .../git/src/composition/components/GitAdd.ts | 39 ++---- .../src/composition/components/GitCommit.ts | 40 ++---- .../git/src/composition/components/GitPush.ts | 55 ++------ .../src/composition/components/GitSwitch.ts | 45 ++----- .../git/src/composition/components/Issue.ts | 85 +++--------- .../composition/components/IssueTracker.ts | 42 ++---- .../components/PullRequestReads.ts | 66 ++------- .../git/src/deno/run-composition/identity.ts | 52 ++------ .../git/src/deno/run-composition/leases.ts | 48 ++----- .../git/src/deno/run-composition/metadata.ts | 29 +--- packages/git/src/git-host/effect.ts | 95 ++++--------- packages/runtime/host-files.ts | 18 +-- packages/test-agent/src/components.ts | 29 ++-- .../test-agent/src/session-coordinator.ts | 21 +-- packages/test-support/bdd.ts | 9 +- packages/testing/src/components.ts | 12 -- .../testing/tests/boundary-contract.test.ts | 11 +- packages/web/client/config.ts | 11 +- packages/web/client/field-template.ts | 15 +-- packages/web/client/outcome.ts | 20 +-- packages/web/client/request.ts | 16 +-- packages/web/src/ajv-options.ts | 37 ++---- packages/workflow/src/deno/lock.ts | 25 +--- packages/workflow/src/deno/provider.ts | 29 +--- packages/workflow/src/deno/transaction.ts | 19 +-- .../workflow/src/deno/workspace/evaluate.ts | 85 +++--------- packages/workflow/src/deno/workspace/files.ts | 74 ++--------- packages/workflow/src/deno/workspace/guard.ts | 27 +--- .../workflow/src/deno/workspace/inspect.ts | 37 ++---- .../workflow/src/deno/workspace/storage.ts | 50 ++----- .../workflow/src/storage/compatibility.ts | 22 +-- .../workflow/tests/workflow-export.test.ts | 5 - scripts/lib/changed-paths.ts | 34 +---- scripts/lib/compile.ts | 33 +---- scripts/lib/main-green.ts | 54 ++------ scripts/lib/prepared-state.ts | 26 +--- site/utils.ts | 2 - 89 files changed, 502 insertions(+), 1817 deletions(-) diff --git a/packages/acp/src/adapter-snapshots.ts b/packages/acp/src/adapter-snapshots.ts index 67a88bcd7..ea67968d5 100644 --- a/packages/acp/src/adapter-snapshots.ts +++ b/packages/acp/src/adapter-snapshots.ts @@ -1,79 +1,26 @@ /** - * The ACP adapters a workflow run executes, and how they reach the disk - * (`packages/acp/vendor/adapters/PROVENANCE.md`). - * - * A workflow Prompt needs an adapter that names the turn it just completed, on - * `_meta`. No published adapter does yet, so this repository carries one npm - * tarball per provider — packed from an exact patched upstream commit by that - * project's own build — and runs those instead of whatever `npx` would resolve. - * - * ## Why the bytes travel in the module graph - * - * A tarball on disk is unreachable from a compiled binary and from the npm - * artifact. The same bytes are therefore carried as a generated module, which - * every distribution inlines identically, and this module writes them out. One - * mechanism, so "the source tree, the npm package and the binary all run the - * same adapter" is a fact rather than three arrangements that happen to agree. - * - * ## Content-addressed, so identity is the location - * - * A snapshot materializes under its own SHA-256. Two runs asking for the same - * adapter name the same directory, a changed snapshot names a different one, - * and nothing has to decide whether an existing directory is current — the - * question does not arise. - * - * ## Identity is not the launch path - * - * Two different things are needed, and conflating them was a defect: an adapter - * has a **stable identity** — its provider, package, version and snapshot - * digest — and a **host-local launch path** under whatever root this machine - * materialized into. - * - * Only the identity is durable. It is what a retained Agent session records and - * what a sealed artifact carries, so two machines running the same snapshot - * agree, and a run exported from one is readable on the other. The path appears - * nowhere durable: it names a directory that exists on one host, and putting it - * in an artifact would make where a file happened to live a compatibility term. - * - * The launch path is quoted, because a root containing a space is an ordinary - * thing on a developer's machine and an unquoted command would split there. - * - * ## Published atomically, verified before use - * - * Materialization happens in a private temporary directory and is published by - * one rename. A concurrent run either wins that rename or finds the directory - * already there — both then verify before using it, so nobody executes a tree - * another process is still filling. - * - * Replacing an *abandoned* tree is the one step that cannot be done by rename - * alone, because a rename will not overwrite a non-empty directory. Removing it - * first is a decision that goes stale: another attempt may publish a valid tree - * between the observation and the removal, and deleting that would pull the - * files out from under an adapter already running. So recovery is serialized on - * an exclusive claim, and the holder re-checks under it before removing - * anything. - * - * The claim is a ticket: the directory `claims/`, taken by renaming a - * prepared directory onto that name, which only one attempt can win and which - * is never handed out a second time. - * - * Two properties come from that, and the claim needs both. Because numbers are - * never reissued, finishing a dead holder's ticket can only ever act on the - * exact ticket that was inspected. Because they are taken in ascending order, - * an attempt arriving later cannot obtain a lower number, so it cannot come to - * precede a holder that has already been elected. - * - * The holder is the lowest ticket still outstanding. Releasing is marking one - * finished, and a process killed mid-recovery leaves a ticket whose owner a - * later attempt reads as dead and finishes on its behalf. - * - * ## It refuses; it never falls back - * - * A digest that does not match, an extraction that fails, a dependency install - * that fails, a missing entry file: each raises. Running the published adapter - * instead would be running one that emits no token, which is the state this - * exists to leave — silently, and after the run had already been told it was - * continuing an exact conversation. + * Materialize the patched ACP adapters that report completed-turn `_meta` + * (`packages/acp/vendor/adapters/PROVENANCE.md`). Their npm tarballs come from + * exact patched upstream commits and travel as a generated module so source, npm + * and compiled distributions execute identical bytes. + * + * A snapshot materializes under its SHA-256. Durable identity is provider, package, + * version and digest; the quoted host-local launch path is never retained in a + * session or sealed artifact. + * + * Stage privately, publish by one rename and verify the published tree before use, + * including when another attempt won. Recovery of an abandoned non-empty tree + * requires an exclusive claim and a fresh check before removal, otherwise a stale + * observation could delete another process's newly published valid adapter. + * + * Recovery claims are prepared directories atomically renamed to `claims/`. + * Tickets increase monotonically and are never reused: late arrivals cannot precede + * an elected holder, and finishing a dead holder cannot affect a later claim. + * The lowest unfinished ticket owns recovery; release marks it finished, and a + * later attempt may finish a dead owner's ticket. + * + * Digest, extraction, installation or missing-entry failures raise. Falling back + * to a published adapter would lose the turn identity continuation depends on. */ import { ensureDir, exists, readTextFile, rm, writeTextFile } from "@effectionx/fs"; diff --git a/packages/acp/src/checkpoint.ts b/packages/acp/src/checkpoint.ts index a7128d0db..3ed5d85c3 100644 --- a/packages/acp/src/checkpoint.ts +++ b/packages/acp/src/checkpoint.ts @@ -1,34 +1,14 @@ /** - * Which provider turn a completed Prompt was, as this package reads it. + * Read a completed Prompt's opaque provider turn identity from `_meta`. * - * ACP carries per-response metadata under `_meta`, and an adapter that knows - * how to name its own turns puts that name there. The runtime carries the whole - * value across untouched and recognizes nothing in it, because which keys mean - * something is this package's decision rather than a transport's. + * Recognized identities are `_meta.codex.turnId` (App Server turn id) and + * `_meta.claudeCode.assistantMessageUuid` (assistant message uuid). The runtime + * passes metadata through; this package discards every other field. * - * Two namespaces mean something here, one per adapter, and each is the - * adapter's own: - * - * | Adapter | Where it says it | What that is | - * | --- | --- | --- | - * | Codex | `_meta.codex.turnId` | the App Server turn id | - * | Claude | `_meta.claudeCode.assistantMessageUuid` | the assistant message uuid | - * - * Everything else in `_meta` is discarded. Quota, failure detail and whatever - * else an adapter reports are that adapter's business; nothing here reads them, - * and nothing here treats an unfamiliar key as a checkpoint because it happens - * to look like one. - * - * The value is opaque. It is compared, never interpreted: this does not check - * it against a UUID grammar, does not shorten or normalize it, and does not - * reconstruct one from anything else. Transcript text repeats, another turn's - * token is a different turn, a provider's current head is a later point in the - * conversation, and prompt or journal position is order rather than identity — - * so a completion that names no turn simply names none. - * - * Ambiguity is refused for the same reason. Two adapters both claiming one turn - * is two answers to which conversation this was, and there is no rule for - * choosing between them, so such a completion carries no checkpoint at all. + * Exactly one recognized non-empty string yields a checkpoint. Missing or + * ambiguous identities yield none; transcript text, current session head and + * journal position never substitute for one. Values are compared unchanged, + * without UUID validation or normalization. */ import type { AgentPromptCheckpoint } from "@executablemd/core"; diff --git a/packages/acp/src/native-launch.ts b/packages/acp/src/native-launch.ts index 4c64a9b40..c6fc5869d 100644 --- a/packages/acp/src/native-launch.ts +++ b/packages/acp/src/native-launch.ts @@ -2,35 +2,17 @@ * Native launcher adapters (specs/native-agent-session-launch-spec.md * §Provider-native identity). * - * An adapter knows one thing a document must never state: the argv that makes - * a particular coding-agent CLI resume one exact provider-native session. - * `claude --resume ` and `codex resume ` are adapter implementation - * details, not authored values, and neither an executable path nor a session - * id ever appears in a document. + * Adapters own native resume argv; executable paths and provider-native session + * ids are never document inputs. Command knowledge alone grants no launch: + * `provider-returned` adapters must prove ACP and the native UI reach the same + * conversation; `client-allocated` adapters must prove native creation uses the + * allocated identity, applies private instructions to the first user turn without + * a bootstrap, and later resumes that conversation. * - * Knowing the command shape is not the same as being launch-capable. - * Advertisement is separate, and what an adapter has to prove depends on who - * names its sessions. An adapter the provider names proves that the session - * ACP created is the session the native UI resumes; an adapter that names its - * own sessions creates one directly, so what it proves instead is that the - * native process makes that exact conversation, that the private instruction - * layer governs its first user turn without a bootstrap, and that a later - * invocation resumes the same identity rather than making a second one. - * Until an adapter has proven its own contract against the installed CLI, - * `` refuses that agent before anything of the session moves — - * before a provider-returned adapter's ACP session is released, and before a - * client-allocated one allocates an identity or writes a private file. That is - * the failure the contract asks for rather than a hopeful spawn. - * - * Adapters differ along two structural axes, and both are discriminated rather - * than inferred. The first is who chooses the provider-native session identity: - * a `provider-returned` adapter can only resume a session something else - * created and named, while a `client-allocated` adapter names the session first - * and hands that name to the native process, which is what lets a launch - * construct a conversation instead of merely reattaching to one. The second is - * whether the adapter pins the build behind its executable, and it is - * independent of the first: a name means one conversation only beside the build - * that issued or accepted it, whichever side chose the name. + * Until that contract is proven against the installed CLI, launch refuses before + * ACP detach, client identity allocation or private-file creation. Build pinning + * is an independent discriminator: either construction route may bind a session + * to the exact executable build that issued or accepted its identity. */ import { randomUUID } from "node:crypto"; diff --git a/packages/acp/src/session-configuration.ts b/packages/acp/src/session-configuration.ts index 2d997236a..234c29e66 100644 --- a/packages/acp/src/session-configuration.ts +++ b/packages/acp/src/session-configuration.ts @@ -1,43 +1,19 @@ /** - * Reading and applying one conversation's model and effort + * Translate ACP session configuration into core's model and effort choices * (specs/acp-client-spec.md §Session configuration). * - * ACP advertises configuration as `configOptions` on a session's status: a list - * of selectors, each with an id, a name, a current value and either a flat list - * of values or a list of groups (`SessionConfigOption` in - * `@agentclientprotocol/sdk`). None of that vocabulary leaves this package. What - * crosses into core is `AgentOptionSet` — exact ids, display names, optional - * descriptions, and the group each value was filed under — in the order the - * provider gave them. + * ACP selectors stay inside this package. `AgentOptionSet` preserves exact ids, + * display names, optional descriptions, groups and provider order. Category takes + * precedence; the exact id `model` also identifies an uncategorized model selector. + * Other controls are ignored. Recognized selectors with malformed or ambiguous + * choices, duplicate ids or a selected value absent from their choices fail the + * operation rather than reporting an empty option set. * - * Two selectors are recognized and no others. Category is the preferred signal - * because ACP says a category is a presentation hint rather than a correctness - * requirement, so an agent that files its model selector under no category is - * still recognized by the exact id `model`. `model_config`, booleans, unknown - * categories and every other control are not this feature and are passed over. - * - * Reading is strict about the selector it recognized and incurious about the - * rest. A recognized selector that does not read back — the wrong type, two - * equally preferred candidates, a malformed value, a duplicate id, a current - * value that is not one of the choices — fails the operation rather than - * degrading to an empty list, because an empty list reads as "this agent offers - * you nothing", which is a different answer from "this run could not tell". - * - * ## Applying - * - * Model first, then effort, because effort choices belong to a model: an agent - * asked to change model answers with that model's levels, and validating effort - * against the previous model's would accept a value the new one does not have. - * So the sequence is read, validate, write model, refresh, validate effort - * against the refreshed choices, write effort, refresh, verify — and a request - * that omits a setting writes nothing for it. - * - * Once a write may have happened, any later failure restores what was there - * before, in the same model-first order, and the original failure is what the - * caller is told. A restoration that cannot be verified leaves a conversation - * whose configuration nobody can state, so the session is marked unusable for - * the rest of the run rather than being prompted under a configuration the - * document did not ask for. + * Apply model first, refresh its effort choices, then apply effort and verify the + * result. Omitted settings cause no write. Once a write may have landed, any later + * failure restores the previous settings in model-first order and preserves the + * original failure. Unverifiable restoration marks the session unusable for the + * rest of the run. */ import { ensure, scoped } from "effection"; diff --git a/packages/acp/src/session-key.ts b/packages/acp/src/session-key.ts index 9585079f0..e7f9a820d 100644 --- a/packages/acp/src/session-key.ts +++ b/packages/acp/src/session-key.ts @@ -1,22 +1,14 @@ /** * Session identity (specs/acp-client-spec.md §Session). * - * Keys are namespaced `xmd:v1:` so they can never collide with sessions - * owned by other ACPX consumers (ACPX's only key convention is an - * optional `agent::` prefix, which this scheme avoids). Every - * variable-length identity component — the agent command, the directory - * and an explicit session name — is digested, so a key stays bounded and - * filesystem-safe however long its inputs are. A session store may use - * the key as a file name and encode it again, which an undigested - * component overruns. + * `xmd:v1:` separates these keys from other ACPX consumers. Variable-length + * agent-command, directory and explicit-name inputs are digested so a store may + * encode the key again as a bounded filesystem-safe filename. * - * Session resolution walks candidates from the contextual cwd toward the - * Git repository root and reuses the nearest candidate whose record - * already exists — checked through the ACPX session store, never through - * `ensureSession()`, which would create one. ACPX only reuses a record - * when the cwd matches, so the matched candidate's directory (not the - * caller cwd) becomes the session cwd. When nothing exists yet, the - * session is created for the exact contextual cwd. + * Resolution reuses the nearest existing ACPX record between contextual cwd and + * the repository root, without calling `ensureSession()` and creating one. ACPX + * requires matching cwd, so the selected candidate's directory becomes session + * cwd. With no record, placement uses the exact contextual cwd. */ import { until } from "effection"; diff --git a/packages/acp/src/session-route.ts b/packages/acp/src/session-route.ts index 6a24c1ff4..2737acd5c 100644 --- a/packages/acp/src/session-route.ts +++ b/packages/acp/src/session-route.ts @@ -1,26 +1,14 @@ /** - * How a logical session was first constructed + * Retain how a logical session was first constructed * (specs/native-agent-session-launch-spec.md §Construction route). * - * Construction and live ownership answer different questions, and #519 keeps - * them apart deliberately: + * The route is strict create-once state: never overwritten, deleted, converted, + * repaired or partially read. Conflicting accounts refuse rather than inventing + * history. It grants no right to ensure, prompt, detach, spawn, resume or accept + * history; the coordinator remains the live owner and owns crash behavior. * - * construction route: how this logical session was first constructed - * session coordinator: who may act on it now - * - * The coordinator is the one live owner and owns crash behavior. A route - * grants no right to ensure, prompt, detach, spawn, resume, or accept history — - * it only says which kind of thing this session is, so that a later attachment - * cannot quietly treat an ACP-created conversation as a client-allocated one. - * - * The route is strict create-once durable state. It is never overwritten, - * deleted, converted, repaired, or partially read. A conflict is a refusal, not - * something to reconcile: both accounts describe a session that already exists, - * and picking one would be inventing history. - * - * Both facts use the same natural key and the same digest the merged - * coordinator already derives, so one session names one lease, one ownership - * record, and one route. + * Route, lease and ownership record use the same natural key and digest, so later + * attachment cannot reclassify an ACP-created conversation as client-allocated. */ import { ensure, scoped, until } from "effection"; diff --git a/packages/acp/tests/acceptance.test.ts b/packages/acp/tests/acceptance.test.ts index 3769c8e33..ac547ea6a 100644 --- a/packages/acp/tests/acceptance.test.ts +++ b/packages/acp/tests/acceptance.test.ts @@ -69,13 +69,10 @@ describe("Tier XA — ACPX provider through the rootProvider seam", () => { return { output, outcome, closedByCompletion }; }); - // Agent availability probed through acpx doctor(). expect(harness.doctorCalls).toBeGreaterThan(0); - // A session was created. expect(harness.ensureCalls.length).toBeGreaterThan(0); // Normalized prompt output — output-stream deltas only (thought hidden). expect(result.output).toContain("hello world"); - // Clean completion. expect(result.outcome.ok).toBe(true); // Handle closed before completion settled. expect(result.closedByCompletion).toBeGreaterThan(0); diff --git a/packages/cli/src/bun-repl.ts b/packages/cli/src/bun-repl.ts index 0a729d0f6..bad55bf06 100644 --- a/packages/cli/src/bun-repl.ts +++ b/packages/cli/src/bun-repl.ts @@ -17,7 +17,6 @@ import type { Operation } from "effection"; import { installReplHost, platformDataRoot } from "./repl-assembly.ts"; import { useBunReplTerminal } from "./bun-repl-terminal.ts"; -/** Install everything the REPL needs from this host. */ export function* useBunRepl(): Operation { yield* installReplHost({ dataRoot: () => platformDataRoot(process.platform, homedir(), process.env, sep), diff --git a/packages/cli/src/compiled-repl.ts b/packages/cli/src/compiled-repl.ts index ad106e719..a8fa63322 100644 --- a/packages/cli/src/compiled-repl.ts +++ b/packages/cli/src/compiled-repl.ts @@ -17,7 +17,6 @@ import type { Operation } from "effection"; import { installReplHost, platformDataRoot } from "./repl-assembly.ts"; import { useCompiledReplTerminal } from "./compiled-repl-terminal.ts"; -/** Install everything the REPL needs from this host. */ export function* useCompiledRepl(): Operation { yield* installReplHost({ dataRoot: () => platformDataRoot(process.platform, homedir(), process.env, sep), diff --git a/packages/cli/src/deno-repl.ts b/packages/cli/src/deno-repl.ts index a8cd25ac9..40d2fe5d5 100644 --- a/packages/cli/src/deno-repl.ts +++ b/packages/cli/src/deno-repl.ts @@ -17,7 +17,6 @@ import type { Operation } from "effection"; import { installReplHost, platformDataRoot } from "./repl-assembly.ts"; import { useDenoReplTerminal } from "./deno-repl-terminal.ts"; -/** Install everything the REPL needs from this host. */ export function* useDenoRepl(): Operation { yield* installReplHost({ dataRoot: () => platformDataRoot(process.platform, homedir(), process.env, sep), diff --git a/packages/cli/src/node-repl.ts b/packages/cli/src/node-repl.ts index 630d61a60..4c6418a7c 100644 --- a/packages/cli/src/node-repl.ts +++ b/packages/cli/src/node-repl.ts @@ -17,7 +17,6 @@ import type { Operation } from "effection"; import { installReplHost, platformDataRoot } from "./repl-assembly.ts"; import { useNodeReplTerminal } from "./node-repl-terminal.ts"; -/** Install everything the REPL needs from this host. */ export function* useNodeRepl(): Operation { yield* installReplHost({ dataRoot: () => platformDataRoot(process.platform, homedir(), process.env, sep), diff --git a/packages/cli/src/repl/application.ts b/packages/cli/src/repl/application.ts index 7a2c444ef..b74680100 100644 --- a/packages/cli/src/repl/application.ts +++ b/packages/cli/src/repl/application.ts @@ -1,28 +1,11 @@ /** - * The product: what is on screen, and what every action changes. + * Own screen state and reduce semantic actions against one resolved model prefix + * and this process's live overlay. Components receive detached view data, with + * no session, repository, route mutator or host operation. * - * One boundary owns state. Everything a frame shows is derived here from a - * resolved model prefix plus this process's explicit overlay, and every action - * the tree returns is answered here. Components receive detached view data and - * hand back a semantic action; they hold no session, no repository, no route - * mutator and no host operation, so a keystroke cannot reach the Journal except - * through this reduction. - * - * ## A prefix is not the present - * - * A view frozen at a history marker is read only and fills nothing from the - * live head: no live output, no waiting question, no pause capability. That is - * why the overlay is a separate member rather than merged into the model — - * merging them is exactly the mistake that shows somebody the present while - * they are looking at the past. - * - * ## Navigation that fails changes nothing - * - * Every navigating action builds a candidate route and resolves it against the - * model before it is adopted. A candidate that does not resolve leaves the - * standing route, selection and draft exactly as they were and reports why. - * There is no half-applied navigation, because a route is adopted whole or not - * at all. + * A frozen prefix fills nothing from the live head: no output, waiting question + * or pause capability. Navigation resolves a whole candidate route before + * adoption; a refusal preserves the standing route, selection and draft. */ import { Ok, type Result } from "effection"; @@ -142,13 +125,8 @@ export interface ReplLive { /** Whether this process holds the continuations, and so may pause at all. */ readonly pausable: boolean; /** - * Whether an entry's execution is still running in this process. - * - * The durable side cannot answer this. A root close is recorded the moment the - * document settles, while the task that produced it is still unwinding — so a - * screen reading only `model.settled` would offer the next entry during a - * teardown that has not finished, and announce readiness the session would - * refuse. Readiness is a fact about both halves, and this is the live half. + * Whether this entry's task is still running, including teardown after its + * recorded root close. Readiness needs both this and `model.settled`. */ readonly running: boolean; /** @@ -170,12 +148,8 @@ export interface ReplLive { } /** - * One turn as the Sessions surface shows it, live or retained. - * - * One type for both, because a person is looking at one turn either way: what - * publication changes is where a turn's facts come from, not which turn it is. - * `key` is its mounted identity and survives that change, so the row a person - * had focus on is the same row afterwards. + * One live or retained Sessions turn. Publication changes its source of facts; + * `key` preserves mounted identity and focus across that transition. */ export interface ReplSessionTurn { /** The mounted identity: this process's slot, or a record's own marker. */ @@ -205,17 +179,9 @@ export interface ReplSessionTurn { } /** - * Every turn this screen can show, in the order their Prompts were scheduled. - * - * Not a concatenation of the retained turns and the live ones. Prompts running - * beside each other publish in whatever order their providers answer, so an - * earlier Prompt can still be live while a later one is already durable — and - * appending the live list to the retained one would put it second. - * - * The turns this process observed carry their own place, taken when each Prompt - * was scheduled. Turns it did not observe are in the prefix it replayed, which - * is entirely earlier than anything it went on to run, so they come first in the - * order their records state. + * Order turns by Prompt scheduling, not publication: concurrent providers can + * publish a later Prompt first. Unobserved turns belong to the replayed prefix + * and precede observed slots, whose own scheduling order is retained. */ function chronology(model: ReplModel, live: ReplLive): readonly ReplSessionTurn[] { const observed = new Set(); @@ -240,18 +206,9 @@ function chronology(model: ReplModel, live: ReplLive): readonly ReplSessionTurn[ } /** - * The one identity a publication is correlated by. - * - * Both halves, because neither is unique on its own. A Prompt's durable name is - * derived from where it was written, and names restart with each entry — two - * entries running the same source hold the same name at the same position, which - * is ordinary rather than damaged. Correlating by the name alone suppresses both - * of those records and resolves both slots to whichever one the chronology - * reached first, so one turn is shown twice and the other not at all. - * - * The entry is the one each side already carries: the slot's own, and the - * record's own. Never the entry that is current, the sequence by itself, or the - * order the two turns happened to finish in. + * Correlate by each slot's and record's own entry plus durable Prompt name. + * Names restart in every entry, so name alone conflates repeated source; the + * current entry, sequence and completion order cannot identify a publication. */ function correlation(entry: string, name: string): string { return `${entry}\u0000${name}`; @@ -348,12 +305,8 @@ export interface ReplFormMessage { } /** - * The form being filled in, while a question is being asked. - * - * Values are keyed by field name because the fields are independent: one global - * string would make editing either field overwrite the other. None of this is - * durable, none of it is in the route, and all of it is discarded when the - * question ends or its drawer is closed. + * Form state is process-local and discarded when the question or drawer ends. + * Values are keyed by field so editing one cannot overwrite another. */ export interface ReplFormState { /** What has been typed into each field so far, by field name. */ diff --git a/packages/cli/src/repl/components/rows.ts b/packages/cli/src/repl/components/rows.ts index 249b81ac9..cf4189fe3 100644 --- a/packages/cli/src/repl/components/rows.ts +++ b/packages/cli/src/repl/components/rows.ts @@ -102,7 +102,6 @@ export function fieldText(prompt: string, text: string, focused: boolean): strin return `${parts.marker}${parts.prompt}${parts.earlier}${parts.value}`; } -/** Read an optional string field. */ function optional(input: ReplViewData, name: string): string | undefined { const value = fields(input)?.[name]; return typeof value === "string" ? value : undefined; diff --git a/packages/cli/src/repl/layout.ts b/packages/cli/src/repl/layout.ts index 4caa26cdb..9e1b0477d 100644 --- a/packages/cli/src/repl/layout.ts +++ b/packages/cli/src/repl/layout.ts @@ -758,7 +758,6 @@ export function flatten(root: ReplBox): readonly ReplBox[] { return [root, ...root.children.flatMap((child) => flatten(child))]; } -/** Build one box. A helper, so no call site assembles the shape by hand. */ export function box(input: { readonly id: string; readonly key?: string; diff --git a/packages/cli/src/repl/presentation-style.ts b/packages/cli/src/repl/presentation-style.ts index af6d38392..97c2f8313 100644 --- a/packages/cli/src/repl/presentation-style.ts +++ b/packages/cli/src/repl/presentation-style.ts @@ -1,43 +1,14 @@ /** - * What a row means, and what that means for the cells it is drawn in. + * Map typed row roles to colour, weight and surface in one pure, private module. + * No model, host Api, Journal access or mutable state reaches this mapping. * - * The application knows what every row *is* while it still has the typed facts - * that produced it — a recorded output, an event's metadata, an entry that - * failed, the position a reader has selected. This module is where that meaning - * becomes colour, weight and a surface, and it is the only place that decides - * one. Nothing above it names a colour and nothing below it reads a model: the - * renderer is handed ops, and the ops carry whatever this said. + * Role, selection and history belong to the reading; keyboard focus arrives + * after reconciliation and adds weight without changing geometry or replacing + * token foregrounds. Only its marker takes the focus colour. Selection keeps + * its own surface, so moving focus cannot erase it. * - * It is pure. There is no operation here, no host Api, no Journal access and no - * mutable state, so a role is recomputed from the frame's own reading every time - * and owns nothing that could outlive it. It is private to the REPL; no package - * exports it and no plugin extends it. - * - * ## Three facts, and what each may change - * - * A row carries one immutable **role**, and separately whether it is - * **selected** and whether it is being read as **history**. Those are facts - * about the reading. Keyboard **focus** is not: it belongs to the mounted tree - * and is known only after reconciliation, so it arrives at draw time and adds - * weight to whatever the row already was. That division is what keeps selection - * visible while focus is somewhere else — the two are drawn by different - * properties of the same cell, so neither can erase the other. - * - * Focus takes no colour of its own away from a row. A row's foregrounds say - * what its characters *are* — a delimiter, a tag, a quoted value, a failure — - * and a focus that repainted them all one colour would cost a reader the - * reading in exchange for a fact the marker in front of the row already - * carries. The marker is the one cyan thing, and it is a run of its own. - * - * No geometry is decided here. Width, height, padding and borders are the - * layout's, and a focused row occupies exactly the cells an unfocused one does. - * - * ## A colourless reading still works - * - * Every state this colours is also said in text: an outcome is spelled `[ok]` or - * `[err]`, a selected row keeps its `*`, and a focused control keeps its `>`. - * Colour is emphasis on a reading that is already complete, which is why a - * terminal that ignores it loses nothing a person needs. + * Text remains sufficient without colour: outcomes spell `[ok]` or `[err]`, + * selection keeps `*`, and focus keeps `>`. */ import { rgba } from "@bomb.sh/tty"; @@ -143,7 +114,6 @@ export interface ReplRowStyle { readonly inspected: boolean; } -/** Build one row's style. A helper, so no call site assembles the shape. */ export function styleOf( role: ReplPresentationRole, facts: { readonly selected?: boolean; readonly inspected?: boolean } = {}, diff --git a/packages/cli/src/repl/terminal-host.ts b/packages/cli/src/repl/terminal-host.ts index 5839d9143..ba2842a78 100644 --- a/packages/cli/src/repl/terminal-host.ts +++ b/packages/cli/src/repl/terminal-host.ts @@ -1,16 +1,10 @@ /** - * The portable half of a REPL terminal, over capabilities a runtime supplies. + * Assemble the REPL terminal over runtime-supplied capabilities: byte-stream + * backpressure, resize notifications and scope-owned release stay portable. + * Runtime-named factories supply their host operations without runtime detection. * - * `terminal.ts` says what the REPL needs; this says how to build it - * once a host has handed over five things it alone can do. Everything that is - * the same on every runtime — turning an async byte source into a stream with - * real backpressure, turning a resize notification into a stream of sizes, - * ending both when the scope ends — lives here, so the runtime-named factories - * contain nothing but their own runtime's spelling of those five capabilities. - * - * Nothing registers this. A runtime entrypoint installs it when the REPL - * command exists; until then it is a factory nobody calls, which is what keeps - * `@bomb.sh/tty` and raw mode off the path of every other command. + * An entrypoint installs this only for the REPL, keeping `@bomb.sh/tty` and raw + * mode off other command paths. */ import { diff --git a/packages/code-review-agent/src/categories.ts b/packages/code-review-agent/src/categories.ts index 479b825c8..7c5d42041 100644 --- a/packages/code-review-agent/src/categories.ts +++ b/packages/code-review-agent/src/categories.ts @@ -41,13 +41,11 @@ const verbositySet = new Set(VERBOSITY_RULES); const typeAwareSet = new Set(TYPE_AWARE_RULES); /** - * Categorize a rule ID into one or more categories. - * Returns an array of category names the rule belongs to. + * A rule may belong to several categories; unmatched rules belong to `other`. */ export function categorizeRule( ruleId: string, ): ("structural" | "verbosity" | "typeAware" | "other")[] { - // Strip plugin prefix (e.g., "eslint/no-unused-vars" → "no-unused-vars") const bare = ruleId.includes("/") ? ruleId.split("/").pop()! : ruleId; const categories: ("structural" | "verbosity" | "typeAware" | "other")[] = []; diff --git a/packages/code-review-agent/src/parse-diff.ts b/packages/code-review-agent/src/parse-diff.ts index 5db308903..38d156d69 100644 --- a/packages/code-review-agent/src/parse-diff.ts +++ b/packages/code-review-agent/src/parse-diff.ts @@ -1,9 +1,6 @@ /** - * parseDiff — transforms raw git diff output into a typed PR object. - * - * Handles: unified diff format, rename detection, binary file skipping, - * language inference, test/config/type-declaration classification, - * diffPreview truncation, directory computation. + * Parse Git unified diffs and name-status output into review data. + * Binary files are omitted; previews are bounded independently of the full diff. */ import type { PR, DiffFile, DiffHunk, DiffLine } from "./types.ts"; @@ -117,7 +114,6 @@ function parseNameStatus(raw: string): Map } if (statusChar === "R" || statusChar === "C") { - // Rename/Copy: STATUS\tOLD\tNEW — use new path const newPath = parts[2] ?? parts[1] ?? ""; result.set(newPath, statusChar); } else { @@ -137,20 +133,17 @@ function parseDiffContent( ): DiffFile[] { const files: DiffFile[] = []; - // Split on `diff --git` headers const fileSections = rawDiff.split(/^diff --git /m).filter(Boolean); for (const section of fileSections) { const lines = section.split("\n"); - // Extract file path from the header: `a/path b/path` const headerMatch = lines[0]?.match(/a\/(.+?) b\/(.+)/); if (!headerMatch) { continue; } const filePath = headerMatch[2]; - // Skip binary files if (section.includes("Binary files ")) { continue; } @@ -207,7 +200,6 @@ function parseDiffContent( addLineNo++; removeLineNo++; } - // Skip lines starting with \ (e.g., "\ No newline at end of file") } files.push({ diff --git a/packages/code-review-agent/src/plugin.ts b/packages/code-review-agent/src/plugin.ts index 4f53795db..51e841ce3 100644 --- a/packages/code-review-agent/src/plugin.ts +++ b/packages/code-review-agent/src/plugin.ts @@ -1,26 +1,10 @@ /** - * The review graph as a Plugin. + * Install the packaged review graph when an operator selects this Plugin. * - * `@executablemd/code-review-agent` is a library, and its default export is the - * Plugin a host installs once an operator has selected this package. Nothing - * about the graph changes here: the same thirty-five Markdown declarations, the - * same six reserved registrations, the same origins, digests and packaged - * assets, read through the same boundary. What changes is who assembles them — - * a Plugin the host installs, rather than a package the CLI imports by name at - * four separate call sites. - * - * ## Which commands claim the graph - * - * A review is the program that must not be answerable by the repository it is - * reviewing, so every command that can *run* a review document claims the - * forty-one names: `xmd run`, `xmd syntax` (which describes what a run may - * write), `xmd plan` (which validates a candidate against the profile a later - * run supplies) and a workflow action that executes a document. - * - * `xmd test` claims none of them. A test document is a different profile and - * may still supply its own component of any of these names — while the nested - * `` child a test can launch *is* the run profile, and - * reinstalls this Plugin with command `run`. + * Run, syntax, plan and executing workflow actions claim its thirty-five Markdown + * declarations and six reserved registrations, so the repository being reviewed + * cannot replace the review program. Root `xmd test` claims none; its isolated + * `` child reinstalls this Plugin with command `run`. */ import type { Operation } from "effection"; @@ -34,22 +18,11 @@ import { reviewComponentDeclarations, useReviewComponents } from "./review-compo const EXECUTING_ACTIONS: ReadonlySet = new Set(["start", "resume", "fork"]); /** - * Every `xmd workflow` option that takes a separated value. - * - * A value is not an action however much it reads like one, so the scan below - * steps over the token after each of these. The list is every non-boolean field - * of the command's own grammar (`workflowConfig` in - * `packages/cli/src/workflow.ts`) plus the two options read out of argv before - * that grammar exists: `--plugin`, and the aggregate and generated root - * properties. The boolean switches — `--verbose`/`-V`, `--raw`, - * `--secret-detection`, `--no-secret-detection`, `--json`, `--forkable` — take - * no value and are skipped as the options they are. - * - * It has to be written out here rather than read from the command, because the - * CLI depends on this package and not the other way round. What makes the - * omission of one visible is the rule it breaks: `xmd workflow --output start - * export run-1` exports a run, and a scan that read `start` as the action would - * have installed the review graph for a command that executes no document. + * Workflow options whose separated values must not be mistaken for actions. + * Keep this aligned with `workflowConfig` in `packages/cli/src/workflow.ts` and + * argv-level Plugin/root-property options; the CLI dependency prevents importing + * its grammar here. For example, `workflow --output start export run-1` exports + * and must not claim the review graph because the output value reads `start`. */ const VALUED_OPTIONS: ReadonlySet = new Set([ "--plugin", @@ -73,13 +46,9 @@ function takesValue(token: string): boolean { } /** - * Whether this workflow command line executes a document. - * - * The action is the first positional after `workflow`: the first token that is - * neither an option nor an option's value. Everything after `--` is positional - * by definition and is not scanned for one, and a token this command defines no - * action for is not one — a malformed command line executes no document either - * way, and the command itself is what says so. + * Read the first positional after `workflow`, skipping options and their values. + * Stop at `--`; unknown actions remain the command's own grammar error and claim + * no review graph. */ function executesDocument(args: readonly string[]): boolean { const start = args.indexOf("workflow"); diff --git a/packages/code-review-agent/src/review-components.ts b/packages/code-review-agent/src/review-components.ts index 765a21e97..31a5cf9c2 100644 --- a/packages/code-review-agent/src/review-components.ts +++ b/packages/code-review-agent/src/review-components.ts @@ -1,45 +1,16 @@ /** - * The review and repository-analysis component graph, as this package declares - * it to one execution. + * Declare the packaged review graph before a root document is imported. * - * The components a review runs used to live in `.reviews/components/` and - * `.reviews/policies/`, and every entrypoint reached them with `--include`. That - * made the graph a property of the checkout being reviewed: a pull request could - * add a file called `Finding.md` and the review would run the branch's own copy - * while reporting on it. A review is exactly the program that must not be - * answerable by its subject, so the graph moved here, into the installation, and - * the host hands it to each execution before any document code exists. + * Thirty-five Markdown components cross as {@link MarkdownComponent} values with + * packaged bytes, stable asset origins and digests. Six TypeScript components use + * reserved registrations. Both claim names so the repository being reviewed + * cannot replace its reviewers; duplicate host claims refuse at admission. + * Ordinary includes and component discovery remain available for unclaimed names. * - * ## Two tiers, one claim - * - * Thirty-five of the components are Markdown, and each crosses as a - * {@link MarkdownComponent}: the exact packaged bytes, a stable origin naming - * the asset rather than a path, and the digest of what this build shipped. Six - * are TypeScript, and each crosses as a **reserved** registration. The two - * mechanisms differ in what they carry; they agree in what they mean — the host - * is claiming the name rather than offering a default for it, so a repository - * file of the same name does not win, and does not silently lose either: a - * second claim on one name is refused at admission, before the root document is - * imported. - * - * What this does *not* do is disable ordinary component discovery. A caller's - * `--include` and a repository's own components resolve exactly as they always - * have. Only these forty-one names are spoken for. - * - * ## Read from the package, never from the caller - * - * Every asset is located from this module's own URL. `deno compile --include` - * embeds `src/documents/` at the same relative path, the npm build copies the - * tree into the emitted package, and JSR publishes the sources — so one lookup - * is correct in a source checkout, a published package and a binary with no - * checkout at all. A build that dropped an asset fails loudly at assembly rather - * than resolving the name and finding nothing behind it. - * - * The read goes to the Effection filesystem directly rather than through - * `API.Fs` or the document-facing `Files` provider. Both of those are - * middleware a running document can compose around, and a review whose own - * components could be answered by the document under review would have moved the - * shadowing problem rather than solved it. + * Assets resolve from this module's own URL in source, npm and compiled builds. + * Read them through the Effection filesystem directly: document-facing API.Fs and + * Files middleware must not substitute the review program. Missing assets fail + * assembly rather than leaving an empty component claim. */ import { readTextFile } from "@effectionx/fs"; @@ -97,17 +68,9 @@ export interface ReviewDocument { } /** - * Every Markdown component this package declares, in the order it declares them. - * - * A written list rather than a directory walk. A compiled binary has no - * directory to walk — `deno compile` embeds files, and enumerating them is not - * something a build guarantees — so the manifest has to be data the module - * carries. It also makes adding a component a reviewable edit rather than a - * side effect of putting a file somewhere. - * - * The grouping is the same one the documents are filed under, and it travels - * into the origin: a policy and a component are different kinds of thing to a - * person reading a catalog, and the origin is where that shows. + * Declare the packaged Markdown manifest in stable order. + * Compiled assets cannot rely on directory enumeration. Groups also determine + * origins, so adding or relocating a component is an explicit identity edit. */ export const REVIEW_DOCUMENTS: readonly ReviewDocument[] = [ { name: "AbstractionNames", group: "components" }, @@ -153,30 +116,17 @@ export function reviewDocumentUrl(document: ReviewDocument): URL { } /** - * How a packaged component identifies itself in a catalog. - * - * The package and the asset, never a filesystem path: the same component is at a - * different absolute path in a checkout, a `node_modules` tree and a binary that - * has no filesystem for it at all, and all three are the same component. This is - * what lets a test compare a source run and a compiled run without knowing where - * either one keeps its files. + * Identify a component by package and asset, never its host filesystem path. + * Source, npm and compiled distributions therefore report the same origin. */ export function reviewDocumentOrigin(document: ReviewDocument): string { return `${REVIEW_ORIGIN}/${document.group}/${document.name}.md`; } /** - * The thirty-five Markdown declarations, read from this build's own assets. - * - * Built fresh per assembly, exactly as ``'s declaration is. A declaration - * is not identified by object identity — what fixes it is the name, the origin, - * the bytes and the digest — so two assemblies in one process declare the same - * components without sharing a mutable array anyone could reach and edit. - * - * Lazy, and the reads happen here: this is trusted host assembly, before the - * root document is imported. A missing asset, or bytes whose parse disagrees - * with what is declared about them, fails here rather than at the moment a - * review writes the name. + * Read this build's packaged Markdown lazily during trusted host assembly. + * Each assembly creates a fresh array; declaration identity is name, origin, bytes + * and digest rather than object identity. Missing assets fail before root import. */ export function* reviewComponentDeclarations(): Operation { const declarations: MarkdownComponent[] = []; @@ -212,24 +162,10 @@ export function* reviewComponentDeclarations(): Operation { } /** - * One review implementation, as a component the engine can call. - * - * Each of the six destructures the props it ships a schema for, and the engine - * validates a record against that schema before it calls anything — so by the - * time the implementation runs, the record is that shape. What TypeScript - * cannot see is the correspondence between a JSON Schema *value* and a - * TypeScript *type*, so a registration whose `fn` states its own prop type does - * not structurally satisfy `FunctionComponent`. - * - * The narrowing is therefore stated once, here, instead of six implementations - * being rewritten to take `Record` and parse themselves. They - * moved out of `.reviews/components/` with their bodies unchanged, which is what - * lets a reader diff the move and see only the import lines; changing every - * signature to satisfy a boundary would have hidden that. - * - * It asserts nothing the schema does not already enforce. A component whose - * declared type disagrees with its declared schema is a mistake in this package, - * and the schema is what the engine holds a document to either way. + * Adapt typed implementations after the engine validates their declared schemas. + * TypeScript cannot infer a prop type from its JSON Schema value. Keep each + * implementation's prop type aligned with that schema; the schema remains the + * runtime check. */ // deno-lint-ignore no-explicit-any function reviewComponent(fn: (props: any) => Operation): FunctionComponent { @@ -237,19 +173,10 @@ function reviewComponent(fn: (props: any) => Operation): FunctionCompon } /** - * The six TypeScript components, as reserved registrations. - * - * Reserved rather than ordinary, which is the registration tier's way of saying - * what a Markdown declaration says: the host claims the name. Leaving these - * ordinary would have moved thirty-five components out of the subject's reach - * and left the six that run processes, read credentials and reach the network - * shadowable — the half worth shadowing. - * - * They stay public and keep their existing names, props, returns and behavior. - * Turning the two `CommentReview` helpers into private declarations was - * considered and rejected: a declaration's privates may only be identity - * factories, and making them private would change a contract the review roots - * already depend on. + * Reserve the six TypeScript component names alongside the Markdown declarations. + * These implementations run processes, read credentials and reach the network; + * leaving them shadowable would let the review subject replace its own reviewers. + * Their existing public names and contracts are retained. */ export const REVIEW_REGISTRATIONS: readonly ComponentRegistration[] = [ { diff --git a/packages/code-review-agent/tests/parse-diff.test.ts b/packages/code-review-agent/tests/parse-diff.test.ts index 598270fcb..6d703c185 100644 --- a/packages/code-review-agent/tests/parse-diff.test.ts +++ b/packages/code-review-agent/tests/parse-diff.test.ts @@ -75,7 +75,6 @@ describe("parseDiff", () => { const pr = parseDiff(rawDiff, rawFiles, META); - // Renamed files produce a file entry with R status and zero hunks expect(pr.files).toHaveLength(1); expect(pr.files[0].path).toBe("new-name.ts"); expect(pr.files[0].status).toBe("R"); diff --git a/packages/core/src/components/CodeBlock.ts b/packages/core/src/components/CodeBlock.ts index d3d94ea26..7025bc9ac 100644 --- a/packages/core/src/components/CodeBlock.ts +++ b/packages/core/src/components/CodeBlock.ts @@ -1,41 +1,18 @@ /** - * `` — place any text inside one fenced Markdown code block + * `` — quote text in a fenced Markdown block * (specs/executable-mdx-spec.md §6.19). * - * A document that shows generated source, a diagnostic, or anything else it did - * not write needs the text to arrive as text. The hazard is the fence itself: a - * value that happens to contain three backticks closes a three-backtick block - * early, and the rest of it lands in the document as Markdown — as headings, as - * component invocations, as another fence. Writing that arithmetic in an eval - * block puts the safety of the surrounding document in the hands of every - * author who needs to quote something. + * The fence has one more backtick than the value's longest run, with a minimum + * of three, so the value cannot close it. The value is otherwise unchanged: + * nothing is trimmed, normalized, escaped, re-encoded or removed, and returned + * text is rendered without being rescanned as source (§6.8). * - * So the fence is chosen here, from the value, and it is the only thing this - * component decides. It scans for the longest run of backticks and opens with - * one more than that, never fewer than three, which is a fence the value cannot - * close no matter what it holds. + * The envelope adds one line feed before and after the value and none after the + * closing fence. A document that wants a final line feed writes it. * - * ## The value is not read for anything else - * - * Nothing is trimmed, normalized, escaped, re-encoded or removed. Text that - * looks like a fence, an element, an interpolation, HTML or an executable code - * block stays exactly as it arrived, because a function component's return is - * rendered rather than rescanned as document source (§6.8). The two line feeds - * that frame the value belong to the envelope, not to the value, and there is - * no line feed after the closing fence: a document that wants one writes it. - * - * ## `value` is an ordinary prop - * - * Unlike `` (§6.12), whose operand must arrive by reference or lose the - * very failures it exists to report, a string crosses the component JSON - * boundary as itself. Keeping `value` on the ordinary boundary is what lets a - * repository `CodeBlock.md` receive it the way it receives every other prop, - * instead of inheriting a capture from core's registration that it never - * declared. - * - * `language` is closed to one token — the info string a Markdown reader expects - * — so that a value cannot reach the opening fence line, where it would be read - * as syntax rather than shown as text. + * `value` is an ordinary string prop: it crosses the JSON boundary unchanged, + * and a repository replacement receives it without inheriting a capture. + * `language` is limited to one token so it cannot inject opening-fence syntax. */ import type { Operation } from "effection"; diff --git a/packages/core/src/components/Fail.ts b/packages/core/src/components/Fail.ts index 3eb4327d8..3e9a05940 100644 --- a/packages/core/src/components/Fail.ts +++ b/packages/core/src/components/Fail.ts @@ -1,56 +1,21 @@ /** - * `` — stop authored work with a message the reader can act on + * `` — stop authored work with the author's exact message * (specs/executable-mdx-spec.md §6.8.2). * - * ```md - * - * ``` + * This is an ordinary function-component failure: core dismantles, names and + * positions the invocation. No prefix or classification changes the message. + * With no `printErrors()` declaration, a text root stops unless its author wrote + * an enclosing ``. A value body's `throw` mode remains final, so a + * printing boundary cannot turn the abort into success or a missing-Return error. * - * A document that has decided it cannot continue has something to say about - * why, and until now the only way to end a value body was to reach its end - * without a `` — which reports that the body selected no value, not - * what the author concluded. This raises the author's own sentence instead, at - * the position the author wrote it. + * Canonical dispatch refuses a paired form before expanding its children. The + * closed schema requires one non-empty string `message`; malformed props fail + * before the body. The body checks `hasBinding` before raising so an invalid `as` + * capture reports the capture mistake instead of the authored message. * - * ## An ordinary failure, deliberately - * - * There is no new error mode here and no root special case. This is the - * ordinary failure of a function component (§6.8.1): the engine dismantles the - * invocation, names it, positions it at the opening tag, and propagates it. The - * message is the author's exact string — nothing is prefixed, classified or - * interpolated into it, because the author already wrote the sentence they - * wanted the reader to see. - * - * It carries no `printErrors()` declaration, and that omission is the whole of - * its recovery policy. A text root therefore stops here by default, and an - * author who wants the document to continue says so with `` around - * the region — the same way they would for any other component that fails. A - * value body installs `throw`, which a printing boundary does not replace, so - * an enclosing `` cannot turn a deliberate abort into a successful - * result; the authored failure settles the body before missing-`` - * settlement can report anything about it. - * - * ## What it refuses, and why it refuses it first - * - * The one form is self-closing, declared here and dispatched by canonical core, - * so a paired spelling never expands its children: an author who wrote a body - * meant something this component does not do. The closed schema takes one - * required non-empty `message`, so a missing, empty, non-string or unknown prop - * is refused by the ordinary props boundary before anything runs. - * - * `as` is the one refusal this body makes for itself, because `as` is valid for - * a text component by default. There is no value to capture: this renders - * nothing and returns nothing, it raises. Asking {@link hasBinding} before - * raising is what makes a mistaken capture a report about the capture rather - * than the authored message arriving under a name that would never be bound. - * - * ## What it owns - * - * Nothing. No permission, no context, no provider, no resource, and no durable - * operation of its own — the only journal activity around it is what ordinary - * execution already owns, importing the selected component and recording the - * root's outcome. Replay of a completed root restores that outcome without - * re-expanding the root. + * It renders and returns nothing, owns no resource, permission, context, provider + * or durable operation, and adds only ordinary import/root-outcome journal work. + * Completed-root replay restores that outcome without expanding the root. */ import type { Operation } from "effection"; diff --git a/packages/core/src/eval-handler.ts b/packages/core/src/eval-handler.ts index 5504bbe93..f09b7673d 100644 --- a/packages/core/src/eval-handler.ts +++ b/packages/core/src/eval-handler.ts @@ -158,7 +158,6 @@ export const evalFactory: ModifierFactory = (_params) => (_args, _next) => ...sourceDescription(ctx.position), }, function* (): Operation { - // Merge incoming bindings snapshot into env before execution Object.assign(evalEnv.values, bindings); const fn = yield* compileBlock(transformed.code, transformed.userImports ?? []); @@ -216,11 +215,9 @@ export const evalFactory: ModifierFactory = (_params) => (_args, _next) => if (result.value && typeof result.value === "object") { const restored = result.value as Record; - // Extract __output before merging into env if (typeof restored.__output === "string") { outputRef.text = restored.__output; } - // Remove __output from exports before assigning to env const { __output: _, ...exports } = restored; Object.assign(evalEnv.values, exports); } diff --git a/packages/core/src/eval-interpolate.ts b/packages/core/src/eval-interpolate.ts index f24aec82a..e10d18a47 100644 --- a/packages/core/src/eval-interpolate.ts +++ b/packages/core/src/eval-interpolate.ts @@ -47,10 +47,8 @@ export function interpolateEvalBindings( content: string, bindings: Record, ): string { - // Protect escaped braces: \{ → placeholder const escaped = content.replaceAll("\\{", ESCAPED_BRACE_PLACEHOLDER); - // Run interpolation on the protected content. // Supports dotted paths: {pr.meta.number} traverses bindings.pr.meta.number const interpolated = escaped.replace(BARE_BINDING_RE, (match, key: string) => { const parts = key.split("."); @@ -73,6 +71,5 @@ export function interpolateEvalBindings( return String(value); }); - // Restore escaped braces: placeholder → literal { return interpolated.replaceAll(ESCAPED_BRACE_PLACEHOLDER, "{"); } diff --git a/packages/core/src/eval-transform.ts b/packages/core/src/eval-transform.ts index d8ee6c758..8c367d775 100644 --- a/packages/core/src/eval-transform.ts +++ b/packages/core/src/eval-transform.ts @@ -105,14 +105,11 @@ export function transformBlock( source.slice(node.start - offset, node.end - offset), ); - // Build AST with only body nodes for mode detection, export collection, etc. // deno-lint-ignore no-explicit-any const ast = { body: bodyNodes, type: "Program" } as any; - // 2. Detect mode const mode = detectMode(ast); - // 3. Collect exports from top-level declarations const exports = collectExports(ast); // 4. Collect imports — free variables present in env. @@ -124,10 +121,8 @@ export function transformBlock( const freeVars = collectFreeVariables(ast, declaredNames); const imports = freeVars.filter((name) => envKeySet.has(name)); - // 5–7. Build transformed code const s = new MagicString(source); - // 5a. Remove import declarations from the body. for (const node of importNodes) { let start = node.start - offset; let end = node.end - offset; @@ -156,10 +151,8 @@ export function transformBlock( } } - // 7. Append sourceURL s.append(`\n//# sourceURL=eval:${blockId}`); - // 8. Generate source map const map = s.generateMap({ source: blockId, hires: true }); return { @@ -364,7 +357,6 @@ function collectFreeVariables(ast: AstNode, declaredNames: Set): string[ const references = new Set(); const localDecls = new Set(declaredNames); - // Also collect names from all top-level variable declarations for (const node of ast.body) { const names = extractDeclaredNames(node); for (const name of names) { @@ -403,14 +395,12 @@ function collectReferences(node: AstNode, references: Set, localDecls: S // Skip key names in object properties (not computed) if (node.type === "Property" && !node.computed) { - // Only visit the value, not the key collectReferences(node.value, references, localDecls); return; } // For variable declarations, skip the declared name(s) and visit init if (node.type === "VariableDeclarator") { - // Don't visit the id (it's a declaration, not a reference) collectReferences(node.init, references, localDecls); return; } diff --git a/packages/core/src/execute.ts b/packages/core/src/execute.ts index 98ff7821f..8fafe1da1 100644 --- a/packages/core/src/execute.ts +++ b/packages/core/src/execute.ts @@ -2939,22 +2939,22 @@ export type JournalAdmission = (retained: readonly DurableEvent[]) => Operation< /** * What a trusted host attaches to one execution. * - * `install` runs contextual behavior the document inherits. `admissions` is - * copied by canonical execution *before* `install` runs, so nothing an - * installation does afterwards — including anything it composes — can add to, - * remove from or observe the collection that ends up authoritative. + * Canonical execution captures the host inputs below by value before any + * installation runs. Later installation, middleware and document code cannot + * replace those captured inputs or alter the collections execution owns. + * `install` runs contextual behavior the document inherits. */ export interface ExecutionInstallation { + /** + * Retained-history requirements, copied into an execution-owned collection + * that installed code cannot observe, add to or remove from. + */ readonly admissions?: readonly JournalAdmission[]; /** * The component bundle this execution is closed over. * * Plain immutable data: the authored names, their canonical paths inside the * pinned tree, their blob object ids, and the exact sources read from it. - * Captured by value alongside the admissions, before any installation runs, - * so what a name resolves to — and which answers a document may invoke — is - * fixed before anything can observe or replace it. - * * One execution runs under one bundle. Two installations supplying one is * refused rather than merged. */ @@ -2966,26 +2966,22 @@ export interface ExecutionInstallation { * origin, the bytes, their digest, the forms and any private declarations * those bytes alone may write; structural syntax states the name, the origin, * the forms, the props schema, its documentation, and whether it is a - * construct or one of that construct's regions. Captured by value alongside - * the admissions, before any installation runs, so what a declared name - * resolves to — and which answers a document may invoke — is fixed before - * anything can observe or replace it. + * construct or one of that construct's regions. */ readonly declarations?: readonly ExecutionDeclaration[]; /** * How this installation expands the structural syntax it declared. * - * Read once and bound with the declarations it belongs to, before any - * installation runs. An installation that declares structural syntax supplies - * one, and one that supplies it declares structural syntax: either half alone - * is refused before the root document is read. + * Read once and bound with the declarations it belongs to. An installation + * that declares structural syntax supplies one, and one that supplies it + * declares structural syntax: either half alone is refused before the root + * document is read. */ expand?(request: ExpansionRequest): Operation; /** * What this installation records inside the durable root. * - * Captured by value alongside the admissions, before any installation runs, - * and invoked after retained-history admission and before any public document + * Invoked after retained-history admission and before any public document * policy or the root import. A handler cannot prevent it, and cannot observe * the run before it exists. */ @@ -2994,35 +2990,29 @@ export interface ExecutionInstallation { * Who receives the harness canonical `` mints for each of its * invocations. * - * Captured by value alongside the admissions, before any installation runs, - * for the same reason: what a test may deliver its harness to is fixed - * before anything can observe or replace it. Nothing is published — the - * capability exists only as the argument of this call — so a document run by - * a host that attaches none has no nested-execution permission anywhere in it. + * Nothing is published — the capability exists only as the argument of this + * call — so a document run by a host that attaches none has no nested-execution + * permission anywhere in it. */ readonly testHarness?: TestHarnessInstaller; /** * The components of this host's whose implementations name durable work * after their own invocation. * - * Captured by value alongside the admissions, before any installation runs, - * for the reason all of these are: what may name durable work here is fixed - * before anything can observe or replace it. Each factory is called once, - * with a claimant this execution minted for that component — delivered as the - * argument of that call and published nowhere — and what it returns is - * registered through the ordinary path. A host that declares none has no - * component that can name a durable operation after its invocation. + * Each factory is called once, with a claimant this execution minted for that + * component — delivered as the argument of that call and published nowhere — + * and what it returns is registered through the ordinary path. A host that + * declares none has no component that can name a durable operation after its + * invocation. */ readonly components?: readonly IdentityComponent[]; /** * The symbols this host's profile describes, when its profile is not the one * the execution itself would derive. * - * Captured by value alongside the admissions, before any installation runs, - * for the reason the rest are: what a document is shown is settled before - * anything can observe or replace it. Omitted is the ordinary case — canonical - * core derives the symbols from the selection inputs this execution captured, - * which is what makes an ordinary run's reference the run's own. + * Omitted is the ordinary case — canonical core derives the symbols from the + * selection inputs this execution captured, which is what makes an ordinary + * run's reference the run's own. * * `xmd plan` states one, because the Plan being written is a program a later * `xmd run` executes: the vocabulary the agent must be shown is that profile's @@ -3037,13 +3027,10 @@ export interface ExecutionInstallation { /** * The maximum permission a generated fragment may be evaluated under here. * - * Captured by value alongside the rest, before any installation runs, for a - * reason the others share and this one sharpens: `` is a public - * component, so any author may write it, and what stops that from being a - * capability is that the ceiling was stated by the host before a document - * existed. Nothing a running document reaches names this — not a context, - * whose name is not a secret; not a registry, which a nested scope layers - * over; not a prop, which an author writes. + * `` is public, so any author may write it; the permission ceiling + * comes only from the trusted host. Nothing a running document reaches names + * this — not a context, whose name is not a secret; not a registry, which a + * nested scope layers over; not a prop, which an author writes. * * Omitted is the ordinary case for a host that offers no evaluation at all: * `` then refuses before the producer runs, rather than evaluating @@ -3057,8 +3044,7 @@ export interface ExecutionInstallation { * Run during profile capture, before this installation's ordinary * `install()`, and handed a registrar fixed to each provider installation. * Every registered handler receives a fresh request carrying that - * installation's origin. Captured by value with the rest: what a provider may - * identify is settled before any document code exists. + * installation's origin. */ readonly componentAnswers?: readonly ComponentAnswerInstallation[]; install?(): Operation; diff --git a/packages/core/src/expand.ts b/packages/core/src/expand.ts index 9e2f26860..7facb1e87 100644 --- a/packages/core/src/expand.ts +++ b/packages/core/src/expand.ts @@ -3461,7 +3461,6 @@ function* expandFunctionComponent( } } - // Resolve expression props let resolvedProps: Record; try { resolvedProps = yield* resolveExpressionProps(openProps, openExpressions, name, projectedEnv); @@ -3475,7 +3474,6 @@ function* expandFunctionComponent( ]; } - // Strip slot prop before validation const asRefused = asBindingViolation(name, resolvedProps.as); if (asRefused !== undefined) { return [yield* raise({ type: "error", message: asRefused.message, source: name })]; @@ -3484,7 +3482,6 @@ function* expandFunctionComponent( const owner = asBinding === undefined ? callerOwner : undefined; const { slot: _slot, as: _as, ...propsForValidation } = resolvedProps; - // Validate props let validatedProps: Record; try { validatedProps = yield* validateProps(name, propsForValidation, definition.props); @@ -3999,10 +3996,8 @@ function* resolveExpressionProps( componentName: string, explicitEnv?: EvalEnv, ): Operation> { - // Start with already-resolved props const resolved = { ...props }; - // Nothing to evaluate if (Object.keys(expressions).length === 0) { return resolved; } diff --git a/packages/core/src/modifiers.ts b/packages/core/src/modifiers.ts index 79e93c658..dc0095725 100644 --- a/packages/core/src/modifiers.ts +++ b/packages/core/src/modifiers.ts @@ -155,7 +155,6 @@ export function composeModifierChain( }; } - // Build the middleware array — each factory is called with its params const middlewares: ModifierMiddleware[] = []; for (const mod of modifiers) { const factory = registry.get(mod.name); @@ -169,7 +168,6 @@ export function composeModifierChain( middlewares.push(factory(mod.params)); } - // Combine all middlewares into a single middleware const composed = combine(middlewares); // Return a thunk that provides the code block contextually for the diff --git a/packages/core/src/modifiers/daemon.ts b/packages/core/src/modifiers/daemon.ts index 251a98b99..18bdcc968 100644 --- a/packages/core/src/modifiers/daemon.ts +++ b/packages/core/src/modifiers/daemon.ts @@ -67,6 +67,5 @@ export const daemonFactory: ModifierFactory = (_params) => (_args, _next) => }; yield* ephemeral(launchDaemon); - // Control returns here immediately after the fork. return { output: "", exitCode: 0, stderr: "" }; })(); diff --git a/packages/core/src/output/normalize.ts b/packages/core/src/output/normalize.ts index aa4b8928b..6781bd6d6 100644 --- a/packages/core/src/output/normalize.ts +++ b/packages/core/src/output/normalize.ts @@ -32,7 +32,6 @@ export function* useNormalizedOutput(): Operation { let normalized = text; - // Strip trailing whitespace on each line normalized = normalized.replace(/[ \t]+\n/g, "\n"); // Collapse leading newlines if previous write already ended @@ -41,10 +40,8 @@ export function* useNormalizedOutput(): Operation { normalized = normalized.replace(/^\n+/, "\n"); } - // Collapse runs of 3+ newlines within a single write normalized = normalized.replace(/\n{3,}/g, "\n\n"); - // Track trailing newlines for next call const match = normalized.match(/\n+$/); trailingNewlines = match ? match[0].length : 0; diff --git a/packages/core/src/plugin.ts b/packages/core/src/plugin.ts index 07fedb18b..5fa3d104a 100644 --- a/packages/core/src/plugin.ts +++ b/packages/core/src/plugin.ts @@ -2,9 +2,7 @@ * The Plugin boundary: trusted code an operator selects, installed once * before an execution imports a root document. * - * XMD ships none and defaults to none. A command that selects no Plugin - * installs no Plugin, and a package that happens to be installed stays inert - * until it is named. + * An installed package stays inert until the host selects its Plugin value. * * A Plugin is a plain structural value. It carries a name and, optionally, one * `install` operation. Everything else about it — what it declares, what it diff --git a/packages/core/src/scanner.ts b/packages/core/src/scanner.ts index 86bae0e9a..0a27bd1ce 100644 --- a/packages/core/src/scanner.ts +++ b/packages/core/src/scanner.ts @@ -229,10 +229,8 @@ export function scanSegments( let textStart = 0; while (pos < text.length) { - // Check for fenced code block const fenceMatch = matchFenceOpen(text, pos); if (fenceMatch) { - // Flush text before fence if (pos > textStart) { pushText(segments, text.slice(textStart, pos)); } @@ -277,12 +275,10 @@ export function scanSegments( } } - // Check for component invocation: `<` followed by uppercase letter if (text[pos] === "<" && pos + 1 < text.length && /[A-Z]/.test(text[pos + 1]!)) { // Make sure we're not inside a fenced code block (handled above) const component = parseComponentTag(text, pos, index, elements); if (component) { - // Flush text before component if (pos > textStart) { pushText(segments, text.slice(textStart, pos)); } @@ -297,7 +293,6 @@ export function scanSegments( pos++; } - // Flush remaining text if (textStart < text.length) { pushText(segments, text.slice(textStart)); } @@ -415,7 +410,6 @@ function findFenceClose( pos++; } - // Check for closing fence if (pos < text.length && text[pos] === fenceChar) { let closeFenceLen = 0; while (pos < text.length && text[pos] === fenceChar) { @@ -465,7 +459,7 @@ function parseComponentTag( index: PositionIndex, elements?: SourceElement[], ): ParsedComponent | null { - let pos = start + 1; // Skip '<' + let pos = start + 1; // Parse tag name — must start with uppercase, can contain dots const nameStart = pos; @@ -481,7 +475,6 @@ function parseComponentTag( return null; } - // Parse attributes const { props, expressions, @@ -493,16 +486,14 @@ function parseComponentTag( } pos = attrEnd; - // Skip whitespace pos = skipWhitespace(text, pos); - // Self-closing tag? if (pos < text.length && text[pos] === "/") { - pos++; // Skip '/' + pos++; if (pos >= text.length || text[pos] !== ">") { return null; } - pos++; // Skip '>' + pos++; elements?.push(Object.freeze({ name, opening: Object.freeze({ start, end: pos }) })); return { @@ -524,7 +515,7 @@ function parseComponentTag( if (pos >= text.length || text[pos] !== ">") { return null; } - pos++; // Skip '>' + pos++; const openingEnd = pos; // Parse children until closing tag. Nested elements are collected aside and @@ -587,7 +578,6 @@ function parseAttributes( return { props, expressions, authoredExpressions, end: -1 }; } - // End of attributes? if (text[pos] === "/" || text[pos] === ">") { return { props, expressions, authoredExpressions, end: pos }; } @@ -609,7 +599,6 @@ function parseAttributes( continue; } - // Attribute name const attrNameStart = pos; while (pos < text.length && /[A-Za-z0-9_-]/.test(text[pos]!)) { pos++; @@ -641,10 +630,9 @@ function parseAttributes( props[attrName] = true; continue; } - pos++; // Skip '=' + pos++; pos = skipWhitespace(text, pos); - // Attribute value if (pos >= text.length) { return { props, expressions, authoredExpressions, end: -1 }; } @@ -722,14 +710,12 @@ function findMatchingBrace(text: string, start: number): number { return pos; } } else if (ch === '"' || ch === "'") { - // Skip string literal const end = findClosingQuote(text, pos + 1, ch); if (end === -1) { return -1; } pos = end; } else if (ch === "`") { - // Skip template literal pos = skipTemplateLiteral(text, pos); if (pos === -1) { return -1; @@ -747,7 +733,7 @@ function findMatchingBrace(text: string, start: number): number { * Returns the position of the closing backtick, or -1. */ function skipTemplateLiteral(text: string, start: number): number { - let pos = start + 1; // Skip opening ` + let pos = start + 1; while (pos < text.length) { const ch = text[pos]!; @@ -755,7 +741,7 @@ function skipTemplateLiteral(text: string, start: number): number { if (ch === "`") { return pos; } else if (ch === "\\" && pos + 1 < text.length) { - pos += 2; // Skip escape sequence + pos += 2; continue; } else if (ch === "$" && pos + 1 < text.length && text[pos + 1] === "{") { // Template expression — find matching brace @@ -870,20 +856,16 @@ function parseChildren( let textStart = pos; const children: Segment[] = []; - // Build the closing tag pattern const closingTag = ``; while (pos < text.length) { - // Check for closing tag if (text.startsWith(closingTag, pos)) { - // Flush remaining text as child if (pos > textStart) { pushText(children, text.slice(textStart, pos)); } return { children, end: pos + closingTag.length }; } - // Check for fenced code block inside children const fenceMatch = matchFenceOpen(text, pos); if (fenceMatch) { if (pos > textStart) { @@ -928,7 +910,6 @@ function parseChildren( } } - // Check for nested component if (text[pos] === "<" && pos + 1 < text.length && /[A-Z]/.test(text[pos + 1]!)) { const nested = parseComponentTag(text, pos, index, elements); if (nested) { diff --git a/packages/core/tests/daemon.test.ts b/packages/core/tests/daemon.test.ts index c48b03a8e..0978c8e25 100644 --- a/packages/core/tests/daemon.test.ts +++ b/packages/core/tests/daemon.test.ts @@ -58,7 +58,6 @@ describe("Tier Q — Daemon modifier", () => { // Q10: daemonFactory is a terminal modifier — it does not call next it("Q10: daemon is a terminal modifier", function* () { - // Verify the factory returns a middleware that takes (args, next) correctly const factory = daemonFactory(undefined); // The function arity indicates it accepts (args, next) expect(factory.length).toBe(2); diff --git a/packages/core/tests/eval-durable.test.ts b/packages/core/tests/eval-durable.test.ts index 72a580c64..a56d1d1f6 100644 --- a/packages/core/tests/eval-durable.test.ts +++ b/packages/core/tests/eval-durable.test.ts @@ -55,7 +55,6 @@ describe("Tier T4 — eval factory and journal integration", () => { }), ); - // Replay const output2 = yield* collect( yield* execute({ path: "test.md", @@ -82,7 +81,6 @@ describe("Tier T4 — eval factory and journal integration", () => { }), ); - // Replay const output2 = yield* collect( yield* execute({ path: "test.md", diff --git a/packages/core/tests/eval-return.test.ts b/packages/core/tests/eval-return.test.ts index 38af216c6..6db39cdbb 100644 --- a/packages/core/tests/eval-return.test.ts +++ b/packages/core/tests/eval-return.test.ts @@ -162,7 +162,6 @@ describe("Eval block return value", () => { expect(output1).toContain("replay-me"); - // Replay const output2 = yield* collect( yield* execute({ path: "test.md", diff --git a/packages/core/tests/execute.test.ts b/packages/core/tests/execute.test.ts index 0012b3828..adab4125f 100644 --- a/packages/core/tests/execute.test.ts +++ b/packages/core/tests/execute.test.ts @@ -261,7 +261,6 @@ describe("Tier B — durable import", () => { expect(result).toContain("Click me"); - // Verify journal has the import with correct path const events = stream.snapshot(); const [compImport] = events.flatMap((e) => e.type === "yield" && @@ -319,7 +318,6 @@ describe("Tier D — code execution and modifiers", () => { expect(run.stdout).toContain("hello"); expect(result).not.toContain("hello"); - // Verify journal const events = stream.snapshot(); const [execEvent] = events.flatMap((e) => e.type === "yield" && e.description.type === "exec" ? [e] : [], @@ -413,7 +411,6 @@ describe("Tier D — code execution and modifiers", () => { }), ); - // Verify the command array in journal contains full script const events = stream.snapshot(); const [execEvent] = events.flatMap((e) => e.type === "yield" && e.description.type === "exec" ? [e] : [], @@ -454,7 +451,6 @@ describe("Tier D — code execution and modifiers", () => { expect(run.stdout).toContain("hello"); expect(run.value).not.toContain("hello"); - // Verify command in journal const events = stream.snapshot(); const [execEvent] = events.flatMap((e) => e.type === "yield" && e.description.type === "exec" ? [e] : [], @@ -741,14 +737,12 @@ describe("execute", () => { }); const result = run.value; - // Check output contains expected content expect(result).toContain("# My Project"); expect(result).toContain("hi Hello, world!"); // The listing was displayed as it arrived, not rendered into the document. expect(run.stdout).toContain("main.ts"); expect(run.stdout).toContain("utils.ts"); - // Check journal has events const events = stream.snapshot(); expect(events.length).toBeGreaterThan(0); diff --git a/packages/core/tests/named-slots.test.ts b/packages/core/tests/named-slots.test.ts index 10c5d0aa3..8b399b9c0 100644 --- a/packages/core/tests/named-slots.test.ts +++ b/packages/core/tests/named-slots.test.ts @@ -917,7 +917,6 @@ describe("Tier NS-F — Edge cases", () => { includes: [path.join(tmpDir, "components"), tmpDir], }), ); - // Replay — same stream, same output const output2 = yield* collect( yield* execute({ path: path.join(tmpDir, "doc.md"), diff --git a/packages/core/tests/sample-component.test.ts b/packages/core/tests/sample-component.test.ts index 47f1a8946..4dddc7f86 100644 --- a/packages/core/tests/sample-component.test.ts +++ b/packages/core/tests/sample-component.test.ts @@ -450,7 +450,6 @@ describe("Tier EO — eval output() function", () => { expect(output1).toContain("journaled-output"); - // Replay const output2 = yield* collect( yield* execute({ path: "test.md", diff --git a/packages/durable-streams/combinators.ts b/packages/durable-streams/combinators.ts index 179f2cc88..8cded6bf9 100644 --- a/packages/durable-streams/combinators.ts +++ b/packages/durable-streams/combinators.ts @@ -42,16 +42,8 @@ import type { Close, Json, Workflow, WorkflowValue } from "./types.ts"; * Run a child workflow within a spawned scope, setting up its own * DurableContext and emitting a Close event when it terminates. * - * This is the core building block for all structured concurrency combinators. - * - * It: - * 1. Checks if the child already completed (has Close event) — short-circuits - * 2. Sets DurableContext on the child's scope with the child's coroutineId - * 3. Runs the child workflow (its DurableEffects use the child's coroutineId) - * 4. Appends Close(ok|err) when the child terminates - * - * IMPORTANT: This must be called inside a spawn() so it gets its own scope. - * The caller is responsible for spawn(). + * The caller must spawn it so the child owns its scope. A recorded Close + * restores the result without running the child again. */ function* runDurableChild( childWorkflow: () => Workflow, @@ -92,7 +84,6 @@ function* runDurableChild( } } - // Set child's DurableContext on this scope const scope = yield* useScope(); parentCtx.durability ??= {}; const childCtx: DurableContext = { @@ -228,11 +219,9 @@ export function durableSpawn( const scope = yield* useScope(); const ctx = scope.expect(DurableContext); - // Assign deterministic child ID const childIndex = ctx.childCounter++; const childId = `${ctx.coroutineId}.${childIndex}`; - // Spawn the child with durable wrapping return yield* spawn(() => runDurableChild(childWorkflow, childId, ctx)); })(), ); @@ -260,8 +249,6 @@ export function durableAll( const scope = yield* useScope(); const ctx = scope.expect(DurableContext); - // Build child Operations, one per workflow. Each gets its own - // deterministic coroutineId and Close event handling. const childOps: Operation[] = workflows.map((workflow) => { const childIndex = ctx.childCounter++; const childId = `${ctx.coroutineId}.${childIndex}`; @@ -273,11 +260,7 @@ export function durableAll( }; }); - // Delegate to Effection's native all() which uses trap() internally - // for proper error isolation. This means: - // - Child errors are catchable by the caller via try/catch - // - When any child fails, remaining siblings are cancelled - // - The error propagates with the original message intact + // Native all() isolates child failures so the caller can catch them. return yield* effectionAll(childOps); })(), ); @@ -307,8 +290,6 @@ export function durableRace( const scope = yield* useScope(); const ctx = scope.expect(DurableContext); - // Build Operations for each child — each gets its own coroutineId - // and Close event handling via runDurableChild. const childOps: Operation[] = workflows.map((workflow) => { const childIndex = ctx.childCounter++; const childId = `${ctx.coroutineId}.${childIndex}`; @@ -320,7 +301,6 @@ export function durableRace( }; }); - // Use Effection's native race() which handles cancellation properly return yield* effectionRace(childOps); })(), ); diff --git a/packages/durable-streams/divergence.ts b/packages/durable-streams/divergence.ts index f155de3b4..b52caabca 100644 --- a/packages/durable-streams/divergence.ts +++ b/packages/durable-streams/divergence.ts @@ -30,9 +30,6 @@ export type DivergenceKind = "description-mismatch" | "continue-past-close"; /** * Information about a detected divergence. - * - * Discriminated union on `kind` so that TypeScript enforces correct - * field access per variant. */ export type DivergenceInfo = | { diff --git a/packages/durable-streams/effect.ts b/packages/durable-streams/effect.ts index 533d1b3c3..81ad75681 100644 --- a/packages/durable-streams/effect.ts +++ b/packages/durable-streams/effect.ts @@ -114,7 +114,6 @@ function checkReplay( const entry = ctx.replayIndex.peekYield(ctx.coroutineId); let abandoned: YieldEntry | undefined; - // ── REPLAY PATH ── // Use a labeled block so that divergence decisions of type "run-live" // can break out to fall through to the live execution path. // biome-ignore lint/suspicious/noConfusingLabels: deliberate labeled block for break-out-of-replay pattern @@ -127,7 +126,6 @@ function checkReplay( // The current desc is passed to the Divergence API as `actual` so // guards can compare both sides if needed. if (entry.description.type !== desc.type || entry.description.name !== desc.name) { - // Delegate divergence policy to the Divergence API. const cursor = ctx.replayIndex.getCursor(ctx.coroutineId); const decision = Divergence.invoke(routine.scope, "decide", [ { @@ -152,7 +150,6 @@ function checkReplay( } // Description matches — now check replay guards before replaying. - // ── REPLAY GUARD: Decide phase ── // An isolated observation, like the check and admit phases: a decision is // policy, and policy reads. Handing the retained description or result // here would let a guard rewrite what replay is about to consume. @@ -187,7 +184,6 @@ function checkReplay( return { path: "replayed", teardown: (exit) => exit(VOID_OK) }; } - // All guards approved — consume the entry and advance cursor ctx.replayIndex.consumeYield(ctx.coroutineId); advanceDurablePosition(ctx); @@ -267,7 +263,6 @@ export function createDurableEffect( return replay.teardown; } - // ── LIVE PATH ── let settled = false; let tornDown = false; let teardown: () => void = () => {}; @@ -325,7 +320,6 @@ export function createDurableEffect( return (exit) => exit(VOID_OK); } - // Return teardown that Effection calls during scope destruction return (exit: Resolve>) => { if (tornDown) { exit(VOID_OK); @@ -389,7 +383,6 @@ export function createDurableOperation( return replay.teardown; } - // ── LIVE PATH ── // Run the entire execute → capture → persist → resolve sequence // as a structured operation in the routine's scope. routine.scope.run(function* () { diff --git a/packages/durable-streams/ephemeral.ts b/packages/durable-streams/ephemeral.ts index 304be3507..62e13b534 100644 --- a/packages/durable-streams/ephemeral.ts +++ b/packages/durable-streams/ephemeral.ts @@ -34,14 +34,9 @@ const VOID_OK: EffectionResult = { /** * Create a DurableEffect that runs an Operation transparently. * - * - No journal write (no Yield event appended) - * - No replay index consumption (cursor not advanced) - * - The Operation runs via scope.run() with full structured concurrency - * - Cancellation of the scope cancels the inner Operation - * - On replay, the Operation re-runs (not cached) - * - * The effect is invisible to the durable execution protocol — it exists - * solely to satisfy the Workflow type constraint. + * The effect satisfies Workflow's yield constraint without writing or + * consuming journal entries. It re-runs on replay, and the routine's scope + * owns its cancellation. */ function createEphemeralEffect(operation: Operation): DurableEffect { return { @@ -52,8 +47,6 @@ function createEphemeralEffect(operation: Operation): DurableEffect { resolve: Resolve>, routine, ): (resolve: Resolve>) => void { - // Run the operation in the routine's scope — full structured - // concurrency, proper cancellation. No journal interaction. routine.scope.run(function* () { try { const value = yield* operation; diff --git a/packages/durable-streams/http-stream.ts b/packages/durable-streams/http-stream.ts index bf5ba5d0e..d54a11142 100644 --- a/packages/durable-streams/http-stream.ts +++ b/packages/durable-streams/http-stream.ts @@ -91,7 +91,6 @@ export function useHttpDurableStream( const epoch = opts.epoch; const fetchFn = opts.fetch ?? globalThis.fetch.bind(globalThis); - // ── One-time setup: create the stream on the server ── yield* call(async () => { const res = await fetchFn(streamUrl, { method: "PUT", @@ -103,15 +102,12 @@ export function useHttpDurableStream( } }); - // ── Mutable state owned by the resource scope ── let nextSeq = 0; let fatalError: Error | undefined; let lastOffset: string | undefined; - // ── Append worker queue ── const queue: Queue = createQueue(); - // ── Spawn the serial append worker ── // Processes one append at a time in FIFO order. Each HTTP POST // completes before the next one starts, guaranteeing server-side // sequence ordering. Fatal errors (stale epoch, network failure) @@ -167,7 +163,6 @@ export function useHttpDurableStream( switch (res.status) { case 200: { - // Success — capture offset const offset = res.headers.get(STREAM_OFFSET_HEADER); if (offset) { lastOffset = offset; @@ -183,7 +178,6 @@ export function useHttpDurableStream( return; } case 403: { - // Stale epoch — fatal error const currentEpoch = Number(res.headers.get(PRODUCER_EPOCH_HEADER) ?? 0); const error = new StaleEpochError(currentEpoch); fatalError = error; @@ -209,7 +203,6 @@ export function useHttpDurableStream( } } - // ── Provide the DurableStream handle ── yield* provide({ get lastOffset() { return lastOffset; @@ -250,7 +243,6 @@ export function useHttpDurableStream( * all future appends to fail-fast without enqueuing. */ *append(event: DurableEvent): Operation { - // Fail-fast if a fatal error has been set if (fatalError) { throw fatalError; } @@ -259,13 +251,10 @@ export function useHttpDurableStream( // async work, even when multiple coroutines call append concurrently const seq = nextSeq++; - // Create a resolver so we can wait for this specific append to complete const { operation, resolve, reject } = withResolvers(); - // Enqueue the request — the worker will process it in FIFO order queue.add({ event, seq, resolve, reject }); - // Suspend until the worker finishes the HTTP POST for this item yield* operation; }, }); diff --git a/packages/durable-streams/position.ts b/packages/durable-streams/position.ts index 6f7dd4495..29b4081e9 100644 --- a/packages/durable-streams/position.ts +++ b/packages/durable-streams/position.ts @@ -1,32 +1,13 @@ /** - * Where a coroutine is in its own durable history. + * A coroutine's durable coordinate: its identity and number of settled yields. + * Operations without an authored name can use this to identify their position. * - * A durable operation is identified by what it is and what it is called. Some - * operations have no name to give: a wait that a document reaches at one point - * in one procedure is that wait *because of where it is*, not because somebody - * named it. This is the coordinate such an operation names itself by — the - * coroutine it runs in, and how many durable yields that coroutine has already - * settled. + * The count advances on replayed yields and committed live yields. The replay + * cursor alone stops at the retained prefix and would collide for every + * operation in a live suffix. * - * ## Why it is not the replay cursor - * - * Replay already keeps a cursor per coroutine, and it looks like the same - * number. It is not. The cursor advances only while entries are being consumed - * from retained history; once a coroutine runs past the end of what was - * retained, the cursor stops while the coroutine keeps performing durable work. - * A position taken from it would be stable across replays of the retained - * prefix and would collide for every operation in the live suffix. - * - * So the position advances on both — a replayed yield and a committed live one - * — which is what makes the index a coroutine reaches at one point in its - * procedure the same index it reaches there next time. - * - * ## Observation, never enforcement - * - * A position describes where execution is. It authorizes nothing, proves - * nothing about who is executing, and is not durable state: it is derived by - * counting what the journal already holds. Anything that must be trusted is - * checked by whoever owns the decision to check it. + * This is derived observation, not durable state or permission. Decisions that + * require trusted identity are checked by their owner. */ import { type Operation } from "effection"; diff --git a/packages/durable-streams/run.ts b/packages/durable-streams/run.ts index 03f049aa6..be8f2bb21 100644 --- a/packages/durable-streams/run.ts +++ b/packages/durable-streams/run.ts @@ -93,7 +93,6 @@ export function* durableRun( ): Operation { const { stream, coroutineId = "root" } = options; - // Read all events and build replay index const events = yield* stream.readAll(); const replayIndex = new ReplayIndex(events); @@ -110,14 +109,12 @@ export function* durableRun( }; scope.set(DurableContext, ctx); - // ── REPLAY GUARD: Check phase ── // Run before the workflow starts. Middleware can yield* for I/O (hash // files, make network requests) to gather observations for the decide // phase. The check loop iterates all Yield events in journal order. // See replay-guard-spec.md §5.5. yield* runCheckPhase(replayIndex, scope); - // ── REPLAY GUARD: Admit phase ── // The retained history has been offered in full and nothing has been reused // yet. A guard that requires something of the history as a whole — that an // event it validates is present, and present once — refuses here, before the @@ -154,8 +151,6 @@ export function* durableRun( replayIndex.claim(coroutineId); try { - // Workflow is structurally assignable to Operation, so - // yield* accepts it directly — no cast needed. const result: T = yield* workflow(); const durabilityFailure = activeDurabilityFailure(ctx); diff --git a/packages/durable-streams/tests/deterministic-id.test.ts b/packages/durable-streams/tests/deterministic-id.test.ts index 996025284..94a9106da 100644 --- a/packages/durable-streams/tests/deterministic-id.test.ts +++ b/packages/durable-streams/tests/deterministic-id.test.ts @@ -62,22 +62,18 @@ describe("deterministic IDs", () => { }; } - // Run 1 const stream1 = new InMemoryStream(); const tracker1 = createCallTracker(); yield* durableRun(makeWorkflow(tracker1), { stream: stream1 }); const events1 = stream1.snapshot(); - // Run 2 const stream2 = new InMemoryStream(); const tracker2 = createCallTracker(); yield* durableRun(makeWorkflow(tracker2), { stream: stream2 }); const events2 = stream2.snapshot(); - // Coroutine IDs must be identical expect(coroutineIds(events1)).toEqual(coroutineIds(events2)); - // Event traces must be identical (same types, same coroutineIds, same descriptions) expect(eventTrace(events1)).toEqual(eventTrace(events2)); }); @@ -133,7 +129,6 @@ describe("deterministic IDs", () => { // IDs from the original run are what matter. expect(liveIds.length > 0).toBe(true); - // Verify expected IDs: root, root.0, root.1 expect(liveIds).toEqual(["root", "root.0", "root.1"]); }); @@ -211,13 +206,7 @@ describe("deterministic IDs", () => { const partialStream = new InMemoryStream(partialEvents); - // Now replay with 3 children instead of 2 — the third child (root.2) - // will execute live since it has no journal entries. But the "after" - // step will try to replay with journal entry for root, which should - // now be different since root.2 has new events. - // Actually, root.2 will just execute live (no journal entries for it). - // The divergence happens only if the post-join effect's description - // mismatches. + // The new third child has no retained entries, so it executes live. const tracker2 = createCallTracker(); // With 3 children, root's childCounter goes to 3, but journal has @@ -276,7 +265,6 @@ describe("deterministic IDs", () => { const winnerYield = events.find((e) => e.type === "yield" && e.coroutineId === "root.0"); expect(winnerYield !== undefined).toBe(true); - // Verify IDs include root.0 (winner) const ids = coroutineIds(events); expect(ids.includes("root.0")).toBe(true); }); diff --git a/packages/durable-streams/tests/durable-each.test.ts b/packages/durable-streams/tests/durable-each.test.ts index 5a4c3932d..31618a760 100644 --- a/packages/durable-streams/tests/durable-each.test.ts +++ b/packages/durable-streams/tests/durable-each.test.ts @@ -78,14 +78,12 @@ describe("durableEach", () => { const yieldEvents = events.filter((e) => e.type === "yield"); expect(yieldEvents.length).toBe(4); // 3 items + 1 done sentinel - // Check each event description for (const y of yieldEvents) { if (y.type === "yield") { expect(y.description).toEqual({ type: "each", name: "queue" }); } } - // Check result values if (yieldEvents[0]!.type === "yield") { expect(yieldEvents[0]!.result).toEqual({ status: "ok", @@ -111,7 +109,6 @@ describe("durableEach", () => { }); } - // Root Close event const closeEvents = events.filter((e) => e.type === "close"); expect(closeEvents.length).toBe(1); expect(closeEvents[0]!.coroutineId).toBe("root"); @@ -268,7 +265,6 @@ describe("durableEach", () => { expect(tracker.calls).toEqual(["process-msg1", "process-msg2"]); - // Verify interleaved journal structure const events = stream.snapshot(); const nonClose = events.filter((e) => e.type === "yield"); diff --git a/packages/durable-streams/tests/durable-run.test.ts b/packages/durable-streams/tests/durable-run.test.ts index 833f1839a..c9d8dd35d 100644 --- a/packages/durable-streams/tests/durable-run.test.ts +++ b/packages/durable-streams/tests/durable-run.test.ts @@ -100,13 +100,10 @@ describe("durableRun", () => { const result = yield* durableRun(workflow, { stream }); - // Verify result expect(result).toBe("alpha-beta"); - // Verify all effects were called expect(tracker.calls).toEqual(["stepA", "stepB"]); - // Verify stream has 2 Yield events + 1 Close event const events = stream.snapshot(); expect(events.length).toBe(3); diff --git a/packages/durable-streams/tests/ephemeral.test.ts b/packages/durable-streams/tests/ephemeral.test.ts index 76f0b812e..6c225d233 100644 --- a/packages/durable-streams/tests/ephemeral.test.ts +++ b/packages/durable-streams/tests/ephemeral.test.ts @@ -102,7 +102,6 @@ describe("ephemeral", () => { const withoutClose = events.filter((e) => e.type !== "close"); const replayStream = new InMemoryStream(withoutClose); - // Reset counter ephemeralCallCount = 0; // Second run — durable calls replay, but ephemeral re-runs @@ -155,7 +154,6 @@ describe("ephemeral", () => { function* () { // Use ephemeral to run an Operation inside a Workflow child const scope = yield* ephemeral(useScope()); - // Just verify we got a scope (infrastructure operation worked) if (!scope) { throw new Error("no scope"); } diff --git a/packages/durable-streams/tests/replay-index.test.ts b/packages/durable-streams/tests/replay-index.test.ts index b046d9992..99cbcfc65 100644 --- a/packages/durable-streams/tests/replay-index.test.ts +++ b/packages/durable-streams/tests/replay-index.test.ts @@ -118,14 +118,12 @@ describe("ReplayIndex", () => { expect(idx.yieldCount("root.0")).toBe(2); - // First peek expect(idx.peekYield("root.0")?.description).toEqual({ type: "sleep", name: "sleep", }); idx.consumeYield("root.0"); - // Second peek expect(idx.peekYield("root.0")?.description).toEqual({ type: "call", name: "transform", @@ -136,7 +134,6 @@ describe("ReplayIndex", () => { }); idx.consumeYield("root.0"); - // Exhausted expect(idx.peekYield("root.0")).toBeUndefined(); expect(idx.getCursor("root.0")).toBe(2); }); @@ -287,7 +284,6 @@ describe("ReplayIndex", () => { // root.0 has 2 yields expect(idx.yieldCount("root.0")).toBe(2); - // Consume both idx.consumeYield("root.0"); idx.consumeYield("root.0"); expect(idx.isFullyReplayed("root.0")).toBe(true); diff --git a/packages/durable-streams/tests/structured-concurrency.test.ts b/packages/durable-streams/tests/structured-concurrency.test.ts index 52638c24d..64388ee7c 100644 --- a/packages/durable-streams/tests/structured-concurrency.test.ts +++ b/packages/durable-streams/tests/structured-concurrency.test.ts @@ -214,7 +214,6 @@ describe("structured concurrency", () => { expect(result).toBe("a+b-B"); expect(tracker.calls.sort()).toEqual(["innerA", "innerB", "outerB"]); - // Verify nested coroutine IDs const events = stream.snapshot(); const coroutineIds = [...new Set(events.map((e) => e.coroutineId))].sort(); expect(coroutineIds).toEqual(["root", "root.0", "root.0.0", "root.0.1", "root.1"]); @@ -271,7 +270,6 @@ describe("structured concurrency", () => { { stream }, ); - // Replay const tracker2 = createCallTracker(); const replayStream = new InMemoryStream(stream.snapshot()); @@ -525,7 +523,6 @@ describe("structured concurrency", () => { expect(result).toBe("PRE-a,b"); - // Replay const replayStream = new InMemoryStream(stream.snapshot()); const tracker2 = createCallTracker(); diff --git a/packages/git/src/composition/components/GitAdd.ts b/packages/git/src/composition/components/GitAdd.ts index ee13ed5e3..6df612917 100644 --- a/packages/git/src/composition/components/GitAdd.ts +++ b/packages/git/src/composition/components/GitAdd.ts @@ -1,36 +1,15 @@ /** - * `` — stage exactly the paths a document names - * (specs/workflow-workspace-spec.md §7.2). + * Stage exactly the authored Git pathspecs (specs/workflow-workspace-spec.md §7.2). * - * ```md - * - * - * - * - * ``` + * `` stages one array in one + * command and effect, preserving order, repetitions, spelling and pathspec magic. + * Paths are required; `"."` explicitly selects everything beneath contextual cwd, + * including a Dir inside the selected Repository. They never select a checkout. * - * `paths` is a Git pathspec, and that is all it is. It does not choose a - * checkout — where this stages is decided the way every Git operation's place is - * decided, by the enclosing `` and the contextual working directory - * — and it is never optional. Omitting it does not mean everything; `"."` is how - * a document says everything here, and "here" is the directory the element was - * written in, so `` inside a `` stages - * that directory rather than the checkout. - * - * What a document wrote is what Git receives. One string is the one-entry array, - * and an array keeps its order, its repetitions, its spelling and its pathspec - * magic, because each of those changes what Git stages. The whole array is one - * command and one effect: Git decides what a pathspec matches, and staging entry - * by entry would be several transitions where the document wrote one. - * - * It renders nothing, binds nothing and takes no content. What the run retains - * is journal evidence — the pathspecs, and the checkout on both sides — rather - * than anything a later element could read. - * - * Failure policy is ``'s. An invocation this cannot read is a fixed - * `GitOperationError`; no Repository in scope is a failed admission and travels - * past every printing boundary, because a document that continued past one would - * run later siblings as though something had been staged. + * The component takes no content, renders nothing and binds nothing. The journal + * retains pathspecs and checkout evidence before and after staging. Invalid input + * is a fixed GitOperationError; missing or invalid Repository admission bypasses + * printing boundaries under the Git.Switch failure contract. */ import { cwd } from "@executablemd/runtime"; diff --git a/packages/git/src/composition/components/GitCommit.ts b/packages/git/src/composition/components/GitCommit.ts index 881951f2e..6fc44a44d 100644 --- a/packages/git/src/composition/components/GitCommit.ts +++ b/packages/git/src/composition/components/GitCommit.ts @@ -1,38 +1,16 @@ /** - * `` — record exactly what is staged, and hand back its SHA + * Commit the staged index and bind its full object id * (specs/workflow-workspace-spec.md §7.3). * - * ```md - * - * - * + * `` + * completes child expansions and their own transactions before describing the + * commit effect. It performs no implicit staging, amend, empty commit or signing. * - * Generated from validated release metadata. - * - * - * ``` - * - * Content expands first, completely, before this element describes an effect of - * its own. That is what makes a nested `` mean what a document written - * that way reads as: the staging is its own expansion, its own effect and its - * own transaction, finished before a commit exists to include it. - * - * The message is composed from what a document wrote and then canonicalized - * once. `message` alone is the whole message; content alone is the whole - * message; both put the prop first and the rendered text one blank line after - * it. Line endings become LF, whitespace at the very end is removed, and exactly - * one final newline is added — leading and interior text are untouched, because - * a commit message is authored prose and rewriting the middle of one would - * commit something nobody wrote. What is left is what Git receives verbatim, - * and the digest and byte length the run retains describe those exact bytes. - * - * It commits the index and nothing else. There is no path, no implicit staging, - * no amend, no empty commit and no signing — each is a different operation, and - * a document that wants one says so with the component that owns it. - * - * Unlike the other two Git operations this one produces a value, so it renders - * nothing and is written with `as`: the binding is the full object id of the - * commit, which is the one fact a later element can act on. + * The message prop, rendered content or both supply the message; both place the + * prop first and content one blank line later. Canonicalization changes line + * endings to LF, removes trailing whitespace and adds one final newline, preserving + * leading and interior text. Git receives those bytes verbatim; the retained digest + * and byte length describe them. The component renders nothing and requires `as`. */ import { cwd } from "@executablemd/runtime"; diff --git a/packages/git/src/composition/components/GitPush.ts b/packages/git/src/composition/components/GitPush.ts index 8c1e5c773..82840c9c8 100644 --- a/packages/git/src/composition/components/GitPush.ts +++ b/packages/git/src/composition/components/GitPush.ts @@ -1,51 +1,20 @@ /** - * `` — publish the checkout's current branch to its origin + * Publish the contextual checkout's current branch to its Repository origin * (specs/workflow-workspace-spec.md §7.4). * - * ```md - * - * - * - * - * - * - * ``` + * `` takes no props or content, renders nothing and binds nothing. + * The enclosing Repository and cwd select the checkout, including a linked + * worktree reached through Dir. Remote, branch, commit, refspec and force are not + * authored inputs; reconciliation evidence stays in the journal. * - * It takes no props. There is nothing to name: the remote is the Repository's - * own `origin`, the branch is the one the checkout is on, and the commit is the - * one that branch points at. Which checkout that is, is decided the way every - * Git operation's place is decided — by the enclosing `` and the - * contextual working directory — so the same element inside a `` at a - * linked worktree publishes that worktree's branch instead. + * The remote cannot join the local transaction. Shared Git-host reconciliation + * observes first, adopts this exact commit, publishes a proven absence or advances + * a proven ancestor once, and refuses unproven compatibility. It never force-pushes + * or changes upstream tracking. * - * A prop for any of that would be a second way to say what the document already - * said by writing the element where it wrote it, and a `remote`, `branch`, - * `refspec` or `force` prop would be a way to say something else entirely. - * Publishing somewhere other than where the checkout is takes an explicit - * contract this component does not have. - * - * It renders nothing, binds nothing and takes no content. A push produces no - * value a later element reads: what the run retains is the reconciliation - * record, which is journal evidence rather than something a document could use. - * - * ## The remote is not the local Git - * - * Switch, Add and Commit move state the run's own SQLite transaction encloses. - * The branch this publishes to belongs to a Git host, which no local - * transaction can enclose, so Push reconciles through the shared Git-host state - * machine instead: it observes the destination before it mutates, adopts a - * destination that already names this exact commit, publishes a proven-absent - * one once, and refuses a destination that names anything else. It never - * force-pushes, and it changes no upstream tracking. - * - * ## Failure - * - * ``'s policy, with one refusal of its own. A checkout whose HEAD - * names no branch has nothing for this to publish, and that is something the - * document can act on: it arrives as a fixed `GitOperationError` before any - * remote is contacted. No Repository in scope is a failed admission and travels - * past every printing boundary, because a document that continued past one - * would run later siblings as though a branch had been published. + * Git.Switch's failure policy applies. Detached HEAD is a fixed GitOperationError + * before remote contact; missing Repository is an admission failure that printing + * cannot recover. */ import { cwd } from "@executablemd/runtime"; diff --git a/packages/git/src/composition/components/GitSwitch.ts b/packages/git/src/composition/components/GitSwitch.ts index 171d40ee9..2c34e6519 100644 --- a/packages/git/src/composition/components/GitSwitch.ts +++ b/packages/git/src/composition/components/GitSwitch.ts @@ -1,42 +1,17 @@ /** - * `` — put the contextual checkout on a named branch + * Switch the contextual checkout to a branch * (specs/workflow-workspace-spec.md §7.1). * - * ```md - * - * - * - * ``` + * `` uses the enclosing Repository + * and contextual cwd; a Dir may select one of its linked worktrees. Both values + * are observations the provider verifies against retained state, never permission. + * The component renders and binds nothing; before/after evidence is journal-only. * - * There is no path prop, and there is no repository prop. Which checkout this - * moves is decided by where it is written: the enclosing `` names - * the repository, and the contextual working directory names the checkout - * inside it, so the same element inside a `` moves that - * linked worktree instead. Both are observations. This component holds no - * permission over either, and the installed provider rereads what this run - * retained rather than believing what it was handed. - * - * It renders nothing and binds nothing. A switch is a state change, not a value - * a later element reads; what the run retains about it is journal evidence - * rather than something a document could have used, and returning a branch name - * a document already wrote would only invite reading it back as though it were - * an answer. - * - * ## Two kinds of failure, and only one of them is the document's - * - * A refusal is something the document asked for and did not get: a base that - * names no commit, a branch another checkout holds, local changes Git would - * overwrite. Each arrives as a fixed `GitOperationError` and then fails the - * operation it is part of, and an authored `` region decides - * otherwise for its whole region. - * - * Admission is not that. No Repository in scope, a Repository this run does not - * retain, a working directory inside none of its checkouts, retained state that - * has stopped agreeing with the identity naming it — none of these is an outcome - * a document could have avoided by asking for something else, and continuing - * past one would run later siblings as though a branch had moved. They travel as - * `GitOperationAdmissionError`, past every printing boundary, and nothing is - * published for them. + * Git refusals such as an unresolved base, an occupied branch or overwritten local + * changes become fixed GitOperationError failures recoverable by PrintErrors. + * Missing or unretained Repository selection, cwd outside its checkouts and identity + * mismatch are GitOperationAdmissionError failures: printing cannot recover them, + * and they publish no outcome. */ import { cwd } from "@executablemd/runtime"; diff --git a/packages/git/src/composition/components/Issue.ts b/packages/git/src/composition/components/Issue.ts index 7fe9b8dee..cf81b7ea5 100644 --- a/packages/git/src/composition/components/Issue.ts +++ b/packages/git/src/composition/components/Issue.ts @@ -1,71 +1,22 @@ /** - * `` — read one issue by URL, or upsert one in the tracker a lexical - * context names (specs/workflow-workspace-spec.md §10.3). - * - * Two forms, and the syntax chooses between them before anything is routed. - * - * ```md - * - * - * {found.title}: {found.description} - * ``` - * - * ```md - * - * - * The publish step failed twice in a row on 503. - * - * - * - * Filed {filed.url}. - * ``` - * - * ## Why the two are one component - * - * They are the same subject at the same altitude: an issue, named - * provider-neutrally. What differs is which question is being asked, and that - * is exactly what the syntax already says — a self-closing element with a `url` - * is asking about an issue that exists, and a paired element with a `title` is - * asking for one to exist saying something. - * - * So the form decides the operation, and a form that is neither is refused - * before a tracker is read and before `IssueApi` is invoked. A `url` with - * content, a `title` without content, content without a title, `tags` on a - * read: each is a document asking for something this element does not do, and - * being told so is better than having one of the two guessed for it. - * - * ## Read needs no tracker - * - * The URL is the identity, so there is nothing for a container to add. A read - * therefore never consults the tracker context — writing one around a read - * changes nothing about it, which is what makes reading an issue from anywhere - * a document happens to be safe. - * - * `provider` is permitted on a read for the same reason it is permitted on a - * tracker: a self-hosted URL nobody recognizes still has to be addressable. - * - * ## Upsert takes its description from what it renders - * - * The content is the description, verbatim after expansion. There is no - * `description` prop, because the thing a person writes at length belongs in - * the document where it can be read, interpolated and reviewed — not squeezed - * into an attribute. - * - * ## What each produces - * - * A read binds the fields every provider has: URL, title, description, tags and - * assignee. An upsert binds exactly `{ url }`. Neither carries a provider's own - * identity, a number, a workflow state or a payload, because a document that - * branched on one of those would stop being portable across providers — which - * is the whole point of this primitive. - * - * ## Failure - * - * A form that is neither read nor upsert, a missing tracker on an upsert, and a - * URL that is not a credential-free container are decided here, before the - * boundary exists in the story. What a provider answers — a conflict, an - * ambiguity, an unavailability, a target outside its ceiling — is the - * provider's own closed vocabulary. + * Read an issue by URL or upsert one in a lexical tracker + * (specs/workflow-workspace-spec.md §10.3). + * + * `` reads without consulting tracker + * context and binds URL, title, description, tags and assignee. Optional `provider` + * addresses a URL the installed adapters do not otherwise recognize. + * + * `…` upserts in + * the enclosing IssueTracker, using its completely rendered content verbatim as + * the description, and binds exactly `{ url }`. Provider ids, issue numbers, + * workflow state and raw payloads are absent from both results. + * + * Form/input mismatches refuse before tracker lookup or IssueApi: URL with + * content, title without content, content without title and tags on reads are + * invalid. Upsert content must render non-empty before the destination is read. + * Invalid invocation, missing tracker and non-credential-free URLs are local + * refusals; provider conflicts, ambiguity, availability and ceiling failures keep + * the provider's own vocabulary. */ import { content, hasContent } from "@executablemd/core"; diff --git a/packages/git/src/composition/components/IssueTracker.ts b/packages/git/src/composition/components/IssueTracker.ts index 205b777dd..9e0d23c1c 100644 --- a/packages/git/src/composition/components/IssueTracker.ts +++ b/packages/git/src/composition/components/IssueTracker.ts @@ -1,38 +1,18 @@ /** - * `` — which tracker or project the issues inside it belong in + * Select the issue destination for a lexical subtree * (specs/workflow-workspace-spec.md §10.3). * - * ```md - * - * - * {finding.evidence} - * - * - * ``` + * ` + * {finding.evidence} + * ` + * names a credential-free issue container. Optional `provider` selects the only + * adapter that may act; without it, each installed middleware recognizes its own + * URLs, and complete delegation reaches NoIssueProvider. * - * `url` is a credential-free URL naming the container new issues are created - * in — a GitHub repository issue collection, an Atlassian project. `provider` - * is optional and names the only adapter allowed to act on it. Without one the - * request is offered to the installed middleware, and each provider decides for - * itself whether it recognizes the URL — nothing resolves one centrally, and a - * URL every provider delegated reaches `NoIssueProvider`. - * - * ## It requests a destination; it grants nothing - * - * This installs composition data, not permission. A document can write any URL - * here and reach nothing it was not already allowed to reach: the trusted host - * installs an adapter-private ceiling beside its credentials, and a target - * outside that ceiling fails before any provider observes anything. Narrowing - * within the ceiling is what a context is for; widening it is not something a - * context can express. - * - * ## Nesting replaces, and never merges - * - * A nested target replaces the whole target for its descendants. Parent and - * child members are never merged, because a child that kept its parent's - * `provider` while replacing its `url` would ask one service about another - * service's container — and that is exactly the mistake an explicit - * discriminator exists to prevent. + * The context carries composition data, never permission. The adapter-private + * ceiling beside its credentials refuses outside targets before observation. + * Nesting replaces the entire target rather than merging URL and provider from + * different trackers. */ import { content, hasContent } from "@executablemd/core"; diff --git a/packages/git/src/composition/components/PullRequestReads.ts b/packages/git/src/composition/components/PullRequestReads.ts index 1e0f3e672..ded014b39 100644 --- a/packages/git/src/composition/components/PullRequestReads.ts +++ b/packages/git/src/composition/components/PullRequestReads.ts @@ -1,61 +1,21 @@ /** - * ``, `` and `` — - * the existing evidence about a numbered pull request + * Read pull-request reviews, comments or checks into separate bound arrays * (specs/workflow-workspace-spec.md §7.7). * - * ```md - * … - * - * - * - * ``` + * `` and the Comments + * and Checks variants identify a numbered pull request by canonical URL, without + * Repository or cwd. Optional `provider` addresses self-hosted/non-standard URLs; + * the host owns endpoint, credential and pagination configuration. Each requires + * `as` so an Agent prompt can explicitly render the evidence it receives. * - * A workflow Agent has no network, so an objection the prompt does not render - * is an objection the review never saw. These are how a document renders them: - * each binds one array, and a caller iterates it with `` into the prompt - * and into whatever material a person is asked to approve. + * Providers compose ordinary PullRequestAPI middleware. Once a provider matches, + * its normalized answer, validation and refusal are final. Each collection has its + * own durable effect, replay and failure, so a partial answer cannot masquerade as + * all three collections. * - * The URL is the identity. A pull request is a public object with a canonical - * address, so a document that can name one can ask what it holds — there is no - * `` to be inside of, no working directory to be at, and no - * repository or number prop, because the URL already says both and the selected - * provider parses them out of it. - * - * `provider` names an adapter explicitly, for a self-hosted or non-standard - * URL. There is no endpoint, token, credential, page, cursor or limit prop: a - * document says which pull request, and the host says which places it may be - * reached at. - * - * `as` is required. These read to be rendered, and an uncaptured one would - * perform requests nobody reads. - * - * ## Where the evidence comes from - * - * From the selected provider, which owns its answer — the shape `` has. - * A provider is ordinary middleware around `PullRequestAPI`: it recognizes the - * URLs it can act on, and once it matches, its validation and its refusal are - * final. What a document binds is what that provider normalized. - * - * This supersedes the request-only route and invocation-private terminal an - * earlier revision carried. Those kept evidence off a public surface at the - * cost of a second admission model beside the Issue surface's, and of a read - * that needed a Repository in scope to name a pull request by number. - * - * ## The form is declared, not asked about - * - * Each is self-closing only, and that is a declaration the engine turns into - * the dispatcher every invocation arrives through. Neither weaker answer would - * do: `hasContent()` resolves through the composable chain, where a handler - * outside the invocation answers ahead of the engine, and an invocation object - * a caller minted answers whatever it likes. A component that read either one - * and got "no content" for a paired element would silently read a pull request - * a document had written children beside. - * - * Three components rather than one for the reason `` and - * `` are two: three separate remote collections, three durable - * effects, three independent replays and failures. One component returning - * three lists would make a partial answer indistinguishable from a complete - * one. + * Self-closing form is declared to canonical dispatch. Neither replaceable + * `hasContent()` nor a caller-made invocation object can turn a paired element + * into an evidence read. */ import type { diff --git a/packages/git/src/deno/run-composition/identity.ts b/packages/git/src/deno/run-composition/identity.ts index c5d45ad4f..f5f1b6dcc 100644 --- a/packages/git/src/deno/run-composition/identity.ts +++ b/packages/git/src/deno/run-composition/identity.ts @@ -1,46 +1,18 @@ /** - * Who an ordinary run's commits are by. + * Capture the invoking user's effective Git author and committer for ordinary + * commits. Workflow commits keep their fixed identity. * - * A workflow run's Git state must not depend on whose machine it was created - * on, so its provider commits under one fixed identity and builds Git's - * environment from nothing. An ordinary run is the opposite case: the commit - * lands in a person's own checkout, on a branch they will look at tomorrow, and - * attributing it to `Executable.md workflow` would put a name in their history - * that nobody there recognizes. + * The first Git.Commit captures `git var GIT_AUTHOR_IDENT` and + * `GIT_COMMITTER_IDENT` once through the trusted entrypoint's reader, using the + * invocation directory and host environment/configuration. A run that commits + * nothing reads no identity. Props, Context and middleware cannot select or + * replace it. * - * So the invoking user's effective identity is captured once, by the first - * `` that needs it, and used for that alone. A run that commits - * nothing asks the host nothing about who it is. - * - * ## Captured from the trusted host, and nowhere else - * - * `git var GIT_AUTHOR_IDENT` and `GIT_COMMITTER_IDENT` are exactly what native - * Git would use: the `GIT_*_NAME`/`GIT_*_EMAIL` variables, then `user.name` and - * `user.email` from the configuration Git itself resolves, then whatever the - * host can auto-detect. Reading it takes the caller's own environment and the - * directory the command was run in, which is why the reader is the trusted - * entrypoint's — constructed at provider installation, where no document code - * exists, and consulted later from the commit that needs an answer. - * - * It is not a prop, a Context value, a component result or a middleware answer, - * and no document can read it, replace it or ask for a different one. - * - * ## Only the identity is borrowed - * - * The commands that run afterwards keep every other protection: hooks, - * file-system monitors, signing programs and repository-supplied credential - * helpers stay disabled by the same fixed command-line configuration a workflow - * run uses, and `HOME` still points at a disposable directory. What crosses - * from the caller's environment is four strings. - * - * ## An unresolvable identity refuses, and refuses narrowly - * - * A host where Git cannot say who the user is is a host that cannot commit, and - * substituting the workflow identity would be writing somebody else's name into - * a person's repository to avoid saying so. `` reports it and names - * the two commands that fix it. Every other component — Repository, Worktree, - * Dir, Switch, Add, Push, Issue, PullRequest — is unaffected: none of them - * writes a commit object. + * Only four identity strings are borrowed. Hooks, filesystem monitors, signing + * programs and repository credential helpers remain disabled by fixed command-line + * configuration, and HOME stays disposable. Missing identity refuses Git.Commit + * with corrective commands; it never substitutes the workflow identity or affects + * other components. */ import type { Operation } from "effection"; diff --git a/packages/git/src/deno/run-composition/leases.ts b/packages/git/src/deno/run-composition/leases.ts index 2e5565f2a..484795a08 100644 --- a/packages/git/src/deno/run-composition/leases.ts +++ b/packages/git/src/deno/run-composition/leases.ts @@ -1,35 +1,13 @@ /** - * The locks an ordinary run holds on the slots it is working in. + * Hold managed checkout slots under non-blocking exclusive kernel advisory locks. + * A busy slot refuses immediately; process death releases the lock without cleanup. * - * A workflow run owns its Workspace outright, so nothing coordinates with - * anything. A managed host root is shared: two `xmd run` processes on one - * machine may name the same Repository at the same moment, and one of them - * cloning into the directory the other is committing in would corrupt both. + * Leases belong to the installed provider's execution scope, outliving the element + * that selected a slot so later Dir and interactive Session siblings stay protected. + * Repeated selection reuses the execution's lease. * - * So a slot is entered under an exclusive kernel-backed advisory lock, taken - * without waiting. Refusing rather than waiting is what makes the answer - * useful: "somebody else is working in this checkout" is something the person - * running the document can act on, and a hang is not. The kernel is also what - * makes it survive a lost host — a killed process runs no cleanup and the - * operating system releases its locks anyway, which is the only evidence this - * accepts that a previous holder is gone. - * - * ## The hold is execution-wide, deliberately - * - * The lease is acquired into the scope the provider was installed in rather - * than into the component invocation that asked for it, so it outlives the - * element. A self-closing `` binds a path that a - * later sibling `` and an interactive `` inside it - * go on using; a lease that ended with the Worktree element would leave both - * working in a slot another process could take. - * - * Selecting the same slot twice in one execution reuses the lease already held. - * It is the same process and the same provider: taking a second exclusive lock - * on a file this process already holds is not a coordination question. - * - * Nothing here unlinks a lock file. Unlinking a locked path lets the next - * caller create and lock a different file at the same name while this lock is - * still held, so the sidecar is created if absent and then left, empty. + * Lock sidecars remain empty on disk. Unlinking a locked path would let another + * process lock a new file at the same name while the original lock is still held. */ import { race, suspend, useScope, withResolvers, type Operation, type Scope } from "effection"; @@ -51,10 +29,7 @@ export interface Leases { } export function* useLeases(root: string): Operation { - // The scope the provider is installed in, captured once. Every lease is - // acquired into it, so all of them are released — by the kernel and by the - // resource's own teardown — when the document execution ends, on success, - // failure and cancellation alike. + // Capture the provider scope so leases outlive individual elements. const owner: Scope = yield* useScope(); const held = new Set(); @@ -64,12 +39,7 @@ export function* useLeases(root: string): Operation { if (held.has(path)) { return; } - // The acquisition runs in the provider's scope and then *suspends*, which - // is what makes the hold last as long as the provider does. A task that - // returned the handle would complete, and completing releases everything - // the task acquired — so the lock would be gone the moment the element - // that asked for it finished, and a second process could take the slot - // out from under an interactive Session still working in it. + // Keep the resource task suspended; returning would release the slot immediately. const acquired = withResolvers(); const failed = withResolvers(); owner.run(function* () { diff --git a/packages/git/src/deno/run-composition/metadata.ts b/packages/git/src/deno/run-composition/metadata.ts index bd683c493..2807b7bb2 100644 --- a/packages/git/src/deno/run-composition/metadata.ts +++ b/packages/git/src/deno/run-composition/metadata.ts @@ -1,28 +1,11 @@ /** - * The sidecar that says what a managed slot is, and what it was created from. + * Retain managed-slot creation identity in a closed, versioned sidecar. + * Every member is parsed. Publication uses an exclusive temporary sibling and an + * atomic rename only after the checkout is complete and verified. * - * A workflow run answers that question from its database. An ordinary run has - * none, so the answer lives beside the checkout — and because it lives on a - * filesystem several processes share, everything about it is defensive: the - * shape is closed and versioned, every member is parsed, and the file is only - * ever written by an exclusive temporary sibling plus an atomic rename, after - * the checkout it describes is complete and verified. - * - * ## Paths are derived, never read back - * - * A slot's checkout path is a function of the root and the identity. It is - * deliberately absent from the metadata: a path read out of a file somebody - * could edit would be a path this provider then joined and followed, and the - * whole point of digesting authored strings into slots is that no authored - * string decides where anything is. - * - * ## What compatibility means - * - * Every member here is *creation* state: what was asked for, and what was true - * the moment the checkout came into being. None of it is current state. HEAD, - * the current branch, the index and the working tree are the mutable work the - * checkout exists to preserve, and a reuse that required them to match creation - * would refuse every checkout anybody had used. + * Checkout paths are derived from the host root and identity, never read from this + * editable metadata. Members describe creation, not current HEAD, branch, index or + * working-tree state; reuse must preserve work done since creation. */ import { members, optionalText, text } from "../../composition/parse.ts"; diff --git a/packages/git/src/git-host/effect.ts b/packages/git/src/git-host/effect.ts index 2c4631636..83b0b7d73 100644 --- a/packages/git/src/git-host/effect.ts +++ b/packages/git/src/git-host/effect.ts @@ -1,80 +1,31 @@ /** - * One shared reconciliation for every external Git-host effect. + * Reconcile external Git-host mutations through {@link reconcileGitHostEffect}. + * Push and pull-request upsert share this boundary; Issue has its own ordinary + * middleware and durable envelope, and Prompt keeps its Agent/session contract. * - * A Git host — the external service that owns remote repositories, pull - * requests and issues — holds state this repository's SQLite transaction cannot - * enclose. Push, pull-request creation and issue creation therefore cannot - * commit "the remote changed" and "the journal says so" together, and each of - * them would otherwise have to invent its own answer to the same question: what - * does an attempt do when it cannot tell whether the previous one already - * succeeded? + * A live attempt observes before mutating: perform proven absence once, adopt + * proven compatible completion, refuse conflict or permanent ambiguity, and report + * temporary unavailability for authored retry policy. After interruption between + * remote mutation and local publication, the same external identity lets observation + * adopt completion without repeating it. * - * They do not invent it. All three run through {@link reconcileGitHostEffect}, - * and one live attempt always observes before it mutates: + * Run and expansion identify the effect; the complete detached request's digest + * names the durable operation so changed inputs cannot consume an earlier answer. + * Retained identities and abandoned-history enforcement remain checked on the live + * path before provider work. * - * - proven absence is performed, once; - * - a proven compatible completion is adopted, and nothing is performed; - * - conflict is refused; - * - permanent ambiguity is refused; and - * - temporary unavailability fails as itself, so the document's own structure - * or explicit middleware — not this engine — decides on a retry. + * {@link GitHost} exposes one frozen, one-use routing request. Public middleware + * may observe, refuse, narrow policy or delegate; it receives no credential, + * capability, answer operation or phase evidence, and its return value is ignored. + * Each phase uses its own descriptor under the stable Api name: names share the + * middleware chain, while that descriptor owns its private terminal. + * `withGitHostProvider()` places the selected handler at the terminal end; only + * its captured continuation inspects the exact request and submits parsed answers. + * Copied, substituted, reused, stale or unsolicited messages refuse before work. * - * That ordering is what survives the gap this exists for. If a remote accepted - * the mutation and the host died before the local result was published, the - * next execution finds no journal entry, observes under the same external - * identity, recognizes its own completion and adopts it. The remote is mutated - * once. Removing the observation, or adopting anything weaker than a proven - * compatible completion, is what would make it twice. - * - * Prompt is not a Git-host effect and does not run through here; it keeps its - * Agent provider and session contract. - * - * ## Identity, and what may name it - * - * The external identity is the run and the expansion — derived here, from the - * host-established `getWorkflowRun()` and the engine's own `getExpansion()`. - * Neither the document nor the provider supplies either member, because a party - * that could name the identity could name someone else's completion. - * - * The durable operation is named by a digest of the complete detached request - * instead. Identity is where the effect *is*; the fingerprint is what it *asks*, - * and separating them is what stops a changed input from consuming the retained - * result of a different question at the same journal position. - * - * ## One surface, and a terminal nobody can address - * - * There is a single contextual operation, {@link GitHost}. Public middleware - * receives one frozen, one-use routing request and may read it, refuse it, - * narrow policy around it, or delegate it. It gets no credential, no - * capability, no answer operation and no phase evidence, and its return value - * is ignored. There is nothing for two handlers to combine, which is the - * property the previous two-surface design did not have: a selection that - * handed back a credential plus a coordination request that handed over a - * capability let ordinary middleware answer a phase itself, and the durable - * journal then recorded a completion no provider had ever produced. - * - * Each phase instead builds its own `createApi()` descriptor under that same - * stable name. Sharing the name shares the middleware chain; owning the - * descriptor owns the default, and that default is this invocation's - * authoritative terminal. `withGitHostProvider()` installs the selected - * provider's handler at the terminal end of the chain, so the handler's own - * continuation — a parameter of its generator, held by nothing else — is the - * only way to reach that terminal. Through it the handler asks the terminal to - * inspect the exact request, calls the provider, and submits the answer. - * - * A handler that short-circuits, forges a return, substitutes the request, - * replays it, or reconstructs the stable name reaches the provider's handler or - * the public refusing default. It never reaches the terminal, and a message - * that is not the initial routing request is refused before any provider work. - * - * ## What is durable - * - * The record — the request, the pre-state, the observations, the decision and - * the result — is the value of one ordinary durable operation, published - * through the existing stream and its existing pre-persistence gate. There is - * no side journal, no payload cache and no schema change. A completed record - * replays without installing or contacting a provider at all, and is parsed and - * held to the current request before it is handed back. + * One ordinary durable operation retains request, pre-state, observations, decision + * and result through the existing pre-persistence gate. Completed replay parses and + * matches that record without selecting or contacting a provider or appending. */ import { createApi } from "@effectionx/context-api"; diff --git a/packages/runtime/host-files.ts b/packages/runtime/host-files.ts index cb8373a9c..0d10b3f22 100644 --- a/packages/runtime/host-files.ts +++ b/packages/runtime/host-files.ts @@ -722,19 +722,11 @@ export function hostFilesHandler(options: HostFilesOptions = {}): FilesHandler { /** * A directory this call created, named by its canonical path. * - * Creation is synchronous so that nothing can suspend between it and the - * `ensure` that removes it. `until()` cannot cancel the promise it is waiting - * on, so an asynchronous `mkdtemp` halted mid-flight would go on to create a - * directory after the generator had already stopped — one nothing owns and - * nothing removes. `mkdtemp` names and creates at once, so the directory is - * never one an earlier run left behind. - * - * Everything after that is ordinary work and suspends. The path is - * canonicalized: on macOS `tmpdir()` is a symlink (`/var/folders/…`) while a - * child process resolves it (`/private/var/…`), and canonicalizing is what - * makes the rendered path, the contextual directory, and a subprocess's own - * `cwd` the same string. Cleanup is already registered by then, so a halt - * during it still takes the directory away. + * Synchronous `mkdtemp` creates a fresh directory without a cancellation gap + * before cleanup registration; an uncancellable asynchronous creation could + * finish after its owner halted. The path is canonicalized after cleanup is + * registered so macOS's symlinked temporary root and a subprocess's `cwd` + * agree. Cancellation during canonicalization still removes the directory. */ function temporaryDirectory(): Operation> { return resource(function* (provide) { diff --git a/packages/test-agent/src/components.ts b/packages/test-agent/src/components.ts index 4a82a2429..50a61416e 100644 --- a/packages/test-agent/src/components.ts +++ b/packages/test-agent/src/components.ts @@ -1,28 +1,17 @@ /** * The `` components (specs/test-agent-spec.md §TestAgent). * - * A prompt that fails inside a `` fails that test. `` says so - * with `installPromptFailurePolicy`, a scoped policy the agent `` - * consults — so nothing here depends on installation order, and a repository - * component named `Prompt` is left alone. + * `installPromptFailurePolicy` makes a first-party Prompt failure fail its Test, + * independent of installation order, without affecting a repository Prompt. * - * Each `` receives fresh ACPX state keyed by its lease EvalScope; - * the state is provisioned by a suspended task spawned into that scope, - * so halting the lease tears the provider down (canceling turns and - * closing workers) and removes the map entry on normal and failure - * paths alike. Outside a ``, the `` scope itself is - * the isolation boundary. + * Each Test's lease EvalScope owns fresh ACPX state through a suspended task; + * halting the lease cancels turns, closes workers and removes the partition on + * success and failure. Outside a Test, the TestAgent invocation owns isolation. + * Scenario resources belong to suspended tasks in that boundary. They are acquired + * in the suspending `withSessionRoute` hook before ACPX pins a synchronous route. * - * Scenario scenarios are resources held by suspended tasks spawned into - * their boundary scope, so a boundary halt releases them. Because acquiring one - * is an operation but the ACPX registry resolves routes synchronously, every - * instance is provisioned inside the provider's own `withSessionRoute` hook — - * which may suspend — before the route it produces is pinned. - * - * One ACP provider is installed here, in the `` invocation, over as - * many partitions as there are tests. Installation says where the provider can - * be reached from and is the only thing holding the launch coordinator; the partition - * a dispatch selects says which state it acts on. + * One invocation installs one ACP provider and holds the launch coordinator; + * each dispatch selects the partition whose state it acts on. */ import { createContext, Err, Ok, spawn, suspend, useScope, withResolvers } from "effection"; diff --git a/packages/test-agent/src/session-coordinator.ts b/packages/test-agent/src/session-coordinator.ts index b37e1ff3a..9e3194f62 100644 --- a/packages/test-agent/src/session-coordinator.ts +++ b/packages/test-agent/src/session-coordinator.ts @@ -1,20 +1,11 @@ /** - * Session ownership for one `` partition - * (specs/test-agent-spec.md §Scenarios). + * Coordinate native launch, session and prompt ownership within one TestAgent + * partition (specs/test-agent-spec.md §Scenarios). * - * The test agent advertises native launch, so every session, prompt and launch - * it serves passes through a coordinator before reaching ACPX. A host that - * installs none refuses, which is right for a host that cannot see whether a - * native UI is in the session — and wrong for a document whose agent is a - * worker this process started and owns outright. - * - * So this answers the same question deterministically, in memory, with the - * semantics the Deno adapter gives: one live owner at a time, and an owner that - * never proved it stopped leaves the session owned. What it deliberately does - * not have is a machine-wide namespace. Its lifetime is the partition that - * constructed it, which is why sibling `` elements naming the same agent, - * session and directory do not contend — they are not two owners of one - * session, they are two sessions. + * The worker belongs to this process, so coordination is deterministic in-memory + * state: one live owner at a time, with ownership retained until quiescence is + * proven. There is no machine-wide namespace. Sibling tests naming the same agent, + * session and directory own separate partitions and do not contend. */ import { ensure, Err, Ok, scoped } from "effection"; diff --git a/packages/test-support/bdd.ts b/packages/test-support/bdd.ts index a68f16b23..62a97aa0c 100644 --- a/packages/test-support/bdd.ts +++ b/packages/test-support/bdd.ts @@ -34,7 +34,6 @@ async function getPrimitives(): Promise { const g = globalThis as any; if (typeof g.Deno !== "undefined" && g.Deno.test) { - // Deno runtime — use @std/testing/bdd // @ts-ignore: Deno-only module, unreachable on Node/Bun const bdd = await import("@std/testing/bdd"); _primitives = { @@ -47,7 +46,6 @@ async function getPrimitives(): Promise { afterAll: (fn) => bdd.afterAll(fn), }; } else if (typeof g.Bun !== "undefined") { - // Bun runtime — use bun:test // @ts-ignore: Bun-only module, unreachable on Node/Deno const bunTest = await import("bun:test"); _primitives = { @@ -60,7 +58,6 @@ async function getPrimitives(): Promise { afterAll: (fn) => bunTest.afterAll(fn), }; } else { - // Node runtime — use node:test const nodeTest = await import("node:test"); _primitives = { describe: (name, _options, fn) => nodeTest.describe(name, fn), @@ -76,9 +73,7 @@ async function getPrimitives(): Promise { return _primitives; } -// Eagerly resolve primitives at module load time. -// On Deno this import is synchronous (already cached); on Node/Bun -// the dynamic import resolves before any test registration. +// Resolve the runtime adapter before any test registration. const primitivesPromise = getPrimitives(); let p: TestPrimitives | undefined; primitivesPromise.then((v) => { @@ -95,10 +90,8 @@ function prims(): TestPrimitives { // Block until primitives are loaded (covers the async gap on first import). // deno-lint-ignore no-explicit-any if (typeof (globalThis as any).Deno !== "undefined") { - // Deno: synchronous import resolution, p is already set p = await primitivesPromise; } else { - // Node/Bun: top-level await p = await primitivesPromise; } diff --git a/packages/testing/src/components.ts b/packages/testing/src/components.ts index b61aa3400..64d4af488 100644 --- a/packages/testing/src/components.ts +++ b/packages/testing/src/components.ts @@ -78,18 +78,6 @@ import type { TestHandlers } from "./handlers.ts"; const TEST_TIMEOUT_MS = 20_000; -/** - * Install the testing components and supply what core's `` does. - * - * `` itself is not registered here. The construct belongs to core, which - * is what makes a checked command failure inside a test that test's outcome - * rather than the run's; this session supplies its behavior and hands nobody an - * identity (#441). - * - * Behavior, and nothing more: a caller that installs this and answers the - * public `testing` boolean has registered what a test does without owning - * anywhere for a result to go. - */ /** * Everything this package makes resolvable, as plain declarations. * diff --git a/packages/testing/tests/boundary-contract.test.ts b/packages/testing/tests/boundary-contract.test.ts index 2b0227b60..789c406ea 100644 --- a/packages/testing/tests/boundary-contract.test.ts +++ b/packages/testing/tests/boundary-contract.test.ts @@ -1,12 +1,7 @@ /** - * Tier TC — what `` and `` guarantee, pinned before they move. - * - * These are characterization tests: every one passes against the handlers as - * they are today, and the migration onto the function-component boundary (#202 - * PR 3) has to keep them passing. They exist because the behaviors the - * migration is most likely to lose quietly are the ones nothing else asserts — - * partial output, where a stray error settles, and which failure a teardown - * produces. + * Tier TC — partial output, stray errors and teardown failures under + * `` and ``. These distinguish content projection that preserves + * the report from one that aborts the boundary and loses it. */ import { describe, it, beforeAll } from "@executablemd/test-support/bdd"; diff --git a/packages/web/client/config.ts b/packages/web/client/config.ts index bcfa0ae82..88b6e068d 100644 --- a/packages/web/client/config.ts +++ b/packages/web/client/config.ts @@ -1,13 +1,6 @@ /** - * The configuration the page fetches, validated before it is believed. - * - * The response comes from this WebForm's own server, but the page checks it - * anyway: the value flows into the DOM, and "the server sent it" is not a shape. - * A malformed or unexpected payload becomes a failure the page can report rather - * than an `undefined` rendered into the body. - * - * `bodyHtml` was sanitized on the server by `renderBody`, and it is the only - * field the page reads. Nothing widens that. + * Validate configuration before it reaches the DOM. `bodyHtml` is the only field + * consumed here and is sanitized on the server by `renderBody`. */ export interface FormConfig { diff --git a/packages/web/client/field-template.ts b/packages/web/client/field-template.ts index f69a407e0..3c946f4ca 100644 --- a/packages/web/client/field-template.ts +++ b/packages/web/client/field-template.ts @@ -1,15 +1,7 @@ /** - * Move the required marker from the label's text into the stylesheet's reach. - * - * The shadcn theme renders a required field's label as `[label, "*"]`, so the - * marker is a bare text node — and no selector reaches one, which leaves it - * unable to take the destructive colour the theme calls for. Spending - * `required` here suppresses that text node and marks the field instead; the - * stylesheet draws the same marker back on as `::after`. - * - * Nothing else in the field template reads the prop. The widgets take their own - * `required` from the field, which is where the select's unanswered-required - * styling comes from, so it is unaffected. + * The shadcn label's bare `"*"` text node cannot be styled by a selector. Suppress + * it with `required: false` and let the field class draw a `::after` marker. + * Widgets receive their own `required` prop and keep their validation styling. */ import { createElement } from "react"; @@ -23,7 +15,6 @@ export interface RequiredMarking { classNames: string; } -/** Pure and free of React, so the substitution is tested rather than rendered. */ export function markingFor(classNames: string | undefined): RequiredMarking { return { required: false, diff --git a/packages/web/client/outcome.ts b/packages/web/client/outcome.ts index 69001da94..16ec88409 100644 --- a/packages/web/client/outcome.ts +++ b/packages/web/client/outcome.ts @@ -1,25 +1,11 @@ /** - * What a person is told after submitting, and whether they can try again. - * - * Three of these are ordinary and one is not. A 204 means the workflow has the - * answer and this tab has no further purpose. A 409 means the form was already - * answered — by another tab, or by this one before a reload — and nothing the - * person does here will change that. A 422 or a transport failure is the only - * case where trying again makes sense, so it is the only case that leaves the - * form usable. - * - * Pure and free of the DOM, so the mapping is tested directly rather than - * inferred from what a page rendered. + * A 204 or 409 ends this tab's work; validation and transport failures leave the + * form usable so the person can retry. This mapping needs no DOM. */ export type OutcomeKind = "accepted" | "already-submitted" | "retryable"; -/** - * How the status region is coloured. Two states, because there are only two - * things a reader needs to tell apart: an answer that landed and one that did - * not. `formUsable` already draws that line — an outcome that leaves the form - * usable is one the person still has to act on. - */ +/** A retryable outcome needs action; either terminal outcome uses `accepted`. */ export type Banner = "accepted" | "failed"; export interface Outcome { diff --git a/packages/web/client/request.ts b/packages/web/client/request.ts index 66e8732f9..787bf1979 100644 --- a/packages/web/client/request.ts +++ b/packages/web/client/request.ts @@ -1,17 +1,7 @@ /** - * The page's HTTP calls, as operations. - * - * `XMLHttpRequest` rather than `fetch` because nothing in this bundle may be a - * promise: the page runs inside one Effection scope, and a promise is work that - * scope cannot cancel. `action()` closes that gap — its executor returns a - * cleanup function that Effection calls however the operation ends, so a halted - * page removes its listeners and aborts the request in flight instead of leaving - * a callback pointed at a torn-down page. - * - * A transport failure is reported as status 0 rather than thrown. The caller has - * to tell a person what happened either way, and `outcomeFor` already treats an - * unrecognized status as retryable — so there is one path through the outcome, - * not two. + * `XMLHttpRequest` exposes abort and listener removal to `action()` cleanup, so + * leaving the page cancels in-flight calls. Transport failures return status 0 + * for the same retryable outcome path as other unrecognized statuses. */ import { action } from "effection"; diff --git a/packages/web/src/ajv-options.ts b/packages/web/src/ajv-options.ts index 3d055c90f..8c8fdb482 100644 --- a/packages/web/src/ajv-options.ts +++ b/packages/web/src/ajv-options.ts @@ -1,27 +1,10 @@ /** - * The shared Ajv policy for WebForm schema validation. - * - * `AJV_OPTIONS` is what both sides override RJSF's own configuration with, and - * `createServerAjv` is how the server gets an Ajv that matches the browser's. - * Formats are disabled on both sides, which is what keeps a compiled validator's - * runtime-helper surface down to `equal` and `ucs2length` — the only two helpers - * the bundled client resolves. - * - * Equivalence is a property of the *construction path*, not of a list of - * options. `compileSchemaValidatorsCode` builds its Ajv through RJSF's - * `createAjvInstance`, which starts from RJSF's `AJV_CONFIG` and then spreads - * these overrides on top. A bare `new Ajv({ ...AJV_OPTIONS })` therefore differs - * from it by everything in `AJV_CONFIG` these options do not mention — - * `multipleOfPrecision: 8`, `verbose: true`, `discriminator: false` — and by the - * `data-url` and `color` formats and the RJSF property-flag keyword that - * function registers. - * - * That is not hypothetical: `multipleOfPrecision` alone made a bare server - * reject `4.22` against `{ type: "number", multipleOf: 0.01 }` while the browser - * accepted it, because binary floating point leaves `4.22 / 0.01` a hair away - * from an integer. So the server is built through the same function rather than - * by restating any single default here, and a future change to `AJV_CONFIG` - * reaches both sides at once. + * Both validators use RJSF's `createAjvInstance` with these overrides and formats + * disabled. A bare Ajv with the same overrides omits RJSF defaults and keywords: + * notably `multipleOfPrecision: 8`, without which the server rejects `4.22` for + * `multipleOf: 0.01` while the browser accepts it. Sharing the construction path + * keeps future RJSF defaults aligned, too. Disabling formats limits the client's + * runtime helpers to `equal` and `ucs2length`. */ import createAjvInstance from "@rjsf/validator-ajv8/lib/createAjvInstance.js"; @@ -39,12 +22,8 @@ export const AJV_OPTIONS = { }; /** - * The server's Ajv: RJSF's construction, these overrides, no formats. - * - * `Ajv` from `"ajv"` is the draft-07 entry — the draft the authoring contract - * names — rather than `ajv/dist/2020`, and it is the class `createAjvInstance` - * defaults to. Nothing in the browser bundle imports this module; the client's - * copy of the policy is baked into the validator the server precompiles for it. + * Uses RJSF's default draft-07 Ajv entry. Only the server imports this module; + * the browser receives its policy through the precompiled validator. */ export function createServerAjv(): Ajv { return createAjvInstance(undefined, undefined, AJV_OPTIONS, false); diff --git a/packages/workflow/src/deno/lock.ts b/packages/workflow/src/deno/lock.ts index 1d7c4e3c5..b686383b5 100644 --- a/packages/workflow/src/deno/lock.ts +++ b/packages/workflow/src/deno/lock.ts @@ -1,23 +1,12 @@ /** - * One database, one operation at a time. + * Serialize all access to one provider-owned database connection. + * Transactions suspend, so synchronous SQLite calls alone cannot prevent another + * operation from joining and committing or rolling back somebody else's work. + * Handles for one run share this cooperative lock; SQLite coordinates processes. * - * SQLite is reached synchronously, but the operations built on it are not: a - * transaction holds the database across every `yield*` its body performs. A - * second operation arriving in that window would run its statements inside - * somebody else's transaction and commit or roll back with it, so the adapter - * serializes everything that touches one database rather than relying on - * callers to take turns. - * - * Turns are taken by the provider-owned entry for one database file. Every - * handle for that run leases the same physical connection, so a second - * operation must wait here before it can issue statements inside the first - * operation's transaction. Waiting cooperatively leaves the host running; - * SQLite's own locking remains responsible for contention between processes. - * - * Waiting is cancellable and hand-off is synchronous. A caller torn down while - * queued leaves the queue without ever running its statements, and a caller - * torn down in the instant between being handed the lock and resuming still - * passes it on — the two states that would otherwise strand it. + * Cancellation removes queued turns before they execute. Synchronous hand-off marks + * the next turn granted before waking it, so cancellation between grant and resume + * still releases the lock rather than stranding it. */ import { ensure, type Operation, resource, type WithResolvers, withResolvers } from "effection"; diff --git a/packages/workflow/src/deno/provider.ts b/packages/workflow/src/deno/provider.ts index d823b6982..494f2e20c 100644 --- a/packages/workflow/src/deno/provider.ts +++ b/packages/workflow/src/deno/provider.ts @@ -1,28 +1,11 @@ /** - * The Deno workflow-run storage provider. + * The Deno workflow-run storage provider owns run-id hashing, authorized-root + * paths, SQLite access and storage-error classification. * - * This module is where the host stops being provider-neutral: it hashes run - * ids, resolves paths beneath the authorized root, opens SQLite, and decides - * what each of SQLite's refusals means. Nothing above it names any of those. - * - * ## Finding a run - * - * A run's file is the SHA-256 of its public run id beneath the root, so - * discovery is arithmetic and there is no index that could disagree with the - * files. Because a path can be derived by anyone, the run id is also stored - * inside the database and checked: a file at the right path holding a different - * run is a collision or tampering, and is refused rather than adopted. - * - * ## Creating is reusing - * - * `create()` answers with the stored run when the request describes it, and - * refuses when any immutable field differs. That is what makes a - * caller-selected id usable twice — as a retry, or as a second process - * addressing the same work — without a separate idempotency concept. - * - * Two callers creating at once converge through SQLite's own write lock: the - * first initializes the file, the second finds it already initialized and - * compares instead of writing. + * A run's path is its public id's SHA-256 beneath the root, with no index. The + * stored id must still match: a correctly located file holding another run refuses. + * `create()` reuses a run only when every immutable field agrees. Concurrent creators + * converge through SQLite's write lock: initialize once, then compare. */ import { dirname, isAbsolute } from "node:path"; diff --git a/packages/workflow/src/deno/transaction.ts b/packages/workflow/src/deno/transaction.ts index 1d979f8a6..e4e303405 100644 --- a/packages/workflow/src/deno/transaction.ts +++ b/packages/workflow/src/deno/transaction.ts @@ -1,18 +1,9 @@ /** - * What "a transaction is open here" means, in two pieces. - * - * Shared state has two forms, and this needed both. Which database the current - * scope is inside a transaction on is composition data: a plain structural - * value under a stable, namespaced name, which any code may read and which can - * only ever cause an operation to be refused. Taking a savepoint inside that - * transaction is an operation, so it lives behind a contextual Api instead of - * being an executable member of a context value. - * - * The savepoint is the seam a Workspace filesystem needs: nested work rolls - * back its own mutations while staying inside the one transaction that - * publishes the effect and its journal result together. It is adapter-private — - * neither piece is exported from the package root — and it hands out no - * database, so nothing above this boundary can reach SQLite through it. + * Track transaction membership separately from savepoint operations. + * Membership is structural data under a stable namespaced context and can only + * cause refusal. Savepoints use an adapter-private contextual Api and expose no + * database. They let Workspace mutations roll back nested work while the outer + * transaction still publishes the effect and journal result atomically. */ import { type Api, createApi } from "@effectionx/context-api"; diff --git a/packages/workflow/src/deno/workspace/evaluate.ts b/packages/workflow/src/deno/workspace/evaluate.ts index a3443faeb..d57bbefa1 100644 --- a/packages/workflow/src/deno/workspace/evaluate.ts +++ b/packages/workflow/src/deno/workspace/evaluate.ts @@ -1,61 +1,24 @@ /** - * What a workflow run lets a generated fragment do + * State the host ceiling for canonical core's Evaluate component * (specs/workflow-workspace-spec.md §8.4). * - * An Agent proposes an observation by returning a fragment of Executable - * Markdown, and an authored workflow writes `` where it wants that - * fragment admitted and performed. The component is canonical core's — public, - * protected, and the same in every execution. What this file states is the - * *ceiling*, which is the only part a host owns. + * The workflow attachment assembles the profile once; canonical execution captures + * it by value before document code. Props, bindings, Context, middleware and + * generated names cannot widen it. Read includes core's self-closing File, Fetch + * only with exact permitted requests, and captured host additions. Write includes + * paired File, an optional host-supplied directory entry, self-closing File.Delete + * and captured additions, in that order. No directory entry means no directory + * grant. `allow` selects classes, defaulting to read, and never supplies permission. * - * ## Every ceiling is captured before a document exists + * The private per-invocation Workspace snapshot reports retained roots and current + * root. Continuation requires admission roots by membership, allowing legitimate + * new roots and frontier advancement without changing the grant. * - * This is built once, when the workflow attachment assembles the execution, and - * canonical execution captures it by value there. Nothing a document, a prop, a - * binding, a context, a contextual API answer, middleware or a generated name - * does reaches back into it. - * - * - the read table is core's read-only ``; `` joins it only - * where this host also states the exact requests it may perform; - * - the write table is core's paired ``, the directory entry this host - * captured — or the one released builds retained, when it captured none — - * and core's self-closing ``; - * - any further read or write comes from the captured host option; and - * - the Workspace basis is answered per invocation by the private operation - * below, because a run's own progress legitimately advances it: every - * committed mutation retains another immutable root. A continuation holds the - * admission's roots by membership, so later publications and an advanced - * current root change nothing the admission was granted under. - * - * ## `allow` narrows; it never grants - * - * `allow` names an effect *class*, and the class resolves to the table stated - * here. Omitting it asks for `read`. Asking for `write` reaches core's paired - * ``, the directory entry this host captured — `` is canonical - * core's own component now, and what a host supplies is the entry admitting it - * — and core's self-closing ``, and nothing else — no Git, no Git host, no Issue, no process, no credential — and - * a host that installed no write table refuses the selection before the - * candidate is parsed. - * - * A deletion is admitted on the same terms as the other two, and accounted for - * the same way: it invokes the ordinary component, crosses the run's existing - * effect transaction, and is retained by the `workspace_file` effect that - * transaction publishes. Nothing about it reaches the value `` - * returns. - * - * ## The operations are the run's own, not this file's - * - * This states names, forms, identities and ceilings, and no operation at all. - * An admitted entry runs canonical core's own component, which performs its - * work through contextual `API.Files` and `API.Fetch` — in a workflow run, - * the transaction-bound provider `workspace/host.ts` installed and the - * transport the workflow host installed. So an admitted write is the same - * durable effect an authored one is, published by the same transaction, - * observed by the same middleware and decided by the same effective - * `Permissions`. A fragment's relative paths resolve against the run's own - * contextual working directory, which is the Workspace root as narrowed by the - * run's own ``, `` and `` — never the directory the - * caller invoked `xmd` from. + * Entries run ordinary canonical components through contextual API.Files/API.Fetch, + * existing middleware, effective Permissions and the run's effect transaction. + * Deletion remains a workspace_file effect. Relative paths use the run's contextual + * cwd, including Dir/Repository/Worktree placement, never the invocation host cwd. + * This profile supplies identities, forms and ceilings rather than operations. */ import { timeoutFetch } from "@executablemd/runtime"; @@ -96,18 +59,10 @@ export interface GeneratedEvaluationOptions { /** Further mutation components this host admits beside the standard profile's. */ readonly writes?: readonly FragmentEntry[]; /** - * The directory component this host admits, between core's write and delete. - * - * Its own member rather than one of the additive entries above, because it is - * not an addition: it occupies the position the standard profile has always - * had a directory entry in, and a continuation compares that table position - * by position. - * - * Optional, and absence grants nothing. `` belongs to - * `@executablemd/git`, and this package states no entry for it: a host that - * supplies none is a Workflow host without a directory capability, which is - * a thing a generic host is entitled to be. The XMD workflow profile supplies - * Git's. + * Optional directory admission, between File write and File.Delete. + * Canonical core owns Dir; the host supplies its admitted entry. Omission grants + * no directory capability. Keep this position: continuation compares the retained + * table entry by entry. */ readonly directory?: FragmentEntry; } diff --git a/packages/workflow/src/deno/workspace/files.ts b/packages/workflow/src/deno/workspace/files.ts index 777bf534d..2576c79de 100644 --- a/packages/workflow/src/deno/workspace/files.ts +++ b/packages/workflow/src/deno/workspace/files.ts @@ -1,67 +1,19 @@ /** - * The transaction-bound `API.Files` provider — a document's filesystem inside a - * workflow run. + * Provide document file operations inside a workflow's logical Workspace. + * POSIX resolution stays under `/` and reaches DOFS, never a host filesystem path. + * Reads, writes, directory ensures, deletions and searches each publish one durable + * effect; mutation, immutable root and filtered journal result commit together. * - * This is what `xmd workflow` installs where `xmd run` installs the host - * adapter. A document names the same paths and `` calls the same - * operations; what changes is where those paths land. Here they land in the - * run's own logical Workspace, and every read, write and search is one durable - * effect published by the run's effect transaction — the mutation, the - * resulting immutable Workspace root and the filtered journal result commit - * together or not at all. + * `checkFilePath` is pure lexical admission: no effect, journal entry or reusable + * grant. Writes repeat admission from the authored path. Permissions are asked + * inside the live performer before I/O, so completed replay restores the recorded + * outcome without re-deciding it under current policy or consulting the frontier. * - * ## Why an authored path never reaches a host filesystem call - * - * Resolution is arithmetic on POSIX segments rooted at `/`, and the result is - * handed to the run's DOFS filesystem. No host path appears anywhere in it, so - * the containment claim needs no stable-namespace qualification: nothing - * outside the Workspace can be named, and no other process can replace part of - * a tree that lives inside one database. - * - * `checkFilePath` stays what the Api says it is — pure lexical admission that - * hands back nothing usable. It performs no effect and appends no journal - * entry, so a check that was skipped or answered elsewhere authorizes nothing; - * the write repeats the same admission from the same authored path. - * - * ## Where permission is asked - * - * Inside the live performer, as its first step. `Permissions` is a question - * about work that is about to happen, and under replay no work is about to - * happen: a check placed around `performed()` would re-decide an operation that - * has already been published, so a run continued under a narrower policy would - * contradict its own journal — and a run continued under a wider one would ask - * for permission it no longer needs. Asking inside the performer means a - * completed effect restores what it recorded and only new work meets current - * policy. - * - * A refusal is an ordinary live outcome, published like any other and - * sanitized the same way, so the journal reads "this operation was refused" - * rather than "this run failed". It changes no target and captures the root it - * already had. - * - * ## What replay does instead - * - * A recorded effect restores its recorded value. A read therefore answers with - * the bytes it read when it ran, even where the current frontier no longer - * holds them, and a write already recorded neither mutates nor captures a root - * again. Nothing here consults current state to decide whether an earlier - * effect happened, which is what lets a create/delete/create history replay in - * order rather than collapsing to whatever the file is now. - * - * ## What crosses the boundary - * - * A documented DOFS refusal selects a `FilesReason` and nothing else travels - * with it: no DOFS message, no errno payload, no SQLite text, no resolved path. - * A refusal is also a *rolled back* refusal — the mutation runs inside a - * savepoint of its own, so partial logical mutation is discarded before the - * sanitized result is durably published, and the run's current root is the one - * it was before. - * - * Everything that is not a documented refusal — connection, admission, - * savepoint, capture, publication, routing, teardown and commit failure — stays - * an infrastructure failure and fails the run. None of them is something a - * document did, and printing one would let the work after this file work run as - * though the file work had happened. + * Documented DOFS refusals roll back the mutation savepoint before publishing a + * sanitized FilesReason against the prior root. No platform message, errno, SQLite + * text or resolved path crosses. Connection, admission, savepoint, capture, + * publication, routing, teardown and commit failures remain infrastructure failures + * that printing cannot recover. */ import { Err, Ok, type Operation, type Result } from "effection"; diff --git a/packages/workflow/src/deno/workspace/guard.ts b/packages/workflow/src/deno/workspace/guard.ts index b032b60f9..b42786b4a 100644 --- a/packages/workflow/src/deno/workspace/guard.ts +++ b/packages/workflow/src/deno/workspace/guard.ts @@ -1,26 +1,11 @@ /** - * Holding a capability to the callback it was handed to. + * Revoke callback-owned Workspace capabilities before later publication work. + * The transaction remains open after a mutation or inspection callback returns; + * retained filesystem, storage and savepoint views must not reach that live window. + * One gate revokes every projection of the callback's argument together. * - * A Workspace transaction stays open after the mutation inside it returns — it - * goes on to capture a root, publish it and enlist the journal — and an - * inspection's transaction is open for the same reason. So a filesystem, a - * storage view or a savepoint that a callback kept is not merely a stale - * object: it is a live capability inside a transaction that is still running, - * and using it would write work no effect publishes and no journal records. - * - * Revocation is what makes "for this callback" a fact. One gate serves every - * projection built from one callback's argument, so the transaction ends all of - * them together rather than each object having a lifetime of its own. - * - * ## Why an operation is checked twice - * - * Most of these members do not do the work; they return an `Operation` that - * does it when something yields it. Checking only when the member is *called* - * would leave the obvious hole open: a callback creates the operations it wants - * while it is still valid, returns, and yields them afterwards. So a gated - * member checks when it is called — which fails fast, and is what a caller - * holding a revoked object sees — and the operation it returns checks again - * when its body begins. + * Operation-returning members check both when called and when yielded, preventing + * a callback from constructing work while authorized and running it after return. */ import type { Operation } from "effection"; diff --git a/packages/workflow/src/deno/workspace/inspect.ts b/packages/workflow/src/deno/workspace/inspect.ts index 557975349..0dfa2e372 100644 --- a/packages/workflow/src/deno/workspace/inspect.ts +++ b/packages/workflow/src/deno/workspace/inspect.ts @@ -1,33 +1,16 @@ /** - * Reading this run's Workspace without performing a durable effect. + * Read authenticated retained Workspace state without a durable effect, journal + * entry or root publication. The transaction ends with the callback, before later + * host work such as a Git subprocess. * - * Some work has to look at retained bytes and retained rows without changing - * anything: exporting a checkout so a subprocess can run against files, or - * proving that what a record names is still there. That is not an effect — it - * journals nothing, publishes no root and has no result to replay — but it does - * need the same authority as one, because the bytes it reads are the run's. + * The filesystem exposes six reading members; storage compiles statements under + * a SQLite authorizer that rejects writes, including `INSERT … RETURNING`. + * Both views are revoked on callback return and rechecked when deferred operations + * start. * - * So this opens the run's ordinary authenticated transaction, hands the - * callback a snapshot that can only read, and closes it. The transaction is - * held for the inspection alone: everything a caller does afterwards runs - * against host files, so a Git subprocess never keeps the run's database open. - * - * "Can only read" is proven rather than promised. The filesystem is the six - * reading members and no others, and the storage view compiles every statement - * under a SQLite authorizer that refuses to admit anything but a read, so - * `INSERT … RETURNING` is rejected during compilation instead of returning the - * row it just wrote. Both are revoked when the callback returns, and both - * recheck when an operation they produced actually begins — a callback that - * built its writes early and yielded them late is the hole that closes. - * - * `rootId` is what makes a historical read possible. A run sometimes has to - * name what it published at an earlier moment, and the Workspace has moved on - * since — so the retained root is materialized inside a rollback-only - * savepoint, the callback reads it, and everything that materialization wrote - * is discarded. The current root, the retained roots, the rows and the journal - * are what they were on every path out, including a failure and a - * cancellation. Nothing here publishes, and there is no ordering in which - * anything else observes the Workspace selected at the historical root. + * An optional historical root is materialized in a rollback-only savepoint. Every + * exit, including failure and cancellation, restores the current root, retained + * roots, rows and journal; no other observer sees the historical root selected. */ import type { Operation, Result } from "effection"; diff --git a/packages/workflow/src/deno/workspace/storage.ts b/packages/workflow/src/deno/workspace/storage.ts index a06f503eb..33cebe151 100644 --- a/packages/workflow/src/deno/workspace/storage.ts +++ b/packages/workflow/src/deno/workspace/storage.ts @@ -1,46 +1,16 @@ /** - * The storage one Workspace transaction or inspection may reach. + * Expose bound SQL statements and raw rows for feature-owned parsers, without + * handing features the database, executor lease, transaction or journal. Every call + * rechecks the issuing transaction's authorization, including lease and database. * - * A generic view rather than a table-shaped one. Workflow owns the database, - * the executor lease, the transaction and the journal; what a feature owns is - * the meaning of its own rows, and this is the narrowest surface that lets it - * keep that meaning without holding any of the rest. Statements are the - * caller's, parameters are bound rather than interpolated, and a read comes - * back as the stored row for the caller's own parser to read — nothing here - * knows what a column means. + * Read views require SQLite's authorizer: `get` and `all` can otherwise execute + * `INSERT`, `UPDATE` or `DELETE … RETURNING`. Only SQLITE_SELECT, SQLITE_READ and + * SQLITE_FUNCTION are admitted; an adapter without authorizer support refuses. * - * ## Why a read view is not merely a view without `run` - * - * Because SQLite does not agree that `get` and `all` only read. `INSERT INTO - * workspace_repositories (…) VALUES (…) RETURNING name` is a statement that - * returns rows, and `StatementSync.all()` runs it and commits the insertion. - * The same is true of `UPDATE … RETURNING` and `DELETE … RETURNING`. Removing - * `run` from an interface removes a spelling, not a capability. - * - * So a read view proves the statement reads before it executes, and SQLite is - * what proves it. Each read compiles under an authorizer that admits - * `SQLITE_SELECT`, `SQLITE_READ` and `SQLITE_FUNCTION` and refuses every other - * action, so an insertion, an update, a deletion, a schema change or a pragma - * is rejected during compilation — before a row is touched. A lexical check for - * a leading `SELECT` would be the wrong tool twice over: it would admit - * `WITH x AS (INSERT …)` and it would be a parser this package would then own. - * - * The authorizer is a property of the connection, so it is installed around one - * read and removed in a `finally`. Nothing can run between those two points: a - * read is synchronous from the call to the returned rows, and this runtime does - * not interleave another coroutine inside it. It stays installed across - * execution as well as compilation, because SQLite recompiles a statement by - * itself when the schema changes underneath it, and a recompilation is exactly - * the moment the check must still be there. - * - * An adapter that offers no authorizer cannot support a read view, and this - * refuses to build one rather than handing back a view that would allow what it - * says it forbids. - * - * Every call re-authorizes against the transaction as well. The view is built - * inside an active transaction and closes over that transaction's own check, so - * a retained view whose transaction has ended, whose lease has moved, or whose - * database is not the one that issued it refuses rather than reaching SQLite. + * Install the authorizer around both compilation and execution, then remove it in + * finally. The read is synchronous, so no coroutine interleaves on the connection; + * keeping authorization through execution also covers SQLite's automatic schema + * recompilation. */ import { constants, type DatabaseSync, type StatementSync } from "node:sqlite"; diff --git a/packages/workflow/src/storage/compatibility.ts b/packages/workflow/src/storage/compatibility.ts index bbb4abe97..18c66f14f 100644 --- a/packages/workflow/src/storage/compatibility.ts +++ b/packages/workflow/src/storage/compatibility.ts @@ -1,21 +1,11 @@ /** - * Whether a request addresses the run that is already stored. + * Compare run-id reuse by immutable identity: public id, complete definition and + * normalized props. Canonical prop comparison ignores object-key order. * - * Reuse of a run id is the mechanism a caller has for saying "the same run - * again", so the question is not whether two requests are byte-identical but - * whether they describe one run. Identity is the run id, the whole definition - * descriptor, and the normalized props. Values are compared canonically, so - * props that differ only in key order are the same props. - * - * Everything a run accumulates is excluded: status, stop reason, retrieval - * metadata, timestamps, document executions and journal records all change - * while the run stays the run it was. A completed run that is asked for again - * is found, not refused. - * - * A run is its entrypoint, the complete canonical source manifest, its - * component mapping and its target. There is one definition shape, so there is - * one comparison rather than a per-version one, and no member a descriptor - * might not have. + * Status, stop reason, retrieval metadata, timestamps, document executions and + * journal records are accumulated state and do not prevent reuse, even after + * completion. Definition comparison includes the entrypoint, complete canonical + * source manifest, component mapping and exact target. */ import type { JsonObject } from "./members.ts"; diff --git a/packages/workflow/tests/workflow-export.test.ts b/packages/workflow/tests/workflow-export.test.ts index 364c664cb..4703d49f0 100644 --- a/packages/workflow/tests/workflow-export.test.ts +++ b/packages/workflow/tests/workflow-export.test.ts @@ -448,7 +448,6 @@ describe("exporting a run that really ran", () => { expect(artifact.run.status).toBe("completed"); expect(artifact.executions).toHaveLength(1); - // --- Retained history -------------------------------------------------- // Six Workspace effects, in the order the document writes them. Asserted // before the state they produced, so a run that silently did less than the // document says fails here rather than passing a thinner comparison. @@ -467,7 +466,6 @@ describe("exporting a run that really ran", () => { // The component the definition declares is nowhere in what ran. expect(artifact.journal.some((row) => row.record.includes("Unused"))).toBe(false); - // --- Multiple Workspace roots ----------------------------------------- const rootIds = artifact.roots.map((root) => root.rootId); expect(new Set(rootIds).size).toBe(rootIds.length); expect(rootIds.length).toBeGreaterThan(1); @@ -480,7 +478,6 @@ describe("exporting a run that really ran", () => { expect(rootIds).toContain(rootId); } - // --- File bytes, mode, symlink and hardlink state --------------------- const current = artifactWorkspace(artifact, artifact.frontier.currentWorkspaceRootId); // Whole tree, path by path: kind, mode and link target for every node the // run's own filesystem holds. @@ -523,7 +520,6 @@ describe("exporting a run that really ran", () => { Buffer.from("rich evidence").toString("base64"), ); - // --- Repository and Worktree ------------------------------------------ expect(artifact.repositories).toHaveLength(1); expect(artifact.repositories[0]).toMatchObject({ name: "project", @@ -547,7 +543,6 @@ describe("exporting a run that really ran", () => { retainedRecord(history, "workspace_worktree")["checkoutPath"], ); - // --- The definition, and the component nothing expanded --------------- const decode = (path: string): string | undefined => { const retained = artifact.definition.sources.find((each) => each.path === path); return retained === undefined ? undefined : new TextDecoder().decode(retained.bytes); diff --git a/scripts/lib/changed-paths.ts b/scripts/lib/changed-paths.ts index 6eb26cc98..50671140e 100644 --- a/scripts/lib/changed-paths.ts +++ b/scripts/lib/changed-paths.ts @@ -1,32 +1,12 @@ /** - * Which paths this branch and worktree touched, from git's two answers. + * Read both sides of renames and copies from Git's two NUL-delimited formats. + * Porcelain places NEW then OLD paths (`R new\0old\0`); name-status places + * OLD then NEW (`R100\0old\0new\0`), so they need distinct parsers. * - * Verify asks one question of these: did anything under `site/` change? The - * answer has to survive a rename, which is where the two sources stop agreeing. - * Measured on this repository, renaming `site/page.md` to `moved-out.md`: - * - * ```text - * git status --porcelain=v1 -z "R moved-out.md"\0"site/page.md"\0 - * ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ - * status and NEW path share one field, then old - * - * git diff --name-status -z -M -C "R100"\0"site/page.md"\0"moved-out.md"\0 - * ^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^^ - * status OLD path new path - * ``` - * - * The path order is reversed between them, so one parser cannot read both. - * Both paths are always yielded: a rename out of `site/` changes `site/` just - * as much as a rename into it does. - * - * Two more shapes came out of the same measurements. An *unstaged* rename is - * not reported as a rename at all — git emits ` D site/page.md` and - * `?? moved-out.md` — so nothing here may assume an `R` exists. And a copy does - * reach porcelain when `status.renames=copies` is configured - * (`C site/copy2.md\0keep.md\0`), so `C` is read, not guessed at. - * - * A status neither parser recognises raises. Reading one path where git meant - * two would silently drop the side that mattered. + * An unstaged rename can appear as a deletion and an untracked path rather than + * `R`; porcelain can also report `C` under `status.renames=copies`. Both paths + * matter when checking a directory a file moved into or out of. Unknown statuses + * raise rather than silently dropping a path. */ export class ChangedPathsError extends Error {} diff --git a/scripts/lib/compile.ts b/scripts/lib/compile.ts index 78129fa16..e676f3fd8 100644 --- a/scripts/lib/compile.ts +++ b/scripts/lib/compile.ts @@ -1,19 +1,8 @@ /** - * Everything a compiled `xmd` is made of, stated once. - * - * `deno compile` embeds what `--include` names and nothing else. An asset left - * out costs nothing at compile time and nothing at startup: the binary runs, - * resolves the name, and fails at the moment a person asks it for the thing - * that was omitted. Three sites compile this entrypoint — `deno task build`, - * `release.yml`'s matrix, and `verify:clean`'s release phase — and while each - * carried its own copy of the list the three disagreed: the release shipped no - * component documentation at all, so every published binary refused - * `xmd syntax TempDir`, and `verify:clean` proved a binary narrower than the one - * a release publishes. - * - * So the inputs live here and each site asks for the argv. What the sites still - * choose for themselves is the two things that genuinely differ between them: - * where the binary is written, and which platform it is for. + * Share compile inputs across local builds, releases and `verify:clean`; callers + * choose only the output path and target. `deno compile` embeds only `--include` + * assets, so a missing document can survive compilation and startup and fail + * only when requested, as omitted component documentation did in releases. */ import { exec } from "@effectionx/process"; @@ -44,17 +33,9 @@ export const COMPILE_FLAGS = [ ]; /** - * A whole package the binary executes Markdown out of. - * - * Empty, and that is a decision rather than an omission: the binary contains - * the program `xmd` is, and a Plugin is not part of it. The code-review graph - * was embedded here while it was bundled; now that it is selected with - * `--plugin` like any other Plugin, it reads its own assets from wherever the - * operator installed it — a source checkout, an npm install, or the path they - * named — and the binary carries none of them. - * - * An entry here is for a package the binary *imports*. Adding one for a package - * nothing in the binary imports would embed bytes no code can reach. + * Whole imported packages whose Markdown assets the binary needs. Selected + * Plugins load their own assets from their installed location. An entry here + * must name an imported package; unreachable bytes serve no binary code. */ export const EMBEDDED_PACKAGES: readonly string[] = []; diff --git a/scripts/lib/main-green.ts b/scripts/lib/main-green.ts index a51d8c90f..e6e177a92 100644 --- a/scripts/lib/main-green.ts +++ b/scripts/lib/main-green.ts @@ -1,28 +1,12 @@ /** - * Decide whether a pull request may claim `green`. + * Require successful CI for `main`'s exact current head before a pull request + * claims `green`. Reuse Main Health's `selectAuthoritative()` rules so the gate + * and its issue agree on head, branch, event, run number and attempt. * - * Main Health reports a red `main` and assigns it to a person. Reporting is not - * gating: an ordinary pull request could still pass every check of its own and - * merge onto a base nothing had proven, which makes the next `main` failure - * indistinguishable from the one already open. This gate closes that by - * refusing the aggregate check until CI has completed successfully for `main`'s - * *exact* current head. - * - * Exact is the whole claim. A successful run for the previous head says only - * that `main` used to work, and that is precisely the state a red `main` is in - * one commit after it broke. So the authoritative run is selected by - * `selectAuthoritative()` — the same head/branch/event/number/attempt rules - * Main Health decides a report with, rather than a second interpretation of - * main health that could disagree with the issue an operator is reading. - * - * Exactness is also why the gate waits rather than answering once. `main`'s - * verdict arrives minutes after its push, and a pull request that asked too - * early has no verdict to read — that is a missing answer, not a red `main`. - * So an absent, queued or in-progress run is a state to wait through, an - * advancing head is one to follow, and only a completed run for the head that - * is still current is a verdict at all. Waiting is a convergence — `when()` - * from `@effectionx/converge` — and running out of it means this pull request - * obtained no proof, which is not the same claim as `main` having failed. + * Absent, queued and in-progress runs wait through `when()` convergence; an + * advancing head restarts the question. Only a completed verdict for the still + * current head passes or fails. Timeout means no proof arrived, not that `main` + * failed. A previous head's success proves nothing about the current one. */ import { createContext, Err, Ok } from "effection"; import type { Context, Operation, Result } from "effection"; @@ -33,13 +17,8 @@ import { selectAuthoritative } from "./main-health.ts"; import type { Run } from "./main-health.ts"; /** - * The one exception, applied by a maintainer to one pull request. - * - * Restoring a red `main` needs a pull request that cannot satisfy this gate, by - * construction — the base it would prove is the broken one. The label buys only - * the remote lookup: the labelled pull request additionally runs - * `composability`, the clean-checkout battery `main` pushes run, so the branch - * that claims to repair `main` proves it the same way `main` itself is proven. + * Maintainer-applied exception for repairing red `main`: bypass only the remote + * lookup and require the clean-checkout `composability` proof instead. */ export const REPAIR_LABEL = "ci-main-red-fix"; @@ -47,25 +26,14 @@ export const REPAIR_LABEL = "ci-main-red-fix"; export const REPAIR_LABEL_DESCRIPTION = "Maintainer-controlled: lands one PR while main is red, only with the full clean-checkout proof"; -/** - * How long the waiter sleeps between polls. - * - * An authoritative `main` run takes tens of minutes, so this is not a race to - * observe the finish; it is short enough that following an advancing head costs - * one interval, and long enough that a waiting job is not a poller. - */ export const POLL_INTERVAL_MILLISECONDS = 15 * 1000; /** The `timeout-minutes` on the job, held here so the two cannot drift. */ export const JOB_TIMEOUT_MINUTES = 60; /** - * When the waiter gives up, which is deliberately before the job does. - * - * The job's timeout kills the step mid-poll and leaves the log saying nothing - * about what was awaited. Converging inside that bound means the gate reports - * the state it last saw, so "no verdict arrived" is legible and stays distinct - * from `main` having failed. + * Expire before the job's hard timeout so the gate reports its last observation + * and distinguishes missing proof from a failed `main` run. */ export const WAIT_TIMEOUT_MILLISECONDS = 55 * 60 * 1000; diff --git a/scripts/lib/prepared-state.ts b/scripts/lib/prepared-state.ts index ad9e4bc8f..f7b705b9e 100644 --- a/scripts/lib/prepared-state.ts +++ b/scripts/lib/prepared-state.ts @@ -24,28 +24,12 @@ * relocates a root is followed rather than silently skipped, and a run whose * `deno info` stops reporting one of the three fails loudly. * - * ## Every read and every hash is synchronous + * ## Cancellation stops subsequent filesystem work * - * `until()` stops Effection *observing* a promise; it does not cancel the work - * behind it. A fingerprint built on `Deno.readFile` and `crypto.subtle.digest` - * would therefore keep reading and hashing after its task was halted — a - * hundred-and-fifty-thousand-file walk that ignores cancellation. - * - * That rules out `@effectionx/fs` at this one boundary. Version 0.3.0 — - * the version this repository vendors — implements every operation as - * `until(fsp.…)` over `node:fs/promises` (`node_modules/@effectionx/fs/api.ts`), - * so `readdir`, `lstat`, and `readTextFile` are exactly the uncancellable - * adapters this module cannot use. Everywhere else in these scripts - * `@effectionx/fs` remains the way to touch the filesystem; the direct - * `Deno.*Sync` calls stop here. - * - * So the reads are `Deno.readFileSync`, `readLinkSync`, `readDirSync`, and - * `lstatSync`, and the digest is `node:crypto`'s synchronous SHA-256 — no less - * trustworthy than `crypto.subtle`'s, and it returns rather than resolving. - * - * Synchronous work still has to be interruptible, so the walk yields to the - * scheduler every `YIELD_EVERY` entries. A halt lands on one of those yields, - * and nothing after it reads or hashes anything. + * Filesystem operations may suspend, and `until()` does not cancel a host call + * already in flight. Once the walk is halted, no further read begins. SHA-256 + * hashing is synchronous, so a completed read leaves no background hash behind. + * The walk also yields every `YIELD_EVERY` entries to keep traversal interruptible. */ import { createContext, sleep, until } from "effection"; diff --git a/site/utils.ts b/site/utils.ts index f404216ed..10081988a 100644 --- a/site/utils.ts +++ b/site/utils.ts @@ -1,7 +1,5 @@ import { createDefine } from "fresh"; -// This specifies the type of "ctx.state" which is used to share -// data among middlewares, layouts and routes. export interface State { shared: string; } From 2bc1f2e4636bdd6333e4cbe686fc955258ca1e9c Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Wed, 14 Oct 2026 07:19:46 -0400 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=93=9D=20Clarify=20architecture=20and?= =?UTF-8?q?=20JSDoc=20terminology?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- architecture.md | 171 +++++++++--------- packages/acp/src/adapter-snapshots.ts | 66 +++---- packages/acp/src/provider.ts | 49 ++--- packages/acp/src/session-route.ts | 2 +- .../acp/tests/adapter-materialization.test.ts | 2 +- .../fixtures/claude-native-launch-proof.ts | 4 +- .../fixtures/claude-native-to-acp-proof.ts | 8 +- .../fixtures/codex-native-launch-proof.ts | 14 +- packages/acp/tests/fixtures/codex-surfaces.ts | 2 +- .../acp/tests/fixtures/npm-package-driver.mjs | 6 +- .../tests/fixtures/session-route-publisher.ts | 4 +- .../acp/tests/fixtures/terminal-screen.ts | 6 +- packages/acp/tests/helpers.ts | 2 +- packages/acp/tests/native-launch.test.ts | 21 ++- packages/acp/tests/provider.test.ts | 6 +- packages/cli/src/compiled-upgrade.ts | 2 +- packages/cli/src/packaged-document.ts | 2 +- packages/cli/src/plan-component.ts | 4 +- packages/cli/src/plan-writer-profile.ts | 2 +- packages/cli/src/plugin-host.ts | 4 +- packages/cli/src/repl/agent.ts | 4 +- packages/cli/src/repl/application.ts | 34 ++-- packages/cli/src/repl/components/rows.ts | 8 +- packages/cli/src/repl/description.ts | 10 +- packages/cli/src/repl/fitting.ts | 2 +- packages/cli/src/repl/frame.ts | 8 +- packages/cli/src/repl/input.ts | 8 +- packages/cli/src/repl/journal.ts | 3 +- packages/cli/src/repl/program.ts | 6 +- packages/cli/src/repl/reconcile.ts | 6 +- packages/cli/src/repl/renderer.ts | 2 +- packages/cli/src/run-profile.ts | 4 +- packages/cli/src/syntax.ts | 4 +- packages/cli/src/workflow-agent.ts | 2 +- packages/cli/src/workflow-bundle.ts | 2 +- .../tests/agent-session-coordinator.test.ts | 4 +- packages/cli/tests/compiled-upgrade.test.ts | 2 +- .../repl/issue-881/controlled-host.ts | 3 +- packages/cli/tests/fixtures/repl/reference.ts | 4 +- packages/cli/tests/fixtures/repl/surface.ts | 2 +- packages/cli/tests/github-zero-effect.test.ts | 2 +- packages/cli/tests/packaged-document.test.ts | 2 +- packages/cli/tests/plan-cli.test.ts | 2 +- .../cli/tests/plan-command-document.test.ts | 8 +- packages/cli/tests/plan-component.test.ts | 8 +- packages/cli/tests/plugin-host.test.ts | 4 +- .../cli/tests/repl-agent-execution.test.ts | 2 +- .../cli/tests/repl-agent-interface.test.ts | 6 +- packages/cli/tests/repl-agent-journey.test.ts | 4 +- packages/cli/tests/repl-boundaries.test.ts | 4 +- packages/cli/tests/repl-composition.test.ts | 2 +- packages/cli/tests/repl-entries.test.ts | 6 +- packages/cli/tests/repl-exit-pty.test.ts | 8 +- packages/cli/tests/repl-forms.test.ts | 2 +- packages/cli/tests/repl-journey.test.ts | 11 +- .../cli/tests/repl-layout-admission.test.ts | 3 +- packages/cli/tests/repl-model.test.ts | 2 +- .../cli/tests/repl-presentation-style.test.ts | 2 +- packages/cli/tests/repl-terminal.test.ts | 2 +- .../cli/tests/run-composition-deno.test.ts | 2 +- .../cli/tests/run-composition-nested.test.ts | 6 +- packages/cli/tests/run-composition.test.ts | 4 +- .../cli/tests/support/pull-request-server.ts | 2 +- packages/cli/tests/syntax-cli.test.ts | 3 +- packages/cli/tests/test-root-profile.test.ts | 2 +- packages/cli/tests/value-root.test.ts | 2 +- packages/cli/tests/workflow-agent.test.ts | 4 +- packages/cli/tests/workflow-cli.test.ts | 2 +- packages/cli/tests/workflow-crash.test.ts | 3 +- .../tests/workflow-export-publication.test.ts | 2 +- .../cli/tests/workflow-suspension.test.ts | 2 +- packages/code-review-agent/src/plugin.ts | 22 ++- .../src/review-components.ts | 17 +- packages/core/host.ts | 7 +- packages/core/src/agent/checkpoint.ts | 6 +- packages/core/src/agent/components.ts | 7 +- .../core/src/agent/configuration-record.ts | 8 +- .../core/src/agent/function-components.ts | 10 +- packages/core/src/agent/journal.ts | 5 +- packages/core/src/agent/launch-coordinator.ts | 2 +- packages/core/src/agent/launch-install.ts | 4 +- packages/core/src/agent/launch-journal.ts | 4 +- packages/core/src/agent/publication.ts | 3 +- packages/core/src/agent/session-use.ts | 36 ++-- packages/core/src/bound-exec.ts | 8 +- packages/core/src/component-answers.ts | 25 ++- packages/core/src/component-expansion.ts | 13 +- packages/core/src/components/Evaluate.ts | 4 +- packages/core/src/components/File.ts | 12 +- packages/core/src/components/Syntax.ts | 26 +-- packages/core/src/components/Test.ts | 14 +- packages/core/src/components/bundle.ts | 10 +- .../src/components/component-resolution.ts | 111 ++++++------ .../core/src/components/declared-markdown.ts | 22 +-- .../core/src/components/declared-registry.ts | 10 +- .../core/src/components/fixed-filesystem.ts | 4 +- packages/core/src/components/protected.ts | 65 +++---- packages/core/src/components/registry.ts | 4 +- packages/core/src/components/select.ts | 8 +- packages/core/src/document-targets.ts | 16 +- packages/core/src/errors.ts | 10 +- packages/core/src/evaluation-profile.ts | 26 +-- packages/core/src/execute.ts | 54 +++--- packages/core/src/execution-declarations.ts | 18 +- packages/core/src/expand.ts | 24 +-- packages/core/src/files.ts | 10 +- packages/core/src/generated-xmd.ts | 14 +- packages/core/src/glob-source.ts | 2 +- packages/core/src/inspect.ts | 10 +- packages/core/src/invocation-identity.ts | 104 ++++++----- packages/core/src/output/exact-source.ts | 16 +- packages/core/src/plugin-apis.ts | 3 +- packages/core/src/plugin.ts | 8 +- packages/core/src/projection.ts | 11 +- packages/core/src/return-flow.ts | 28 +-- packages/core/src/secrets/policy.ts | 2 +- packages/core/src/structural.ts | 7 +- packages/core/src/types.ts | 10 +- packages/core/src/validate.ts | 8 +- .../tests/agent-function-components.test.ts | 7 +- .../core/tests/agent-session-launch.test.ts | 2 +- .../agent-session-use-loaded-copy.test.ts | 2 +- packages/core/tests/agent-session-use.test.ts | 5 +- packages/core/tests/all.test.ts | 5 +- packages/core/tests/answer-identity.test.ts | 19 +- packages/core/tests/answers-component.test.ts | 9 +- packages/core/tests/capture-errors.test.ts | 6 +- packages/core/tests/component-returns.test.ts | 7 +- .../tests/construct-error-observation.test.ts | 14 +- .../tests/declared-markdown-component.test.ts | 26 +-- .../tests/document-target-execution.test.ts | 2 +- packages/core/tests/document-targets.test.ts | 6 +- packages/core/tests/eval-bindings.test.ts | 22 +-- .../core/tests/evaluate-component.test.ts | 7 +- .../core/tests/evaluate-loaded-copy.test.ts | 2 +- .../tests/evaluate-provider-lifetime.test.ts | 2 +- .../core/tests/expansion-identity.test.ts | 8 +- .../tests/fixed-filesystem-components.test.ts | 4 +- packages/core/tests/foreground-exec.test.ts | 14 +- .../core/tests/generated-composition.test.ts | 5 +- packages/core/tests/generated-xmd.test.ts | 10 +- .../core/tests/invocation-identity.test.ts | 35 ++-- packages/core/tests/loaded-copy-files.test.ts | 8 +- packages/core/tests/output-error-mode.test.ts | 8 +- .../tests/registered-printed-errors.test.ts | 11 +- packages/core/tests/root-composition.test.ts | 2 +- packages/core/tests/secret-detection.test.ts | 2 +- packages/core/tests/secret-rules.test.ts | 4 +- .../shared-operation-permissions.test.ts | 4 +- packages/core/tests/state-ownership.test.ts | 16 +- .../core/tests/support/answer-provider.ts | 43 ++--- packages/core/tests/syntax-component.test.ts | 8 +- .../core/tests/syntax-loaded-copy.test.ts | 14 +- packages/durable-streams/guard.ts | 2 +- packages/durable-streams/replay-index.ts | 2 +- packages/durable-streams/retained.ts | 8 +- packages/git/src/composition/api.ts | 6 +- packages/git/src/composition/git-api.ts | 2 +- .../git/src/composition/git-push-records.ts | 10 +- packages/git/src/composition/installation.ts | 6 +- packages/git/src/composition/parse.ts | 2 +- .../composition/pull-request-read-records.ts | 2 +- .../src/composition/pull-request-records.ts | 2 +- .../src/deno/composition/authentication.ts | 10 +- packages/git/src/deno/composition/commit.ts | 2 +- packages/git/src/deno/composition/git.ts | 21 +-- .../deno/composition/github-pull-request.ts | 2 +- .../git/src/deno/composition/operations.ts | 10 +- packages/git/src/deno/composition/provider.ts | 6 +- .../deno/composition/pull-request-evidence.ts | 2 +- .../deno/composition/pull-request-reads.ts | 4 +- packages/git/src/deno/composition/push.ts | 5 +- .../git/src/deno/composition/repository.ts | 10 +- .../src/deno/run-composition/operations.ts | 2 +- .../src/deno/run-composition/pull-request.ts | 2 +- packages/git/src/deno/selections.ts | 2 +- packages/git/src/git-host/identities.ts | 4 +- packages/git/src/git.ts | 6 +- packages/git/src/issue/identities.ts | 2 +- .../git/tests/ambient-authentication.test.ts | 17 +- packages/git/tests/api-entrypoint.test.ts | 2 +- packages/git/tests/git-add-durability.test.ts | 8 +- packages/git/tests/git-add.test.ts | 8 +- .../git/tests/git-commit-durability.test.ts | 4 +- packages/git/tests/git-push-crash.test.ts | 10 +- .../git/tests/git-push-durability.test.ts | 22 +-- packages/git/tests/git-push.test.ts | 10 +- .../git/tests/git-switch-durability.test.ts | 25 ++- .../git/tests/github-pull-requests.test.ts | 6 +- packages/git/tests/issue-records.test.ts | 4 +- packages/git/tests/materialization.test.ts | 6 +- packages/git/tests/module-partition.test.ts | 8 +- packages/git/tests/plugin.test.ts | 2 +- packages/git/tests/pull-request-crash.test.ts | 10 +- .../git/tests/pull-request-durability.test.ts | 14 +- packages/git/tests/pull-request-read.test.ts | 8 +- .../git/tests/pull-request-records.test.ts | 12 +- .../git/tests/repository-components.test.ts | 6 +- .../tests/repository-materialization.test.ts | 15 +- .../git/tests/run-composition-ambient.test.ts | 2 +- .../git/tests/run-composition-lazy.test.ts | 2 +- .../git/tests/run-composition-managed.test.ts | 8 +- packages/git/tests/support/composition.ts | 15 +- packages/git/tests/support/git-remotes.ts | 6 +- packages/git/tests/support/github.ts | 2 +- packages/git/tests/support/issue-providers.ts | 2 +- packages/git/tests/support/replay.ts | 16 +- .../tests/support/run-composition-child.ts | 2 +- .../git/tests/support/run-composition-tier.ts | 2 +- packages/git/tests/support/run-composition.ts | 20 +- packages/runtime/apis.ts | 8 +- packages/runtime/files.ts | 10 +- packages/runtime/tests/fetch.test.ts | 2 +- packages/runtime/tests/host-files.test.ts | 16 +- packages/test-agent/src/worker/acp-server.ts | 6 +- .../tests/cross-package-resolution.test.ts | 11 +- packages/test-support/journal.ts | 6 +- packages/testing/src/activation.ts | 14 +- packages/testing/tests/test-component.test.ts | 5 +- packages/web/src/declaration.ts | 4 +- packages/web/tests/component-support.ts | 4 +- packages/web/tests/declaration.test.ts | 2 +- packages/web/tests/markdown.test.ts | 3 +- packages/workflow/deno.ts | 3 +- packages/workflow/src/bundle.ts | 4 +- packages/workflow/src/deno/advisory-lock.ts | 9 +- .../workflow/src/deno/artifact/records.ts | 15 +- packages/workflow/src/deno/artifact/schema.ts | 12 +- packages/workflow/src/deno/artifact/source.ts | 2 +- packages/workflow/src/deno/artifact/types.ts | 4 +- packages/workflow/src/deno/artifact/write.ts | 10 +- .../workflow/src/deno/definition-source.ts | 2 +- packages/workflow/src/deno/delivery.ts | 2 +- .../workflow/src/deno/provider-sessions.ts | 6 +- packages/workflow/src/deno/schema.ts | 10 +- .../src/deno/workspace/agent-checkpoints.ts | 2 +- .../src/deno/workspace/agent-sessions.ts | 4 +- packages/workflow/src/deno/workspace/files.ts | 8 +- packages/workflow/src/journal.ts | 11 +- packages/workflow/src/lifecycle/api.ts | 4 +- packages/workflow/src/lifecycle/source.ts | 2 +- packages/workflow/src/run.ts | 2 +- packages/workflow/src/storage/errors.ts | 10 +- packages/workflow/src/storage/record.ts | 6 +- packages/workflow/src/suspension/answer.ts | 2 +- packages/workflow/src/suspension/api.ts | 13 +- .../workflow/src/suspension/elicitation.ts | 6 +- packages/workflow/src/suspension/suspend.ts | 2 +- .../tests/generated-agent-component.test.ts | 12 +- .../tests/support/artifact-fixture.ts | 4 +- .../workflow/tests/support/restart-child.ts | 10 +- .../tests/workflow-agent-checkpoints.test.ts | 10 +- .../tests/workflow-checkpoint.test.ts | 12 +- .../tests/workflow-definition.test.ts | 4 +- .../workflow-lifecycle-authority.test.ts | 5 +- .../workflow-lifecycle-inspection.test.ts | 8 +- .../tests/workflow-run-storage.test.ts | 2 +- .../tests/workflow-suspension-answer.test.ts | 4 +- .../tests/workflow-suspension.test.ts | 2 +- .../workspace-effect-transaction.test.ts | 8 +- .../workflow/tests/workspace-files.test.ts | 2 +- packages/workflow/tests/xmd-artifact.test.ts | 2 +- scripts/files-contract-probe.ts | 3 +- scripts/lib/compile.ts | 2 +- scripts/lib/consumer-cycle.ts | 2 +- scripts/lib/main-green.ts | 2 +- scripts/lib/test-files.ts | 2 +- scripts/lib/verify.ts | 3 +- scripts/lib/version-lockstep.ts | 2 +- scripts/main-green.ts | 2 +- scripts/measure-test-weights.ts | 2 +- .../oxlint-rules/no-module-scoped-registry.js | 2 +- scripts/smoke-documentation.ts | 2 +- scripts/smoke-fetch.ts | 2 +- scripts/smoke-foreground.ts | 2 +- scripts/smoke-run-composition.ts | 2 +- scripts/tests/adapter-distribution.test.ts | 4 +- scripts/tests/build-web-client.test.ts | 2 +- scripts/tests/ci-workflow.test.ts | 2 +- scripts/tests/cli-npm-bin.test.ts | 2 +- .../filesystem-contract-workflow.test.ts | 4 +- .../tests/jsr-consumer-documentation.test.ts | 2 +- scripts/tests/main-green.test.ts | 3 +- scripts/tests/plan-component-compiled.test.ts | 5 +- scripts/tests/plugin-compiled.test.ts | 3 +- scripts/tests/prepared-state.test.ts | 3 +- scripts/tests/runtime-tests.test.ts | 4 +- scripts/tests/shard-execution.test.ts | 2 +- scripts/tests/verify-clean.test.ts | 2 +- scripts/verify-clean.ts | 6 +- site/components/Prose.tsx | 2 +- 291 files changed, 1324 insertions(+), 1281 deletions(-) diff --git a/architecture.md b/architecture.md index a69d83e9b..734a1f10e 100644 --- a/architecture.md +++ b/architecture.md @@ -39,7 +39,7 @@ and categorization rather than clarify them, so both stay exactly as written. | 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 claims 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 claim 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 | +| 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 | @@ -56,7 +56,7 @@ and categorization rather than clarify them, so both stay exactly as written. | 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, claimed 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 | +| 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 | @@ -102,7 +102,7 @@ and categorization rather than clarify them, so both stay exactly as written. | 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, which it does not claim: an interruption before its record commits may repeat the read | +| 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 | @@ -119,7 +119,7 @@ and categorization rather than clarify them, so both stay exactly as written. | 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 claim 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 | +| 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 | @@ -138,12 +138,12 @@ and categorization rather than clarify them, so both stay exactly as written. | 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 claiming 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 | +| 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 claim on it is atomic, so a second executed return fails the body rather than replacing its value, and it appends no durable event | +| 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 @@ -193,7 +193,7 @@ creates no workflow run and the root document does not expand. `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 claim about a repository the run never had. It neither creates nor +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. @@ -501,7 +501,7 @@ value that describes nothing, or unable to transact. Collapsing them would leave a host guessing whether to create, refuse, or report damage. Recognizing storage means holding its structure to the one this build writes, -not reading the names of its parts. Storage whose own header claims a version +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. @@ -570,7 +570,7 @@ definition as a `components` array in canonical order — so each declared path 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 claim structural syntax, a component the +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. @@ -741,7 +741,7 @@ through an adapter-private provider operation, just as Workspace transaction ownership is validated behind its provider-neutral selection. Inspection, cancellation and deletion return immutable parsed values and no database, stream, transaction or connection capability. `WorkflowDeletion` lists -categories actually removed; it contains no claim about external effects. +categories actually removed; it contains no statement about external effects. Acquisition has three observable outcomes: acquired, already held by a live workflow executor, or a storage/authorization failure. The initial local CLI @@ -792,11 +792,11 @@ and lock teardown leaves the run recoverable by the next proven workflow executor. Teardown is part of settlement evidence, not work performed after the outcome. -If teardown raises, the host does not claim `suspended`: the +If teardown raises, the host does not report `suspended`: the execution settles `failed` with a filtered journal reason when one identifies the failure and a categorical host reason otherwise. Durability and Files infrastructure failures still cross by identity and win by kind; if their -lifecycle transition cannot persist, no terminal status is claimed. Every +lifecycle transition cannot persist, no terminal status is reported. Every finalizer is attempted before any such result is observable. Retained lifecycle state gates every later acquisition before canonical @@ -1044,7 +1044,7 @@ provider-owned retained records are removed. Only the empty lock file may remain. Every non-live status may be deleted. The explicit run ID is the confirmation boundary, so the command has no interactive prompt and no wildcard. An absent run is reported rather than treated as an idempotent -deletion. Deletion never claims to undo an external effect. +deletion. Deletion does not report that it undid an external effect. ## Durable suspension @@ -1070,7 +1070,7 @@ replay and a different logical wait cannot receive its input. The operation first publishes an ordinary durable `suspension_request` Yield. Its description contains the suspension ID, request and response schema. Its successful Result means only that the request publication committed; it does -not claim that the wait or answer completed. The complete event crosses the +not establish that the wait or answer completed. The complete event crosses the existing secret gate and receives the current Workspace-root association in the same way as every other nonmutating event. The run's stop reason references that already-filtered event by ID, so request text is never duplicated into @@ -1418,7 +1418,7 @@ answers is infrastructure rather than a finding about the remote. The relation, not the traversal that found it, is what the record keeps. The Workspace transaction such an effect opens is read-only and is -closed before the host is observed: no transaction is claimed across the +closed before the host is observed: no transaction is held across the Workspace and the external service, and reconciliation rather than a distributed transaction is what makes an interrupted attempt reach the host once. @@ -1713,8 +1713,9 @@ member, a declared Markdown component, a middleware replacement and a definition from a second loaded copy are each refused where they are made. The two groups differ only in where the implementation comes from. Syntax and -Evaluate are built per execution from a claimant that execution minted, because -each is handed a site canonical execution built for it. File, File.Delete and +Evaluate are built per execution from an invocation authenticator that execution +minted, because each is handed a site canonical execution built for it. File, +File.Delete and Dir are ordinary components whose bodies reach the filesystem through contextual `API.Files`, so each is one definition built once per loaded copy of core and answered with as it stands — which is also the definition the @@ -2007,7 +2008,7 @@ not hidden host prompts. > Plan remains source and is not executed during planning. The mixed File/Glob/Syntax example above accompanies this instruction. There is -no claim that the Agent can use native tools or ask for additional permissions. +no guarantee that the Agent can use native tools or ask for additional permissions. **Successful follow-up prompt:** @@ -2033,8 +2034,8 @@ value explicitly with `Json`. > Plan authorship reached the limit of 8 XMD information requests before a Plan > was approved. No Plan was returned. Start again with a more specific prompt. -The command adds `Nothing was output.`; the embedded component adds no command -output claim. Neither surface starts a ninth evaluation or another turn. +The command adds `Nothing was output.`; the embedded component adds no sentence +about command output. Neither surface starts a ninth evaluation or another turn. **Stale continuation:** @@ -2185,7 +2186,7 @@ authored fragment renders; its own durable effect record remains the account of what it did. An admitted effect names its durable operation after the invocation the engine -handed it, through the claimant this execution delivered to the protected +handed it, through the invocation authenticator this execution delivered to the protected `` body it built (*Capability-backed invocation identity*). Nothing else carries the capability: an Effection Context is addressed by name, a contextual Api handler installed outside an invocation answers ahead of the engine's own, @@ -2225,7 +2226,7 @@ under the exact identities it was admitted with. authored Markdown owns iteration with ``, branches on whether a reply is another information request or a final proposal, and makes exhaustion an explicit document failure. `` is canonical core's own protected -component, claimed ahead of every host and author tier, so the name means the +component, reserved ahead of every host and author tier, so the name means the same thing in every execution and no registration, repository file, bundle member, declared Markdown component, import handler or second loaded copy answers for it. A host does not supply the component; it supplies the @@ -2300,7 +2301,7 @@ assertion conflicting with what is retained, one that replaced it, and more than one at once each refuse. Once the mapping has committed, a restart compares the provider's current assertion against it before continuing, and reattaches only when the kind and the value both still agree. No refusal substitutes a new -session or a reconstructed transcript while claiming continuity. +session or a reconstructed transcript while reporting continuity. Cancellation owns both sides of a live step. It stops the Prompt stream or the generated-XMD evaluation, completes provider and evaluator teardown, and removes @@ -2546,7 +2547,7 @@ live references, projection handles or callables. Completed replay performs fresh installation and identity attestation, then restores historical rendered output without repeating fragment bodies, Syntax documentation lookups, File reads or Glob traversal. Missing or invalid current -attestation refuses before those effects. It does not reuse an expired claim +attestation refuses before those effects. It does not reuse an expired attestation or refresh information to validate history. One narrow namespaced classification identifies the normalized recoverable @@ -2866,7 +2867,7 @@ request and the public chain composes around it; a handler delegates that exact request once with `next(request)`. The authority is the shape bound execution already uses. The request is branded -with a private field, so a copy carrying the same members is not it; the claim +with a private field, so a copy carrying the same members is not it; the request is spent once, so a repeated delegation runs nothing; and the settlement is readable whether or not the chain returned normally, so a handler that catches what canonical expansion raised has not rescued it. A handler that returns @@ -3107,7 +3108,7 @@ not resolving the parent would miss a directory link leading out. A working directory that names itself is classified directly rather than through its parent, which is otherwise outside it. -The two providers make different containment claims, and both are stated rather +The two providers make different containment guarantees, and both are stated rather than implied: - **`xmd run`** resolves document paths in the caller's own filesystem. The @@ -3118,7 +3119,7 @@ than implied: relative target from the enclosing cwd. It creates directly and enlists in no transaction, so directories it created persist after the component and the document end — including when later content fails or is cancelled — and a - recursive attempt is never rolled back or removed by teardown. These claims + recursive attempt is never rolled back or removed by teardown. These guarantees hold while the host namespace is stable; this is not a sandbox, and closing the replacement window would require a native dependency this project does not take. @@ -3127,7 +3128,7 @@ than implied: never becomes a host path, so there is no host namespace to replace. An absolute Dir target is an absolute logical Workspace path, never a host path. -Neither claim covers a native command a document runs. +Neither guarantee covers a native command a document runs. The workflow provider's operations are durable effects. A read, a write, a directory ensure, a deletion and a search each carry a description derived from @@ -3213,7 +3214,7 @@ replay remains aligned, while retained history containing a now-incompatible successful eval is rejected by the existing replay guard or divergence path. Every root and child termination checks its retained subtree before appending a `Close`. The replay index tracks which coroutine identities the current -definition claims, so a completed retained child is not mistaken for aligned +definition uses, so a completed retained child is not mistaken for aligned history merely because it already has a `Close`. Durability failures take precedence over ordinary termination even after the last retained `Yield` was consumed. If collision handling terminates immediately, @@ -3270,7 +3271,7 @@ 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 claim a value +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 @@ -3279,7 +3280,7 @@ 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`. -The first executed `` claims the state before evaluating its expression, +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 @@ -3299,8 +3300,8 @@ carrier itself is sealed, because the document calls the engine's own helper wit the engine's own carrier. So selection uses neither. The body that owns a value is a plain object whose -claim, selection and settlement are closures over state nothing else holds, and -it reaches the `` that claims it as an ordinary parameter of expansion — +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 @@ -3342,7 +3343,7 @@ switch renders nothing and reports nothing. 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 -`` claims the value body that owns the switch, a `` exits the +`` 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. @@ -3436,7 +3437,7 @@ concerned. What a run retains is therefore what its **configured execution environment** forwarded. `xmd run --journal` is diagnostic persistence: it records what that environment forwarded, not what a child wrote to its pipe, which nothing here -observes and nothing here claims. A workflow's process results are durable +observes and nothing here guarantees. A workflow's process results are durable within the environment the workflow authorized. Middleware enclosing an execution — the host's own, and anything the host composed into it — may preprocess that output before either sees it. @@ -3445,7 +3446,7 @@ preprocess that output before either sees it. `Stdio` middleware finish, so output a child writes as the pumps settle may never reach the boundary and may therefore be absent from what a run retains. effectionx #244 owns that, and until its solution is integrated nothing here -claims pump-complete tail delivery or retention. +guarantees pump-complete tail delivery or retention. So transformed text is what a run captures and journals, consumed output is absent from both, and output an enclosing handler forwards on the other channel is recorded as that other channel. @@ -3458,8 +3459,8 @@ guarantee gets today: `Process.join()` may settle before the stdout and stderr pumps and their `Stdio` middleware have finished, so output written as the pumps settle may never reach this boundary. effectionx #244 owns the stronger guarantee. "Exactly what the command produced" means, throughout this -repository, *exactly the bytes received here* — never a claim about what the -child wrote to its pipe, which no execution observes, and never a claim of +repository, *exactly the bytes received here* — never a guarantee about what the +child wrote to its pipe, which no execution observes, and never a guarantee of pump-complete tail delivery. **A run's own display policies are downstream and change nothing.** `silent`, a @@ -3561,7 +3562,7 @@ The public `testing` boolean and the recording middleware around it remain composable policy, and stay useful as policy: a handler may narrow testing to false, observe a result, refuse, and wrap recording. They are not activation activation, and neither is a stable contextual or Api name — a name is the -routing every loaded copy shares, and treating it as the claim would let +routing every loaded copy shares, and treating it as the authentication would let anything able to spell it declare a complete boundary. What a `` requires instead is a conjunction of a private one-use request, a private live boundary credential, and the acceptance record of a terminal created for that one call: @@ -3948,7 +3949,7 @@ what the process settled to. Neither is block data. `Component.applyModifiers` and `Component.codeBlock` are supported override surfaces, and what passes through them is middleware's to rewrite or to answer. So a bound block is asked for through `applyBoundModifiers`, with a one-use -request canonical core issues and claims. The request retains the authored +request canonical core issues and consumes. The request retains the authored modifier chain and the block context; both are frozen when it is issued. Public middleware composes around the operation on the same terms it composes anywhere: it may observe the request, refuse by throwing, and delegate. It @@ -3990,11 +3991,11 @@ components name durable work, on the terms every other trusted-host value travels: read once and copied before any installation runs, so what may name durable work is fixed before installed code, middleware or a document exists (*Trusted host orchestration*). The execution mints one domain per declared -component, calls that component's factory with the domain's **claimant**, and -registers what the factory returns through the ordinary path — validated like +component, calls that component's factory with the domain's **invocation +authenticator**, and registers what the factory returns through the ordinary path — validated like any registration, and activated only once that batch has committed, so a refused -registration leaves a claimant that answers for nothing. The claimant exists as -the argument of that one call: not published, not named, not reachable from a +registration leaves an invocation authenticator that answers for nothing. It +exists as the argument of that one call: not published, not named, not reachable from a document, and not derivable from anything a handler holds. **The invocation carries one readable fact, for the same reason.** How the @@ -4010,7 +4011,7 @@ immutable, projecting nothing and spending no identity, held as owner-kept state inside canonical core and reachable only through the object the engine minted. There is no context, map, registry entry or exported lookup beside it, and implementing the method does not make an object an invocation — durable identity -remains the private field a claimant recognizes. +remains the private field an invocation authenticator recognizes. Reading the method is not authenticating the object, and neither is a component able to authenticate it. A component is handed whatever its caller passes, so a @@ -4130,18 +4131,18 @@ Canonical answer windows are owned the same way and by the same kind of value an explicit object rather than a scope — but serially: component answers are resolved in one capture phase before any document expands, so one window is open at a time. Each provider request captures that window object before its handler -runs, a claim states it back explicitly, and a handler delegating through a +runs, a registration states it back explicitly, and a handler delegating through a descendant scope answers the resolution it was opened in. One installation may answer more than one import with the same definition — a reusable provider owns -one object and a claim is per window — and a second, *different* answer in +one object and a registration is per window — and a second, *different* answer in either still refuses. Concurrent document imports happen after capture, with no window open at all: such an import may be answered as ordinary middleware, and acquires no profile identity. The engine then mints one issuance per invocation, carrying that domain — or none — the authored name for what a refusal says, and the frame the body is -about to run in. A claimant answers only for an issuance that satisfies all of -it: +about to run in. An invocation authenticator answers only for an issuance that +satisfies all of it: - **its own execution's**, still running — an implementation kept past teardown, or built by another attachment, answers for nothing; @@ -4321,7 +4322,7 @@ can read, transport or remove the collection. A declared component travels the same way and for the same reason. What the host supplies is a factory, not an implementation: the execution calls it with the -claimant it minted for that component, so the capability is delivered as the +invocation authenticator it minted for that component, so the capability is delivered as the argument of one call the execution makes, and what a document, a component or middleware can reach afterwards is the implementation alone (*Capability-backed invocation identity*). A host that declares none has no component that can name @@ -4484,7 +4485,7 @@ they did not ask for. `git` is a reserved *host selector*, not a package name: writing `--plugin git` names the value the profile already holds, resolves without loading a module, -and is a no-op however many times it appears. A module that merely claims the +and is a no-op however many times it appears. A module that merely uses the same Plugin name is not that value — it loads like any other specifier and is refused as a duplicate. @@ -4538,7 +4539,7 @@ that happens before anything can look at what it exported. Selected Plugin code can execute whatever the surrounding runtime permits. The engine refuses a *malformed* Plugin — a module exporting no default, a default carrying no name, an `install` -that is not callable, two selections claiming one name — and it refuses them +that is not callable, two selections using one name — and it refuses them before any `install()` runs and before a root document is read. It constrains a well-formed one not at all, and none of this is a permission boundary. @@ -4557,13 +4558,13 @@ because this boundary fetches no code. Specifiers resolve from the invocation's own captured working directory rather than from the CLI module, so a global install, an npm install and a compiled binary agree about what one name means. V1 performs no ambient or document-declared discovery — that is a decision about -what V1 does, not a claim that discovery can never be added. +what V1 does, not a guarantee that discovery can never be added. **Order composes and never arbitrates.** The bundled Plugin installs first where the profile carries it, then the selections in occurrence order, and the first Plugin installed is the outermost middleware wrapper. Position decides nothing else: two Plugins -claiming one Plugin name, one component name, one structural construct or one +reserving one Plugin name, one component name, one structural construct or one documentation contribution are refused at admission, exactly as two trusted hosts already were. @@ -4710,14 +4711,14 @@ the return and the accepted forms. Canonical core parses that source and refuses the declaration when the digest is not the digest of those bytes, when a stated schema is not the schema they declare, when the forms are not canonical, when the name is not a component name or is structural syntax, when one name is -declared twice, or when a reserved registration already claims it. A build that +declared twice, or when a reserved registration already reserves it. A build that ships different bytes under a declared name therefore fails where it is installed rather than where a document happens to write the name. -**The name is claimed, not offered.** Resolution places a declared component in +**The name is reserved, not offered.** Resolution places a declared component in the same host tier as a reserved registration, above the workflow component bundle, repository files and every registered default — and below the canonical -protected tier, which is the engine's own claim rather than a host's. Two claims +protected tier, which is the engine's own reservation rather than a host's. Two reservations on one name are refused rather than ordered, so the tier never chooses. A repository `Policy.md`, a bundled `Policy`, an ordinary registration and another loaded copy of the host package can none of them answer for a declared `Policy`; @@ -4753,7 +4754,7 @@ replaced nothing. **The private closure is lexical and expansion-scoped.** A declaration's private components are minted exactly like the identity components a host declares — -one domain, one claimant, revoked when the execution is torn down — and then +one domain, one invocation authenticator, revoked when the execution is torn down — and then registered nowhere. Canonical core offers one for the duration of one import, from the closure the segments being expanded carry, and the resolver takes it once. Content the caller projected expands through the invocation's projection @@ -4791,18 +4792,18 @@ asking for it is inside the same declaration. a program's source or presented as prose is decided from two things no answer can write: that canonical execution authorized the import for a name this execution closed, and that the host's own admitted declaration for that name -states it. A definition carrying the claim, a segment arriving already marked, a +states it. A definition carrying the disposition metadata, a segment arriving already marked, a frontmatter key and a middleware answer are each data that reached the engine from somewhere, so none of them decides it — an ordinary `Component.importComponent` handler answering an open name with a definition -claiming the disposition publishes prose, exactly as a repository file of that +stating the disposition publishes prose, exactly as a repository file of that name does. The record of which segments an expansion produced as source belongs to the execution that made it and is handed down **by value** on canonical core's private execution environment. Not through a context: a context resolves by name, and a name is not a secret, so a component could build one, reach the record and -answer that everything is exact. It is reclaimed with its execution, reaches no +answer that everything is exact. It is released with its execution, reaches no public entrypoint, and marks nothing on the segments themselves. ### The review graph is the mechanism's first whole consumer @@ -4856,18 +4857,18 @@ narrower one that would refuse a program the run would have accepted, and the three checks inside one Plan command consume one retained assembly rather than reinstalling and re-reading every packaged asset. -The Plugin claims the forty-one names for the commands that can run a review — +The Plugin reserves the forty-one names for the commands that can run a review — `run`, `syntax`, `plan`, and a `workflow` action that executes a document — and returns nothing for the rest. `xmd test` at its root is a different profile and gains none of it; the nested `` child it can launch installs the same Plugin values again with command `run` and gains all of it. **What it does not change.** Ordinary inclusion and repository discovery are -untouched. A caller's own component of an unclaimed name resolves as it always -did; only these forty-one names are spoken for. The claims do include generic +untouched. A caller's own component of an unreserved name resolves as it always +did; only these forty-one names are spoken for. The reserved names do include generic ones — `Format`, `Pattern`, `Threshold`, `Instruction`, `Sample` — which is the intended consequence of the anti-shadowing contract rather than an oversight, and -a collision with another host claim is refused at assembly rather than settled by +a collision with another host name reservation is refused at assembly rather than settled by order. **One deliberate duplication.** The package ships its own copies of `Sample.md` @@ -4914,7 +4915,7 @@ at admission. The association is a field of that entry rather than an entry in a registry, a contextual slot or a second dispatch protocol, so the only way to reach a handler is to hold the catalog canonical core built. -**The name is claimed on the declared-Markdown terms.** A declared construct +**The name is reserved on the declared-Markdown terms.** A declared construct answers ahead of the workflow component bundle, repository files and every registered default, and never over the engine's own structural table or the canonical protected tier. One name is declared once across both arms and across @@ -5011,7 +5012,7 @@ never becomes an ordinary failure. ## The canonical protected tier Resolution already had a protected tier — a reserved registration, or exact -Markdown a host declared. Both of those are *a host's* claim, made by whoever +Markdown a host declared. Both of those are *a host's* name reservation, made by whoever assembled the run. Above them sits the engine's own, and a name in it means the same thing in every execution: whichever host built it, whichever package registered what, and whatever the repository holds. @@ -5029,14 +5030,14 @@ every host or author tier, and consulted unconditionally: no option a caller passes — or leaves out — puts a repository file, a bundle member or a registration in front of it. -Collision is refused where each claim is made, so the tier never has to choose: +Collision is refused where each name reservation is made, so the tier never has to choose: a registration under the name is refused atomically at registration, a host's declared Markdown and a workflow bundle member are each refused at admission before the root import, and a repository `Syntax.md`, `Syntax.ts` or directory candidate is never probed for because selection has already answered. **Invocation is canonical.** The execution mints one identity domain per -protected component, calls its factory with that domain's claimant, and registers +protected component, calls its factory with that domain's invocation authenticator, and registers what comes back nowhere. Import is closed for exactly those names, on the terms a declaration's names are closed: `Component.importComponent` middleware may observe the import, delegate it and refuse it by throwing, and what it cannot do @@ -5065,7 +5066,7 @@ imports still require their own settled selection frame; a routed function cannot repair a missing or multiply selected domain. Paired producers retain their lexical site route and operational permission. -A trusted provider may therefore delegate and claim canonical self-closing +A trusted provider may therefore delegate and register canonical self-closing `` as a component answer. Its bare form reports the admitted vocabulary; its named form renders the enclosing authoring documentation with narrowed availability. Verified protected documentation provenance survives sealing even @@ -5164,7 +5165,7 @@ kind, `protected`, rather than borrowing `registered` with `reserved: true`. The two answer a reader's actual question — *could I supply this name myself?* — oppositely: a reserved registration is a host installing something under a name it wants kept, so it can be absent from another run, replaced by a different -host, or refused when two hosts claim it, and none of that is true here. A +host, or refused when two hosts reserve it, and none of that is true here. A workflow bundle member gained its own kind for the same reason: reported as a `repository` path it read as a file the reader could edit, when it is the exact blob `sourceHash` names, fixed when the run was defined. Both are why the symbols @@ -5177,7 +5178,7 @@ and no implementation to serialize, so the record says only which tier answered and replay asks the running execution for the implementation it built. An execution that built none refuses rather than resolving the name again, because a replay that fell back to the ordinary tiers would run whatever is offered under -that name today. Each occurrence then claims the identity this execution minted, +that name today. Each occurrence then authenticates against the identity this execution minted, performs one `syntax_symbols` read, and retains a closed value carrying exactly one member — `{ symbols: string }` for a successful rendering, or `{ refused: non-empty string }` for a named selection canonical core refused. @@ -5271,7 +5272,7 @@ selected, so an entry absent from that admission is absent from the reference. only the declarative registration layer selection needs. It does not enter `execute()`, construct a durable stream, install a Files, Service, Agent or elicitation provider, start testing, reserve the terminal, mint an invocation -claimant, call an identity component's factory, or expand a body. `` is +invocation authenticator, call an identity component's factory, or expand a body. `` is described from the plain declaration a host would make; the factory that names durable work is reached only by a real execution. @@ -5431,7 +5432,7 @@ Status is measured against main. | Construct | Does | Status | | --- | --- | --- | | `xmd syntax` | describes every structural construct and every selected component the production `run` profile would let a document write in the contextual working directory, as deterministic Markdown or as version-2 JSON, from one construction. `xmd syntax Elicit` names one component instead and renders its symbol metadata followed by the long-form documentation the owning package ships, through the same selection, index and renderer `` uses. Inspection only: it registers the run profile's declarations in a bounded scope and reads the filesystem for which files exist and, for a selected Markdown component, that file's frontmatter. It runs no body, imports no repository TypeScript module, installs no provider, mints no capability and writes no journal. An include it cannot enumerate — a selection-relevant symbolic link to a directory beneath it included — fails the whole request rather than printing a healthy subset. The Markdown renderer is core's rather than this command's, because canonical `` prints the same symbols for a running document and the two must be the same bytes for the same site | built on the #632 stack, with the shared Markdown renderer added on this stack | -| `` | outputs the components and control-flow constructs a document may write at the site it is written at, as the Markdown `xmd syntax` prints — one construction and one renderer, so an operator and an agent are never told different things about one profile. Self-closing only, with one optional closed `names` prop, and a text component: the bare form lists the symbols available here, `` renders those components' metadata and the long-form documentation their owning package ships, and the ordinary `as` captures the same text and emits nothing — while a paired spelling, an unknown prop, an empty list, a duplicate or a non-string member refuses before anything is claimed or read. It is the one member of the canonical protected tier, resolved after structural syntax and ahead of every host or author tier: a repository `Syntax.md`, a bundled `Syntax`, an ordinary or reserved registration, a host's declared Markdown and an implementation from a second loaded copy can none of them answer for it, and `Component.importComponent` middleware may observe, delegate or refuse the import without being able to answer one. What the symbols say is the execution's own — built 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 — and they are carried lexically on canonical core's execution environment rather than through any context. The documentation the named form reads is collected the same way: each package's bootstrap contributes its own through the additive `Documentation` Api, canonical core is the terminal, and the execution collects once after the trusted host's bootstrap and snapshots by value before the root import, so middleware a running document installs composes into a chain nothing reads and two contributions that disagree about one owning package and component name refuse at collection whichever order they were bootstrapped in, while a repetition of the same four values — owner, asset, exact text and component set — adds nothing and succeeds, because one package is deliberately bootstrapped at more than one layer. Each occurrence claims the identity the execution minted, performs one `syntax_symbols` read, and retains a closed value carrying exactly one member — `{ symbols: string }` for a successful rendering, or `{ refused: non-empty string }` for a named selection canonical core refused, interpreted only after publication succeeds so it means the same thing live and on replay; a continuation hostile-parses that record and answers from it without rediscovering a moved environment, while existing `{ symbols }` histories stay readable and a missing, additional, mistyped, empty or simultaneous member is stale input that refuses before output or binding. A cancelled read completes its teardown and commits nothing. It reports itself under its own origin kind, `protected`, never as a reserved registration, and selection records `{ kind: "protected" }` alone — replay asks this execution for the implementation it built rather than resolving the name again. It decides nothing at all: a component the symbols name is neither registered, resolved nor authorized by being named | built on this stack; the narrower reference a trusted evaluation boundary installs for its subtree is the seam #713 fills | +| `` | outputs the components and control-flow constructs a document may write at the site it is written at, as the Markdown `xmd syntax` prints — one construction and one renderer, so an operator and an agent are never told different things about one profile. Self-closing only, with one optional closed `names` prop, and a text component: the bare form lists the symbols available here, `` renders those components' metadata and the long-form documentation their owning package ships, and the ordinary `as` captures the same text and emits nothing — while a paired spelling, an unknown prop, an empty list, a duplicate or a non-string member refuses before anything is authenticated or read. It is the one member of the canonical protected tier, resolved after structural syntax and ahead of every host or author tier: a repository `Syntax.md`, a bundled `Syntax`, an ordinary or reserved registration, a host's declared Markdown and an implementation from a second loaded copy can none of them answer for it, and `Component.importComponent` middleware may observe, delegate or refuse the import without being able to answer one. What the symbols say is the execution's own — built 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 — and they are carried lexically on canonical core's execution environment rather than through any context. The documentation the named form reads is collected the same way: each package's bootstrap contributes its own through the additive `Documentation` Api, canonical core is the terminal, and the execution collects once after the trusted host's bootstrap and snapshots by value before the root import, so middleware a running document installs composes into a chain nothing reads and two contributions that disagree about one owning package and component name refuse at collection whichever order they were bootstrapped in, while a repetition of the same four values — owner, asset, exact text and component set — adds nothing and succeeds, because one package is deliberately bootstrapped at more than one layer. Each occurrence authenticates against the identity the execution minted, performs one `syntax_symbols` read, and retains a closed value carrying exactly one member — `{ symbols: string }` for a successful rendering, or `{ refused: non-empty string }` for a named selection canonical core refused, interpreted only after publication succeeds so it means the same thing live and on replay; a continuation hostile-parses that record and answers from it without rediscovering a moved environment, while existing `{ symbols }` histories stay readable and a missing, additional, mistyped, empty or simultaneous member is stale input that refuses before output or binding. A cancelled read completes its teardown and commits nothing. It reports itself under its own origin kind, `protected`, never as a reserved registration, and selection records `{ kind: "protected" }` alone — replay asks this execution for the implementation it built rather than resolving the name again. It decides nothing at all: a component the symbols name is neither registered, resolved nor authorized by being named | built on this stack; the narrower reference a trusted evaluation boundary installs for its subtree is the seam #713 fills | | document validation | validates one supplied root projection and the recursive Markdown source closure normal component selection discovers, returning deterministic version-1 document diagnostics and `valid`, `invalid` or `not-statically-checkable` invocation outcomes without evaluating document code or installing operational host behavior | built on the #654 stack | | `xmd plan` | turns one Prompt into approved Plan source and delivers it, by executing exactly one root document and starting no program. That root is the packaged plan command document, under the internal `` identity — an adapter that projects the request into `` and returns what comes back — and inside that, the packaged `` Component under the Plan writer profile its own `` installs: one enclosing Session, a host ceiling of one host-owned directory dedicated to that logical session — under `~/.xmd/plan/sessions` by default, keyed by the digest of the name, never the name, created empty and required to be empty before the provider exists or a session is materialized, refused rather than cleaned when it is not, durable when the caller named the session and handed back non-recursively after teardown when it did not — with no additional directories, no MCP servers, no native tools and a private strict denial no permission flag widens, no write, delete, directory-ensure, temporary-directory, command, service or network capability for that document — reading is not refused at all, because the packaged workflow is trusted source and takes the ordinary contextual route under the scope's effective `Permissions`; the #762 information-request boundary selects the shared ordinary profile's Syntax, File and Glob reads, no repository component search, and the Component's own private ``, whose closed assessment reports the structural defects the draft authored. The invocation settles one structural check — `validateDocumentStructure` under the ordinary run-profile registry, the `` identity, the caller's includes and the run profile's declarations — and ``, `` and the command's own final gate all ask that one, so what they can disagree about is when it was asked rather than what was asked. There is no caller-source defect to tell them apart from: the grammar is fixed and complete before a draft exists, because no generated document adds an option to a command whose result *is* the document. Its instructions require every Plan to begin with one descriptive level-one title and to keep the Prompt's outcomes as readable steps with each component beside the step it performs, through repairs and revisions alike; that is an authorship and human-review requirement, and `` never enforces it. A tenth draft that still has problems may be stopped or explained: the explanation is one more ordinary turn in the same Session carrying only the final diagnostics, is inert text, reopens no draft limit, and ends the command. The host's instruction layer states only that an answer belongs to the message that asked for it, so which shape a turn wants stays in the document. Authorship reports itself as it happens: the command root's rendered transcript is progress on stderr — one Markdown phase announced before each piece of work, its attempt and repair ordinals derived from the two bounds `Plan.md` binds once, with `--verbose` adding every cleared draft, every failed check's structured findings, and the committed information requests and results described in the #762 amendment — written through a private paired `` that renders its content, sends it through the current document-output operation and returns nothing, so a phase can never enter ``'s capture or the declaration's exact-source disposition. Which surface is asking and whether `--verbose` was written are sealed host facts, so the ordinary `` surface announces nothing and expands no progress body. The host owns the stream and the terminal alike: whitespace normalization for every invocation, terminal formatting only when the entrypoint states its own stderr is one, the transcript drained inside the scope that owns the execution, and a destination that stops accepting bytes cancelling the producer and waiting for every owned teardown before it reports — with no stdout fallback. Authorship's own durable stream is the host's choice and is written rather than read: a fresh invocation-owned in-memory one, or the file `--journal` exclusively created, holding the ordinary `serializeDurableEvent()` JSONL in commit order under the same serialized pre-append secret gate, so a rejected event reaches neither the file nor the committed sequence and the prefix before it stays readable. Nothing opens either as input, replays it, or resumes from it. Then, only after every provider, Prompt task and Elicitation resource inside the Plan writer frame has torn down, the Component's own `` structurally admits the exact approved bytes, and after that execution ends the host asks the same check once more — about a tree the whole teardown has had time to move, so a component the approved Plan names and something removed after that admission is refused here and nowhere else, and a Plan declaring properties a later run will supply is admitted rather than refused — and delivers it to exactly one sink: stdout byte for byte by default, or an exclusively created `--output` path. It starts no later root and retains no later execution, so the caller's own composition decides whether the program runs: `xmd plan … | xmd run -`, or an `--output` artifact a later `xmd run` names. Its grammar is what that leaves: one request, `--include`, `--agent-provider`, `--default-agent`, `--session`, `--timeout`, `--output`, `--verbose`, `--journal`, and ordinary help and version. The last two are spelled in full and observe this authorship alone — `-V` and `-j` are `xmd run`'s aliases for options about a program's run, and each is refused by naming the long spelling. Every option that configured the former execution — `--run`, the aggregate and generated root properties, `--raw`, the exec and fetch deadlines, the three permission flags and both secret-detection spellings — is refused by name in fixed preflight, before the general parser can drop or coerce a token and before `--help` can short-circuit the dispatch, in either order; `--run` reports the migration that names both compositions, and every other one reports that `xmd run` is where a program is configured. The same options are unchanged under `xmd run`. No permission mode is settled at all. The retired `prompt` spelling is not a command and is not absorbed by the default `run` grammar, which would read it as a document reference and execute a file of that name: an invocation whose exact first token is `prompt` is refused before any scan, selection or path lookup, establishing nothing, while `xmd run ./prompt` still executes a document legitimately called that | built on the #660 stack | | `` | writes and reviews one Plan, from a Prompt an ordinary document wrote. `…` expands its paired body once with the capabilities the calling document already has — the complete untrimmed rendering is the Prompt, and it is never emitted separately — and produces the exact approved Plan source. It is a paired **exact text** component: the bare form emits that source into the calling document's own rendering, and the `as` form captures the same bytes instead. Neither form evaluates what it produced, and neither announces a phase: the progress `xmd plan` writes is a private side effect of the command surface, so an ordinary `` expands no progress body at all. It is the public name of the packaged `` Component: exact first-party Markdown declared to every ordinary run, so a repository `Plan.md`, a workflow bundle, a registration, `Component.importComponent` middleware and another loaded copy can none of them answer for it. Paired only, with one optional non-empty `session` prop and an optional `as`; a body that renders to nothing fails before any inspection, directory, Session, turn, review or check exists. The Agent writes under exactly the `xmd plan` fixed policy however broad the calling document's permissions are, and a host that supplies no Agent context refuses before placement — including the `` child an `xmd test` document launches, which is the run profile and therefore resolves the same protected bytes rather than reporting a missing component, and which supplies one when it declares a canonical ``. An authored `session` keeps the existing durable named-directory lifetime, so the same name at the same site reaches the same conversation next time, while an omitted one is site- and iteration-unique, replay-stable and handed back after teardown; sibling sites stay distinct even when they write one name, and the name never becomes a path. Every turn, answer, check, approval and admission belongs to the enclosing document's journal, so a continuation restores completed authorship instead of repeating it; there is no second journal. Complete authorship teardown precedes structural admission, which precedes the emission or the binding — and the admission is structure alone, so a Plan declaring properties a later run will supply is produced rather than refused. It creates no file and executes nothing it produced | built on the #660 stack; no delivery, custom root, policy prop or replacement selector exists (#536 owns constrained caller-authored policy) | @@ -5455,8 +5456,8 @@ Status is measured against main. | targeted `xmd run` | reads a file argument as a document reference and executes the one exact target its selector resolved to, replacing the selector before execution rereads the file | built on the #412 stack | | targeted workflow definition | a workflow definition of either version optionally carries the exact canonical document target, which takes part in definition identity and in compatible reuse but not in the source-bundle hash | built on the #412 stack; `xmd workflow start` takes a document reference and resolves any selector through core against the bytes it is about to retain | | source-bundle workflow definition | version 2 of the workflow definition is the exact bytes themselves: an entrypoint, a canonically ordered manifest of logical paths with each source's domain-separated SHA-256 and byte length, a bundle hash over that manifest and mapping, and the optional exact target and component mapping. The bytes are retained with the run in live schema version 2, so starting, resuming, replaying, forking and exporting need no repository and survive the original being edited, moved or deleted | built on the #443 stack; version 1 is unchanged, nothing migrates between them, and the artifact-backed fork remains unbuilt | -| installed structural syntax | a trusted host declares a structural construct and the regions written directly inside it, as the second arm of the same `declarations` list: name, origin, accepted forms, props schema, syntax examples, description, what the content means, and `parent` — `null` for the construct, the construct's name for one of its regions. The accepted regions are derived from the regions that named the construct rather than restated by it. The installation that declares them supplies the one `expand` handler, read once and bound at capture, and held on the admitted catalog entry rather than in any registry, context or second dispatch protocol. Admission refuses an invalid name, an empty origin, absent or non-canonical forms, an uncompilable schema, missing syntax examples or description, a context that is neither prose nor `null`, a name the engine's structural table or the canonical protected tier owns, a name a reserved registration claims, a duplicate across either arm or across installations, a collision with a private closure name, an orphan region, a region of a region, a pair split across two installations, a construct with no region, declarations with no handler, and a handler with no declarations — all of it before the root document is read. Resolution places a declared construct in the host tier beside declared Markdown; `inspectComponent()`, `inspectSyntax()` and document validation describe and check it from the same catalog, with the structural entries sorted by code point beside the engine's own and the symbols unchanged at version 2. Expansion asks the catalog after every engine branch and before component import, settles placement, forms, `as`/`slot` and every construct and region prop, and then calls the captured handler once inside its own scope with a frozen request. Each region is an operation whose subscription owns one demand-driven producer: a chunk is delivered only to a waiting read, authored work waits for the read that permits it, output never reaches `DocumentOutput` or the journal, and leaving the handler's scope halts and joins every producer it entered | built on the #806 stack | -| declared Markdown component | a trusted host declares exact first-party Markdown to one execution as immutable data on an `ExecutionInstallation`, built with `Markdown({…})`: the host states the name, origin, source, its SHA-256, the accepted forms, an optional statement of the props and return that must agree with the parsed source, and an optional private component closure, and the constructor returns a fresh declaration carrying the required `kind: "component"` written after that description. It validates, hashes, copies and freezes nothing. Admission reads the kind before any other member and refuses a missing, unknown or superseded one — including the `"markdown"` earlier versions stated — rather than reading the value as Markdown, then parses the bytes and refuses a mismatched digest or schema, a non-canonical form, a name that is not a component name or is structural, a duplicate, a reserved-registration collision and a private name a registration also claims. Resolution places it in the protected tier with reserved registrations, above the workflow component bundle, repository files and every registered default. Live import and retained history are held to the declared origin, digest and bytes, private names resolve only while canonical core expands the declaring bytes' own body — by the authored occurrence rather than by the name, so an answer kept from a legitimate private import authorizes no later site, no alias, no copy of the definition, no invocation that is over and no later execution — including one that declares no Markdown at all — while a private name written anywhere else resolves to nothing before the bundle, the repository or a registration can answer for it — and `xmd syntax` and document validation describe the declared contract from the same declaration without describing the closure. Closure is per name: only the declared component and its private closure become canonical imports, and every other name in the execution stays the ordinary open import middleware may still answer | built on the #660 stack; no public component uses it yet (#660 PR 2) | +| installed structural syntax | a trusted host declares a structural construct and the regions written directly inside it, as the second arm of the same `declarations` list: name, origin, accepted forms, props schema, syntax examples, description, what the content means, and `parent` — `null` for the construct, the construct's name for one of its regions. The accepted regions are derived from the regions that named the construct rather than restated by it. The installation that declares them supplies the one `expand` handler, read once and bound at capture, and held on the admitted catalog entry rather than in any registry, context or second dispatch protocol. Admission refuses an invalid name, an empty origin, absent or non-canonical forms, an uncompilable schema, missing syntax examples or description, a context that is neither prose nor `null`, a name the engine's structural table or the canonical protected tier owns, a name a reserved registration reserves, a duplicate across either arm or across installations, a collision with a private closure name, an orphan region, a region of a region, a pair split across two installations, a construct with no region, declarations with no handler, and a handler with no declarations — all of it before the root document is read. Resolution places a declared construct in the host tier beside declared Markdown; `inspectComponent()`, `inspectSyntax()` and document validation describe and check it from the same catalog, with the structural entries sorted by code point beside the engine's own and the symbols unchanged at version 2. Expansion asks the catalog after every engine branch and before component import, settles placement, forms, `as`/`slot` and every construct and region prop, and then calls the captured handler once inside its own scope with a frozen request. Each region is an operation whose subscription owns one demand-driven producer: a chunk is delivered only to a waiting read, authored work waits for the read that permits it, output never reaches `DocumentOutput` or the journal, and leaving the handler's scope halts and joins every producer it entered | built on the #806 stack | +| declared Markdown component | a trusted host declares exact first-party Markdown to one execution as immutable data on an `ExecutionInstallation`, built with `Markdown({…})`: the host states the name, origin, source, its SHA-256, the accepted forms, an optional statement of the props and return that must agree with the parsed source, and an optional private component closure, and the constructor returns a fresh declaration carrying the required `kind: "component"` written after that description. It validates, hashes, copies and freezes nothing. Admission reads the kind before any other member and refuses a missing, unknown or superseded one — including the `"markdown"` earlier versions stated — rather than reading the value as Markdown, then parses the bytes and refuses a mismatched digest or schema, a non-canonical form, a name that is not a component name or is structural, a duplicate, a reserved-registration collision and a private name a registration also reserves. Resolution places it in the protected tier with reserved registrations, above the workflow component bundle, repository files and every registered default. Live import and retained history are held to the declared origin, digest and bytes, private names resolve only while canonical core expands the declaring bytes' own body — by the authored occurrence rather than by the name, so an answer kept from a legitimate private import authorizes no later site, no alias, no copy of the definition, no invocation that is over and no later execution — including one that declares no Markdown at all — while a private name written anywhere else resolves to nothing before the bundle, the repository or a registration can answer for it — and `xmd syntax` and document validation describe the declared contract from the same declaration without describing the closure. Closure is per name: only the declared component and its private closure become canonical imports, and every other name in the execution stays the ordinary open import middleware may still answer | built on the #660 stack; no public component uses it yet (#660 PR 2) | | workflow component bundle | a workflow root declares a closed set of authored Markdown components; the workflow definition optionally carries them as one canonically ordered array, and an absent member identifies a run closed over no components — so a definition closed over none identifies exactly that. An entry maps the name onto a logical path the same source bundle retains. `start` reads every component from beside the root and retains it, and `resume` executes the closure the lifecycle authenticated; the array takes part in definition identity and is compared as part of the same descriptor in compatible reuse; and canonical core resolves those names and holds both live import and retained history to that exact bundle | built on the #301 stack; the full adversarial implementation loop and its scheduling remain unbuilt (#300), and generated XMD admits no bundled Markdown component (#369) | | `getWorkflowRun()` | reads the run the current execution is associated with | built on the #366 stack | | `retainedWorkflowInstallation()` | associates one document execution with a run storage already created, requiring exact journal agreement. It resolves no revision and names no Git feature, and a run retains the bytes it executes, so nothing afterwards reaches a repository for its source | built on the #366 stack | @@ -5469,11 +5470,11 @@ Status is measured against main. | explicit WorkflowRun journal route | binds one already-filtered publication to one exact active transaction and otherwise uses ordinary serialized journal storage | built on the #365 stack | | `API.Service` / `startService()` | creates an authenticated, supervised loopback service attachment through a provider-neutral operation | built on main | | foreground command routing and retention | forwards a child's channels live, captures stdout for a `` region, and retains output only when the host asked for a record | built on the #441 stack | -| `exec as="name"` | binds one command's settled outcome — exit status, stdout and stderr — as an ordinary mutable binding; the block displays neither channel, renders nothing, and a nonzero status raises nothing. Only the built-in exec terminal and the built-in `timeout` may compose one, authorized by factory identity rather than by registered name, and asked for through a capability-backed request public middleware composes around but cannot issue, claim twice or answer | built on the #447 stack | +| `exec as="name"` | binds one command's settled outcome — exit status, stdout and stderr — as an ordinary mutable binding; the block displays neither channel, renders nothing, and a nonzero status raises nothing. Only the built-in exec terminal and the built-in `timeout` may compose one, authorized by factory identity rather than by registered name, and asked for through a capability-backed request public middleware composes around but cannot issue, consume twice or answer | built on the #447 stack | | testing harness (``) | runs another document as a real root under a production host profile, authorized by canonical `` alone: declarations installed before the root import, child output displayed progressively and collected only when asked, journal retention selected independently of observation, and the outcome published by the invocation's own terminal through a request public middleware composes around but cannot answer | built on the #454 stack for `host="run"`; the workflow profile and `` are unbuilt, and a host that offers no workflow profile refuses them | | nested run-profile Agent and elicitation declarations | lets one `` declare one child-scoped `` scenario set and one non-delegating `` matcher set; only frozen test data crosses the harness request, the trusted host constructs both providers inside the isolated child, siblings share no session or provider state, ordinary component shadowing remains in force, and the child journal retains only the selected Prompt and Elicit components' ordinary results. A controlled `` may author an exact scenario label that this host alone maps to Plan's derived conversation identity; declaration selection uses the label while runtime state stays keyed by the opaque identity and child, with no matcher or fallback added to ordinary TestAgent sessions | built on the #641 stack; controlled Plan routing added on the #728 stack | | `Config` run deadline / exec default / Fetch default / verbosity | three independently owned contextual timeouts, absent unless configured, each read by exactly one consumer, and contextual verbosity — a boolean that is false unless configured, seeded by the command line and overridable for a lexical subtree, bounding nothing and deciding no permission | built on this stack | -| Agent session configuration (`` / `Agent.options()`) | a `` says which model and effort level its conversation runs under, in exact provider ids, and no other element does. `Agent.session()` continues to route only a name or opaque placement; configuration is not a middleware argument. Each provider installation owns one private registration closure for its exact lifetime. An opaque placement carries an unreadable reference to its operation-local issuance, including optional frozen configuration and durable component identity; `with({ name })` preserves it, another placement substitutes its own, and a raw string or directly returned raw Session selects no configuration. The directly delivered provider coordinator accepts the final live placement once and completes it with the provider's exact Session plus either fresh state or one stable established-session configuration operation. Fresh completion performs no configuration work; established completion applies and verifies eagerly, and the returned canonical value is sealed into one opaque frozen session use selected lexically for nested prompts and launches. The owner refuses a different operation for an already registered exact Session, registration or lookup after teardown, and copied or foreign placements and uses; teardown drops its registrations after provider finalizers. No Context, module registry, public Agent operation, middleware-readable member, return value or Session property exposes the owner or operation, and the provider retains no desired-settings association. A string passed to `useConfiguredSession()` creates one operation-local placement with no durable component identity. Middleware may observe, refuse or reroute whole Sessions. The final routed value decides the operation: an authentic configured use applies and verifies its own settings; another authentic use applies its settings; a raw Session, name or absence is unconfigured; and a copied or foreign configured claim refuses before provider work. The journal records only the verified configuration the final route actually started under, never an earlier lexical request. Settings are applied under the Session's existing serialization and ownership — read, apply model, refresh for that model's effort choices, apply effort, verify exact equality — before a turn or native UI. Omission performs no configuration read or write. An unavailable option, unsupported capability, rejected write, mismatching readback or unverifiable restoration fails before the turn, restoring model first and reporting the original rejection; a restoration nobody can verify makes that exact Session unusable for the rest of the run. A prompt that started and a successful launch preparation retain one canonical `configuration`; a configuration refusal and an unconfigured operation retain none. Completed replay contacts no provider, and an incomplete configured launch reapplies that canonical value to the exact retained Session or fails. Released launch `requestedModel` and observational `model` strings are compatibility-reader inputs only: valid values are discarded, malformed values refuse, and neither can configure replay. A final configured provider-returned launch verifies before materialization, detach and native UI; a final configured client-allocated launch refuses before route, identity, private file or process, while middleware that routes an unconfigured Session receives the unchanged unconfigured contract. `Agent.options()` reports provider-ordered, grouped choices through one scoped unretained inspection session that sends no prompt and creates no XMD execution, journal or durable session, and `xmd agent options` renders them as text or version-1 JSON | built on the #828 stack; ACP translation lives entirely in `@executablemd/acp`, and no ACP or ACPX type crosses into core | +| Agent session configuration (`` / `Agent.options()`) | a `` says which model and effort level its conversation runs under, in exact provider ids, and no other element does. `Agent.session()` continues to route only a name or opaque placement; configuration is not a middleware argument. Each provider installation owns one private registration closure for its exact lifetime. An opaque placement carries an unreadable reference to its operation-local issuance, including optional frozen configuration and durable component identity; `with({ name })` preserves it, another placement substitutes its own, and a raw string or directly returned raw Session selects no configuration. The directly delivered provider coordinator accepts the final live placement once and completes it with the provider's exact Session plus either fresh state or one stable established-session configuration operation. Fresh completion performs no configuration work; established completion applies and verifies eagerly, and the returned canonical value is sealed into one opaque frozen session use selected lexically for nested prompts and launches. The owner refuses a different operation for an already registered exact Session, registration or lookup after teardown, and copied or foreign placements and uses; teardown drops its registrations after provider finalizers. No Context, module registry, public Agent operation, middleware-readable member, return value or Session property exposes the owner or operation, and the provider retains no desired-settings association. A string passed to `useConfiguredSession()` creates one operation-local placement with no durable component identity. Middleware may observe, refuse or reroute whole Sessions. The final routed value decides the operation: an authentic configured use applies and verifies its own settings; another authentic use applies its settings; a raw Session, name or absence is unconfigured; and a copied or foreign configured session use refuses before provider work. The journal records only the verified configuration the final route actually started under, never an earlier lexical request. Settings are applied under the Session's existing serialization and ownership — read, apply model, refresh for that model's effort choices, apply effort, verify exact equality — before a turn or native UI. Omission performs no configuration read or write. An unavailable option, unsupported capability, rejected write, mismatching readback or unverifiable restoration fails before the turn, restoring model first and reporting the original rejection; a restoration nobody can verify makes that exact Session unusable for the rest of the run. A prompt that started and a successful launch preparation retain one canonical `configuration`; a configuration refusal and an unconfigured operation retain none. Completed replay contacts no provider, and an incomplete configured launch reapplies that canonical value to the exact retained Session or fails. Released launch `requestedModel` and observational `model` strings are compatibility-reader inputs only: valid values are discarded, malformed values refuse, and neither can configure replay. A final configured provider-returned launch verifies before materialization, detach and native UI; a final configured client-allocated launch refuses before route, identity, private file or process, while middleware that routes an unconfigured Session receives the unchanged unconfigured contract. `Agent.options()` reports provider-ordered, grouped choices through one scoped unretained inspection session that sends no prompt and creates no XMD execution, journal or durable session, and `xmd agent options` renders them as text or version-1 JSON | built on the #828 stack; ACP translation lives entirely in `@executablemd/acp`, and no ACP or ACPX type crosses into core | | native session launch (`` / `launchAgentSession()`) | prepares one durable coding-agent session from the rendered body of `` and hands the provider's native UI the terminal for that exact session, then continues the document after it exits. The body renders completely first and only what it rendered crosses as the instruction layer; the launch performs no model turn except an adapter's declared materialization turn, which runs at most once, only for a conversation the launch just created, and only with that adapter's fixed prompt; it takes the run's foreground-terminal lease before an agent is resolved. A host with no applicable terminal refuses without probing for an installed CLI. A session is constructed once, by one of two mechanisms, and its create-once construction route says which. Where the provider returns the identity, the ACPX provider creates the session, installs the layer at creation, releases ACP ownership before the spawn, and marks its handle stale so a later `` reattaches. Where the adapter names its own sessions, it allocates the identity inside ownership before any process exists, the native process creates the session under that name from a private mode-0600 instruction file, and ACP creates nothing — the instruction text reaches neither argv nor environment, and the file is removed on success, failure and cancellation alike while ownership is still held. Neither route converts into the other, and which one governs is chosen by the first operation that consumes the placement rather than by the `` that made it: a fresh `` publishes no route and establishes nothing, so a `` nested inside one constructs the session it placed, while a first subscribed `` publishes ACP-first before it ensures and keeps that account even if the turn that follows is never accepted. An established route is validated eagerly by a later ``, and a launch meeting a published ACP-first route refuses before an identity exists. A `` or `` meeting a bound client-allocated route attaches under the route's exact identity; a legacy unbound route or an unavailable attachment capability refuses before a turn and creates no substitute conversation. Phases are retained as `agent_session_launch` records under one expansion identity — `prepared` before ownership is released, then `materialized` where an adapter required a materialization turn, then `detached`, then `exited` — so a completed replay launches nothing, a replay holding only `prepared` proves the handoff never began and may still create under the retained identity, and one holding `detached` resumes and never falls back. The public route carries an opaque one-use launch request and answers nothing; the right to run and retain a phase is delivered to the installed provider directly, so neither a returned completion nor a rebuilt request authors a launch. Every operation that can act on an advertised session takes exclusive ownership under one natural key first, through a coordinator the host built and passed in; contention refuses instead of queueing, and an owner that never proved it stopped leaves a recovery tombstone. A host that cannot say who owns a session refuses every advertised operation, and one that cannot say how a session was constructed additionally refuses an agent that names its own — before any provider effect. Every private setup or child-creation failure is normalized to `process-creation-failed` with fixed provider-owned text, carrying no path, argv, environment or host message. No launch path discards persistent provider state. A session whose adapter pins a build is bound to that one build, whichever side named it: the build is observed inside ownership before an identity is allocated or a provider session is created, the binding is published with the bound route — V2 for client-native, V3 for ACP-first — and retained beside the prepared record, the native child runs the exact observed path in place of the launcher name, and every later create, resume, attachment and incomplete replay reobserves and compares before a process, an ensure or a turn. A `` or `` meeting a bound client-native route attaches to it: it reobserves the build, requires any retained provider arrangement to assert that same conversation, calls ensure with the route identity as `resumeSessionId`, and requires the provider to report that identity before a turn — refusing on missing capability, build drift, missing history or a differing assertion without creating a substitute conversation. ACP runtimes are partitioned by resolved agent command and binding, each handle is closed by the partition that created it, and a bound partition is torn down when its last handle closes. A legacy V1 client-native route keeps exactly the released native-only behavior and never attaches, and a legacy V1 ACP-first route refuses an agent whose adapter binds a build rather than gaining the current executable | built on the #517 stack, extended by the #519 and #561 stacks; Deno and the compiled binary assemble the host — coordinator, route store and executable observer — and Node and Bun keep the same advertised names while assembling none of it, so every advertised operation refuses before provider work; `claude` is advertised for native launch after passing the client-allocated gate at Claude Code 2.1.241 on macOS arm64 (#520) and separately for client-native attachment after passing the native-to-ACP marker gate (#561); `codex` is advertised for native launch after passing the provider-returned gate at `codex-cli 0.153.2` on macOS arm64 with the vendored `@agentclientprotocol/codex-acp` 1.6.2 snapshot that asserts the App Server thread on the response `_meta` (#755), which costs one fixed `codex-materialization.v1` turn because Codex writes the rollout `codex resume ` reads at a thread's first turn. That tuple is the compatibility point the advertisement stands on rather than an allowlist: admission accepts one canonical `codex-cli x.y.z` line, so another canonical version is admitted while bare, malformed, ambiguous or multi-line output refuses; exactness belongs to the session, whose accepted string becomes its retained executable binding and is reobserved and compared before every later create, resume, attachment and incomplete replay, so continuing a session across releases is not offered. Reading the ACP session id as the native identity stays forbidden; `Agent.AddDir` is unbuilt | | `` | performs one XMD-mediated HTTP read through contextual `API.Fetch`, admitting the whole request before transport, and retains the normalized request and the detached response as one `fetch` durable observation; capture decides whether a status is data or a failure, and the trusted host's destination ceiling sits below the component | built on the #456 stack; a generated fragment may name the pinned identity only for a request the trusted host stated exactly, on the #369 stack | | `API.Files` | routes every document filesystem operation to the installed provider, with no host default and structural failure data. Its mandatory semantic operations include `ensureDirectory`, which recursively creates or adopts one directory and returns Unit; separately loaded copies compose through the stable Api name | built on the #227 stack; directory ensure added by #643 | @@ -5492,9 +5493,9 @@ Status is measured against main. | `` under a workflow run | upserts one pull request of the selected checkout's current named branch, reconciled through the shared Git-host state machine: a required `title`, an optional positive-integer `number`, an optional `base` defaulting to the Repository's retained initial branch, an optional `draft`, and the rendered content as the body; it renders nothing and returns stable evidence through `as` — the filtered Repository identity, the provider's own stable pull-request identity, number, URL, open state, and the head and base SHAs of the snapshot it finished at. Without a number it creates one pull request for the head/base pair or adopts the compatible one an interrupted attempt left; with a number it brings that exact pull request's title, body, draft state and base to what the request says, records a no-op when they already match, and refuses a number belonging to another repository, opened from another head, or no longer open. It never pushes, never rewrites a head, and never reopens, merges or comments. The run must already hold its own successful `Git.Push` result for that exact Repository identity, head branch, destination ref and commit — proven by a scan of the whole successful history that requires each relevant record's natural key, inputs and result to describe one publication; a branch is published repeatedly, so the whole history is read in order and the run's last publication of that branch decides — an earlier one behind it is history rather than disagreement, while a last one naming another commit is the branch having moved on; that is conflicting, no relevant record at all is missing, and a relevant record that cannot be read whole is unreadable, each failing locally before the Git host is observed; the first adapter works over `github.com` on REST plus the two GraphQL draft transitions, selected from the private retained locator, credentialed from `GH_TOKEN`, then `GITHUB_TOKEN`, then the machine's own `gh` login, issuing each required mutation at most once per attempt and deciding the outcome by one observation, with the locator, endpoint, credential and payload confined to the per-invocation provider closure | built on the #295 stack, Deno provider only | | repository composition vocabulary | one array of thirteen ordinary, shadowable registrations — `Repository`, `Worktree`, `Dir`, the four `Git.*` operations, `PullRequest` and its three evidence reads, `IssueTracker` and `Issue` — declared by the bundled Git Plugin and consumed wherever its profile is assembled: an ordinary document execution, `xmd syntax`, `xmd plan`'s validation and generation, and a workflow action that executes a document, so one vocabulary is described and resolved everywhere. A Workspace attachment installs this run's providers and durable state and declares none of it. Registering it installs no provider, discovers no repository, acquires no lock, spawns no Git and reads no credential; what a name does is the installed provider's. A repository-local Markdown or TypeScript component of the same name is chosen ahead of any of them | built on the #643 stack | | `` / `` composition under an ordinary run | selects a managed checkout under `~/.xmd/repositories`, addressed by a digest of its whole identity and described by a closed version 1 sidecar written by exclusive temporary sibling plus atomic rename only after the checkout is complete and verified. The slot is entered under an exclusive non-blocking advisory lock held for the whole document execution, so a second process is refused rather than made to wait and a self-closing Worktree captured with `as` stays protected while a later sibling `` and an interactive Session use it. Reuse compares creation identity alone — the immutable request, the recorded creation facts, the canonical checkout and common directory, the object format, the admitted `origin` and the creation commit still being present — and never HEAD, the current branch, the index or the working tree, which are the mutable work the checkout exists to preserve; a conflict refuses and leaves every byte where it was, and nothing resets, switches, cleans, fetches, moves, replaces, repairs or deletes. A metadata-free slot is adopted only after the stricter pre-exposure state is proved — exact owner and locator, the branch and base this request resolves to, the creation commit still being HEAD, the object format, linked-worktree registration where applicable, and nothing in the slot but the checkout — and refuses otherwise. Written outside a lexical ``, a Worktree belongs to the ambient Repository; outside a Git checkout it refuses locally and names how to run inside one | built on the #643 stack, Deno and compiled only | -| local Git operations (`Git.Switch` / `Git.Add` / `Git.Commit`) under an ordinary run | perform the same authored transitions the workflow performers perform — named branches only, explicit Add pathspecs, index-only Commit, no implicit stage or push, and the same fixed provider Git configuration that disables hooks, signing, file-system monitors and repository-supplied helper programs — directly against the authenticated selected checkout. A commit records the invoking user's own effective Git identity, captured from the trusted host by the first `` that needs it and read back off the written object — a run that commits nothing asks the host nothing about who it is; a host that can name no identity refuses `` and names the commands that fix it rather than writing the workflow identity into somebody's repository, and every other component stays usable. They enlist in no transaction, roll back nothing and replay nothing, and a failure claims neither. Which checkout one runs in is decided by the Repository selection in scope and the contextual working directory, resolved through the provider's own invocation-owned checkout registry rather than through anything the selection says about itself | built on the #643 stack, Deno and compiled only | +| local Git operations (`Git.Switch` / `Git.Add` / `Git.Commit`) under an ordinary run | perform the same authored transitions the workflow performers perform — named branches only, explicit Add pathspecs, index-only Commit, no implicit stage or push, and the same fixed provider Git configuration that disables hooks, signing, file-system monitors and repository-supplied helper programs — directly against the authenticated selected checkout. A commit records the invoking user's own effective Git identity, captured from the trusted host by the first `` that needs it and read back off the written object — a run that commits nothing asks the host nothing about who it is; a host that can name no identity refuses `` and names the commands that fix it rather than writing the workflow identity into somebody's repository, and every other component stays usable. They enlist in no transaction, roll back nothing and replay nothing, and a failure promises neither. Which checkout one runs in is decided by the Repository selection in scope and the contextual working directory, resolved through the provider's own invocation-owned checkout registry rather than through anything the selection says about itself | built on the #643 stack, Deno and compiled only | | `Git.Push` under an ordinary run | keeps the same observe/adopt/fast-forward/refuse rules and the same isolated transport aimed at the checkout's admitted `origin`: a destination proven absent is published once, one already naming this exact commit is adopted, one holding a proven ancestor is published over by the same exact non-force refspec, and a divergent or unreadable one is a conflict, with an unreachable host never read as absence. It reconciles no Git-host effect and retains nothing. After a verified performed or adopted publication it stores one private evidence entry — the authenticated Repository identity, canonical checkout root, origin, named branch, destination ref and exact commit — in the provider instance's own closure. A checkout with no admitted `origin` refuses before a credential, a session or a transport exists | built on the #643 stack, Deno and compiled only | -| `` and its evidence reads under an ordinary run | share the URL matching, host ceiling, response normalization and low-level GitHub reconciliation, and differ in lifecycle and admission. A read is performed afresh every execution and retained nowhere. An upsert authenticates the Repository selection and the contextual checkout, reads the current named branch and commit, and requires the exact matching entry this provider instance already holds — a Push for another checkout, Repository, origin, destination, branch or commit is irrelevant, a later Push of the same destination supersedes the earlier entry, and missing or conflicting evidence is a local refusal before a credential is opened. Nothing crosses executions: a new run and a new `--journal` run each start with a new invocation identity and empty evidence, and copying a Context value, a component result or a previous trace file grants nothing. Within one invocation the attempt happens at most once; across a process interruption there is no exactly-once claim | built on the #643 stack, Deno and compiled only | +| `` and its evidence reads under an ordinary run | share the URL matching, host ceiling, response normalization and low-level GitHub reconciliation, and differ in lifecycle and admission. A read is performed afresh every execution and retained nowhere. An upsert authenticates the Repository selection and the contextual checkout, reads the current named branch and commit, and requires the exact matching entry this provider instance already holds — a Push for another checkout, Repository, origin, destination, branch or commit is irrelevant, a later Push of the same destination supersedes the earlier entry, and missing or conflicting evidence is a local refusal before a credential is opened. Nothing crosses executions: a new run and a new `--journal` run each start with a new invocation identity and empty evidence, and copying a Context value, a component result or a previous trace file grants nothing. Within one invocation the attempt happens at most once; across a process interruption there is no exactly-once guarantee | built on the #643 stack, Deno and compiled only | | `` under an ordinary run | reaches the same configured transport under the same host ceiling, with no durable envelope: identity is this execution's own opaque invocation identity together with the engine's expansion identity, so an upsert presents an idempotency key a provider can carry and a second run is a new request rather than a resumption. Absent or out-of-ceiling configuration installs no matching provider and sends no credential and no request | built on the #643 stack, Deno and compiled only | | ordinary repository provider assembly | the Deno source entrypoint and the compiled binary install the live provider for `xmd run`, parameterized by the same credential-helper assembly the workflow host uses. It reads no configuration: `XMD_WORKFLOW_GITHUB_ISSUES` and `XMD_WORKFLOW_GITHUB_PULL_REQUESTS` belong to the GitHub adapter inside `@executablemd/git`, which reads and validates one when an invoked GitHub-backed operation needs it, so a run that opens no pull request and files no issue reads neither. Installing the provider acquires nothing at all — no managed root, no lease, no Git session, no identity, no ambient discovery; each of those is acquired by the first operation that needs it and kept for the rest of the execution. A nested `` child receives a fresh instance — its own invocation identity, leases and Push evidence — so nothing it publishes authorizes its parent or a sibling. The outer `xmd test` command installs none — it is not a run profile, and a nested `` child assembles one for itself rather than inheriting what its parent declined. Node and Bun register the vocabulary and install no operational provider, so every repository operation reports an absent provider before a lock, a credential, a subprocess or a request exists | built on the #643 stack | | `` under a workflow run | asks one of two questions, decided by its own shape, through a boundary of its own rather than the Git host's. Self-closing with `url` reads that issue and binds `{ url, title, description, tags, assignee }`; paired with `title` upserts and binds exactly `{ url }`, its rendered content being the description. There is no `description` prop. Props are exactly `url`, `title`, optional `tags`, optional `assignee` and — on a read only — optional `provider`; no repository/token/label/milestone/project/comment/close or approval prop. Both forms render nothing. The form is decided before the tracker is read, before any provider is asked and before an `issue_effect` record exists, and that is where a mixed `url`+`title`, a read carrying content or `tags`/`assignee`, an upsert with no content, an upsert naming a `provider`, and an element that is neither are all refused. A read needs no tracker — its URL is the identity; an upsert requires the nearest lexical `` and takes its discriminator only from there. The tracker carries a credential-free `url` and an optional `provider`; the URL is canonicalized — a credential, a query and a fragment are refused rather than stripped — and a nested tracker replaces the whole value for its descendants, never merging members, with the enclosing one restored on leaving. It is composition data, not permission: the provider holds an adapter-private ceiling beside its credentials, admitted before it connects, so a target outside it sends nothing. One stable contextual operation, `executablemd.git.issue`, with `read(url, options)` and `upsert(issue, options)`; a provider is ordinary middleware around it, matching its own URLs without a discriminator and only its own name with one, independently per member, with no host-side resolution. Once middleware matches it owns the answer — it never delegates afterwards, and nothing catches its refusal to try somebody else — and a request everyone delegated reaches `NoIssueProvider` unchanged. `issue_effect` records an operation discriminator with the normalized request and result; both forms replay without reaching `IssueApi` and therefore without network access; only an upsert derives an idempotency key, from the operation, the canonical target and the run's own effect identity. Retention excludes credentials, endpoints, payloads, provider identities, origin markers and host paths. Observing, adopting, creating once and recovering an interrupted creation are the provider's, because they are knowledge about what a service can prove; title is never identity, and tags are a code-point-sorted set. The bundled Git Plugin installs the GitHub adapter itself rather than a decision about it: installing reads no variable, obtains no credential and opens no socket, and configuration is read only when a matching invoked operation recognizes a GitHub target. Absence is therefore not an uninstalled provider but an adapter that delegates, and the request reaches the boundary's own `NoIssueProvider` refusal unchanged — fail-closed either way, and without making startup depend on what a run turns out to do | built on the #296 stack; GitHub middleware, Deno host | @@ -5505,7 +5506,7 @@ Status is measured against main. | history fork | creates a new run from one compatible checkpoint and retained Workspace root, under a new immutable definition and normalized props | built on the #368 stack, Deno provider only | | workflow Agent session | a workflow document's `` runs under a profile the host attaches only for a live or partial run: an empty host-owned working directory instead of any Workspace, checkout or caller path, no MCP servers, an empty requested native tool set, and `deny-all` with a permission path that denies every native request and fails the turn that asked without reaching the public permission chain. Within a run a session is identified by the Agent/Session expansion identity the engine derived — the authored name is descriptive, so two sibling `` elements are two sessions — routed inside a placement bound to its element and good for one use, so a kept placement cannot be substituted for the next. The conversation is retained as a row in the run's own database with the provider, resolved agent command and policy fingerprint beside it as compatibility attributes. The order is placement, the backend's acceptance of the session's first turn, the provider's canonical tagged assertion, then the mapping commit — and only then is anything that turn produced exposed. A placement is inert: it creates no provider session and writes no row. Occupancy of a provider key is not an assertion, and a record held for a first turn nobody accepted asserts nothing at all; the pre-commit window reconciles only from exactly one canonical assertion, and a missing, conflicting, replaced or ambiguous assertion is one explicit refusal that starts no replacement. Deleting a run removes the row with the run and the provider-session directory beside it, and reports the categories. The profile selects ACP-only capability explicitly — no native-launch advertisement and no client-native attachment advertisement — rather than inheriting the provider package's ordinary-run sets by omission, and it supplies no machine session coordinator, construction-route store or executable observer: a workflow session belongs to a run, and the machine-wide account describes a different thing entirely | built on the #302 stack, with the explicit ACP-only selection from #561; the portable proof that an adapter honours an empty tool set is tracked by #496 and does not widen the ceiling | | generated-XMD admission | admits one Agent-generated fragment through the trusted-host seam: host policy is a `read` table and a `write` table of exact pinned identities, each carrying the authored forms it is admitted for, and an authored `allow` selects a canonical non-empty subset of the closed classes — omitted means `read`. The complete source is preflighted inside one `generated_xmd` durable effect before its first generated effect; only the pinned identity the selected classes hold for that name **and** that form executes; and the admitted source, class selection, selected root, every selected entry with its forms, the identity and form of each element named, and the normalized request policy are retained in that effect's own result — so a continuation restores the decision without reading the current candidate and expands only the retained source. The roots are an as-of-admission retained basis checked by membership — the run's own later root publications and an advanced retained current root pass, while a lost admission root or lost selected root refuses — and every non-root term is checked exactly, refusing a run whose classes, identities, forms or requests have moved. The admission and every nested generated effect are offered inline by the owning expansion in authored order, so a partial continuation restores each completed one without another live execution. Each admitted effect is retained by its own ordinary record, and every component keeps its ordinary binding and output behavior | built on the #369 stack, continuation basis amended by #589; core owns the mechanics and the workflow policy wrapper is internal | -| `` | canonical core's own protected component, written where program text the document did not author should run. Core claims the name ahead of every host and author tier, so no registration, repository file, bundle member, declared Markdown component, import handler answer or second loaded copy replaces it; a handler may observe or refuse the import, and only canonical execution answers one. Protection settles which implementation runs and grants nothing: a host supplies the *ceiling* as one `ExecutionInstallation.evaluation` profile, captured by value before any installation runs, and an execution accepts one and refuses two. Its schema is closed on `text` and an optional `allow` array selecting a non-empty duplicate-free subset of the closed effect classes `read` and `write` — omitted means `read`. The two input forms are disjoint: `text` states the program, paired content renders it, and an element stating both is refused rather than resolved by precedence. A paired producer renders under the narrowed syntax reference through an execution-owned one-shot projection that bypasses the public `content()`/`tryContent()` chain, and keeps its own operational permission while doing so. Evaluate renders the fragment's ordinary output and invents no observation or result envelope. Fragment-local `as` bindings suppress their component's output normally, and language constructs plus pure components such as `` remain available regardless of effect selection; the fragment explicitly renders any bound values it wants to expose. Every ceiling comes from values the host captured at installation — the run's retained roots and its authoritative current root read from the run's own storage per invocation, as-of-admission provenance a continuation holds by membership so the run's own later publications and an advanced retained current root invalidate nothing, core's self-closing `` read — joined in the ordinary run profile by core's self-closing `` and canonical protected `` — the write table of core's paired ``, core's `` under the identity the host that assembles the profile states, since this package states no directory entry of its own — and core's self-closing ``, and `` only when the captured request ceiling is non-empty — and no prop, binding, context or middleware return value supplies or widens one. An entry states what is behind a name in one of exactly two ways, and neither carries a function. A *capability* names the component canonical core supplies for it: capture answers with core's own ordinary definition — the same ``, ``, ``, ``, `` or `` an author writes — held to the execution's lifetime, with the component's own form dispatcher travelling beside it so canonical selection enters the body the scan chose. The operation it performs is therefore the ordinary one, through contextual `API.Files` and `API.Fetch`, under the provider the host installed and the effective `Permissions` of the consuming scope; the host hands the profile no operation of its own. A capability states what it binds wherever the ordinary component does because it *is* the ordinary component, so an admitted `` is the value component the ordinary one is — sharing its props, return contract, source rules and sanitized failure sentence, refusing a missing `as` and an unusable pattern before the search, and resolving its paths against the contextual working directory. One name runs one component, so a name admitted for capabilities owned by two different components refuses at capture. An admitted `` is the one entry with a ceiling: the element is classified against the entry's exact admitted requests, performs the admitted one rather than its props, and that ceiling is installed as an ordinary `Permissions` restriction for the invocation, so a contextual transformation that moves the request off it is refused by the terminal rather than sent. A *component answer* names an implementation the ordinary import chain resolves, and states only the identity a provider must have claimed for it; canonical execution resolves that name once — before the root import and before any document code, through the complete ordinary `Component.importComponent` chain and a private terminal that writes no record — and asks the identity owner about the exact final answer in one call. That call answers with the claim *and* core's own copy of what was claimed, taken when the claim was recorded: the check and the thing kept are one result, so nothing downstream reads the chain's object a second time and an answer whose members read differently on each read cannot pass a check with one reading and be sealed with another. The identity is then compared whole, and the copy — not the answer — is sealed behind the same revocation. One name states one identity, however many forms and tables hold it: two entries under one name are the two spellings of one component and share one lookup and one sealed implementation, while a second identity for that name, or a name held as both a capability and a component answer, refuses at capture rather than letting assembly order decide. Provider installation and the right to answer one occurrence are separate: installation receives a registrar that installs import middleware, and every invocation of that middleware receives a fresh request fixed to the exact name, position, provider installation, origin and resolution-window object it was asked under. Only that request may claim, and it states the answer plus key and revision without restating the name. Canonical execution closes the request synchronously when its handler returns, fails or is cancelled; an outer request remains live while it delegates and may claim a replacement after the inner handler returns. Enclosing resolution still closes in its own `finally` on success, fallback, failure or cancellation. A claim therefore requires the execution, request and exact current window to remain active, the request's fixed name to match that window, and that provider installation not to have stated a different answer in the window. Identification takes the expected window explicitly and accepts only a claim recorded for that exact object and name, so a stale request cannot answer a later same-name resolution or retag itself while another name is live. The installation is reusable: one provider may answer several admitted names and repeated resolutions through distinct requests. All of this state is held in ordinary private closures — no Context, shared symbol, public brand or module-global registry — and an unidentified middleware replacement remains a valid ordinary import answer outside fragment evaluation. A capability entry also states the exact version-1 identity strings it succeeds, which is the only thing a released untagged record reconciles against; a component answer states none. A capability-only profile performs no such lookup at all. Resolution happens at capture and never again: a fragment runs the sealed snapshot, a continuation resolves once more in its own capture and reconciles before any effect, and a provider still answering when a fragment resolves its admitted name is answering a generated import, which only canonical execution answers. A trusted layering control may enter one package bootstrap through an inherited layer and an execution-local one — documentation, registrations and the provider together — and the repeat is additive: the outer entry observes and delegates rather than claiming a second identity for an implementation that already states what it is, and a non-identical documentation overlap on one owner and component still refuses at the child collection boundary, before the root import and therefore before the provider is asked at all. `allow` selects among those tables and adds nothing to them; approval, when a workflow needs one, is authored control flow before the element. Its durable operation is named through that claimant, on the exact invocation the engine handed it and in that invocation's own frame — not from a context a document could rebind, a contextual Api answer, a definition, or a registry answer. Generated effects use occurrence-owned identities in the existing ordinary durable sequence: their records persist and replay normally, with no staging or rollback. The generated projection and its structured teardown complete before Evaluate returns and later parent work begins. It is deliberately not wrapped in `printErrors`, so a refused fragment stops the authored loop rather than becoming text the next turn could read as a read that happened | built on the #302 stack, extended by #369 | +| `` | canonical core's own protected component, written where program text the document did not author should run. Core reserves the name ahead of every host and author tier, so no registration, repository file, bundle member, declared Markdown component, import handler answer or second loaded copy replaces it; a handler may observe or refuse the import, and only canonical execution answers one. Protection settles which implementation runs and grants nothing: a host supplies the *ceiling* as one `ExecutionInstallation.evaluation` profile, captured by value before any installation runs, and an execution accepts one and refuses two. Its schema is closed on `text` and an optional `allow` array selecting a non-empty duplicate-free subset of the closed effect classes `read` and `write` — omitted means `read`. The two input forms are disjoint: `text` states the program, paired content renders it, and an element stating both is refused rather than resolved by precedence. A paired producer renders under the narrowed syntax reference through an execution-owned one-shot projection that bypasses the public `content()`/`tryContent()` chain, and keeps its own operational permission while doing so. Evaluate renders the fragment's ordinary output and invents no observation or result envelope. Fragment-local `as` bindings suppress their component's output normally, and language constructs plus pure components such as `` remain available regardless of effect selection; the fragment explicitly renders any bound values it wants to expose. Every ceiling comes from values the host captured at installation — the run's retained roots and its authoritative current root read from the run's own storage per invocation, as-of-admission provenance a continuation holds by membership so the run's own later publications and an advanced retained current root invalidate nothing, core's self-closing `` read — joined in the ordinary run profile by core's self-closing `` and canonical protected `` — the write table of core's paired ``, core's `` under the identity the host that assembles the profile states, since this package states no directory entry of its own — and core's self-closing ``, and `` only when the captured request ceiling is non-empty — and no prop, binding, context or middleware return value supplies or widens one. An entry states what is behind a name in one of exactly two ways, and neither carries a function. A *capability* names the component canonical core supplies for it: capture answers with core's own ordinary definition — the same ``, ``, ``, ``, `` or `` an author writes — held to the execution's lifetime, with the component's own form dispatcher travelling beside it so canonical selection enters the body the scan chose. The operation it performs is therefore the ordinary one, through contextual `API.Files` and `API.Fetch`, under the provider the host installed and the effective `Permissions` of the consuming scope; the host hands the profile no operation of its own. A capability states what it binds wherever the ordinary component does because it *is* the ordinary component, so an admitted `` is the value component the ordinary one is — sharing its props, return contract, source rules and sanitized failure sentence, refusing a missing `as` and an unusable pattern before the search, and resolving its paths against the contextual working directory. One name runs one component, so a name admitted for capabilities owned by two different components refuses at capture. An admitted `` is the one entry with a ceiling: the element is classified against the entry's exact admitted requests, performs the admitted one rather than its props, and that ceiling is installed as an ordinary `Permissions` restriction for the invocation, so a contextual transformation that moves the request off it is refused by the terminal rather than sent. A *component answer* names an implementation the ordinary import chain resolves, and states only the identity a provider must have registered for it; canonical execution resolves that name once — before the root import and before any document code, through the complete ordinary `Component.importComponent` chain and a private terminal that writes no record — and asks the identity owner about the exact final answer in one call. That call answers with the registered identity *and* core's own copy of what was registered, taken when the identity was registered: the check and the thing kept are one result, so nothing downstream reads the chain's object a second time and an answer whose members read differently on each read cannot pass a check with one reading and be sealed with another. The identity is then compared whole, and the copy — not the answer — is sealed behind the same revocation. One name states one identity, however many forms and tables hold it: two entries under one name are the two spellings of one component and share one lookup and one sealed implementation, while a second identity for that name, or a name held as both a capability and a component answer, refuses at capture rather than letting assembly order decide. Provider installation and the right to answer one occurrence are separate: installation receives a registrar that installs import middleware, and every invocation of that middleware receives a fresh request fixed to the exact name, position, provider installation, origin and resolution-window object it was asked under. Only that request may register an identity, and it states the answer plus key and revision without restating the name. Canonical execution closes the request synchronously when its handler returns, fails or is cancelled; an outer request remains live while it delegates and may register a replacement after the inner handler returns. Enclosing resolution still closes in its own `finally` on success, fallback, failure or cancellation. A registration therefore requires the execution, request and exact current window to remain active, the request's fixed name to match that window, and that provider installation not to have stated a different answer in the window. Identification takes the expected window explicitly and accepts only a registration recorded for that exact object and name, so a stale request cannot answer a later same-name resolution or retag itself while another name is live. The installation is reusable: one provider may answer several admitted names and repeated resolutions through distinct requests. All of this state is held in ordinary private closures — no Context, shared symbol, public brand or module-global registry — and an unidentified middleware replacement remains a valid ordinary import answer outside fragment evaluation. A capability entry also states the exact version-1 identity strings it succeeds, which is the only thing a released untagged record reconciles against; a component answer states none. A capability-only profile performs no such lookup at all. Resolution happens at capture and never again: a fragment runs the sealed snapshot, a continuation resolves once more in its own capture and reconciles before any effect, and a provider still answering when a fragment resolves its admitted name is answering a generated import, which only canonical execution answers. A trusted layering control may enter one package bootstrap through an inherited layer and an execution-local one — documentation, registrations and the provider together — and the repeat is additive: the outer entry observes and delegates rather than registering a second identity for an implementation that already states what it is, and a non-identical documentation overlap on one owner and component still refuses at the child collection boundary, before the root import and therefore before the provider is asked at all. `allow` selects among those tables and adds nothing to them; approval, when a workflow needs one, is authored control flow before the element. Its durable operation is named through that invocation authenticator, on the exact invocation the engine handed it and in that invocation's own frame — not from a context a document could rebind, a contextual Api answer, a definition, or a registry answer. Generated effects use occurrence-owned identities in the existing ordinary durable sequence: their records persist and replay normally, with no staging or rollback. The generated projection and its structured teardown complete before Evaluate returns and later parent work begins. It is deliberately not wrapped in `printErrors`, so a refused fragment stops the authored loop rather than becoming text the next turn could read as a read that happened | built on the #302 stack, extended by #369 | | generated mutation proposals | lets an Agent propose constrained executable changes that a separate admission then performs against the run's own Workspace | built on the #369 and #567 stacks, with directory creation added by #643: the standard Deno profile's write table is core's paired `File:write`, the paired `@executablemd/workflow/composition/dir-v2#Dir` and core's self-closing `File.Delete`, in that retained order and followed by any host extension. `allow={["write"]}` intentionally authorizes Dir's persistent recursive directory creation; its versioned identity makes every continuation retained under the former non-mutating Dir identity refuse before generated execution. Admitted mutations run as the ordinary components they are through the run's effect transactions, and the evaluator adds no mutation API or receipt. Approval is authored control flow before the write-enabled element. Local Git, Git-host, issue, process, execution, credential and external-write effects are outside the class | | Deno-local DOFS provider | owns one authoritative SQLite/DOFS connection per run path, captures arbitrary canonical retained roots, privately restores them, and atomically coordinates one Workspace mutation with its filtered Yield | built on the #365 stack; public document filesystem effects and the CLI lifecycle route to it on the #366 stack | | 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 | @@ -5550,8 +5551,8 @@ node, no input, no focus, no frame contribution and no output anywhere. A component is constructed synchronously inside the commit and may own ongoing work in its node's scope; a render body owns nothing. Normalized host input is decided once, at the host, which names a target and an event shape and never an -action; the tree walks that target's own ancestry, and the first node to claim -the event produces the typed action the root acts on. An event nothing claims +action; the tree walks that target's own ancestry, and the first node to handle +the event produces the typed action the root acts on. An event nothing handles is an explicit failure. Freedom is vendored from a pinned unpublished commit under @@ -5688,7 +5689,7 @@ admitted box mounted a live control — bounds alone cannot establish it, since the engine reports a clipped child's whole rectangle and says nothing about what was painted. Resolution is half-open on both axes, because the engine's own hit test includes a box's trailing edge and every row of a stacked list would -otherwise be claimed by two neighbours. A bound that is not whole cells is +otherwise be assigned to two neighbours. A bound that is not whole cells is refused rather than rounded: the engine produces fractional geometry wherever something is centred or sized by a share, and a rounded hit box disagrees with the text underneath it. A pointer that does resolve becomes the same normalized @@ -5704,7 +5705,7 @@ and is not containment — whether a dispatch may reach a node behind the modal is the reconciler's to refuse, and it refuses with capture off. Text is its own member of that normalized union, not a key with a payload: a -named key — submit, dismiss, traverse, erase — is a command whoever claims it +named key — submit, dismiss, traverse, erase — is a command whoever handles it recognizes, and text is content that goes wherever content goes. It carries what the terminal decoded, so shifted, accented and multi-byte characters arrive already assembled, and a newline inside a paste arrives as one. A chord carries diff --git a/packages/acp/src/adapter-snapshots.ts b/packages/acp/src/adapter-snapshots.ts index ea67968d5..933b1b86f 100644 --- a/packages/acp/src/adapter-snapshots.ts +++ b/packages/acp/src/adapter-snapshots.ts @@ -8,16 +8,17 @@ * version and digest; the quoted host-local launch path is never retained in a * session or sealed artifact. * - * Stage privately, publish by one rename and verify the published tree before use, - * including when another attempt won. Recovery of an abandoned non-empty tree - * requires an exclusive claim and a fresh check before removal, otherwise a stale - * observation could delete another process's newly published valid adapter. + * Stage privately, publish by one rename and verify the published tree before + * use, including when another attempt won. Recovery of an abandoned non-empty + * tree requires exclusive ownership of recovery and a fresh check before + * removal, otherwise a stale observation could delete another process's newly + * published valid adapter. * - * Recovery claims are prepared directories atomically renamed to `claims/`. - * Tickets increase monotonically and are never reused: late arrivals cannot precede - * an elected holder, and finishing a dead holder cannot affect a later claim. - * The lowest unfinished ticket owns recovery; release marks it finished, and a - * later attempt may finish a dead owner's ticket. + * Recovery tickets are prepared directories atomically renamed to `claims/`. + * Tickets increase monotonically and are never reused: late arrivals cannot + * precede an elected holder, and finishing a dead holder cannot affect a later + * ticket. The lowest unfinished ticket owns recovery; release marks it + * finished, and a later attempt may finish a dead owner's ticket. * * Digest, extraction, installation or missing-entry failures raise. Falling back * to a published adapter would lose the turn identity continuation depends on. @@ -67,10 +68,10 @@ const RECOVERY_ATTEMPTS = 400; const OWNER = "owner"; const DONE = "done"; -/** A ceiling on ticket numbers, so a pathological claims directory cannot spin. */ +/** A ceiling on ticket numbers, so a pathological recovery-ticket directory cannot spin. */ const MAX_TICKETS = 10_000; -/** Who holds a recovery claim, so a later attempt can tell live from dead. */ +/** Who holds a recovery ticket, so a later attempt can tell live from dead. */ interface RecoveryOwner { readonly pid: number; readonly host: string; @@ -97,7 +98,7 @@ function parseOwner(raw: string): RecoveryOwner | undefined { * Signal 0 asks without delivering anything. `EPERM` means it exists and * belongs to somebody else, which is still alive; only `ESRCH` means gone. An * answer this cannot interpret is treated as alive, so an unreadable state - * never becomes a reason to take somebody's claim. + * never becomes a reason to take somebody's recovery ownership. */ function alive(pid: number): boolean { try { @@ -378,10 +379,10 @@ export function createEmbeddedAdapters( * on. An attempt arriving later cannot obtain a number below one already * taken, so it cannot come to sit ahead of a holder. * - * Ordering names by time could not offer that. Two claims made in the same - * millisecond were separated only by the random part of their names, and a - * clock adjustment could hand a later arrival an earlier name — either way an - * elected holder could be preceded after the fact. + * Ordering names by time could not offer that. Two recovery tickets issued in + * the same millisecond were separated only by the random part of their names, + * and a clock adjustment could hand a later arrival an earlier name — either + * way an elected holder could be preceded after the fact. */ function* takeTicket(claims: string): Operation { yield* ensureDir(claims); @@ -412,15 +413,15 @@ export function createEmbeddedAdapters( } /** - * Whether this attempt now holds the claim. + * Whether this attempt now owns recovery. * * The holder is the lowest ticket still outstanding, so every number below - * this attempt's own is examined in order: a finished ticket is passed over, a - * ticket whose owner is a dead process on this host is finished here, and a + * this attempt's own is examined in order: a finished ticket is passed over, + * a ticket whose owner is a dead process on this host is finished here, and a * live owner, an owner on another machine, or a record that cannot be read * each stop the election where it stands. The last one says so, because * refusing to act on what it cannot read is the only safe reading of somebody - * else's claim. + * else's recovery ticket. * * Finishing a dead holder's ticket is safe for the reason the election is: * the number is never reissued, so this can only ever act on the exact ticket @@ -465,17 +466,18 @@ export function createEmbeddedAdapters( } /** - * Replace an abandoned tree at the target, holding an exclusive claim. + * Replace an abandoned tree at the target, under exclusive ownership of + * recovery. * - * Reached only when the rename failed and what is there does not verify. The - * claim makes "check, then remove" one decision instead of two: without it, a - * second attempt could publish a valid tree in the gap and this one would - * delete it, taking the files out from under an adapter that had already - * resolved and might already be running. + * Reached only when the rename failed and what is there does not verify. + * Exclusive recovery ownership makes "check, then remove" one decision + * instead of two: without it, a second attempt could publish a valid tree in + * the gap and this one would delete it, taking the files out from under an + * adapter that had already resolved and might already be running. * - * An attempt that does not hold the claim never removes anything. It waits - * and answers from what the holder published — including when the wait ends - * with this attempt elected, because a holder finishes its ticket only after + * An attempt that does not own recovery never removes anything. It waits and + * answers from what the holder published — including when the wait ends with + * this attempt elected, because a holder finishes its ticket only after * publishing. */ function* recover( @@ -637,9 +639,9 @@ export function createEmbeddedAdapters( * * A closed registry was the wrong shape for the same reason. It made "this * build has no Codex snapshot problem to solve for Gemini" into "this build - * refuses Gemini", which is a much larger claim than the one being made, and it - * would have changed the retained identity of agents the checkpoint work has - * nothing to say about. + * refuses Gemini", which is a much broader restriction than the one being made, + * and it would have changed the retained identity of agents the checkpoint work + * has nothing to say about. * * The overlay is *qualified*: an embedded provider never falls through. A * snapshot that cannot be verified or materialized refuses the agent, and does diff --git a/packages/acp/src/provider.ts b/packages/acp/src/provider.ts index 573ce388b..63d7230a4 100644 --- a/packages/acp/src/provider.ts +++ b/packages/acp/src/provider.ts @@ -384,7 +384,7 @@ interface RuntimeEntry { /** Handles created through this runtime that have not been closed. */ handles: number; /** - * Work that has claimed this runtime and has not yet produced a handle. + * Work that has reserved this runtime and has not yet produced a handle. * * Counted apart from `handles` because the two are true at different times * and both keep the partition alive. An ensure in flight owns no handle yet, @@ -471,9 +471,9 @@ function asName(routed: string | Session | undefined): string | undefined { * it. * * The coordinator is the only thing that can tell a configured use from a value - * that merely claims to be one, so every route asks it. An embedder driving + * that merely reports that shape, so every route asks it. An embedder driving * this provider directly holds no coordinator and therefore no configured - * session exists for it — a value that claims otherwise refuses rather than + * session exists for it — a value that reports otherwise refuses rather than * being run unconfigured. */ function routedSession( @@ -1063,14 +1063,14 @@ function* useAcpxProviderState( } /** - * Elect the runtime for this partition and claim it, in one step. + * Elect the runtime for this partition and reserve it, in one step. * - * Synchronous from the map read to the claim, and that is the whole point. - * Publishing an entry and then claiming it across a suspension leaves it in - * the map standing on nothing — long enough for a sibling giving up its own - * claim to evict it, after which this caller holds a runtime the map no - * longer names and the next operation builds a second child for the same - * build. Here the entry is published already claimed. + * Synchronous from the map read to the reservation, and that is the whole + * point. Publishing an entry and then reserving it across a suspension leaves + * it in the map standing on nothing — long enough for a sibling giving up its + * own reservation to evict it, after which this caller holds a runtime the + * map no longer names and the next operation builds a second child for the + * same build. Here the entry is published already reserved. */ function electRuntime(partition: string | undefined, options: AcpRuntimeOptions): RuntimeEntry { const held = partition === undefined ? unbound : runtimes.get(partition); @@ -1133,7 +1133,7 @@ function* useAcpxProviderState( * * A bound partition holds a live executable path for the work it owns, so it * is kept exactly as long as something is standing on it — a handle nobody - * has closed, or work that has claimed the runtime and not yet produced one. + * has closed, or work that has reserved the runtime and not yet produced one. * Both have to be zero: evicting while either is nonzero is how a concurrent * operation ends up building a second child for a build the first is still * talking to. The unbound runtime is ordinary ACP-first state and stays. @@ -1148,7 +1148,8 @@ function* useAcpxProviderState( } /** - * The claimed work produced this handle, so the claim becomes ownership of it. + * The pending work produced this handle, so the runtime reservation becomes + * ownership of it. * * One step, because the two counts must never both be zero in between: that * gap is a partition another operation could evict out from under a handle @@ -1160,7 +1161,7 @@ function* useAcpxProviderState( owned.add(session); } - /** The claimed work produced no handle. Nothing is standing on it here. */ + /** The pending work produced no handle. Nothing is standing on it here. */ function releaseReservation(entry: RuntimeEntry): void { entry.active = Math.max(0, entry.active - 1); evictIfIdle(entry); @@ -1171,7 +1172,7 @@ function* useAcpxProviderState( * * Never called for a close that failed: a failed close released nothing, so * decrementing the partition, evicting it, or forgetting the handle would all - * be claiming something that did not happen. Idempotent, because the set + * be reporting something that did not happen. Idempotent, because the set * membership is the guard — a handle released twice must not decrement twice. */ function releasedHandle(session: ManagedSession): void { @@ -1183,8 +1184,8 @@ function* useAcpxProviderState( } /** - * Ensure through the runtime for `build`, settling that work's claim exactly - * once however this operation ends. + * Ensure through the runtime for `build`, settling that work's runtime + * reservation exactly once however this operation ends. * * `ensureSession()` is a Promise, and starting one is not the same as owning * it. Once called it runs whether or not anybody is still waiting: a scope @@ -1195,10 +1196,10 @@ function* useAcpxProviderState( * So the settlement is scope-owned rather than written into a `catch`, which * a cancellation does not run at all. The cleanup is registered with the * Promise already started and before anything yields, so there is no window - * in which this can end with the claim unsettled and the answer unobserved. - * The three ways out are the three branches below, and the flag is what keeps - * the normal continuation and the cleanup from both taking one: nothing - * yields between the handle arriving and that flag being set. + * in which this can end with the reservation unsettled and the answer + * unobserved. The three ways out are the three branches below, and the flag + * is what keeps the normal continuation and the cleanup from both taking one: + * nothing yields between the handle arriving and that flag being set. */ function ensureThrough( build: BoundBuild | undefined, @@ -1690,7 +1691,7 @@ function* useAcpxProviderState( /** * Whether this provider still holds a handle that can act on `sessionKey`. * - * The one thing quiescence is a claim about. `quiesced()` does not mean "I + * The one thing quiescence establishes. `quiesced()` does not mean "I * finished" — it means nothing this owner started can still touch the * session, and a live ACP handle is exactly such a thing. So every path * acknowledges through this: a released handle quiesces, and a release that @@ -2410,7 +2411,7 @@ function* useAcpxProviderState( * The answer is read back from the agent rather than echoed: the selectors * this returns are what the apply operation verified, so a provider that * quietly landed on something else is caught by the caller comparing them - * instead of having its own claim recorded. + * instead of having the requested value recorded. */ function* configureSession( agentName: string, @@ -3296,8 +3297,8 @@ function* useAcpxProviderState( * * A member the provider did not report is left absent rather than copied as * `undefined`, because these are merged over what earlier events reported: an - * explicit `undefined` would overwrite a figure the provider did give with the - * claim that it gave none. Zero is a figure; saying nothing is not. + * explicit `undefined` would overwrite a figure the provider did give with + * the report that it gave none. Zero is a figure; saying nothing is not. */ function reportedUsage( breakdown: AcpRuntimeUsageBreakdown | undefined, diff --git a/packages/acp/src/session-route.ts b/packages/acp/src/session-route.ts index 2737acd5c..0f62bc718 100644 --- a/packages/acp/src/session-route.ts +++ b/packages/acp/src/session-route.ts @@ -58,7 +58,7 @@ export type AgentSessionRouteV1 = * * V1 `client-native` is not upgraded into this. A build observed later says * which build is installed now, not which one established the session, and - * writing it into an old record would claim knowledge XMD never had. + * writing it into an old record would assert knowledge XMD never had. */ export interface AgentSessionRouteV2 { schema: "session-route.v2"; diff --git a/packages/acp/tests/adapter-materialization.test.ts b/packages/acp/tests/adapter-materialization.test.ts index 9392ed19c..bf2c68898 100644 --- a/packages/acp/tests/adapter-materialization.test.ts +++ b/packages/acp/tests/adapter-materialization.test.ts @@ -70,7 +70,7 @@ function* takenTickets(claims: string): Operation { .sort((left, right) => left - right); } -/** Wait until `ticket` has been taken, so a barrier is read from the claim. */ +/** Wait until `ticket` has been taken, so a barrier is read from the recovery ticket. */ function* untilTicketTaken(claims: string, ticket: number): Operation { for (let attempt = 0; attempt < 600; attempt += 1) { if ((yield* takenTickets(claims)).includes(ticket)) { diff --git a/packages/acp/tests/fixtures/claude-native-launch-proof.ts b/packages/acp/tests/fixtures/claude-native-launch-proof.ts index cb61a72d3..c0182b8f7 100644 --- a/packages/acp/tests/fixtures/claude-native-launch-proof.ts +++ b/packages/acp/tests/fixtures/claude-native-launch-proof.ts @@ -1640,8 +1640,8 @@ function decideTwoTurn(verdict: JourneyVerdict): void { * Gate, run and dismantle one journey, then report it. * * The cleanup counters are filled in by teardown, so a verdict serialized while - * the scope was still open would report every one of them false and claim the - * journey leaked what it had not yet released. + * the scope was still open would read every cleanup counter as false and + * incorrectly report a leak before those resources had been released. */ function* runJourney( mode: Mode, diff --git a/packages/acp/tests/fixtures/claude-native-to-acp-proof.ts b/packages/acp/tests/fixtures/claude-native-to-acp-proof.ts index 2575566e5..007aac289 100644 --- a/packages/acp/tests/fixtures/claude-native-to-acp-proof.ts +++ b/packages/acp/tests/fixtures/claude-native-to-acp-proof.ts @@ -18,8 +18,8 @@ * second is an authored, marker-free `` — * an ordinary ACP turn, through the same built binary, in the same directory. * - * Recovering the marker there is the whole claim. Equal identities are not: - * two accounts agreeing about a UUID says nothing about whether the + * Recovering the marker there is the behavior being proved. Equal identities + * are not: two accounts agreeing about a UUID says nothing about whether the * conversation behind it is the one the native turn happened in. * * The first command runs inside a byte-for-byte copy of the repository's own @@ -1874,8 +1874,8 @@ function decideAttachment(verdict: JourneyVerdict): void { * Gate, run and dismantle one journey, then report it. * * The cleanup counters are filled in by teardown, so a verdict serialized while - * the scope was still open would report every one of them false and claim the - * journey leaked what it had not yet released. + * the scope was still open would read every cleanup counter as false and + * incorrectly report a leak before those resources had been released. */ function* runJourney( mode: Mode, diff --git a/packages/acp/tests/fixtures/codex-native-launch-proof.ts b/packages/acp/tests/fixtures/codex-native-launch-proof.ts index 75217a62d..e3cf04a0b 100644 --- a/packages/acp/tests/fixtures/codex-native-launch-proof.ts +++ b/packages/acp/tests/fixtures/codex-native-launch-proof.ts @@ -91,7 +91,7 @@ const ACP_DOCUMENT = fileURLToPath(new URL("./codex-native-to-acp-prompt.md", im * The compatibility point these journeys are only meaningful against * (`issue-755-codex-materialization-turn-implementor-handoff.md`). * - * Frozen rather than read from the machine, because the whole claim is that one + * Frozen rather than read from the machine, because the proof requires that one * exact build was proven. A run against another build is not a weaker pass; it * is a different question, and it says so. */ @@ -176,10 +176,10 @@ const SURFACE_MS = 240_000; /** * How long one native answer is waited for. * - * Twice the Claude proof's bound, because two Codex answers reached that one and - * the second was still showing a working state when the classifier read the - * screen afterwards. A bound is not a claim about the product: reaching it says - * this harness stopped waiting, and `answerSurface` says what was on screen. + * Twice the Claude proof's bound, because two Codex answers reached that one + * and the second was still showing a working state when the classifier read the + * screen afterwards. A bound is not a product finding: reaching it says this + * harness stopped waiting, and `answerSurface` says what was on screen. */ const ANSWER_MS = 600_000; const SETTLE_MS = 120_000; @@ -1915,8 +1915,8 @@ function decideNativeLaunch(verdict: JourneyVerdict): void { * Gate, run and dismantle one journey, then report it. * * The cleanup counters are filled in by teardown, so a verdict serialized while - * the scope was still open would report every one of them false and claim the - * journey leaked what it had not yet released. + * the scope was still open would read every cleanup counter as false and + * incorrectly report a leak before those resources had been released. */ function* runJourney( mode: Mode, diff --git a/packages/acp/tests/fixtures/codex-surfaces.ts b/packages/acp/tests/fixtures/codex-surfaces.ts index 08bafa44b..44a9eef45 100644 --- a/packages/acp/tests/fixtures/codex-surfaces.ts +++ b/packages/acp/tests/fixtures/codex-surfaces.ts @@ -106,7 +106,7 @@ const WITNESSED_REFUSAL = "You've hit your usage limit."; * Wording this does not recognize is not exhaustion here, even if it is * exhaustion in fact. That direction is the safe one: an unrecognized surface * is reported as a harness that could not read the screen, which costs an - * investigation, where the other direction costs a false claim about the + * investigation, where the other direction costs an incorrect finding about the * product's environment. */ export function exhaustedUsage(snapshot: ScreenSnapshot): boolean { diff --git a/packages/acp/tests/fixtures/npm-package-driver.mjs b/packages/acp/tests/fixtures/npm-package-driver.mjs index cf14ba433..f2591b171 100644 --- a/packages/acp/tests/fixtures/npm-package-driver.mjs +++ b/packages/acp/tests/fixtures/npm-package-driver.mjs @@ -6,9 +6,9 @@ * and completes a real ACP exchange against the fake provider. * * A separate process rather than an import into the test, because what an npm - * package is *for* is being consumed by Node: running it that way is the claim, - * and it keeps the assertion independent of whichever runtime the suite is - * executing under. + * package is *for* is being consumed by Node: the test must exercise that + * consumption, and it keeps the assertion independent of whichever runtime the + * suite is executing under. * * Prints one line per observation, which the test parses. */ diff --git a/packages/acp/tests/fixtures/session-route-publisher.ts b/packages/acp/tests/fixtures/session-route-publisher.ts index ac578da17..c66dbe990 100644 --- a/packages/acp/tests/fixtures/session-route-publisher.ts +++ b/packages/acp/tests/fixtures/session-route-publisher.ts @@ -1,8 +1,8 @@ /** * One other process publishing one route. * - * The create-once race is a claim about two processes, and only two processes - * can make it: one runtime racing itself shares a filesystem cache and a + * The create-once race must hold across two processes, and only two processes + * can demonstrate it: one runtime racing itself shares a filesystem cache and a * scheduler, and would agree with a broken implementation as readily as a * working one. * diff --git a/packages/acp/tests/fixtures/terminal-screen.ts b/packages/acp/tests/fixtures/terminal-screen.ts index 074b99bb2..049fff3f8 100644 --- a/packages/acp/tests/fixtures/terminal-screen.ts +++ b/packages/acp/tests/fixtures/terminal-screen.ts @@ -742,9 +742,9 @@ export function screenShows(snapshot: ScreenSnapshot, marker: string): boolean { * Every invocation gets one, because every invocation decides what surface it * is looking at and a surface is a fact about the screen: the byte stream * retains a composer drawn before a dialog covered it, and text an erase wiped - * out. Only an invocation that submits a turn also *watches* — see - * {@link watching} — because latching an answer is a claim about a reply to a - * turn, and a run that spoke none has no reply to attribute. + * out. Only an invocation that submits a turn also *watches* — see {@link + * watching} — because latching an answer attributes a reply to a turn, and a + * run that spoke none has no reply to attribute. * * The latch latches. Once the answer has been on the screen it stays observed, * because the question is whether the agent answered and a TUI is entitled to diff --git a/packages/acp/tests/helpers.ts b/packages/acp/tests/helpers.ts index 2705ad270..f0546cf0b 100644 --- a/packages/acp/tests/helpers.ts +++ b/packages/acp/tests/helpers.ts @@ -129,7 +129,7 @@ export interface FakeRuntimeHarness { * * A discard and a release are the same call with different options, so the * option is the only thing that tells them apart — and "no launch path ever - * discards persistent state" is a claim about exactly that. + * discards persistent state" depends on that distinction. */ closeInputs: Record[]; /** diff --git a/packages/acp/tests/native-launch.test.ts b/packages/acp/tests/native-launch.test.ts index f5c0a3064..a0010fe6e 100644 --- a/packages/acp/tests/native-launch.test.ts +++ b/packages/acp/tests/native-launch.test.ts @@ -239,9 +239,9 @@ interface ProviderOptions { /** * Share one coordinator with another provider scope. * - * Contention is a claim about one owner excluding another, and it can only be - * made where both reach the same coordinator. Isolation is the opposite - * claim, and making it here would prove neither. + * Contention means one owner excludes another and can only be tested where + * both reach the same coordinator. Isolation is the opposite property. + * Testing isolation here would prove neither. */ coordinator?: AgentSessionCoordinator; /** Host-owned session placement and retention, as a workflow host supplies. */ @@ -2542,9 +2542,9 @@ describe("Tier RR — racing construction routes", () => { /** * What ownership said at each route operation. * - * The ordering claim is about *when* reconciliation happens, and reading - * that off the production source is not evidence. The coordinator's own log - * is: `owned` means an acquisition is live and has not been released. + * The test must establish *when* reconciliation happens, and reading that + * off the production source is not evidence. The coordinator's own log is: + * `owned` means an acquisition is live and has not been released. */ during: string[]; } @@ -4145,10 +4145,11 @@ describe("Tier CV — canonical Claude version", () => { * (specs/native-agent-session-launch-spec.md §Executable binding). * * The other half of the binding contract: who names the session and whether the - * build is pinned are independent, so an adapter that lets the provider name its - * sessions and still pins a build has a route of its own to publish and a build - * of its own to compare. Tier CN is the same claim from the client-allocated - * side, and Tier NL is what an adapter binding nothing still does. + * build is pinned are independent, so an adapter that lets the provider name + * its sessions and still pins a build has a route of its own to publish and a + * build of its own to compare. Tier CN is the same verification from the + * client-allocated side, and Tier NL is what an adapter binding nothing still + * does. */ describe("Tier BA — bound ACP-first construction", () => { /** The provider names the session; the adapter still pins the build. */ diff --git a/packages/acp/tests/provider.test.ts b/packages/acp/tests/provider.test.ts index 26c876047..b57129543 100644 --- a/packages/acp/tests/provider.test.ts +++ b/packages/acp/tests/provider.test.ts @@ -766,7 +766,7 @@ interface CoordinatorLog extends AgentLaunchCoordinator { checkpoints: unknown[]; } -/** The claim an authentic use carries, which any copy of it also carries. */ +/** The configuration marker an authentic use carries, which any copy of it also carries. */ const CONFIGURED_SESSION = Symbol.for("executablemd.agent.session.configured"); function stubCoordinator(): CoordinatorLog { @@ -1363,7 +1363,7 @@ describe("Tier PT — partitioned provider installation", () => { * the Deno workflow host composes it: a host-decided working directory, no MCP * servers, an empty requested tool set, and a permission path the public Agent * chain does not reach. The contextual cwd is a Workspace root throughout, - * because "the Agent never sees it" is the claim. + * because "the Agent never sees it" is the property under test. */ /** The logical Workspace root a workflow document's contextual cwd answers with. */ @@ -2714,7 +2714,7 @@ describe("Tier SO — agent option discovery", () => { * An established session is reattached eagerly, so the reconfiguration happens * while this run holds both a handle and the session's ownership. Neither may * outlive the attempt: a handle kept past it is a second owner of a - * conversation a native process may be in, and ownership left claimed is a + * conversation a native process may be in, and ownership left active is a * session no other operation can reach. */ describe("Tier SE — reconfiguring an owned session", () => { diff --git a/packages/cli/src/compiled-upgrade.ts b/packages/cli/src/compiled-upgrade.ts index a226d7c35..2c1fb071d 100644 --- a/packages/cli/src/compiled-upgrade.ts +++ b/packages/cli/src/compiled-upgrade.ts @@ -512,7 +512,7 @@ export function* compiledUpgradeComponents( * What every phase after the listing checks first. * * A value nothing admitted, a candidate from another invocation, and a - * candidate presented out of order are all the same thing: a claim of + * candidate presented out of order are all the same thing: an assertion of * admission that was never granted. None is a failure code, because * answering with an outcome would make a forged capability indistinguishable * from a release this command could not install. diff --git a/packages/cli/src/packaged-document.ts b/packages/cli/src/packaged-document.ts index 1cdb0bad2..954455c5f 100644 --- a/packages/cli/src/packaged-document.ts +++ b/packages/cli/src/packaged-document.ts @@ -33,7 +33,7 @@ export const UPGRADE_COMMAND_DOCUMENT = "upgrade-command.md"; * `xmd plan` reaches it through the thin root above and an ordinary run reaches * it by writing ``, and both expand these exact bytes. There is no * generated TypeScript copy and no second Markdown implementation, which is what - * makes "the same workflow" a fact about the file rather than a claim about two + * makes "the same workflow" a fact about the file rather than an assertion about two * of them. */ export const PLAN_DOCUMENT = "Plan.md"; diff --git a/packages/cli/src/plan-component.ts b/packages/cli/src/plan-component.ts index 8aaee7a7d..b7e0fa4ea 100644 --- a/packages/cli/src/plan-component.ts +++ b/packages/cli/src/plan-component.ts @@ -432,7 +432,7 @@ export function* planComponentDeclaration( * run in one. * * Inspection and validation answer about what a document may write. They mint no - * execution, so there is no claimant to build a private capability from and no + * execution, so there is no invocation authenticator to build a private capability from and no * frame to install — and none of that is describable anyway: a private name * is not syntax a document may write, so symbols listing one would describe an * environment that does not exist. @@ -464,7 +464,7 @@ export function* planComponentDescription(): Operation { * The private closure as a description: the names, origins and contracts, with * no implementation behind them. * - * Describing an environment mints no execution and therefore no claimant, so + * Describing an environment mints no execution and therefore no invocation authenticator, so * there is nothing to build one from. The factory is a refusal rather than an * omission: nothing that only describes a document reaches an implementation, so * it is unreachable — it is there so that anything which ever did would fail diff --git a/packages/cli/src/plan-writer-profile.ts b/packages/cli/src/plan-writer-profile.ts index 334411b12..d8f2b8b27 100644 --- a/packages/cli/src/plan-writer-profile.ts +++ b/packages/cli/src/plan-writer-profile.ts @@ -308,7 +308,7 @@ export function planAgentContext( }); } -/** What claiming one conversation's directory needs, and nothing more. */ +/** What exclusively acquiring one conversation's directory needs, and nothing more. */ export interface PlanWriterPlacement { /** Where this host keeps its authorship session directories. */ readonly root: string; diff --git a/packages/cli/src/plugin-host.ts b/packages/cli/src/plugin-host.ts index 7b4e9b66a..c67fab63a 100644 --- a/packages/cli/src/plugin-host.ts +++ b/packages/cli/src/plugin-host.ts @@ -7,7 +7,7 @@ * is decided — and an empty list installs nothing at all. That order fixes how * middleware composes — the first Plugin installed is the outermost wrapper — * and decides nothing else: - * two Plugins claiming one name, one component name or one structural construct + * two Plugins reserving one name, one component name or one structural construct * are refused rather than settled by position. * * Installation happens once per command, in the scope that encloses everything @@ -99,7 +99,7 @@ function incomplete(name: string, half: IncompleteStructural): Error { ); } -/** What two selections claiming one Plugin name are refused with. */ +/** What two selections using one Plugin name are refused with. */ function duplicate(name: string): Error { return new Error( `two selected Plugins are named ${name}. A Plugin name identifies one Plugin to this ` + diff --git a/packages/cli/src/repl/agent.ts b/packages/cli/src/repl/agent.ts index 964ed8524..ed68f6f16 100644 --- a/packages/cli/src/repl/agent.ts +++ b/packages/cli/src/repl/agent.ts @@ -40,8 +40,8 @@ * durable handoff, and the live turn it began is removed inside that same * transition, so no announced snapshot holds a turn both ways or neither. * - * A direct `Agent.prompt()` call begins nothing. It gets no reading, claims no - * record, and cannot be claimed by one. A turn replay restored asks no + * A direct `Agent.prompt()` call begins nothing. It gets no reading, correlates with no + * record, and cannot be correlated with one. A turn replay restored asks no * provider, so it begins nothing either: no association, and no live turn. * * ## A request without one owner is an invariant failure diff --git a/packages/cli/src/repl/application.ts b/packages/cli/src/repl/application.ts index b74680100..cdcfe3125 100644 --- a/packages/cli/src/repl/application.ts +++ b/packages/cli/src/repl/application.ts @@ -342,7 +342,7 @@ export type ReplFocusRestore = * * Named by what it caused rather than by where it sits: the record appends * after the drawer is gone, so the row does not exist yet at the moment the - * claim is made. `known` is every answer already retained when this one was + * association is recorded. `known` is every answer already retained when this one was * taken and `answer` is exactly what was sent, which together name one * record — not the newest one, and not an answer somebody else caused. */ @@ -433,7 +433,7 @@ export interface ReplState { /** * Where focus starts again, for the one commit after a drawer went. * - * One-shot and process-local. A claim repeated every frame would drag focus + * One-shot and process-local. A focus request repeated every frame would drag focus * back after every Tab, so the next action clears it: from then on focus is * the tree's, which is the only thing that knows where it is. */ @@ -599,7 +599,7 @@ export function permissionSettled(state: ReplState, turn: string): ReplState { * * Teardown and publication can both remove a request nobody answered. The drawer * it left behind can resolve to nothing, so it is withdrawn — and nothing here - * claims a choice or a denial, because none was made. + * reports a choice or a denial, because none was made. */ export function permissionWithdrawn(state: ReplState): ReplState { return Object.freeze({ @@ -1635,11 +1635,11 @@ function row( } /** - * Which control this frame claims focus for, because a drawer went. + * Which control this frame requests focus for, because a drawer went. * - * Resolved against what is mounted rather than stored: a claim naming a row this + * Resolved against what is mounted rather than stored: a request naming a row this * view does not draw would be focus asked for on behalf of nothing, and the - * commit that honoured it would throw. So the claim is silent for as long as the + * commit that honoured it would throw. So the request is silent for as long as the * row it names is not there — the answer's record has not been projected yet — * and the hint waits rather than being spent on nothing. */ @@ -1683,23 +1683,23 @@ export function focusClaim(view: ReplView): string | undefined { /** * The state after a commit settled focus. * - * A restoration claim is one claim, not a standing one. It survives the frames + * A restoration request is one request, not a standing one. It survives the frames * between the answer and its record — nothing can be focused that is not there * yet — and is spent by the commit that puts focus where it asked. Focus - * traversal is not an action, so a claim nobody retired would pull somebody back + * traversal is not an action, so a request nobody retired would pull somebody back * after every Tab and traversal would never move. */ export function focusSettled( view: ReplView, focused: string | undefined, /** - * What the frame that satisfied the claim admitted. + * What the frame that satisfied the request admitted. * - * Needed because a claim can *move* a window to show the row it names, and - * the move was computed from the claim: spending the claim without keeping + * Needed because a request can *move* a window to show the row it names, and + * the move was computed from the request: spending the request without keeping * the move would scroll the catalog straight back and take the row focus has * just landed on off the screen. A caller with no committed frame to hand — - * one asking only whether a claim is spent — leaves it out. + * one asking only whether a request is spent — leaves it out. */ admission?: ReplAdmission, ): ReplState { @@ -3308,7 +3308,7 @@ function drawerContent( * than the generic close action that means "this changed nothing". */ let dismissing: string | undefined; - /** Whether a field line may take the focus claim this drawer opens with. */ + /** Whether a field line may take the focus request this drawer opens with. */ let entering = false; if (open.kind === "binding") { @@ -3543,7 +3543,7 @@ function drawerContent( /** * One row of a drawer's ordered content, and what it would take to focus it. * - * A field's editable line is built unfocused and the claim is placed afterwards, + * A field's editable line is built unfocused and the focus request is placed afterwards, * once the window is known: focusing a row that scrolled out would put focus * where nothing is drawn, and which row is first inside the window is not * something the loop that builds them can see. @@ -3557,7 +3557,7 @@ interface DrawerRow { * The rows one drawer's measured window shows. * * Nothing while the frame is being measured, because the window is what that - * pass is asking about. The drawer's opening focus claim goes to the first field + * pass is asking about. The drawer's opening focus request goes to the first field * line the window actually holds. */ function windowed( @@ -4890,10 +4890,10 @@ export function entriesRowCount(model: ReplModel): number { } /** - * How far one window is scrolled, with a row this frame claims focus for shown. + * How far one window is scrolled, with a row this frame requests focus for shown. * * The offset this process is holding, moved only as far as it takes to put a - * claimed row inside the window: a claim naming a row the window does not hold + * requested row inside the window: a request naming a row the window does not hold * would be focus asked for on behalf of nothing, and an answer given at a narrow * size is restored to the entry that owns it — which may be above or below what * the catalog is showing. The window itself is the existing one and the offset is diff --git a/packages/cli/src/repl/components/rows.ts b/packages/cli/src/repl/components/rows.ts index cf4189fe3..56091684e 100644 --- a/packages/cli/src/repl/components/rows.ts +++ b/packages/cli/src/repl/components/rows.ts @@ -1,13 +1,13 @@ /** * The things a REPL screen is made of. * - * Each one renders exactly what its input says and claims exactly the input it + * Each one renders exactly what its input says and handles exactly the input it * has a meaning for. A row that has no use for Escape lets Escape pass, so the - * drawer above it still closes. That is the whole reason claims are per-node + * drawer above it still closes. That is the whole reason event handlers are per-node * rather than a table somewhere: the answer to "what does this keystroke mean" * depends on what is under the cursor. * - * A row that has no use for text claims none, and text nothing claims reaches + * A row that has no use for text handles none, and text nothing handles reaches * nothing: propagation runs up the ancestors of whatever holds focus, and the * draft is a sibling of these rows rather than an ancestor of them. So typing at * a control leaves the draft exactly as it was — which is the behavior, not an @@ -334,7 +334,7 @@ function rendered(input: ReplViewData): string { /** * A drawer: a modal branch, closed by Escape. * - * It claims Escape and nothing else. Escape closes the drawer and never answers + * It handles Escape and nothing else. Escape closes the drawer and never answers * the question inside it, because a person dismissing a prompt has not chosen * one of its options. */ diff --git a/packages/cli/src/repl/description.ts b/packages/cli/src/repl/description.ts index 2a02feb12..28994d4e4 100644 --- a/packages/cli/src/repl/description.ts +++ b/packages/cli/src/repl/description.ts @@ -34,7 +34,7 @@ import type { ReplPresentationRole } from "./presentation-style.ts"; * What a component may be given, and therefore what a tree may hold. * * View data and nothing else. A function or a class instance would carry - * behavior into a tree whose whole claim is that it holds values, and would be + * behavior into a tree whose contract is that it holds values, and would be * a way for a component to reach something the commit never saw. A component * narrows what it is given by parsing it, the way everything else in this * repository narrows data it did not construct. @@ -103,7 +103,7 @@ export function runText(runs: readonly ReplTokenRun[]): string { * Named because each one means something structural — submit, dismiss, move * focus, erase, interrupt — as opposed to text, which means only itself. * - * `Interrupt` is the one named key no mounted node claims: ending the command is + * `Interrupt` is the one named key no mounted node handles: ending the command is * a lifecycle outcome its owner decides, so the program answers this key where * it answers end of input, rather than a row answering it for the screen that * happens to be up. @@ -118,7 +118,7 @@ export type ReplKey = "Enter" | "Escape" | "Tab" | "Backtab" | "Backspace" | "In * happened and where; it never says what it means. * * Text is its own member rather than a key with a payload, because the two are - * answered differently: a named key is a command whoever claims it recognizes, + * answered differently: a named key is a command its handler recognizes, * and text is content that goes wherever content goes. It carries the string the * terminal decoded — one grapheme as typed, or `"\n"` for a newline inside a * paste — and never a raw terminal event. @@ -153,7 +153,7 @@ export interface ReplNode { /** What this node contributes to a frame. Replaces its previous cell. */ render(cell: string): void; /** - * Claim events reaching this node or passing through it on the way up. + * Handle events reaching this node or passing through it on the way up. * * Returning an action stops the walk and hands that action to the root; * returning nothing lets the next ancestor decide. @@ -165,7 +165,7 @@ export interface ReplNode { export interface ReplDefinition { readonly name: string; /** - * Construct this node: what it draws, what it claims, whether it can focus. + * Construct this node: what it draws, which events it handles, whether it can focus. * * Synchronous and effect-free. It runs once, during the commit that mounts * the node, and may return what to run when the node is removed. That diff --git a/packages/cli/src/repl/fitting.ts b/packages/cli/src/repl/fitting.ts index 3688fd7d2..3fb0354ea 100644 --- a/packages/cli/src/repl/fitting.ts +++ b/packages/cli/src/repl/fitting.ts @@ -79,7 +79,7 @@ export interface ReplPreparedRow { * whitespace of the logical line it continues as well — so a line that * wrapped is still read at the column it was written at. Without it a * continuation sits further left than the row above it and reads as a new, - * shallower line, which is a claim about structure that the source does not + * shallower line, which is a structural distinction that the source does not * make. * * Display only. No source byte and no offset moves, and concatenating a diff --git a/packages/cli/src/repl/frame.ts b/packages/cli/src/repl/frame.ts index 510415905..2dba2677d 100644 --- a/packages/cli/src/repl/frame.ts +++ b/packages/cli/src/repl/frame.ts @@ -23,7 +23,7 @@ * participant that subscribed for itself would keep its own clock running after * a sibling left, and a distant ancestor would hold the timer alive for a * subtree that stopped animating. The ancestor in between is the one whose - * lifetime matches the animation's, so a claim from anywhere else is refused. + * lifetime matches the animation's, so an ownership request from anywhere else is refused. * * `delta` is in **seconds**, because that is what the layout engine's * transitions take; handing it milliseconds runs every transition 1000x fast. @@ -81,13 +81,13 @@ export type ReplAncestry = readonly string[]; /** Who wants frames, and for what. */ export interface ReplFrameRequest { - /** The node claiming ownership. */ + /** The node requesting ownership. */ readonly owner: string; /** The ancestry of each participant, one entry per participating node. */ readonly participants: readonly ReplAncestry[]; } -/** A claim that is not the nearest common ancestor of its participants. */ +/** An ownership request naming something other than its participants' nearest common ancestor. */ export class ReplFrameOwnerError extends Error { constructor(owner: string, expected: string | undefined) { super( @@ -129,7 +129,7 @@ export interface ReplFrames { /** * Ask for frames for as long as the result is held. * - * A refused claim registers no demand at all, so holding an `Err` keeps no + * A refused ownership request registers no demand at all, so holding an `Err` keeps no * timer alive. */ subscribe(request: ReplFrameRequest): Operation>; diff --git a/packages/cli/src/repl/input.ts b/packages/cli/src/repl/input.ts index 443ca6e13..e708aa307 100644 --- a/packages/cli/src/repl/input.ts +++ b/packages/cli/src/repl/input.ts @@ -5,7 +5,7 @@ * composition layer has a meaning for and hands them over in its own closed * shape. Nothing here knows an action name: a normalized event says what * happened and where, and what it means is decided by whichever mounted node - * claims it. + * handles it. * * ## A lone Escape is not yet Escape * @@ -61,7 +61,7 @@ export interface ReplNormalized { * The keys this composition layer has a meaning for. * * Everything else a terminal can send is decoded and then dropped here rather - * than invented into an action: a key nothing claims is not an event the tree + * than invented into an action: a key nothing handles is not an event the tree * should be asked about. * * `Backspace` is the terminal's `DEL` (`0x7f`), which is what a keyboard's @@ -111,7 +111,7 @@ const INTERRUPT_CHORD = "c"; * so here, where the spelling stops mattering. * * Control is not consulted: a chord is dropped before this is asked, so - * Control-Shift-Tab stays a chord nothing claims rather than becoming a way to + * Control-Shift-Tab stays a chord nothing handles rather than becoming a way to * traverse. */ function backward(event: Extract): boolean { @@ -184,7 +184,7 @@ export interface ReplInputScan { * * Resize arrives here because the scanner decodes it, and leaves again as a * flag rather than an event: it is a host fact about the terminal, not - * something a mounted node claims. + * something a mounted node handles. */ export function scanInput(input: Input, bytes?: Uint8Array): ReplInputScan { const result: ScanResult = bytes === undefined ? input.scan() : input.scan(bytes); diff --git a/packages/cli/src/repl/journal.ts b/packages/cli/src/repl/journal.ts index 8e2d4a5bf..bfa304a78 100644 --- a/packages/cli/src/repl/journal.ts +++ b/packages/cli/src/repl/journal.ts @@ -20,8 +20,7 @@ * argument, so the kernel never reads a home directory, an environment variable * or a platform name to find one. * - * Writing is single-writer, which is the `DurableStream` contract and not a - * claim this feature strengthens. Two processes appending to one execution is + * Writing is single-writer, which is the `DurableStream` contract and not a guarantee this feature strengthens. Two processes appending to one execution is * outside that contract and unsupported; no lease is taken, because a lease * whose crash behavior nothing here proves would be a worse answer than the * documented one. diff --git a/packages/cli/src/repl/program.ts b/packages/cli/src/repl/program.ts index 4f48fbf89..0798c657e 100644 --- a/packages/cli/src/repl/program.ts +++ b/packages/cli/src/repl/program.ts @@ -1252,10 +1252,10 @@ interface ReplPainted { /** * What this frame admitted. * - * Handed back because settling a focus claim has to keep what the claim - * moved: a window the claim scrolled to show a row is the window a person is + * Handed back because settling a focus request has to keep what the request + * moved: a window the request scrolled to show a row is the window a person is * now looking at, and the offset this process holds has to become that one - * before the claim is spent. + * before the request is spent. */ readonly admission: ReplAdmission; } diff --git a/packages/cli/src/repl/reconcile.ts b/packages/cli/src/repl/reconcile.ts index 10ac101e3..7aa4f99fc 100644 --- a/packages/cli/src/repl/reconcile.ts +++ b/packages/cli/src/repl/reconcile.ts @@ -53,7 +53,7 @@ import type { ReplViewData, } from "./description.ts"; -/** An event reached a live node and nothing claimed it. */ +/** An event reached a live node and nothing handled it. */ export class ReplUnownedEventError extends Error { constructor(ancestry: readonly string[]) { super( @@ -97,9 +97,9 @@ export interface ReplFrame { * What delivering one normalized event did. * * Closed, so every outcome has to be handled and none of them is the absence - * of another: an action a node claimed, a focus move the tree itself owns, or + * of another: an action a node produced, a focus move the tree itself owns, or * an event that never reached a live node at all. An event that reached one - * and nothing claimed is not in here — that is an `Err`. + * and nothing handled is not in here — that is an `Err`. */ export type ReplDispatched = | { diff --git a/packages/cli/src/repl/renderer.ts b/packages/cli/src/repl/renderer.ts index 5fde5d7f2..6861dd990 100644 --- a/packages/cli/src/repl/renderer.ts +++ b/packages/cli/src/repl/renderer.ts @@ -98,7 +98,7 @@ export interface ReplFrameMap { /** * One box the committed frame may publish a target for. * - * Membership is the claim: a target exists because an admitted box mounted a + * Membership determines eligibility: a target exists because an admitted box mounted a * live node and that node is a control. Bounds alone cannot establish it — the * engine reports a clipped child's full rectangle, so geometry says nothing * about whether anything was painted. diff --git a/packages/cli/src/run-profile.ts b/packages/cli/src/run-profile.ts index f4963f750..4be96ba08 100644 --- a/packages/cli/src/run-profile.ts +++ b/packages/cli/src/run-profile.ts @@ -16,7 +16,7 @@ * here, without loading a module, and writing it once or five times leaves the * profile exactly as it was: Git appears once, first. That is a property of the * *host's own selector for its own bundled value*, and of nothing else — a - * module that merely claims the same Plugin name is a duplicate like any other, + * module that merely uses the same Plugin name is a duplicate like any other, * and `admitPlugins()` refuses it before anything installs. * * ## What this is not @@ -104,7 +104,7 @@ export function* assembleRunProfile( * dropped is the one object this host statically bundled — an operator who * wrote the reserved selector is holding exactly that value, and prefixing it * twice would be the host duplicating itself. A *different* Plugin that merely - * claims the same name is not this value, is not dropped, and meets + * uses the same name is not this value, is not dropped, and meets * `admitPlugins()`'s duplicate-name refusal like any other collision. Comparing * names here would have let an impostor disappear instead of collide. */ diff --git a/packages/cli/src/syntax.ts b/packages/cli/src/syntax.ts index f75da1b90..1a860891b 100644 --- a/packages/cli/src/syntax.ts +++ b/packages/cli/src/syntax.ts @@ -63,7 +63,7 @@ export { renderSyntaxMarkdown }; * operational and belongs to a run, so none of it happens here. * * `` travels as a declaration for the same reason: its factory takes - * an execution's claimant, and describing an environment mints no execution. + * an execution's invocation authenticator, and describing an environment mints no execution. * * The scope is bounded, and everything installed in it is declarative registry * state and documentation middleware. Leaving it removes the layer, and there @@ -115,7 +115,7 @@ function* profileSymbols( * round. * * The order is fixed rather than incidental. Nothing depends on it for - * resolution — two declarations claiming one name is refused at admission + * resolution — two declarations declaring one name is refused at admission * rather than settled by position — but a stable order makes a catalog's bytes * stable, which is what lets a source run and a compiled run be compared * directly. diff --git a/packages/cli/src/workflow-agent.ts b/packages/cli/src/workflow-agent.ts index cfc8e76e2..297cf4506 100644 --- a/packages/cli/src/workflow-agent.ts +++ b/packages/cli/src/workflow-agent.ts @@ -42,7 +42,7 @@ * Every other agent resolves through the baseline registry, to the same command * it always did, and retains the same compatibility identity it always did. * Carrying a patched Codex adapter says nothing about Gemini, and a registry - * that refused one would be making a far larger claim than this work needs. + * that refused one would be making a far broader restriction than this work needs. * * The override is qualified: an embedded provider never falls through. A * snapshot that cannot be verified, materialized or launched refuses that agent diff --git a/packages/cli/src/workflow-bundle.ts b/packages/cli/src/workflow-bundle.ts index 67754ed8f..ff9e5a605 100644 --- a/packages/cli/src/workflow-bundle.ts +++ b/packages/cli/src/workflow-bundle.ts @@ -153,7 +153,7 @@ export function declaredBundle( } /** - * Whether a declared name is one this bundle may claim, or the refusal saying + * Whether a declared name is one this bundle may declare, or the refusal saying * why it is not. * * Structural syntax and core's own components are fixed and checked here, while diff --git a/packages/cli/tests/agent-session-coordinator.test.ts b/packages/cli/tests/agent-session-coordinator.test.ts index e7b6ef213..644f77e77 100644 --- a/packages/cli/tests/agent-session-coordinator.test.ts +++ b/packages/cli/tests/agent-session-coordinator.test.ts @@ -2,7 +2,7 @@ * Tier HC — which hosts can own an agent session, and what the others do * (specs/native-agent-session-launch-spec.md §Hosts). * - * This file runs under all three runtimes, because the claim it makes is about + * This file runs under all three runtimes, because the behavior it tests is about * the differences between them: Deno and the compiled binary build a * coordinator, Node and Bun build none, and a provider handed none refuses * every advertised provider-returned operation before contacting an agent. @@ -227,7 +227,7 @@ const CLIENT_ALLOCATED: NativeAdapter = { /** * A route store that records every operation performed on it. * - * "Performs no route work" is a claim about absence, and absence is only + * "Performs no route work" is an assertion about absence, and absence is only * provable where something was watching. */ function countingRoutes(): { store: AgentSessionRouteStore; operations: string[] } { diff --git a/packages/cli/tests/compiled-upgrade.test.ts b/packages/cli/tests/compiled-upgrade.test.ts index 08db68e9f..28b263c53 100644 --- a/packages/cli/tests/compiled-upgrade.test.ts +++ b/packages/cli/tests/compiled-upgrade.test.ts @@ -154,7 +154,7 @@ function candidateIdentity(staged: unknown): string { /** A self-closing invocation, which is how every phase is written. */ const INVOCATION: ComponentInvocation = { hasContent: () => false }; -/** A claimant nothing here spends: none of these phases names durable work. */ +/** An invocation authenticator nothing here uses: none of these phases names durable work. */ // deno-lint-ignore require-yield function* claimNothing(): Operation { return "unused"; diff --git a/packages/cli/tests/fixtures/repl/issue-881/controlled-host.ts b/packages/cli/tests/fixtures/repl/issue-881/controlled-host.ts index 2c18b5ab5..de3192d87 100644 --- a/packages/cli/tests/fixtures/repl/issue-881/controlled-host.ts +++ b/packages/cli/tests/fixtures/repl/issue-881/controlled-host.ts @@ -38,8 +38,7 @@ import { ordinaryEvaluationProfile } from "../../../../src/evaluation-profile.ts * The two latch paths, narrowed once at the edge. * * Read and checked here so everything below has two strings rather than two - * possibly-absent ones: asserting them later would be claiming what this - * check is for. + * possibly-absent ones: asserting them later would be assuming what this check establishes. */ function latches(): { readonly entered: string; readonly release: string } { const entered = process.env.XMD881_ENTERED; diff --git a/packages/cli/tests/fixtures/repl/reference.ts b/packages/cli/tests/fixtures/repl/reference.ts index 5388283e9..c8921caf4 100644 --- a/packages/cli/tests/fixtures/repl/reference.ts +++ b/packages/cli/tests/fixtures/repl/reference.ts @@ -2,9 +2,9 @@ * The reference entry, executed for real. * * Every REPL test that needs a Journal gets one from here rather than from a - * recorded file, because the projector's whole claim is that it reads what the + * recorded file, because the projector's contract is that it reads what the * *current* runtime writes. A frozen event array would keep passing on the day - * core changed a record's shape, which is the day the claim stopped being true. + * core changed a record's shape, which is the day the contract stopped being true. * * The entry is one document deliberately holding one of each thing this slice * projects: a durable evaluation that publishes JSON, one nested component diff --git a/packages/cli/tests/fixtures/repl/surface.ts b/packages/cli/tests/fixtures/repl/surface.ts index 2f9a3ea3e..abd82d12c 100644 --- a/packages/cli/tests/fixtures/repl/surface.ts +++ b/packages/cli/tests/fixtures/repl/surface.ts @@ -200,7 +200,7 @@ const DRAWER_COMPONENT: ReplComponent = component({ /** * The draft line, which is where typing goes. * - * It claims text and Backspace as well as Enter, and answers each with its own + * It handles text and Backspace as well as Enter, and answers each with its own * semantic action. The host said what arrived; what it means to a draft — append, * erase, submit — is this component's to decide, which is why the same Enter that * activates a row submits here. diff --git a/packages/cli/tests/github-zero-effect.test.ts b/packages/cli/tests/github-zero-effect.test.ts index 85bebc7c8..19bb633a6 100644 --- a/packages/cli/tests/github-zero-effect.test.ts +++ b/packages/cli/tests/github-zero-effect.test.ts @@ -35,7 +35,7 @@ function forbidden(): never { /** * The bundled adapters, installed as a run profile installs them. * - * Present but untouched is the whole claim: describing a profile that *has* + * Present but untouched is the required behavior: describing a profile that *has* * the GitHub adapters in it must still read nothing. Without them installed * these cases would pass for the trivial reason that there was no adapter to * read anything. diff --git a/packages/cli/tests/packaged-document.test.ts b/packages/cli/tests/packaged-document.test.ts index 7b2008067..42e6cd925 100644 --- a/packages/cli/tests/packaged-document.test.ts +++ b/packages/cli/tests/packaged-document.test.ts @@ -29,7 +29,7 @@ import { useWorkingDirectory } from "./support/plan-harness.ts"; /** * The whole of the adapter's body, exactly. * - * Pinned rather than sampled, because "there is nothing else here" is the claim: + * Pinned rather than sampled, because "there is nothing else here" is the requirement: * `xmd plan` drains this root's rendered transcript onto stderr as the operator's * progress, so any prose the adapter regained would be printed in the middle of * a Plan being written. diff --git a/packages/cli/tests/plan-cli.test.ts b/packages/cli/tests/plan-cli.test.ts index 052c98a92..ad759b24f 100644 --- a/packages/cli/tests/plan-cli.test.ts +++ b/packages/cli/tests/plan-cli.test.ts @@ -1008,7 +1008,7 @@ function* journalEvents(path: string): Operation { * * Only the newline-terminated ones. An append this command made and the * filesystem then failed is not a transaction — `appendFile` can write some of - * a record and stop — so what a case about a *failed* append may claim is the + * a record and stop — so what a case about a *failed* append may establish is the * sequence that committed before it, and anything after the last terminator is * not part of that sequence. A case about an ending where no append failed * reads the whole file instead, and compares its bytes. diff --git a/packages/cli/tests/plan-command-document.test.ts b/packages/cli/tests/plan-command-document.test.ts index c454259d5..a084d27eb 100644 --- a/packages/cli/tests/plan-command-document.test.ts +++ b/packages/cli/tests/plan-command-document.test.ts @@ -145,8 +145,7 @@ interface RunOptions { * Providers backing this case's `component-answer` entries. * * Only a row that admits a name core supplies no body for needs one: the - * profile arm has nowhere to put an implementation, so a provider has to - * claim it during resolution. + * profile arm has nowhere to put an implementation, so a provider has to register its identity during resolution. */ componentAnswers?: readonly ComponentAnswerInstallation[]; /** @@ -1281,9 +1280,8 @@ describe("Tier PI — read-only information requests", () => { * A held-cleanup barrier cannot be built for this settlement, and the reason * is structural rather than an oversight. Cleanup inside a fragment is per * element: every element before the failure has already torn down, and no - * element after it runs. A provider handler cannot hold it either — the claim - * window is deliberately synchronous, so an `ensure` registered there ends the - * resolution ("this resolution has settled, so a claim stated now identifies + * element after it runs. A provider handler cannot hold it either — the registration window is deliberately synchronous, so an `ensure` registered there ends the + * resolution ("this resolution has settled, so an identity registered now identifies * nothing"). Nothing else a host supplies to a fragment has projection * lifetime. * diff --git a/packages/cli/tests/plan-component.test.ts b/packages/cli/tests/plan-component.test.ts index fd6c64b8c..545ba54eb 100644 --- a/packages/cli/tests/plan-component.test.ts +++ b/packages/cli/tests/plan-component.test.ts @@ -613,7 +613,7 @@ describe("Tier PC — in an ordinary document", () => { * the projection — and the refusal it produces is an ordinary one, which * this workflow turns into exactly one more turn. * - * The ordering half of this claim — that a descendant answering `true` + * The ordering half of this behavior — that a descendant answering `true` * cannot defeat an enclosing `false` — is Tier PM's, proved there against * the Api itself rather than duplicated here as another permutation. */ @@ -675,9 +675,9 @@ describe("Tier PC — in an ordinary document", () => { * trusted workflow reads through the ordinary chain either way. * * This drives the **real private body** off the declaration the production - * path builds, with a claimant that refuses the way core's does for a forged - * invocation; the control beside it, a claimant that answers, shows the body - * gets past the claim and on to its projection. So the ordering is what is + * path builds, with an authenticator that refuses the way core's does for a forged + * invocation; the control beside it, an authenticator that answers, shows the body + * gets past authentication and on to its projection. So the ordering is what is * asserted rather than the fact that something threw. */ it("PI25: the private information body runs only for its own invocation", function* () { diff --git a/packages/cli/tests/plugin-host.test.ts b/packages/cli/tests/plugin-host.test.ts index be6e4dc19..0fa516117 100644 --- a/packages/cli/tests/plugin-host.test.ts +++ b/packages/cli/tests/plugin-host.test.ts @@ -2,13 +2,13 @@ * Tier PH — installing the Plugins one command runs with. * * Order, admission and lifetime, and what each of them decides. Order fixes - * composition and nothing else: two Plugins claiming one name are refused + * composition and nothing else: two Plugins using one name are refused * before either installs, rather than the later one winning. Admission happens * before the first `install()`, so a refused selection installs nothing and * reads no document. And the whole list has the command's lifetime, so a * failure part-way through unwinds what came before it. * - * The review Plugin's own rows are here too, because which commands claim its + * The review Plugin's own rows are here too, because which commands reserve its * forty-one names is a property of this assembly rather than of the package — * and because nothing installs it until a selection names it. The graph itself * is `scripts/tests/review-infrastructure.test.ts`. diff --git a/packages/cli/tests/repl-agent-execution.test.ts b/packages/cli/tests/repl-agent-execution.test.ts index eff91a92f..f5bfc028d 100644 --- a/packages/cli/tests/repl-agent-execution.test.ts +++ b/packages/cli/tests/repl-agent-execution.test.ts @@ -1836,7 +1836,7 @@ function admitted(result: Result): void { } /** - * The same journal with its last recorded prompt claiming an earlier sequence. + * The same journal with its last recorded prompt reporting an earlier sequence. * * Doctored, because no run writes it: a sequence counts the Prompts of one * execution, so one entry holding a value twice is damage to the file rather than diff --git a/packages/cli/tests/repl-agent-interface.test.ts b/packages/cli/tests/repl-agent-interface.test.ts index a54c5bf86..d9dcbe967 100644 --- a/packages/cli/tests/repl-agent-interface.test.ts +++ b/packages/cli/tests/repl-agent-interface.test.ts @@ -2821,7 +2821,7 @@ function* showing(terminal: Terminal, expected: string): Operation { * * Bounded by the same real-time deadline every other wait here uses, and it * reports the rendered footer on timeout: a wait that only says it timed out - * leaves whoever reads it guessing which half of the claim failed. + * leaves whoever reads it guessing which half of the synchronization failed. */ function* untilScreen( terminal: Terminal, @@ -3835,7 +3835,7 @@ function* focusTheDraft(terminal: Terminal, limit = 240): Operation { * Read from the file rather than from the screen, because what a catalog row * proves is that an entry exists — not which bytes became it. The draft * clearing and `2.` appearing are both true of an entry admitted from the wrong - * source, so neither is the claim. + * source, so neither is the asserted behavior. * * Through the product's own reader, so the records are *parsed* rather than * trusted: a journal is whatever is on disk, and annotating `JSON.parse` would @@ -3860,7 +3860,7 @@ function* admittedSources(hostRoot: string): Operation { * * Read off the bottom-most row that carries the draft's own prompt, because the * draft owns the last footer row at every size and shares it with nothing. Exact - * rather than a containment check: the claim is that what somebody typed survived + * rather than a containment check: the requirement is that what somebody typed survived * byte for byte, and `contains` would pass on a draft that had grown a character. */ function draftOn(terminal: Terminal): string { diff --git a/packages/cli/tests/repl-agent-journey.test.ts b/packages/cli/tests/repl-agent-journey.test.ts index 9491e7f70..623df7163 100644 --- a/packages/cli/tests/repl-agent-journey.test.ts +++ b/packages/cli/tests/repl-agent-journey.test.ts @@ -13,7 +13,7 @@ * * The source in `STORY` is the one the Story publishes, exactly. The revised * program in `REVISED` is what a deterministic Agent returns for it, and it is - * fixture data rather than a claim about what a model would write: what it has + * fixture data rather than a prediction of what a model would write: what it has * to be is *legal* — a generated fragment under the ordinary ceiling, which may * write JSON literals, its own bindings, arrays and objects and may not compute * anything. That is why it compares two `` renderings instead of @@ -2342,7 +2342,7 @@ function occurrences(terminal: Terminal, text: string): number { * #881 PR 2 gave the Transcript the selected entry's reading, so the records of * every scope no longer appear there at once; the answers a nested scope * retained are read by selecting that scope, which is where the product says - * they were asked. Selecting is the claim: a row counted under the wrong scope + * they were asked. Selection is the behavior being tested: a row counted under the wrong scope * would be an answer attributed to somewhere it never happened. */ function* answeredUnder(terminal: Terminal, scope: string, text: string): Operation { diff --git a/packages/cli/tests/repl-boundaries.test.ts b/packages/cli/tests/repl-boundaries.test.ts index d2c7dd43b..275c61090 100644 --- a/packages/cli/tests/repl-boundaries.test.ts +++ b/packages/cli/tests/repl-boundaries.test.ts @@ -1,7 +1,7 @@ /** * The REPL's source boundaries (#848 S1). * - * Read from the source rather than from behaviour, because these are claims about + * Read from the source rather than from behaviour, because these are constraints on * what a module *can* reach. A component that never happens to touch the Journal * in one test is not a component that cannot; an import is. * @@ -677,7 +677,7 @@ interface Invocation { /** * Drive `runXmd` in this process with a REPL installer that counts. * - * The lifecycle claim is not about what the output says: it is that describing a + * The lifecycle requirement is not about what the output says: it is that describing a * command and refusing one never reach the host at all — no per-user directory, * no history file, no terminal mode. An installer that is never entered is the * only way to see that from outside. diff --git a/packages/cli/tests/repl-composition.test.ts b/packages/cli/tests/repl-composition.test.ts index 38597eb69..fa529880e 100644 --- a/packages/cli/tests/repl-composition.test.ts +++ b/packages/cli/tests/repl-composition.test.ts @@ -123,7 +123,7 @@ function banner(journal: Journal): ReplComponent { }); } -/** A focusable leaf that claims nothing, so events pass to its ancestors. */ +/** A focusable leaf that handles nothing, so events pass to its ancestors. */ function control(journal: Journal): ReplComponent { return component({ name: "control", diff --git a/packages/cli/tests/repl-entries.test.ts b/packages/cli/tests/repl-entries.test.ts index f49ae54cf..b7e574770 100644 --- a/packages/cli/tests/repl-entries.test.ts +++ b/packages/cli/tests/repl-entries.test.ts @@ -2,10 +2,10 @@ * Where one entry's history stops, and what the next one inherits (#827). * * Every journal here is written by really executing entries over one physical - * stream, each through its own segment view, because the whole claim is that the + * stream, each through its own segment view, because the invariant is that the * boundary is already in the records the current runtime writes. A frozen event * array would keep passing on the day core changed the shape of a root - * admission or a close — which is the day the claim stopped being true. + * admission or a close — which is the day the invariant stopped being true. * * The rows are named for the frozen evidence matrix: ES1 the exact segments, ES2 * the malformed prefixes that refuse whole, EM1 the stable keys and markers, EP1 @@ -2336,7 +2336,7 @@ function* transcriptOf(view: ReplView): Operation { /** * The Output half of the reading this view draws, caption included. * - * For the cases whose claim is about what an entry *produced*, which the + * For the cases that assert what an entry *produced*, which the * reading states separately from the source that produced it. */ function* outputOf(view: ReplView): Operation { diff --git a/packages/cli/tests/repl-exit-pty.test.ts b/packages/cli/tests/repl-exit-pty.test.ts index 8191b612a..2d0531726 100644 --- a/packages/cli/tests/repl-exit-pty.test.ts +++ b/packages/cli/tests/repl-exit-pty.test.ts @@ -36,7 +36,7 @@ import process from "node:process"; import { randomBytes } from "node:crypto"; import { ensure, type Operation, scoped, sleep, spawn, withResolvers } from "effection"; -/** Let every ready task run, so "still unwinding" is a claim about turns. */ +/** Let every ready task run, so "still unwinding" is an observation about turns. */ function* settled(turns = 8): Operation { for (let turn = 0; turn < turns; turn += 1) { yield* sleep(0); @@ -49,7 +49,7 @@ const WINDOW = { columns: 160, rows: 36 }; /** * How long reaching the screen may take, and how long leaving may take. * - * Two deadlines because they are two claims. Reaching the screen compiles an + * Two deadlines because they are two timing requirements. Reaching the screen compiles an * entrypoint, which is slow and uninteresting. Leaving is the subject: a command * that has been told to go and is waiting for a keystroke nobody will press is * the defect, and seconds are generous for a teardown that joins what it owns. @@ -138,9 +138,9 @@ function described(attempt: Attempt): string { /** * A child this scope owns, from before it exists until after it has closed. * - * The lifecycle claim this file is about applies to the file itself: a test that + * The lifecycle requirement this file is about applies to the file itself: a test that * proved a command joins what it owns, while leaking the process it proved it - * with, would be making the claim and breaking it in one row. + * with, would be stating the requirement and breaking it in one row. * * So the release is registered before the child is spawned — a cancellation * between the two must leave nothing running — and on teardown the child is diff --git a/packages/cli/tests/repl-forms.test.ts b/packages/cli/tests/repl-forms.test.ts index b4e18fb1f..152fb106a 100644 --- a/packages/cli/tests/repl-forms.test.ts +++ b/packages/cli/tests/repl-forms.test.ts @@ -1,7 +1,7 @@ /** * Bounded Elicit forms (#854 F1, F2, F3). * - * Three levels, each as small as the claim allows. F1 is the schema language on + * Three levels, each as small as the behavior being tested allows. F1 is the schema language on * its own, because parsing is a pure question. F2 drives the real provider — the * one `useReplElicitation()` installs — through the real reducer, so what judges * a submission is the compiled schema and not a test's idea of one. F3 reads the diff --git a/packages/cli/tests/repl-journey.test.ts b/packages/cli/tests/repl-journey.test.ts index 2a9a3adeb..5f9795a01 100644 --- a/packages/cli/tests/repl-journey.test.ts +++ b/packages/cli/tests/repl-journey.test.ts @@ -4152,7 +4152,7 @@ describe("REPL journey: a selection, a position and a draft across a resize", () * Whether one of these rows carries the selection marker before this label. * * The same reading as `marked`, over rows a caller has already chosen — which is - * what a claim about one size needs, since the accumulated buffer still holds + * what an assertion about one size needs, since the accumulated buffer still holds * the rows the other size drew. */ function markedIn(rows: readonly string[], label: string): boolean { @@ -4197,8 +4197,7 @@ const COLD_FOUR = [ * What each category of position is called, written out here on purpose. * * A second opinion about the wording. Reading it from `pointLabel()` would make - * the comparison below say only that one function agrees with itself, and the - * claim is that the drawer offers *these* words — a category and an order, with + * the comparison below say only that one function agrees with itself, and the requirement is that the drawer offers *these* words — a category and an order, with * nothing of the payload in them. */ const CATEGORIES: Readonly> = Object.freeze({ @@ -4247,7 +4246,7 @@ function bandOf(terminal: Terminal): string[] { /** * The same five rows, out of rows a caller has already chosen. * - * What a claim about one size needs: this renderer writes diffs, so the whole + * What an assertion about one size needs: this renderer writes diffs, so the whole * accumulated buffer still holds the rows the size before it drew, and the * footer of a 36-row screen is not where a 20-row screen keeps its band. */ @@ -5333,7 +5332,7 @@ describe("REPL first use: UI1 selection", () => { /** * The narrow guidance row is composed, not cut (#870 UI10/UI16). * - * Asserted by exact equality, because the claim is about the whole row. A row + * Asserted by exact equality, because the assertion covers the whole row. A row * written long and left to the renderer loses its last fact with nothing to say * that it has — and the facts at the end are the way out of a modal and the way * back to the draft. Equality catches both the overflow and the silent cut. @@ -6170,7 +6169,7 @@ describe("REPL first use: UI8", () => { * * `UI8` walks this path at `160x36`, where there is a transcript column to read * the answer's output in. A narrow frame has no transcript region at all — it - * mounts one routed outlet — so this row proves the other half of the claim: that + * mounts one routed outlet — so this row proves the other half of the behavior: that * everything a person has to *do* is reachable at `72x20`, found from the labels * and the one guidance row, with no hidden key and no semantic lookup. * diff --git a/packages/cli/tests/repl-layout-admission.test.ts b/packages/cli/tests/repl-layout-admission.test.ts index 11de370c9..f31c3842c 100644 --- a/packages/cli/tests/repl-layout-admission.test.ts +++ b/packages/cli/tests/repl-layout-admission.test.ts @@ -2,8 +2,7 @@ * Measured admission (#875 TL2–TL5). * * One real layout engine pair, one real Freedom tree, and a terminal cell grid - * that accumulates what every frame actually wrote. What is under test is the - * one claim the whole boundary rests on: **the rows and controls a person can + * that accumulates what every frame actually wrote. What is under test is the invariant the whole boundary rests on: **the rows and controls a person can * see, focus and click are exactly the rows and controls the measured frame * admitted.** * diff --git a/packages/cli/tests/repl-model.test.ts b/packages/cli/tests/repl-model.test.ts index f79903fbb..849b7866d 100644 --- a/packages/cli/tests/repl-model.test.ts +++ b/packages/cli/tests/repl-model.test.ts @@ -38,7 +38,7 @@ function projected(events: readonly DurableEvent[], selection?: string): ReplMod /** * The root scope of the one entry a one-entry journal projects. * - * Read off `entries` at the public boundary, which is where this suite's claim + * Read off `entries` at the public boundary, which is where this suite's assertions * now lives: every journal here holds one entry, and what these assertions are * about is what that entry holds rather than how many the collection can hold. */ diff --git a/packages/cli/tests/repl-presentation-style.test.ts b/packages/cli/tests/repl-presentation-style.test.ts index 553b4a11b..87b1481c7 100644 --- a/packages/cli/tests/repl-presentation-style.test.ts +++ b/packages/cli/tests/repl-presentation-style.test.ts @@ -9,7 +9,7 @@ * * Every assertion names a rectangle the committed frame published and reads the * characters and the attributes out of it. That is the whole discrimination: a - * cyan code written anywhere else on the screen cannot satisfy a claim about the + * cyan code written anywhere else on the screen cannot satisfy an assertion about the * selected field, and a role attached to a candidate the manifest left out paints * nothing at all. * diff --git a/packages/cli/tests/repl-terminal.test.ts b/packages/cli/tests/repl-terminal.test.ts index c324cf767..9fb5da910 100644 --- a/packages/cli/tests/repl-terminal.test.ts +++ b/packages/cli/tests/repl-terminal.test.ts @@ -1483,7 +1483,7 @@ describe("REPL terminal: an owned input stream, and what releasing it costs", () * A Node-shaped standard input this row pushes into by hand. * * The real `process.stdin` decides for itself when a paste becomes one chunk or - * several, which is exactly what the claim below must not depend on. This one + * several, which is exactly what the assertion below must not depend on. This one * delivers precisely the chunks it is told to, so "two chunks were already * waiting" is a fact of the row rather than a hope about the host. */ diff --git a/packages/cli/tests/run-composition-deno.test.ts b/packages/cli/tests/run-composition-deno.test.ts index 50f80a5b8..b576d45cf 100644 --- a/packages/cli/tests/run-composition-deno.test.ts +++ b/packages/cli/tests/run-composition-deno.test.ts @@ -6,7 +6,7 @@ * describe the same language and operate none of it — is * `run-composition.test.ts`, which runs everywhere. * - * Three claims about a root execution's own provider: where a Session launched + * Three behaviors about a root execution's own provider: where a Session launched * in a managed Worktree lands, that an ordinary journal is diagnostic, and that * a diagnostic trace grants nothing. What a nested `host="run"` child gets is a * separate question about a separate provider instance, asked in diff --git a/packages/cli/tests/run-composition-nested.test.ts b/packages/cli/tests/run-composition-nested.test.ts index f43bede6b..5a97faae5 100644 --- a/packages/cli/tests/run-composition-nested.test.ts +++ b/packages/cli/tests/run-composition-nested.test.ts @@ -121,7 +121,7 @@ function runOrdinary( describe("ORC19 — a nested run profile", () => { /** - * The claims here are about a real `` child, so they + * These cases exercise a real `` child, so they * are asked of a real `xmd run` — a subprocess, launched the way a person * launches one. * @@ -149,7 +149,7 @@ describe("ORC19 — a nested run profile", () => { * * ## Why `` rather than `xmd test` * - * Two of these claims are about what a *parent* holds while its child runs — + * Two of these cases exercise what a *parent* holds while its child runs — * publication evidence, and a lease. `xmd test` installs no repository * provider for its own document, by design: only its children get one. So the * parent here is an ordinary `xmd run`, which has a provider of its own, and @@ -418,7 +418,7 @@ describe("ORC19 — a nested run profile", () => { * `` reaches its Git host through `source.open()`, and the * evidence gate runs ahead of it. The refusal says so itself — "Nothing was * observed at the Git host, and no pull request was created" — so that - * sentence is the claim rather than an inference from it. + * sentence is the assertion rather than an inference from it. * * The second assertion is the corroborating one: a local file origin is not * a Git host, so an execution that had got past the gate would have failed diff --git a/packages/cli/tests/run-composition.test.ts b/packages/cli/tests/run-composition.test.ts index 60419a49e..6642637b1 100644 --- a/packages/cli/tests/run-composition.test.ts +++ b/packages/cli/tests/run-composition.test.ts @@ -1,7 +1,7 @@ /** * Tier ORC — how the command line assembles repository operations. * - * Three claims, and they are about opposite things. Describing the vocabulary + * Three requirements, and they are about opposite things. Describing the vocabulary * must reach nothing; one runtime *operates* it; and one only *describes* it. * All three have to be true at once, so a document written for `xmd run` * resolves the same twelve names everywhere, and on a runtime that operates @@ -13,7 +13,7 @@ * The declarations are the same array in every case, which is why there is no * fourth thing to keep in agreement. * - * Everything here runs under Deno, Node and Bun. The parity claim is not one to + * Everything here runs under Deno, Node and Bun. The parity requirement is not one to * defer to CI: what it asserts is that a runtime with no operational provider * still describes and resolves the whole language. */ diff --git a/packages/cli/tests/support/pull-request-server.ts b/packages/cli/tests/support/pull-request-server.ts index af3a3c2c2..0021897b7 100644 --- a/packages/cli/tests/support/pull-request-server.ts +++ b/packages/cli/tests/support/pull-request-server.ts @@ -5,7 +5,7 @@ * seam to inject a transport through: what the adapter talks to has to be a * socket. This is that socket — the three review endpoints and the pull request * itself, answering the shapes the adapter parses, and recording every request - * so a fork that performed one cannot claim it restored instead. + * so a fork that performed one cannot report that it restored instead. */ import { createServer, type IncomingMessage, type ServerResponse } from "node:http"; diff --git a/packages/cli/tests/syntax-cli.test.ts b/packages/cli/tests/syntax-cli.test.ts index c7b1b6c58..8717fd31a 100644 --- a/packages/cli/tests/syntax-cli.test.ts +++ b/packages/cli/tests/syntax-cli.test.ts @@ -2,8 +2,7 @@ * Tier SX — the `xmd syntax` command. * * Two halves, matching the command's own. The profile rows run in process, - * because what they check is which declarations `xmd run` installs — a claim - * about assembly, not about argv. The grammar, failure and delivery rows shell + * because what they check is which declarations `xmd run` installs — an assertion about assembly, not about argv. The grammar, failure and delivery rows shell * out, so exit status, stdout and stderr are the ones an operator sees. * * Symbol behavior itself is Tier SY's; nothing here re-proves selection. diff --git a/packages/cli/tests/test-root-profile.test.ts b/packages/cli/tests/test-root-profile.test.ts index dea9235fc..7932f926e 100644 --- a/packages/cli/tests/test-root-profile.test.ts +++ b/packages/cli/tests/test-root-profile.test.ts @@ -4,7 +4,7 @@ * XMD bundles one Plugin and activates it for the commands that execute or * describe a document. `xmd test` is not one of them: the root is a harness * that decides what its children run, and a harness that quietly gained the - * repository vocabulary would be claiming names its children are entitled to + * repository vocabulary would be reserving names its children are entitled to * shadow. * * So the same element resolves in two places and not in a third, and that diff --git a/packages/cli/tests/value-root.test.ts b/packages/cli/tests/value-root.test.ts index fc2a586ec..67cea52e8 100644 --- a/packages/cli/tests/value-root.test.ts +++ b/packages/cli/tests/value-root.test.ts @@ -133,7 +133,7 @@ const DUPLICATE_RETURN_ROOT = [ * * `expand.return` is reachable by name from an eval block, so the document * reads the carrier the engine published, tries to write a selected value onto - * it, tries to clear its claim, and finally replaces the context with a + * it, tries to clear its return-state reservation, and finally replaces the context with a * fully-formed forgery. Its one authored `` is unselected, so anything * it manages to select would be a value the engine never validated. */ diff --git a/packages/cli/tests/workflow-agent.test.ts b/packages/cli/tests/workflow-agent.test.ts index 171ef1feb..4f2f46905 100644 --- a/packages/cli/tests/workflow-agent.test.ts +++ b/packages/cli/tests/workflow-agent.test.ts @@ -53,7 +53,7 @@ const NOTE = "the release checklist is three items long\n"; * What ACPX resolves this agent to, and what the base branch retained for it. * * Written out rather than read back through `createAgentRegistry()`, because - * the claim is that this value did not move. Recomputing it from the same + * the requirement is that this value did not move. Recomputing it from the same * registry the profile now overlays would agree with whatever that registry * currently says, which is not the thing being asserted. */ @@ -787,7 +787,7 @@ describe("Tier WAL — the workflow Agent observation loop", () => { /** * One complete run under its own materialization root. * - * Real embedded adapters, because the claim is about what a real + * Real embedded adapters, because the assertion covers what a real * materialization retains — a stub would be asserting on a value this test * had chosen. */ diff --git a/packages/cli/tests/workflow-cli.test.ts b/packages/cli/tests/workflow-cli.test.ts index 6ccf01527..f48c4555f 100644 --- a/packages/cli/tests/workflow-cli.test.ts +++ b/packages/cli/tests/workflow-cli.test.ts @@ -70,7 +70,7 @@ const RELEASE = [ * * A `` refusal is a *printed* error — data, and the run still completes — * so a failed run needs an error nothing recovers. The unresolvable component - * is one, and it doubles as the evidence for the other claim this fixture + * is one, and it doubles as the evidence for the other invariant this fixture * carries: a workflow definition is one immutable object, 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. diff --git a/packages/cli/tests/workflow-crash.test.ts b/packages/cli/tests/workflow-crash.test.ts index 0105d01ef..53ffbe18d 100644 --- a/packages/cli/tests/workflow-crash.test.ts +++ b/packages/cli/tests/workflow-crash.test.ts @@ -69,8 +69,7 @@ function definition(count: number): string { * in a position to notice one, and a runtime notices at its event loop. A * document made only of file effects is a long stretch of work that reaches the * event loop rarely, so a `SIGINT` aimed at it may be observed nowhere near - * where it was sent — the interruption is real but its timing is not the test's - * to claim. This document has a place where the run is unambiguously waiting, + * where it was sent — the interruption is real but its timing is not the test's to determine. This document has a place where the run is unambiguously waiting, * and everything about interruption is asserted there. * * Its shape also makes the wait *observable from outside*: the effects before it diff --git a/packages/cli/tests/workflow-export-publication.test.ts b/packages/cli/tests/workflow-export-publication.test.ts index d016d329a..67602163a 100644 --- a/packages/cli/tests/workflow-export-publication.test.ts +++ b/packages/cli/tests/workflow-export-publication.test.ts @@ -140,7 +140,7 @@ interface Step { interface Recorder { /** The steps that were reached, in order. */ readonly log: string[]; - /** Each step with the path it acted on, so a claim can name the path too. */ + /** Each step with the path it acted on, so an assertion can name the path too. */ readonly steps: Step[]; readonly filesystem: ExportFilesystem; } diff --git a/packages/cli/tests/workflow-suspension.test.ts b/packages/cli/tests/workflow-suspension.test.ts index 8c62dc735..76b596201 100644 --- a/packages/cli/tests/workflow-suspension.test.ts +++ b/packages/cli/tests/workflow-suspension.test.ts @@ -786,7 +786,7 @@ describe("Tier WFS — a suspended run and its no-input resumes", () => { * One real `` turn, one real generated-XMD observation and one real * file mutation, all before the question. Each is an ordinary durable effect * with its own journal entry, which is what makes "the resume repeated none of - * them" a claim about the journal rather than about a counter this suite kept. + * them" an assertion about the journal rather than about a counter this suite kept. */ const CHECKPOINT_SCHEMA = `{"type":"object","properties":{"proceed":{"type":"boolean"}},"required":["proceed"]}`; diff --git a/packages/code-review-agent/src/plugin.ts b/packages/code-review-agent/src/plugin.ts index 51e841ce3..40749d2bb 100644 --- a/packages/code-review-agent/src/plugin.ts +++ b/packages/code-review-agent/src/plugin.ts @@ -1,10 +1,11 @@ /** * Install the packaged review graph when an operator selects this Plugin. * - * Run, syntax, plan and executing workflow actions claim its thirty-five Markdown - * declarations and six reserved registrations, so the repository being reviewed - * cannot replace the review program. Root `xmd test` claims none; its isolated - * `` child reinstalls this Plugin with command `run`. + * Run, syntax, plan and executing workflow actions reserve its thirty-five + * Markdown declarations and six reserved registrations, so the repository being + * reviewed cannot replace the review program. Root `xmd test` reserves none; + * its isolated `` child reinstalls this Plugin with + * command `run`. */ import type { Operation } from "effection"; @@ -20,9 +21,10 @@ const EXECUTING_ACTIONS: ReadonlySet = new Set(["start", "resume", "fork /** * Workflow options whose separated values must not be mistaken for actions. * Keep this aligned with `workflowConfig` in `packages/cli/src/workflow.ts` and - * argv-level Plugin/root-property options; the CLI dependency prevents importing - * its grammar here. For example, `workflow --output start export run-1` exports - * and must not claim the review graph because the output value reads `start`. + * argv-level Plugin/root-property options; the CLI dependency prevents + * importing its grammar here. For example, `workflow --output start export + * run-1` exports and must not install the review graph because the output value + * reads `start`. */ const VALUED_OPTIONS: ReadonlySet = new Set([ "--plugin", @@ -46,9 +48,9 @@ function takesValue(token: string): boolean { } /** - * Read the first positional after `workflow`, skipping options and their values. - * Stop at `--`; unknown actions remain the command's own grammar error and claim - * no review graph. + * Read the first positional after `workflow`, skipping options and their + * values. Stop at `--`; unknown actions remain the command's own grammar error + * and install no review graph. */ function executesDocument(args: readonly string[]): boolean { const start = args.indexOf("workflow"); diff --git a/packages/code-review-agent/src/review-components.ts b/packages/code-review-agent/src/review-components.ts index 31a5cf9c2..03c52a811 100644 --- a/packages/code-review-agent/src/review-components.ts +++ b/packages/code-review-agent/src/review-components.ts @@ -1,16 +1,17 @@ /** * Declare the packaged review graph before a root document is imported. * - * Thirty-five Markdown components cross as {@link MarkdownComponent} values with - * packaged bytes, stable asset origins and digests. Six TypeScript components use - * reserved registrations. Both claim names so the repository being reviewed - * cannot replace its reviewers; duplicate host claims refuse at admission. - * Ordinary includes and component discovery remain available for unclaimed names. + * Thirty-five Markdown components cross as {@link MarkdownComponent} values + * with packaged bytes, stable asset origins and digests. Six TypeScript + * components use reserved registrations. Both reserve names so the repository + * being reviewed cannot replace its reviewers; duplicate host reservations + * refuse at admission. Ordinary includes and component discovery remain + * available for unreserved names. * * Assets resolve from this module's own URL in source, npm and compiled builds. - * Read them through the Effection filesystem directly: document-facing API.Fs and - * Files middleware must not substitute the review program. Missing assets fail - * assembly rather than leaving an empty component claim. + * Read them through the Effection filesystem directly: document-facing API.Fs + * and Files middleware must not substitute the review program. Missing assets + * fail assembly rather than leaving an empty component reservation. */ import { readTextFile } from "@effectionx/fs"; diff --git a/packages/core/host.ts b/packages/core/host.ts index f044081e3..f9d3e8ac4 100644 --- a/packages/core/host.ts +++ b/packages/core/host.ts @@ -198,9 +198,10 @@ export type { SyntaxSymbolsProvider } from "./src/syntax-reference.ts"; export type { DurablePreparation } from "./src/document-request.ts"; /** - * What a trusted host declares to an execution when one of its components names - * durable work after its own invocation — see `src/invocation-identity.ts`. - * The claimant is delivered to the factory and published nowhere. + * What a trusted host declares to an execution when one of its components + * names durable work after its own invocation — see + * `src/invocation-identity.ts`. The identity authenticator is delivered to the + * factory and published nowhere. */ export { ComponentInvocationError } from "./src/invocation-identity.ts"; export type { IdentityClaimant, IdentityComponent } from "./src/invocation-identity.ts"; diff --git a/packages/core/src/agent/checkpoint.ts b/packages/core/src/agent/checkpoint.ts index f315c69da..c7433aa5b 100644 --- a/packages/core/src/agent/checkpoint.ts +++ b/packages/core/src/agent/checkpoint.ts @@ -33,9 +33,9 @@ export interface AgentPromptCheckpoint { /** * What kind of identity the value is. * - * Tagged, because "an App Server turn id" and "an assistant message uuid" are - * different claims that happen to be strings. A host comparing them without - * the tag would accept one for the other. + * Tagged, because "an App Server turn id" and "an assistant message uuid" + * are different identifiers that happen to be strings. A host comparing them + * without the tag would accept one for the other. */ readonly kind: string; /** diff --git a/packages/core/src/agent/components.ts b/packages/core/src/agent/components.ts index 8c87d4712..b2b7c61f7 100644 --- a/packages/core/src/agent/components.ts +++ b/packages/core/src/agent/components.ts @@ -84,9 +84,10 @@ interface SequencedFailure { * * `` is not registered with the rest of the agent words: its * implementation names durable work after its own invocation, and what may do - * that is fixed by the execution before any installation runs, from a claimant - * delivered straight to this factory. A document run by a host that declares - * none has no `` at all, which is the safe direction. + * that is fixed by the execution before any installation runs, from an + * identity authenticator delivered straight to this factory. A document run by + * a host that declares none has no `` at all, which is the safe + * direction. */ export function agentIdentityComponents(): readonly IdentityComponent[] { return [ diff --git a/packages/core/src/agent/configuration-record.ts b/packages/core/src/agent/configuration-record.ts index a1eb84017..06123f294 100644 --- a/packages/core/src/agent/configuration-record.ts +++ b/packages/core/src/agent/configuration-record.ts @@ -18,10 +18,10 @@ * asked for. * * So they are read and dropped: validated, because a member that does not read - * back means the record is not the record it claims to be, and then discarded. - * Neither is ever written again, and a record carrying one *beside* a canonical - * configuration is ambiguous about which account is current — which is a - * refusal rather than a precedence rule. + * back means the record is not the record it describes itself as, and then + * discarded. Neither is ever written again, and a record carrying one *beside* + * a canonical configuration is ambiguous about which account is current — + * which is a refusal rather than a precedence rule. */ import { Err, Ok } from "effection"; diff --git a/packages/core/src/agent/function-components.ts b/packages/core/src/agent/function-components.ts index 367e52540..f2a6bdcc9 100644 --- a/packages/core/src/agent/function-components.ts +++ b/packages/core/src/agent/function-components.ts @@ -217,11 +217,13 @@ export function* AgentComponent(props: Record): Operation { } /** - * ``, closed over the claimant that names its placements. + * ``, closed over the identity authenticator that names its + * placements. * - * Built per execution, from the claimant that execution delivered to this - * factory: an implementation built for one execution's `` names - * nothing under another's, and nothing at some other element's invocation. + * Built per execution, from the identity authenticator that execution + * delivered to this factory: an implementation built for one execution's + * `` names nothing under another's, and nothing at some other + * element's invocation. */ export function sessionComponent(claim: IdentityClaimant): FunctionComponent { return function* SessionComponent( diff --git a/packages/core/src/agent/journal.ts b/packages/core/src/agent/journal.ts index 44aed8831..058b4d036 100644 --- a/packages/core/src/agent/journal.ts +++ b/packages/core/src/agent/journal.ts @@ -623,7 +623,8 @@ function serializePermission(permission: PromptPermission): Json { const UNREADABLE = Symbol("unreadable permission audit"); /** - * The audits one durable record carries, read as the closed shape they claim. + * The audits one durable record carries, read as the closed shape they + * describe. * * Closed in both directions: every member is checked, and a member nothing here * defines refuses the whole record rather than being read past. An audit is @@ -722,7 +723,7 @@ function isRecord(value: unknown): value is Record { } /** - * One durable `agent_prompt` result, as the record it claims to be. + * One durable `agent_prompt` result, as the record it describes itself as. * * Pure and total: it reads a value nobody has authenticated and answers with * the record or with nothing, so a caller that has only retained bytes — a diff --git a/packages/core/src/agent/launch-coordinator.ts b/packages/core/src/agent/launch-coordinator.ts index 956100727..ff387ece6 100644 --- a/packages/core/src/agent/launch-coordinator.ts +++ b/packages/core/src/agent/launch-coordinator.ts @@ -121,7 +121,7 @@ export interface AgentLaunchCoordinator { * authored. A name answers with nothing; an ordinary session answers with * itself and no configuration; a use this installation issued answers with * the value the provider issued and what it runs under; and a value that - * claims to be a configured use and is not one refuses. + * presents itself as a configured use and is not one refuses. */ sessionUse(routed: string | Session | undefined): ReadSessionUse | undefined; /** diff --git a/packages/core/src/agent/launch-install.ts b/packages/core/src/agent/launch-install.ts index b229b2ee5..52cd1a050 100644 --- a/packages/core/src/agent/launch-install.ts +++ b/packages/core/src/agent/launch-install.ts @@ -159,8 +159,8 @@ export function* useConfiguredSession( * * Core's own read, for the one thing core owns about a configuration: writing * it down. A name or an ordinary session answers with nothing; a value that - * claims to be a configured use and is not one refuses here exactly as it would - * at the provider. + * presents itself as a configured use and is not one refuses here exactly as + * it would at the provider. */ export function* sessionUseConfiguration( routed: string | Session | undefined, diff --git a/packages/core/src/agent/launch-journal.ts b/packages/core/src/agent/launch-journal.ts index 929e175e5..322d476de 100644 --- a/packages/core/src/agent/launch-journal.ts +++ b/packages/core/src/agent/launch-journal.ts @@ -138,8 +138,8 @@ function reconciliation(value: unknown): InstructionReconciliation | undefined { * A merged #518 record has no provenance member, and could not have been * client-allocated because that path did not exist in the released format. So * absence reads as `provider-returned`. That is the one inference this parser - * makes, and it only ever infers the weaker claim: client allocation must say - * so explicitly. + * makes, and it only ever infers the weaker provenance: client allocation must + * say so explicitly. */ function provenance(value: unknown): IdentityProvenance | undefined { if (value === undefined) { diff --git a/packages/core/src/agent/publication.ts b/packages/core/src/agent/publication.ts index 88d49543a..1b00b34ea 100644 --- a/packages/core/src/agent/publication.ts +++ b/packages/core/src/agent/publication.ts @@ -68,7 +68,8 @@ export interface AgentPromptPublication { * This is the only thing that says which live turn this publication ends. A * prompt that never began canonically — a direct `Agent.prompt()` call from * a component, which core does not journal — reaches no publication at all, - * so it can neither claim this one nor be claimed by it. + * so this publication cannot be associated with that prompt in either + * direction. */ readonly begun: AgentPromptHandle; /** diff --git a/packages/core/src/agent/session-use.ts b/packages/core/src/agent/session-use.ts index 927d79a6f..7c89ffcc4 100644 --- a/packages/core/src/agent/session-use.ts +++ b/packages/core/src/agent/session-use.ts @@ -13,15 +13,15 @@ * provider returned and wraps it: the result *is* that session — same * `sessionKey`, same `cwd`, same asserted identity — so every consumer written * against `string | Session` keeps working and nothing new appears in the - * public signatures. What the wrapper adds is a claim anyone can see and an + * public signatures. What the wrapper adds is a marker anyone can see and an * authority nobody can copy. * - * The claim is a symbol-keyed marker, deliberately visible and deliberately - * copied by a spread. The authority is a private field, which appears in no key - * list, no descriptor and no copy. A value carrying the claim without the - * authority is therefore not an ordinary session that happens to look like one: - * it is something that presented itself as a configured use and cannot be, and - * it is refused rather than quietly run unconfigured. + * The marker is symbol-keyed, deliberately visible and deliberately copied by + * a spread. The authority is a private field, which appears in no key list, no + * descriptor and no copy. A value carrying the marker without the authority is + * therefore not an ordinary session that happens to look like one: it is + * something that presented itself as a configured use and cannot be, and it is + * refused rather than quietly run unconfigured. * * Authority belongs to the installation that issued it. A use from another * document installation, or from a second loaded copy of this package, carries @@ -32,10 +32,10 @@ import type { Session, SessionConfiguration } from "./agent-api.ts"; /** - * What a configured use claims to be. + * What a configured use presents itself as. * * Exported so a reader can recognize the shape; holding it grants nothing, - * because the claim is not the authority. + * because the marker is not the authority. */ export const CONFIGURED_SESSION: unique symbol = Symbol.for( "executablemd.agent.session.configured", @@ -60,7 +60,7 @@ export interface ReadSessionUse { readonly configuration?: SessionConfiguration; } -/** Why a routed value that claims to be a configured use is not one. */ +/** Why a routed value that presents itself as a configured use is not one. */ export class AgentSessionUseError extends Error { override name = "AgentSessionUseError"; } @@ -152,13 +152,13 @@ export function sessionOf(value: string | Session | undefined): Session | undefi /** * What a routed value says its conversation runs under. * - * Nothing for a name or an ordinary session. The frozen configuration for a use - * this build issued. A refusal for a value that claims to be one and is not: - * reading such a value as an ordinary session would run the conversation under - * settings nobody chose, which is the failure this whole shape exists to - * prevent. Whether a use belongs to *this* installation is a further question, - * and it is answered where the operation acts — through the coordinator core - * delivers to the installed provider. + * Nothing for a name or an ordinary session. The frozen configuration for a + * use this build issued. A refusal for a value that presents itself as one and + * is not: reading such a value as an ordinary session would run the + * conversation under settings nobody chose, which is the failure this whole + * shape exists to prevent. Whether a use belongs to *this* installation is a + * further question, and it is answered where the operation acts — through the + * coordinator core delivers to the installed provider. */ export function configurationOf( value: string | Session | undefined, @@ -202,7 +202,7 @@ export function issueSessionUse( * - nothing, for a name or an ordinary `Session` — an unconfigured operation, * which reads and writes no configuration at all; * - the frozen configuration, for a use this installation issued; - * - a refusal, for a value that claims to be a configured use and is not one — + * - a refusal, for a value that presents itself as a configured use and is not one — * a spread, a descriptor-for-descriptor copy, the real session paired with * different settings, a use from another installation or another loaded copy. * diff --git a/packages/core/src/bound-exec.ts b/packages/core/src/bound-exec.ts index 0f2acba70..5639c840e 100644 --- a/packages/core/src/bound-exec.ts +++ b/packages/core/src/bound-exec.ts @@ -14,12 +14,12 @@ * invented an outcome would decide what the document read. * * So a bound block is asked for through a request only this module issues, and - * canonical core composes the chain against the context it kept rather than the - * one that came back. Middleware still composes around the operation: it may - * observe it, refuse it by throwing, and delegate it. What it cannot do is + * canonical core composes the chain against the context it kept rather than + * the one that came back. Middleware still composes around the operation: it + * may observe it, refuse it by throwing, and delegate it. What it cannot do is * produce the outcome — whatever it returns is ignored, a failure canonical * execution raised stays raised even if it is caught, and a request that was - * not issued here, was issued for another block, or has already been claimed + * not issued here, was issued for another block, or has already been consumed * runs nothing at all. */ diff --git a/packages/core/src/component-answers.ts b/packages/core/src/component-answers.ts index 05ba2a835..7709123d2 100644 --- a/packages/core/src/component-answers.ts +++ b/packages/core/src/component-answers.ts @@ -1,11 +1,11 @@ /** * How a trusted host says what is behind a provider-backed fragment entry. * - * A `component-answer` entry names something the ordinary import chain resolves - * rather than an operation core supplies a body for. The host does not hand - * over the implementation — it states which name, and which structural identity - * a provider must have claimed for that name. This module is the seam a - * provider uses to make that claim. + * A `component-answer` entry names something the ordinary import chain + * resolves rather than an operation core supplies a body for. The host does + * not hand over the implementation — it states which name, and which + * structural identity a provider must have stated for that name. This module + * is the seam a provider uses to state that identity. * * ## Being asked and answering are two separate rights * @@ -29,14 +29,13 @@ * context name behind any of these objects, which is what lets a separately * loaded copy of core hold one without any of those being a way in. * - * ## Claiming is not permission + * ## Identifying is not permission * - * Claiming identifies an answer. It permits nothing. A fragment still needs - * the host entry, an exact identity match, the right `allow` class, whole- - * fragment preflight and canonical generated import — all of them - * independently. Middleware that answers an import without claiming anything is - * an ordinary replacement and stays exactly as valid as it was; what it cannot - * do is enter an admitted fragment. + * An identity statement permits nothing. A fragment still needs the host entry, an exact identity match, the right `allow` + * class, whole- fragment preflight and canonical generated import — all of + * them independently. Middleware that answers an import without stating an + * identity is an ordinary replacement and stays exactly as valid as it was; + * what it cannot do is enter an admitted fragment. */ import type { Operation } from "effection"; @@ -58,7 +57,7 @@ export type { ComponentAnswerRequest } from "./components/component-resolution.t * the asked name and position arriving as a request rather than as loose * arguments. Delegation is unchanged: `yield* next()` reaches the rest of the * chain, and an outer handler may delegate, look at what came back, and then - * claim its own replacement before returning. + * identify its own replacement before returning. */ export type ComponentAnswerHandler = ( request: ComponentAnswerRequest, diff --git a/packages/core/src/component-expansion.ts b/packages/core/src/component-expansion.ts index c5ab0b874..16321664d 100644 --- a/packages/core/src/component-expansion.ts +++ b/packages/core/src/component-expansion.ts @@ -6,12 +6,13 @@ * the public `Component.expand` chain composes around it, and exactly one * delegation of that exact request runs the work. * - * Observation only. What middleware returns is ignored, what it catches it does - * not rescue, and the outgoing result stays private until canonical acceptance - * has reconciled it — so an observer learns what happened and decides nothing - * about it. The authority is the same one `bound-exec.ts` keeps: a private - * brand nothing outside can forge, a claim that can be spent once, and a - * settlement readable whether or not the chain returned normally. + * Observation only. What middleware returns is ignored, what it catches it + * does not rescue, and the outgoing result stays private until canonical + * acceptance has reconciled it — so an observer learns what happened and + * decides nothing about it. The authority is the same one `bound-exec.ts` + * keeps: a private brand nothing outside can forge, a request that can be + * consumed once, and a settlement readable whether or not the chain returned + * normally. */ import { createQueue, ensure, Err, Ok } from "effection"; diff --git a/packages/core/src/components/Evaluate.ts b/packages/core/src/components/Evaluate.ts index 87f33b49e..d5b33e00c 100644 --- a/packages/core/src/components/Evaluate.ts +++ b/packages/core/src/components/Evaluate.ts @@ -98,7 +98,7 @@ import { CORE_ORIGIN } from "./registry.ts"; import { documented } from "./documentation.ts"; import type { FunctionComponentDefinition, Json, PropsSchema } from "../types.ts"; -/** The public name canonical core claims for the evaluation component. */ +/** The public name canonical core reserves for the evaluation component. */ export const EVALUATE_COMPONENT = "Evaluate"; /** The classes this component accepts, and the order a selection canonicalizes to. */ @@ -325,7 +325,7 @@ interface SelectedTables { * The host's captured tables, as the pinned identities the evaluator admits. * * A class the host installed nothing for is refused here — before the durable - * name is claimed and before a program exists — rather than reaching the + * name is assigned and before a program exists — rather than reaching the * evaluator as an empty table. The identity a run retains is built from the * three structural parts the host stated, so a reader comparing two admissions * can say which part moved. diff --git a/packages/core/src/components/File.ts b/packages/core/src/components/File.ts index febe76bf7..c650bbcce 100644 --- a/packages/core/src/components/File.ts +++ b/packages/core/src/components/File.ts @@ -50,12 +50,12 @@ * * ## Threat model * - * Containment is the provider's claim, not this component's. The host provider - * judges it against the filesystem as it observes it, which is sound while the - * host pathname namespace is stable; a transaction-bound provider resolves - * logical paths that never reach a host filesystem call at all. Deferring the - * second stage until immediately before the write is what covers the - * document's own children under either. + * Containment is the provider's responsibility, not this component's. The host + * provider judges it against the filesystem as it observes it, which is sound + * while the host pathname namespace is stable; a transaction-bound provider + * resolves logical paths that never reach a host filesystem call at all. + * Deferring the second stage until immediately before the write is what covers + * the document's own children under either. */ import type { Operation } from "effection"; diff --git a/packages/core/src/components/Syntax.ts b/packages/core/src/components/Syntax.ts index 5c123e7e8..6982b8e55 100644 --- a/packages/core/src/components/Syntax.ts +++ b/packages/core/src/components/Syntax.ts @@ -9,12 +9,12 @@ * ## Why canonical core owns it * * The symbols describe the vocabulary an execution actually has. A repository - * `Syntax.md`, a bundled `Syntax`, a registration, an import handler or a second - * loaded copy answering for the name would each describe a vocabulary the run - * does not have — to whoever is reading, and to whichever agent is being told - * what to write next. So the name is claimed by the canonical protected tier, - * ahead of every host and author tier, and the definition canonical core - * selected is what runs. + * `Syntax.md`, a bundled `Syntax`, a registration, an import handler or a + * second loaded copy answering for the name would each describe a vocabulary + * the run does not have — to whoever is reading, and to whichever agent is + * being told what to write next. So the name is reserved by the canonical + * protected tier, ahead of every host and author tier, and the definition + * canonical core selected is what runs. * * Protection is about the *answer*, not about power. The component receives one * reference that renders symbol text and nothing else: no definitions, no @@ -24,12 +24,12 @@ * * ## What one occurrence does * - * It claims the occurrence identity this execution minted, renders once, and - * retains exactly what it rendered. A continuation reads that record and hands - * the same text back without consulting the filesystem, the registry, the - * bundle, the host or the lexical reference again — so an agent resuming - * authorship is shown the vocabulary the run actually showed it, not one - * rebuilt from a tree that has moved since. + * It authenticates the occurrence identity this execution minted, renders + * once, and retains exactly what it rendered. A continuation reads that record + * and hands the same text back without consulting the filesystem, the + * registry, the bundle, the host or the lexical reference again — so an agent + * resuming authorship is shown the vocabulary the run actually showed it, not + * one rebuilt from a tree that has moved since. */ import { createDurableOperation, StaleInputError } from "@executablemd/durable-streams"; @@ -52,7 +52,7 @@ import { CORE_ORIGIN } from "./registry.ts"; import { documented } from "./documentation.ts"; import type { Json, PropsSchema, SourcePosition } from "../types.ts"; -/** The public name canonical core claims for the syntax component. */ +/** The public name canonical core reserves for the syntax component. */ export const SYNTAX_COMPONENT = "Syntax"; /** The durable effect one occurrence records. */ diff --git a/packages/core/src/components/Test.ts b/packages/core/src/components/Test.ts index d590456eb..67201ce11 100644 --- a/packages/core/src/components/Test.ts +++ b/packages/core/src/components/Test.ts @@ -1,13 +1,13 @@ /** * `` — the construct whose invocation contains a checked failure (§3.6). * - * This function is the whole of core's claim. It is private to this module in - * every sense that matters: it is never registered by another package, never - * handed to an installation, never named in an option, and never reachable - * through the public surface. `expandFunctionComponent` grants containment to - * the definition it is expanding when that definition is this one, so what may - * contain a checked command failure is decided by canonical core and by - * nothing else. + * This function is the whole of core's containment authority. It is private to + * this module in every sense that matters: it is never registered by another + * package, never handed to an installation, never named in an option, and + * never reachable through the public surface. `expandFunctionComponent` grants + * containment to the definition it is expanding when that definition is this + * one, so what may contain a checked command failure is decided by canonical + * core and by nothing else. * * It is an ordinary **default**, like every other component in the core * registry: a repository `Test.md` or `Test.ts` is chosen ahead of it, and so diff --git a/packages/core/src/components/bundle.ts b/packages/core/src/components/bundle.ts index 91b59b0c9..2a6de9a89 100644 --- a/packages/core/src/components/bundle.ts +++ b/packages/core/src/components/bundle.ts @@ -32,7 +32,7 @@ * witness for the answer it produced and verifies it at the call site. * * All of it is execution-local. The catalog is created per invocation and - * reclaimed with it, so two concurrent workflows declaring one name with + * released with it, so two concurrent workflows declaring one name with * different sources resolve their own and can observe neither. */ @@ -145,10 +145,10 @@ export class WorkflowComponentCatalog implements ImportTier { * which was consulted first. * * The collision checks run here, before the root document is imported, because - * a bundle that claims a name the engine or a host already owns describes a - * document that cannot mean what it says. Structural syntax and core's defaults - * are fixed; a reserved registration is whatever this host installed, read once - * from the registry the execution starts with. + * a bundle that reserves a name the engine or a host already owns describes a + * document that cannot mean what it says. Structural syntax and core's + * defaults are fixed; a reserved registration is whatever this host installed, + * read once from the registry the execution starts with. */ export function installedBundle( bundles: readonly WorkflowComponentBundle[], diff --git a/packages/core/src/components/component-resolution.ts b/packages/core/src/components/component-resolution.ts index bf208a370..582bd21c6 100644 --- a/packages/core/src/components/component-resolution.ts +++ b/packages/core/src/components/component-resolution.ts @@ -36,11 +36,11 @@ export interface ComponentResolution { * * Owning a name's resolution includes refusing it canonically when no * definition is admitted; it does not mean a usable definition was found. - * It is a claim about *that name*, not about the execution that made it. A - * workflow bundle closes every import because a workflow run is a run of one - * pinned tree; a host declaring exact Markdown closes only the names it - * declared, so an unrelated name resolves and composes exactly as it does in - * an execution that closes nothing. + * Ownership covers *that name*, not the whole execution. A workflow bundle + * closes every import because a workflow run is a run of one pinned tree; a + * host declaring exact Markdown closes only the names it declared, so an + * unrelated name resolves and composes exactly as it does in an execution + * that closes nothing. */ resolves(name: string): boolean; /** @@ -190,7 +190,7 @@ export interface ClaimedIdentity { * One identified answer: what a provider stated, and what core kept of it. * * The two travel together because a caller needs both and must not obtain them - * separately. The definition is core's own copy, taken when the claim was + * separately. The definition is core's own copy, taken when the identity was * recorded; it is what the caller keeps, and it is why nothing downstream ever * reads the object the public chain returned a second time. */ @@ -200,7 +200,8 @@ export interface IdentifiedAnswer { } /** - * What one answer object was claimed to be, and which resolutions claimed it. + * What one answer object was identified as, and which resolutions identified + * it. * * One implementation says what it is once, so the name, the identity and the * installation belong to the object: a new resolution cannot rename it, restate @@ -215,9 +216,10 @@ export interface IdentifiedAnswer { * cannot be forged into being the one the caller opened. * * A reusable provider returns one immutable definition to every import it - * answers. Keying the claim by the object alone made the first resolution part - * of the object's permanent identity and refused the same definition the second - * time, which is a provider being punished for not copying itself. + * answers. Keying the identity record by the object alone made the first + * resolution part of the object's permanent identity and refused the same + * definition the second time, which is a provider being punished for not + * copying itself. */ interface Claim { readonly name: string; @@ -225,26 +227,28 @@ interface Claim { /** Which provider installation stated it, so a second cannot overwrite. */ readonly installation: object; /** - * Core's copy of the definition the first claim described. + * Core's copy of the definition the first identity statement described. * - * The identity above is a statement about *this* definition, so a later claim - * of the same object has to be a claim about the same definition. Without this - * baseline, a provider could claim an object, edit it, and have the next window - * retain the edited version under the identity and revision that described the - * original — a different implementation wearing the first one's name. + * The identity above is a statement about *this* definition, so a later + * identity statement of the same object has to be a statement about the same + * definition. Without this baseline, a provider could identify an object, + * edit it, and have the next window retain the edited version under the + * identity and revision that described the original — a different + * implementation wearing the first one's name. * - * Absent when the first claim could not be copied at all, which is not a state - * a later claim can improve: an answer core could not retain is not one it can - * start vouching for because the object has since changed. + * Absent when the definition in the first identity statement could not be + * copied at all, which is not a state a later identity statement can + * improve: an answer core could not retain is not one it can start vouching + * for because the object has since changed. */ readonly baseline: ImportedDefinition | undefined; /** - * One retained copy per resolution this answer was claimed in. + * One retained copy per resolution this answer was identified in. * - * Weak on the window, so a claim lasts exactly as long as somebody still holds - * the resolution it belongs to. Presence is the provenance check: a window - * that never claimed this answer has no entry, and `identify` answers nothing - * for it however many other windows did. + * Weak on the window, so an identity record lasts exactly as long as + * somebody still holds the resolution it belongs to. Presence is the + * provenance check: a window that never identified this answer has no entry, + * and `identify` answers nothing for it however many other windows did. */ readonly copies: WeakMap; } @@ -254,7 +258,7 @@ export const REVOKED_ANSWER_IDENTIFICATION = "the execution that installed this answer provider has ended, so nothing it states identifies " + "an implementation here"; -/** A claim stated outside the handler invocation it would have been an answer to. */ +/** An identity stated outside the handler invocation it would have been an answer to. */ export const SETTLED_CLAIM = "this resolution has settled, so a claim stated now identifies nothing. An answer is " + "identified by the handler invocation the import asked, while that invocation is still " + @@ -279,7 +283,7 @@ export interface ResolutionWindow { readonly name: string; /** Which resolution this is, for a reader following two of them. */ readonly occurrence: number; - /** Stop admitting claims for this resolution. Idempotent. */ + /** Stop accepting identity statements for this resolution. Idempotent. */ close(): void; } @@ -287,11 +291,12 @@ export interface ResolutionWindow { * What one handler invocation may state about the import it was asked. * * Minted per invocation, and closed the moment that invocation returns, throws - * or is cancelled. This is what a provider actually claims through: - * the installation gives a provider the right to *be asked*, and the request - * gives it the right to answer this one asking. Separating them is what makes a - * claim provable — a stable installation handle can only say "some provider", - * while a request says "this handler, deciding this import, right now". + * or is cancelled. This is what a provider states an identity through: the + * installation gives a provider the right to *be asked*, and the request gives + * it the right to answer this one asking. Separating them is what makes a + * statement provable — a stable installation handle can only say "some + * provider", while a request says "this handler, deciding this import, right + * now". * * There is no `name` parameter on `claim`. The name is fixed when the request * is minted, from what the chain asked, so a handler cannot state an answer for @@ -373,17 +378,17 @@ export class CanonicalImports { /** * The one resolution this owner has open, if it has one. * - * A provider installation outlives every resolution it takes part in, while a - * fresh request belongs to one handler invocation. Canonical execution asks - * the chain for one name, reads the answer, and closes the occurrence. A - * claim arriving outside that window is a losing or delayed handler recording - * into a decision already made, which is exactly what an admission must not - * acquire afterwards. + * A provider installation outlives every resolution it takes part in, while + * a fresh request belongs to one handler invocation. Canonical execution + * asks the chain for one name, reads the answer, and closes the occurrence. + * An identity statement arriving outside that window is a losing or delayed + * handler recording into a decision already made, which is exactly what an + * admission must not acquire afterwards. * - * So the window carries both terms. The occurrence keeps a claim from - * belonging to a resolution other than the live one, and the name keeps a - * handler settled for one name from recording under it while a different - * name is being resolved. + * So the window carries both terms. The occurrence keeps an identity + * statement from belonging to a resolution other than the live one, and the + * name keeps a handler settled for one name from recording under it while a + * different name is being resolved. * * One window at a time, because component answers are resolved in one serial * capture phase before any document expands: the execution asks for each @@ -433,7 +438,7 @@ export class CanonicalImports { } /** - * Open the claim window for one resolution of one name. + * Open the identity-recording window for one resolution of one name. * * Canonical execution calls this immediately before asking the ordinary chain * and closes it in a `finally`, so the window ends the same way whether the @@ -640,13 +645,13 @@ export class CanonicalImports { * the caller's question. * * Both halves come back together, and the copy is the one taken when the - * claim was recorded rather than one made now. Answering with the identity - * alone would leave the caller holding the chain's object and needing to copy - * it itself — one more read of a value the chain controls, after the read - * this one checked. An alternating proxy or an accessor that answers twice - * would pass the check and hand the second answer to the copy. So the check - * and the thing kept are one result of one call, and the object that - * travelled through the chain is never read again. + * identity was recorded rather than one made now. Answering with the + * identity alone would leave the caller holding the chain's object and + * needing to copy it itself — one more read of a value the chain controls, + * after the read this one checked. An alternating proxy or an accessor that + * answers twice would pass the check and hand the second answer to the copy. + * So the check and the thing kept are one result of one call, and the object + * that travelled through the chain is never read again. */ identify(resolution: ResolutionWindow, answer: unknown): IdentifiedAnswer | undefined { if (!this.#active || typeof answer !== "object" || answer === null) { @@ -792,13 +797,13 @@ export interface ImportTier { claims(name: string): boolean; /** * Whether this tier closes every import in the execution, or only the names - * it claims. + * it reserves. * * A workflow bundle closes the execution: a run is a run *of* that pinned * tree, and a name resolving outside it is the thing the bundle exists to * prevent. Exact declared Markdown closes only what it declares: the host - * claimed those names and nothing else, so closing an unrelated import would - * take away a supported way to decide what a name means without any + * reserved those names and nothing else, so closing an unrelated import + * would take away a supported way to decide what a name means without any * declaration having said anything about it. */ readonly closesExecution: boolean; @@ -853,7 +858,7 @@ export class ExecutionImports implements ComponentResolution { /** * The tier this name is closed by, if any. * - * A tier that claims the name answers for it; otherwise a tier that closes + * A tier that reserves the name answers for it; otherwise a tier that closes * the whole execution does, which is what keeps a bundled run's every import * — and every refusal's wording — exactly what it was. */ diff --git a/packages/core/src/components/declared-markdown.ts b/packages/core/src/components/declared-markdown.ts index 85ff9e57a..3a2318f7c 100644 --- a/packages/core/src/components/declared-markdown.ts +++ b/packages/core/src/components/declared-markdown.ts @@ -16,21 +16,21 @@ * * A repository file, a workflow bundle member and an ordinary registration can * all answer for a name. A declared component answers ahead of every one of - * them, beside a reserved registration, because the host is claiming the name - * rather than offering a default for it. Two claims on one name are a + * them, beside a reserved registration, because the host is reserving the name + * rather than offering a default for it. Two reservations of one name are a * configuration failure rather than a precedence question, so a declaration - * colliding with a reserved registration or with another declaration is refused - * before the root document is imported. + * colliding with a reserved registration or with another declaration is + * refused before the root document is imported. * * ## The private closure * * A declaration may carry components only its own bytes may write. They are - * *lexical availability*, not permission: each is an ordinary - * {@link IdentityComponent}, built from a claimant this execution minted, and - * it names nothing once the invocation it was given settles. What makes them - * private is that nothing registers them — they are resolvable only while - * canonical core is expanding the body of the exact declaration that carries - * them, and the register below is offered and taken inside one import. + * *lexical availability*, not permission: each is an ordinary {@link + * IdentityComponent}, built from an identity authenticator this execution + * minted, and it names nothing once the invocation it was given settles. What + * makes them private is that nothing registers them — they are resolvable only + * while canonical core is expanding the body of the exact declaration that + * carries them, and the register below is offered and taken inside one import. * * Caller-projected content is not that body. Projection restores the caller's * frame and the caller's own resolution, so content written by whoever invoked the @@ -514,7 +514,7 @@ export class InstalledComponents implements ImportTier { } /** - * A declaration claims the names it declares and says nothing about any + * A declaration reserves the names it declares and says nothing about any * other, so an unrelated import composes exactly as it does in an execution * with no declarations at all. Closing those too would take a supported way * to decide what a name means away from every host that declares one asset. diff --git a/packages/core/src/components/declared-registry.ts b/packages/core/src/components/declared-registry.ts index a06683782..ea30b49e7 100644 --- a/packages/core/src/components/declared-registry.ts +++ b/packages/core/src/components/declared-registry.ts @@ -19,11 +19,11 @@ import type { ComponentRegistry, FunctionComponentDefinition, RegistryEntry } fr * can decide against. * * The implementation slot holds a refusal rather than what the factory would - * build, because building it is exactly what this cannot do: the factory - * takes an execution's claimant, and there is no execution here. Nothing that - * only describes a document reaches an implementation, so the refusal is - * unreachable — it is there so that anything which ever did would fail loudly - * rather than run a component with no execution behind it. + * build, because building it is exactly what this cannot do: the factory takes + * an execution's identity authenticator, and there is no execution here. + * Nothing that only describes a document reaches an implementation, so the + * refusal is unreachable — it is there so that anything which ever did would + * fail loudly rather than run a component with no execution behind it. */ export function declaredRegistry(components: readonly IdentityComponent[]): ComponentRegistry { const entries = new Map(); diff --git a/packages/core/src/components/fixed-filesystem.ts b/packages/core/src/components/fixed-filesystem.ts index 68e4b358f..67248023e 100644 --- a/packages/core/src/components/fixed-filesystem.ts +++ b/packages/core/src/components/fixed-filesystem.ts @@ -1,6 +1,6 @@ /** - * The three filesystem components canonical core claims the names of - * (spec §§6.13, 6.13.1, 6.13.2). + * The three filesystem components canonical core reserves the names of (spec + * §§6.13, 6.13.1, 6.13.2). * * ``, `` and `` read, write, remove and enter paths. A * document that names one has named an effect on the author's own filesystem, diff --git a/packages/core/src/components/protected.ts b/packages/core/src/components/protected.ts index fd254d3f3..84df6637c 100644 --- a/packages/core/src/components/protected.ts +++ b/packages/core/src/components/protected.ts @@ -2,10 +2,11 @@ * The names canonical core answers for, ahead of every other tier. * * Resolution already had a protected tier — a reserved registration, or exact - * Markdown a host declared — but both of those are *a host's* claim, made by - * whoever assembled the run. This tier is the engine's own, and it sits above - * them: a protected name means the same thing in every execution, whichever host - * built it, whichever package registered what, and whatever a repository holds. + * Markdown a host declared — but both of those are *a host's* reservation, + * made by whoever assembled the run. This tier is the engine's own, and it + * sits above them: a protected name means the same thing in every execution, + * whichever host built it, whichever package registered what, and whatever a + * repository holds. * * There are five components in it, for two reasons. `` describes the * vocabulary of the site it is written at, and a description of a run's @@ -21,13 +22,13 @@ * * ## Two shapes, one tier * - * What a protected name claims is settled here; how its implementation comes + * What a protected name denotes is settled here; how its implementation comes * about is not the same for all five. `` and `` are handed * a site canonical execution built for them, so each execution builds their - * bodies from a claimant it minted. The three filesystem components are - * ordinary components whose bodies reach the filesystem through contextual - * operations, so each is one definition built once per loaded copy of core and - * answered with as it stands. + * bodies from an identity authenticator it minted. The three filesystem + * components are ordinary components whose bodies reach the filesystem through + * contextual operations, so each is one definition built once per loaded copy + * of core and answered with as it stands. * * Both shapes carry the same descriptive members, because selection, * inspection, documentation and validation ask every protected component the @@ -71,24 +72,25 @@ import type { ProtectedDeclaration } from "../invocation-identity.ts"; import type { ComponentOrigin, FunctionComponentDefinition } from "../types.ts"; /** - * One component canonical core claims the name of, whose body each execution + * One component canonical core reserves the name of, whose body each execution * builds. * - * The same contract an identity component declares, minus the choice of origin: - * a protected component is core's, so it reports core's origin. Its body is - * built once per execution, with the claimant that execution minted, and the - * implementation the execution wraps it in is the only thing that name resolves - * to there. + * The same contract an identity component declares, minus the choice of + * origin: a protected component is core's, so it reports core's origin. Its + * body is built once per execution, with the identity authenticator that + * execution minted, and the implementation the execution wraps it in is the + * only thing that name resolves to there. */ export interface ExecutionBuiltComponent extends ProtectedDeclaration, ComponentDocumentation {} /** - * One component canonical core claims the name of and supplies as it stands. + * One component canonical core reserves the name of and supplies as it stands. * - * The definition is the whole of it. There is no claimant to mint and no site - * to build, so the execution's protected table answers with this exact object — - * which is also what the generated-XMD write table pins, so an authored element - * and an admitted generated one invoke one implementation. + * The definition is the whole of it. There is no identity authenticator to + * mint and no site to build, so the execution's protected table answers with + * this exact object — which is also what the generated-XMD write table pins, + * so an authored element and an admitted generated one invoke one + * implementation. */ export interface FixedComponent extends ComponentDocumentation { readonly name: string; @@ -100,7 +102,7 @@ export interface FixedComponent extends ComponentDocumentation { readonly definition: FunctionComponentDefinition; } -/** One component canonical core claims the name of, however it is supplied. */ +/** One component canonical core reserves the name of, however it is supplied. */ export type ProtectedComponent = ExecutionBuiltComponent | FixedComponent; /** @@ -134,7 +136,7 @@ export const FIXED_COMPONENTS: readonly FixedComponent[] = Object.freeze( FIXED_FILESYSTEM_DEFINITIONS.map(fixedComponent), ); -/** Every name the engine itself claims. */ +/** Every name the engine itself reserves. */ export const PROTECTED_COMPONENTS: readonly ProtectedComponent[] = Object.freeze([ ...EXECUTION_BUILT_COMPONENTS, ...FIXED_COMPONENTS, @@ -158,10 +160,10 @@ export function protectedComponent(name: string): ProtectedComponent | undefined * Its own kind, because reusing `registered` with `reserved: true` said * something untrue. A reserved registration is a *host* installing a component * under a name it wants kept, so it can be absent from another execution, - * replaced by a different host, or refused when two hosts claim it. A protected - * component is core's own declaration: present in every execution, supplied by - * no registry, and unable to be registered at all. Reporting one as the other - * told a reader the name was a host's to take. + * replaced by a different host, or refused when two hosts reserve it. A + * protected component is core's own declaration: present in every execution, + * supplied by no registry, and unable to be registered at all. Reporting one + * as the other told a reader the name was a host's to take. */ export function protectedOrigin( component: ProtectedComponent, @@ -169,12 +171,12 @@ export function protectedOrigin( return { kind: "protected", origin: component.origin }; } -/** A protected name a host, a bundle or a registration tried to claim. */ +/** A protected name a host, a bundle or a registration tried to reserve. */ export class ProtectedComponentError extends Error { override name = "ProtectedComponentError"; } -/** What a name that canonical core owns refuses a second claim with. */ +/** What a name that canonical core owns refuses a second reservation with. */ export function protectedNameRefusal(name: string, claim: string): string { return ( `cannot ${claim} "${name}": canonical core owns that name, so what it means is the same in ` + @@ -199,9 +201,10 @@ const REFUSED: Record = { /** * The tier a protected import is verified through. * - * It closes the names it claims and nothing else, exactly as a declaration does: - * claiming `Syntax` says nothing about what any other name in the execution may - * resolve to, and every other import stays the open one it has always been. + * It closes the names it reserves and nothing else, exactly as a declaration + * does: reserving `Syntax` says nothing about what any other name in the + * execution may resolve to, and every other import stays the open one it has + * always been. */ export class ProtectedImports implements ImportTier { claims(name: string): boolean { diff --git a/packages/core/src/components/registry.ts b/packages/core/src/components/registry.ts index e32a2629b..82f3ef794 100644 --- a/packages/core/src/components/registry.ts +++ b/packages/core/src/components/registry.ts @@ -7,7 +7,7 @@ * * They are ordinary **defaults**, not reserved names. A repository component * with one of these names is chosen ahead of the default, exactly as it would - * be ahead of any other package's registration. Nothing here claims a name a + * be ahead of any other package's registration. Nothing here reserves a name a * document cannot take back. * * This is the terminal of `selectComponent()` rather than an installation, so @@ -15,7 +15,7 @@ * having to install them. * * The components core supplies are not all here. ``, ``, - * ``, `` and `` are names canonical core claims + * ``, `` and `` are names canonical core reserves * (`protected.ts`), so they are answered above every registry rather than from * one — which is why `CORE_COMPONENT_NAMES` below is the registrations alone * and documentation reads a wider set. diff --git a/packages/core/src/components/select.ts b/packages/core/src/components/select.ts index dd464f871..9cb1633c0 100644 --- a/packages/core/src/components/select.ts +++ b/packages/core/src/components/select.ts @@ -5,11 +5,11 @@ * disagree about which tier won: * * 1. structural syntax the engine owns; - * 2. a component canonical core protects. The engine's own claim rather than a - * host's, so a protected name means the same thing in every execution, + * 2. a component canonical core protects. The engine reserves the name rather + * than a host, so a protected name means the same thing in every execution, * whichever host assembled it and whatever a repository holds; - * 3. a host claiming the name — a reserved registration, or the exact Markdown - * and structural syntax this environment declares. Two claims on one name + * 3. a host reserving the name — a reserved registration, or the exact Markdown + * and structural syntax this environment declares. Two reservations of one name * are refused where they are installed, so this tier never has to choose * between them; * 4. the workflow component bundle this execution is closed over; diff --git a/packages/core/src/document-targets.ts b/packages/core/src/document-targets.ts index 6567a8519..c3d61aa9d 100644 --- a/packages/core/src/document-targets.ts +++ b/packages/core/src/document-targets.ts @@ -205,10 +205,10 @@ function targetList(value: unknown): string[] | undefined { * * The check re-derives the outcome rather than trusting the three fields to * agree: the selector is parsed, matched against the catalog the candidate - * supplied, and the result compared with the matches it claims. A record whose - * kind, selector, matches, and catalog cannot all be true at once is refused, - * so an inconsistent journal or a hand-built candidate cannot describe a - * selection that never happened. + * supplied, and the result compared with the matches it reports. A record + * whose kind, selector, matches, and catalog cannot all be true at once is + * refused, so an inconsistent journal or a hand-built candidate cannot + * describe a selection that never happened. */ function consistentOutcome(fields: TargetFailureFields): boolean { const levels = parseSelector(fields.selector); @@ -453,10 +453,10 @@ export function documentTargetError(data: DocumentTargetFailure): DocumentTarget * copy's constructor is a different function producing the same name. * * The shell is checked as strictly as the data. The message has to be the one - * the data derives, so a diagnostic cannot disagree with the fields it claims; - * there can be no cause and no enumerable member beyond the contract, so a - * candidate cannot carry a path, a foreign object, or a second message under a - * recognized tag. + * the data derives, so a diagnostic cannot disagree with the fields it + * reports; there can be no cause and no enumerable member beyond the contract, + * so a candidate cannot carry a path, a foreign object, or a second message + * under a recognized tag. */ function readDocumentTargetError(error: unknown): DocumentTargetFailure | undefined { return attempt(() => { diff --git a/packages/core/src/errors.ts b/packages/core/src/errors.ts index 616994f2d..fe04a3827 100644 --- a/packages/core/src/errors.ts +++ b/packages/core/src/errors.ts @@ -71,11 +71,11 @@ export function* settle(segment: ErrorSegment): Operation { * built for the segment therefore has its `cause` in place before any observer — * including middleware that catches what `raise` throws — can look at it. * - * The table belongs to the run that fills it: created when a run installs it and - * reclaimed when its scope ends, so nothing one execution recorded is still - * answering questions during the next. Keyed by segment identity — the object a - * boundary handled is the object the document renders and an observer already - * saw, and copying it to record a decision would break both. + * The table belongs to the run that fills it: created when a run installs it + * and released when its scope ends, so nothing one execution recorded is still + * answering questions during the next. Keyed by segment identity — the object + * a boundary handled is the object the document renders and an observer + * already saw, and copying it to record a decision would break both. */ export type SegmentCauses = WeakMap; diff --git a/packages/core/src/evaluation-profile.ts b/packages/core/src/evaluation-profile.ts index ff9949d72..40499f5c7 100644 --- a/packages/core/src/evaluation-profile.ts +++ b/packages/core/src/evaluation-profile.ts @@ -168,17 +168,17 @@ export interface CapabilityEntry { * An entry whose implementation the ordinary import chain answers for. * * The host states *what it expects* — the name, the structural identity a - * provider must claim, and the forms — and states no implementation at all. + * provider must state, and the forms — and states no implementation at all. * There is no definition, function, resolver, provider operation or context * handle on this arm to hold one. * * Canonical capture resolves the name once, before the root import and before * any document code, through the complete ordinary `Component.importComponent` - * chain; reads the identity the provider claimed on that exact final answer; - * compares it with what this entry expects; retains the answer defensively; and - * seals the result. Props and the callable definition are derived from that - * answer rather than restated here, so a host cannot describe a contract the - * implementation does not have. + * chain; reads the identity the provider stated on that exact final answer; + * compares it with what this entry expects; retains the answer defensively; + * and seals the result. Props and the callable definition are derived from + * that answer rather than restated here, so a host cannot describe a contract + * the implementation does not have. * * Resolution happens at capture and never again. A fragment invokes the sealed * snapshot, and a continuation resolves once more in its own capture and @@ -192,7 +192,7 @@ export interface CapabilityEntry { export interface ComponentAnswerEntry { readonly kind: "component-answer"; readonly name: string; - /** What a provider must have claimed for this name, exactly. */ + /** What a provider must have stated for this name, exactly. */ readonly identity: FragmentIdentity; readonly forms: readonly FragmentForm[]; readonly description?: string; @@ -468,12 +468,12 @@ function coreEntry(name: string, key: string, capability: FragmentCapability): C /** * One provider-backed name, already resolved and reconciled. * - * Produced by canonical execution's capture step before this module is asked to - * seal anything: the chain has answered, the provider's claim has been read off - * that exact final object, it has been compared with what the host entry - * expects, and the answer has been retained defensively. What arrives here is - * the settled result, so nothing in this module resolves, looks up, or holds a - * resolver it could call later. + * Produced by canonical execution's capture step before this module is asked + * to seal anything: the chain has answered, the provider's identity statement + * has been read off that exact final object, it has been compared with what + * the host entry expects, and the answer has been retained defensively. What + * arrives here is the settled result, so nothing in this module resolves, + * looks up, or holds a resolver it could call later. */ export interface ResolvedAnswer { /** Core's own retained copy, which is what a fragment invokes. */ diff --git a/packages/core/src/execute.ts b/packages/core/src/execute.ts index 8fafe1da1..978be5411 100644 --- a/packages/core/src/execute.ts +++ b/packages/core/src/execute.ts @@ -281,10 +281,10 @@ type DurableSelection = /** * A component only the declaration that carries it may write. * - * Nothing else is retained: the implementation is built from a claimant this - * execution minted and is reachable from nowhere, so a replay reconstructs it - * the same way the live run did — by being inside the same declaration's body - * when it asks. + * Nothing else is retained: the implementation is built from an identity + * authenticator this execution minted and is reachable from nowhere, so a + * replay reconstructs it the same way the live run did — by being inside the + * same declaration's body when it asks. */ | { kind: "declared-private"; origin: string } /** @@ -770,9 +770,10 @@ const UNIDENTIFIED_ANSWER = * What a provider-backed name whose answer is somebody else's refuses with. * * Both identities are spelled the one way a reader is ever shown one, so a - * diagnostic and a claim describe the same thing the same way. Neither is a - * secret: an origin, a key and a revision are what a host published in order to - * admit the name, and naming them is what makes this actionable. + * diagnostic and an identity statement describe the same thing the same way. + * Neither is a secret: an origin, a key and a revision are what a host + * published in order to admit the name, and naming them is what makes this + * actionable. */ function differentAnswer(name: string, expected: FragmentIdentity, stated: AnswerIdentity): string { return ( @@ -787,10 +788,10 @@ function differentAnswer(name: string, expected: FragmentIdentity, stated: Answe * * A protected component's implementation is the one this execution built; an * ordinary core component's is the definition core registered. Both are core's - * own object, and the identity comparison is the whole check: an answer that is - * anything else — a repository component of the same name, a registration a + * own object, and the identity comparison is the whole check: an answer that + * is anything else — a repository component of the same name, a registration a * nested scope layered over, a middleware's replacement — is not this, so it - * receives no canonical claim and the entry refuses it. + * receives no canonical identity and the entry refuses it. */ function sealedByCore(inputs: ImportInputs, name: string): FunctionComponentDefinition | undefined { return inputs.guarded.get(name) ?? coreComponentDefinition(name); @@ -809,13 +810,13 @@ function sealedByCore(inputs: ImportInputs, name: string): FunctionComponentDefi * is not authored work, and a durable record for it would be an effect a * continuation then had to account for. * - * What comes back is asked about once. The provider's claim is read off the - * *exact final answer* rather than off anything the chain held in between, and - * that one call answers with both the identity and core's own copy of what was - * claimed — taken when the claim was recorded, before the chain could see it - * again. So the value this run keeps is the value the check was made about: - * there is no second read of the chain's object for an alternating proxy or a - * computed member to answer differently. + * What comes back is asked about once. The provider's identity statement is + * read off the *exact final answer* rather than off anything the chain held in + * between, and that one call answers with both the identity and core's own + * copy of what was identified — taken when the identity was recorded, before + * the chain could see it again. So the value this run keeps is the value the + * check was made about: there is no second read of the chain's object for an + * alternating proxy or a computed member to answer differently. * * The identity is then compared whole with what the host entry expects, and the * copy — not the answer — is what the profile seals. @@ -2432,8 +2433,9 @@ function* executeDocument( * identifies. * * Built before any installation ran, so a provider could state identities - * during profile capture; handed here so the component resolution this execution - * imports through is the same table those claims went into. + * during profile capture; handed here so the component resolution this + * execution imports through is the same table those identity statements went + * into. */ canonicalImports: CanonicalImports = new CanonicalImports(), /** @@ -2999,11 +3001,11 @@ export interface ExecutionInstallation { * The components of this host's whose implementations name durable work * after their own invocation. * - * Each factory is called once, with a claimant this execution minted for that - * component — delivered as the argument of that call and published nowhere — - * and what it returns is registered through the ordinary path. A host that - * declares none has no component that can name a durable operation after its - * invocation. + * Each factory is called once, with an identity authenticator this execution + * minted for that component — delivered as the argument of that call and + * published nowhere — and what it returns is registered through the ordinary + * path. A host that declares none has no component that can name a durable + * operation after its invocation. */ readonly components?: readonly IdentityComponent[]; /** @@ -3822,8 +3824,8 @@ export function executeInstalled( * executions in one process are unaffected by each other. * * It exists because cancelling *inside documentation-index construction* is a - * different claim from cancelling inside symbol discovery, and there is no - * other point in that operation a test can stand at. + * different cancellation boundary from cancelling inside symbol discovery, and + * there is no other point in that operation a test can stand at. */ export function executeReadingAssetsWith( options: ExecuteOptions, diff --git a/packages/core/src/execution-declarations.ts b/packages/core/src/execution-declarations.ts index 5f7066e2a..9d83ab055 100644 --- a/packages/core/src/execution-declarations.ts +++ b/packages/core/src/execution-declarations.ts @@ -23,12 +23,12 @@ * * ## One error for the catalog, one for the bytes * - * Everything this module decides about a *set* — a malformed structural member, - * a schema that will not compile, a name claimed twice, a pair that cannot - * expand — is an `ExecutionDeclarationError`. What exact Markdown's own bytes - * say about themselves stays `DeclaredMarkdownError`, and so does an unknown - * discriminant, which is a value that never reached either arm. A host reading - * one of those two knows which question it failed. + * Everything this module decides about a *set* — a malformed structural + * member, a schema that will not compile, a name reserved twice, a pair that + * cannot expand — is an `ExecutionDeclarationError`. What exact Markdown's own + * bytes say about themselves stays `DeclaredMarkdownError`, and so does an + * unknown discriminant, which is a value that never reached either arm. A host + * reading one of those two knows which question it failed. * * ## The pair is derived from the regions * @@ -41,9 +41,9 @@ * ## What crosses to the handler * * Nothing here calls a handler. The declarations are admitted, the handler an - * installation supplied is retained beside them, and the entry that holds it is - * reachable only by holding this catalog. There is no registry, registrar, - * plugin object, contextual slot, token or claim. + * installation supplied is retained beside them, and the entry that holds it + * is reachable only by holding this catalog. There is no registry, registrar, + * plugin object, contextual slot, token or authentication handle. */ import type { Operation, Stream } from "effection"; diff --git a/packages/core/src/expand.ts b/packages/core/src/expand.ts index 7facb1e87..648f57e48 100644 --- a/packages/core/src/expand.ts +++ b/packages/core/src/expand.ts @@ -323,9 +323,10 @@ interface ProjectionState { * Raised for the whole of one projection of this invocation's own content. * * Everything nested is reached through here, so this is where an invocation - * stops naming itself: a durable identity claimed while it is raised is being - * claimed by something inside the content, not by the invocation that owns it - * (`component-invocation.ts`). A Markdown body has no issuance to raise. + * stops naming itself: a durable identity authenticated while it is raised + * is being authenticated by something inside the content, not by the + * invocation that owns it (`component-invocation.ts`). A Markdown body has + * no issuance to raise. */ projecting?: () => () => void; enclosing: ProjectionHandle | undefined; @@ -2124,10 +2125,11 @@ function* structuralOperand(segment: ComponentElement, construct: string): Opera * * The selected case is transparent, exactly as a selected `` branch is. It * opens no binding scope, no observation boundary and no loop boundary: a - * `` it creates stays available after ``, a `` claims the - * value body that owns the switch, and a `` exits the loop that lexically - * encloses it. Errors the construct creates itself — a broken structure, a - * selector or matcher that fails to evaluate — are reported here, exactly once. + * `` it creates stays available after ``, a `` reserves + * the value body that owns the switch, and a `` exits the loop that + * lexically encloses it. Errors the construct creates itself — a broken + * structure, a selector or matcher that fails to evaluate — are reported here, + * exactly once. */ function* expandSwitch( segment: ComponentElement, @@ -4049,10 +4051,10 @@ function* resolveExpressionProps( /** * Evaluate one expression prop against the binding environment. * - * Exported within the package because a claimed construct resolves its own - * props: the expansion hook is offered the element before prop resolution runs, - * so `` and `` reach their `value` and `delegate` expressions - * through here rather than receiving them already evaluated. + * Exported within the package because an intercepted construct resolves its own + * props: the expansion hook is offered the element before prop resolution + * runs, so `` and `` reach their `value` and `delegate` + * expressions through here rather than receiving them already evaluated. */ export function* evaluateExpression( expression: string, diff --git a/packages/core/src/files.ts b/packages/core/src/files.ts index 0ba4f39ab..331fb764c 100644 --- a/packages/core/src/files.ts +++ b/packages/core/src/files.ts @@ -99,7 +99,8 @@ function present(target: unknown, name: string): boolean | undefined { * A `Result` is only conventionally a `Result`: what a provider actually * returned is an arbitrary runtime value, and reading `ok` on a Proxy that * refuses can throw. The type says otherwise, which is exactly why the check - * belongs here — the signature is a claim about the provider, not a guarantee. + * belongs here — the signature is an assertion about the provider, not a + * guarantee. * * The value comes back boxed so that a member which really is `undefined` is * distinguishable from one that could not be read. Collapsing those is how a @@ -368,10 +369,9 @@ export function temporaryDirectory(): Operation> { /** * What a write reported, or nothing when it succeeded. * - * A write is the one operation whose outcome makes a claim about the world: the - * file was replaced, or it was not, or nobody can tell. Every sentence a - * consumer could print asserts one of those, so an outcome that does not - * validate leaves none of them available — and a provider that cannot describe + * A write outcome reports whether the target file was replaced: it was, it + * was not, or nobody can tell. Every sentence a consumer could print asserts + * one of those, so an outcome that does not validate leaves none of them available — and a provider that cannot describe * what it did is treated as one that may not have done it. Both a malformed * success and a malformed failure are therefore fatal, and so is a container * that will not say which it is. diff --git a/packages/core/src/generated-xmd.ts b/packages/core/src/generated-xmd.ts index ca2e32d78..0b4101818 100644 --- a/packages/core/src/generated-xmd.ts +++ b/packages/core/src/generated-xmd.ts @@ -1428,10 +1428,10 @@ function retainedIdentityRecord(identity: RetainedIdentity): Json { /** * Whether an object carries exactly these members and nothing else. * - * Every retained shape below is closed, which is a stronger claim than "the - * members it needs are present and well-typed". A record carrying an extra - * member was written by something this build does not know the rules of, and - * reading the members it recognizes would be admitting a grant on terms it + * Every retained shape below is closed, which is a stronger requirement than + * "the members it needs are present and well-typed". A record carrying an + * extra member was written by something this build does not know the rules of, + * and reading the members it recognizes would be admitting a grant on terms it * never saw. Destructuring alone cannot say that, because a destructure is * blind to what it did not name. */ @@ -1978,9 +1978,9 @@ interface Lexical { * What encloses the fragment's own top level. * * A generated fragment is not a component body and not a value body: there is - * no caller content for `` to claim, no output region for `` - * to select, and no value body for `` to answer. It is also not inside - * a loop. + * no caller content for `` to project, no output region for + * `` to select, and no value body for `` to answer. It is also + * not inside a loop. */ const ROOT_LEXICAL: Lexical = Object.freeze({ insideLoop: false }); diff --git a/packages/core/src/glob-source.ts b/packages/core/src/glob-source.ts index 47c3f81eb..7876382a1 100644 --- a/packages/core/src/glob-source.ts +++ b/packages/core/src/glob-source.ts @@ -57,7 +57,7 @@ export const GLOB_RETURNS: ReturnsSchema = { * The patterns a prop holds, checked for the two things that make one unusable. * * Prop validation has already established an array of strings, so the shape is - * re-read rather than asserted (`as` would claim it instead) and a value that + * re-read rather than asserted (`as` would assert it instead) and a value that * somehow is not one contributes nothing. What validation cannot express is * *meaning*: patterns match paths relative to the working directory, so an * absolute pattern and one that starts by leaving cannot match anything a diff --git a/packages/core/src/inspect.ts b/packages/core/src/inspect.ts index 9b44ac462..81a10537f 100644 --- a/packages/core/src/inspect.ts +++ b/packages/core/src/inspect.ts @@ -165,7 +165,7 @@ export type ComponentInfo = returns?: ReturnsSchema; } & DescribedContract) /** - * A component canonical core claims the name of. + * A component canonical core reserves the name of. * * Its own `kind` for the same reason its origin has one: a caller asking what * `Syntax` is needs to learn that no registry supplies it and none can, which @@ -533,10 +533,10 @@ export interface InspectSyntaxOptions { * meaning `ExecuteOptions.components` gives them — admissibility included. * * A set an execution would refuse is refused here too: two declarations of - * one name, and any declaration registration would not accept. Read for their - * structural metadata alone; the factory is never called, because it takes an - * execution's claimant and describing an environment mints no execution and - * no claimant to give it. + * one name, and any declaration registration would not accept. Read for + * their structural metadata alone; the factory is never called, because it + * takes an execution's identity authenticator and describing an environment + * mints no execution and no identity authenticator to give it. */ readonly components?: readonly IdentityComponent[]; /** diff --git a/packages/core/src/invocation-identity.ts b/packages/core/src/invocation-identity.ts index 381412cb4..1d8507dd1 100644 --- a/packages/core/src/invocation-identity.ts +++ b/packages/core/src/invocation-identity.ts @@ -2,29 +2,30 @@ * The identity a trusted host's component names its durable work after * (architecture.md, *Capability-backed invocation identity*). * - * A component that names a durable operation after its own invocation is making - * an ownership claim: the name decides which retained record a replay restores, - * so two invocations arriving at one name each replay the other's work, and an - * implementation running under somebody else's identity commits against its own - * storage under their expansion. Code Rule 15 says such a decision never trusts - * replaceable state, and every channel a component could *read* one from is - * replaceable — a Context is addressed by name, a contextual Api answer is - * composed by whoever installed a handler, and the registry is an answer a - * handler may keep from one attachment and hand back inside another, record and - * all. + * A component that names a durable operation after its own invocation is + * asserting ownership: the name decides which retained record a replay + * restores, so two invocations arriving at one name each replay the other's + * work, and an implementation running under somebody else's identity commits + * against its own storage under their expansion. Code Rule 15 says such a + * decision never trusts replaceable state, and every channel a component could + * *read* one from is replaceable — a Context is addressed by name, a + * contextual Api answer is composed by whoever installed a handler, and the + * registry is an answer a handler may keep from one attachment and hand back + * inside another, record and all. * * So nothing is read. The execution is *told*, before any installation runs, * which components name durable work; it mints one domain for each, builds the - * implementation by handing that domain's **claimant** straight to the host's - * factory, and registers what comes back. The domain exists only here, the - * claimant exists only as the argument of that call, and neither is published, - * named, or reachable from a document. An implementation from another execution - * holds another execution's claimant, which answers for nothing here. + * implementation by handing that domain's **identity authenticator** straight + * to the host's factory, and registers what comes back. The domain exists only + * here, the identity authenticator exists only as the argument of that call, + * and neither is published, named, or reachable from a document. An + * implementation from another execution holds another execution's identity + * authenticator, which answers for nothing here. * - * A claimant answers only for the invocation the engine is running: the one the - * engine minted for a component in this domain, still live, not expanding its - * own content, running in the frame the engine invoked it in, and not already - * answered. Everything else refuses. + * An identity authenticator answers only for the invocation the engine is + * running: the one the engine minted for a component in this domain, still + * live, not expanding its own content, running in the frame the engine invoked + * it in, and not already answered. Everything else refuses. * * ## Which invocation is in the domain * @@ -65,10 +66,10 @@ import type { /** * What a function component receives beside its props. * - * Almost opaque. What it names is answered by a claimant, and only for the - * execution that minted both; there is no shape here to copy and nothing to - * read about the caller, the binding, the children, the environment or the - * scope. + * Almost opaque. What it names is answered by an identity authenticator, and + * only for the execution that minted both; there is no shape here to copy and + * nothing to read about the caller, the binding, the children, the environment + * or the scope. * * The one thing it reports is how the element that caused this invocation was * written, because that is a fact about *this invocation* rather than about the @@ -88,10 +89,11 @@ export interface ComponentInvocation { * * The authored shape, immutable and synchronous. It projects nothing, * suspends on nothing, asks nothing of the middleware chain, and does not - * spend this invocation's durable identity — reading it leaves the claimant - * exactly as it was. On an invocation the engine issued this is the canonical - * fact, and a component that reaches nothing else — no import, no context, no - * helper of its own copy — reads it by calling what it received. + * spend this invocation's durable identity — reading it leaves the identity + * authenticator exactly as it was. On an invocation the engine issued this + * is the canonical fact, and a component that reaches nothing else — no + * import, no context, no helper of its own copy — reads it by calling what + * it received. * * **Observation only.** Calling it is not authentication: a component * receives whatever its caller passed, and a wrapper can pass an object @@ -115,7 +117,7 @@ export interface ComponentInvocation { hasContent(): boolean; } -/** A durable identity that cannot be claimed here. */ +/** A durable identity that cannot be authenticated here. */ export class ComponentInvocationError extends Error { override name = "ComponentInvocationError"; } @@ -135,7 +137,8 @@ export interface IdentityClaimant { * * Declared to the execution rather than registered by the host, because what * may name durable work here has to be fixed before anything can observe or - * replace it. The factory is called once, with this execution's claimant. + * replace it. The factory is called once, with this execution's identity + * authenticator. */ export interface IdentityComponent extends ComponentDocumentation { readonly name: string; @@ -227,13 +230,13 @@ export interface ProtectedSite { /** * The bodies one execution will enter, keyed by the exact function it built. * - * Execution-owned and reclaimed with the execution, like the domains beside it, + * Execution-owned and released with the execution, like the domains beside it, * and handed to core's own expansion by value. Two things follow. An * implementation another loaded copy built — which is ordinary, because a * component can be loaded from disk beside its own copy — is in that copy's - * table rather than this one, so it has no body here. And an implementation kept - * past this execution's teardown reaches nothing, because the table went with - * the execution. + * table rather than this one, so it has no body here. And an implementation + * kept past this execution's teardown reaches nothing, because the table went + * with the execution. */ export interface ComponentRouting { /** The body canonical expansion may enter for this exact implementation. */ @@ -365,7 +368,7 @@ function createComponentRouting(): ComponentRoutingInstallation { } /** - * A component canonical core claims the name of, as this module builds one. + * A component canonical core reserves the name of, as this module builds one. * * The same declaration a host's identity component makes, except that the * factory hands over a body rather than an implementation: what a protected @@ -609,7 +612,7 @@ export function isFormDispatcher(fn: unknown): boolean { * satisfies all of: * * - the invocation is an object **this** copy of core minted, recognized by the - * same private field a claimant recognizes — a structural look-alike carrying + * same private field an identity authenticator recognizes — a structural look-alike carrying * `hasContent()` is not one; * - the issuance is still live, and its frame is the one running now, so an * invocation kept from a sibling or a finished element answers nothing here; @@ -866,7 +869,7 @@ export function issueInvocation( }; } -/** One domain, and the claimant that is the only way to spend it. */ +/** One domain, and the identity authenticator that is the only way to spend it. */ interface Minted { /** The implementation this execution built for it, by identity. */ implementation?: FunctionComponent; @@ -1035,20 +1038,21 @@ export interface IdentityInstallation { /** * The implementations that are declared but never registered, by name. * - * A private declaration is minted exactly like a registered one — one domain, - * one claimant, revoked with the execution — and then handed here instead of - * to registration, because what makes it private is that no registry answers - * for it. Canonical core resolves one only while it is expanding the body of - * the declaration that carries it. + * A private declaration is minted exactly like a registered one — one + * domain, one identity authenticator, revoked with the execution — and then + * handed here instead of to registration, because what makes it private is + * that no registry answers for it. Canonical core resolves one only while it + * is expanding the body of the declaration that carries it. */ readonly privates: ReadonlyMap; /** * The implementations canonical core's own protected tier resolves, by name. * - * Minted exactly like the rest — one domain, one claimant, revoked with the - * execution — and then registered nowhere, because a registry is precisely - * what must not decide a protected name. Canonical resolution answers for - * these from its own table (`components/protected.ts`). + * Minted exactly like the rest — one domain, one identity authenticator, + * revoked with the execution — and then registered nowhere, because a + * registry is precisely what must not decide a protected name. Canonical + * resolution answers for these from its own table + * (`components/protected.ts`). */ readonly protected: ReadonlyMap; /** The bodies canonical expansion may enter for those implementations. */ @@ -1060,11 +1064,11 @@ export interface IdentityInstallation { /** * Mint this execution's domains and build the implementations from them. * - * The factory is called here, with a claimant that answers only for this - * execution's own invocations of that component. Nothing is registered yet: - * the caller registers what comes back, and activates only once that batch has - * been validated and committed, so a refused registration leaves a claimant - * that answers for nothing. + * The factory is called here, with an identity authenticator that answers only + * for this execution's own invocations of that component. Nothing is + * registered yet: the caller registers what comes back, and activates only + * once that batch has been validated and committed, so a refused registration + * leaves an identity authenticator that answers for nothing. */ export function installIdentities( components: readonly IdentityComponent[], diff --git a/packages/core/src/output/exact-source.ts b/packages/core/src/output/exact-source.ts index cd3e79d89..61e32638b 100644 --- a/packages/core/src/output/exact-source.ts +++ b/packages/core/src/output/exact-source.ts @@ -1,14 +1,14 @@ /** * Which rendered segments carry a program's source rather than prose. * - * Exact presentation is a *provenance*, not a property. The question it answers - * is "did canonical execution produce these bytes by expanding a declared - * Markdown component the trusted host said renders source?" — and no object can - * answer that about itself. A definition claiming the disposition, a segment - * arriving already marked, a frontmatter key, a prop: each is data that reached - * the engine from somewhere, and any of them would let ordinary - * `Component.importComponent` middleware publish unpresented bytes by writing a - * field. + * Exact presentation is a *provenance*, not a property. The question it + * answers is "did canonical execution produce these bytes by expanding a + * declared Markdown component the trusted host said renders source?" — and no + * object can answer that about itself. A definition asserting the disposition, + * a segment arriving already marked, a frontmatter key, a prop: each is data + * that reached the engine from somewhere, and any of them would let ordinary + * `Component.importComponent` middleware publish unpresented bytes by writing + * a field. * * So the record is kept beside the segments rather than on them, keyed by the * identity of the objects canonical expansion marked. A segment scanned from a diff --git a/packages/core/src/plugin-apis.ts b/packages/core/src/plugin-apis.ts index 97a6c1551..986b9e34d 100644 --- a/packages/core/src/plugin-apis.ts +++ b/packages/core/src/plugin-apis.ts @@ -141,7 +141,8 @@ export const rootMetadata: Operation>> = { * The complete list, installed before the first `install()` runs, so every * Plugin and every later consumer reads the same one. An execution nobody * installed Plugins for reads the empty list rather than failing: the API is - * how a Plugin asks what it is running beside, not a claim that any exist. + * how a Plugin asks what it is running beside, not an assertion that any + * exist. */ export interface ActivePluginsApi { readonly plugins: readonly Plugin[]; diff --git a/packages/core/src/plugin.ts b/packages/core/src/plugin.ts index 5fa3d104a..db83c75bc 100644 --- a/packages/core/src/plugin.ts +++ b/packages/core/src/plugin.ts @@ -70,10 +70,10 @@ export interface PluginInstallation { /** * One Plugin: a name, and what installing it does. * - * The name identifies the Plugin to an operator and to the refusal that reports - * two selections claiming it. It is not a package identity, a version or a - * capability: nothing resolves a name to a module, and nothing grants a Plugin - * anything for being called one thing rather than another. + * The name identifies the Plugin to an operator and to the refusal that + * reports two selections using it. It is not a package identity, a version or + * a capability: nothing resolves a name to a module, and nothing grants a + * Plugin anything for being called one thing rather than another. */ export interface Plugin { readonly name: string; diff --git a/packages/core/src/projection.ts b/packages/core/src/projection.ts index c4ae302b9..3ee0308a3 100644 --- a/packages/core/src/projection.ts +++ b/packages/core/src/projection.ts @@ -8,9 +8,10 @@ * its live effects belong to the invocation rather than to the caller that wrote * the content, and stop before the invocation cleans up its own. * - * `` differs only in how its segments are chosen: slots are resolved - * during body substitution, and the resolved segments ride on the element the - * handle claims. The others ask the handle to select their segments. + * `` differs only in how its segments are chosen: slots are + * resolved during body substitution, and the resolved segments ride on the + * element the handle marks. The others ask the handle to select their + * segments. * * The two selecting methods differ in what a failure looks like. `project()` * hands ErrorSegments back structurally, which is how a function component's @@ -48,12 +49,12 @@ export interface ProjectionHandle { /** * Mark a `` element as carrying a resolved projection, so * expansion runs its children in this invocation's content scope. Identity - * is the boundary: an unclaimed `` is not a projection. + * is the boundary: an unmarked `` is not a projection. */ claim(element: ComponentElement): ComponentElement; claims(element: ComponentElement): boolean; /** - * Expand a claimed element's children inside the content scope, writing into + * Expand a marked element's children inside the content scope, writing into * the region the caller is rendering. Projected content is the caller's own * text, so what it produced before a failure belongs to that region. */ diff --git a/packages/core/src/return-flow.ts b/packages/core/src/return-flow.ts index 081401a24..1cd7198fe 100644 --- a/packages/core/src/return-flow.ts +++ b/packages/core/src/return-flow.ts @@ -5,7 +5,7 @@ import type { ReturnsSchema } from "./types.ts"; * The value body a `` selects for (spec §6.10). * * A value root and a Markdown value component each create one of these for the - * body it expands, and `` claims it. This is what lets a return be + * body it expands, and `` reserves it. This is what lets a return be * written wherever the body's own flow reaches — under ``, inside a * ``, in content the caller projected — instead of only as a direct * top-level child. @@ -31,27 +31,27 @@ import type { ReturnsSchema } from "./types.ts"; * carrier itself is sealed: the document calls the engine's own helper with the * engine's own carrier. * - * So there is no carrier and no context. A `ReturnBody` is a plain object whose - * operations are closures over state nothing else holds, and it reaches the - * `` that claims it as an ordinary parameter of expansion — down the - * call stack, which document code has no way to read or replace. Importing this - * module gains a document nothing: `createReturnBody()` hands back a body of its - * own, unconnected to any execution, and no exported function takes someone - * else's. + * So there is no carrier and no context. A `ReturnBody` is a plain object + * whose operations 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 has no way to read or replace. Importing + * this module gains a document nothing: `createReturnBody()` hands back a body + * of its own, unconnected to any execution, and no exported function takes + * someone else's. */ export interface ReturnBody { /** * Take the body for the return about to execute, and say what it declares. * - * Synchronous on purpose. The claim is recorded before the caller suspends to - * evaluate the return's expression, so two returns racing through one body - * cannot both believe they were first — the second throws here, having - * evaluated nothing. + * Synchronous on purpose. The reservation is recorded before the caller + * suspends to evaluate the return's expression, so two returns racing + * through one body cannot both believe they were first — the second throws + * here, having evaluated nothing. */ claim(): { owner: string; returns: ReturnsSchema }; /** - * Record the value the claiming return produced. Only a claimed body accepts - * one, so a value is selected exactly where a claim was taken. + * Record the value the reserving return produced. Only a reserved body + * accepts one, so a value is selected exactly where the reservation was made. */ select(value: Json): void; /** diff --git a/packages/core/src/secrets/policy.ts b/packages/core/src/secrets/policy.ts index 870eb4463..5750e1f6e 100644 --- a/packages/core/src/secrets/policy.ts +++ b/packages/core/src/secrets/policy.ts @@ -3,7 +3,7 @@ * * Detection is on unless the trusted host asks for it to be off. The policy is * created inside the execution that owns it, before any document work can run, - * and is reclaimed with that execution. + * and is released with that execution. * * ## Why there are two mechanisms * diff --git a/packages/core/src/structural.ts b/packages/core/src/structural.ts index afc5c21fb..6a4463828 100644 --- a/packages/core/src/structural.ts +++ b/packages/core/src/structural.ts @@ -1,9 +1,10 @@ /** * The structural constructs (spec §5.3). * - * These names are the language's own syntax, not components. The expansion loop - * handles each one directly, so none of them reaches component resolution: a - * repository file cannot supply them and a registration cannot claim them. + * These names are the language's own syntax, not components. The expansion + * loop handles each one directly, so none of them reaches component + * resolution: a repository file cannot supply them and a registration cannot + * reserve them. * * The table below is the single place that decides which names are reserved, * and it carries the documentation `xmd syntax` prints beside each one. diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 7730e1337..66e4d45e5 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -343,7 +343,7 @@ export type ComponentOrigin = | { kind: "repository"; path: string } | { kind: "registered"; origin: string; reserved: boolean } /** - * A component canonical core claims the name of, ahead of every host and + * A component canonical core reserves the name of, ahead of every host and * author tier (`components/protected.ts`). * * Its own kind rather than a reserved registration, because it is not one: a @@ -393,10 +393,10 @@ export type ComponentOrigin = export type ComponentSelection = | { kind: "structural"; construct: string } /** - * A component canonical core claims the name of, ahead of every host or author - * tier. The declaration is core's own; the implementation belongs to whichever - * execution is running, so selection reports the contract and the execution - * supplies what it built (`components/protected.ts`). + * A component canonical core reserves the name of, ahead of every host or + * author tier. The declaration is core's own; the implementation belongs to + * whichever execution is running, so selection reports the contract and the + * execution supplies what it built (`components/protected.ts`). */ | { kind: "protected"; diff --git a/packages/core/src/validate.ts b/packages/core/src/validate.ts index 752eef2fd..dc7d457f0 100644 --- a/packages/core/src/validate.ts +++ b/packages/core/src/validate.ts @@ -29,7 +29,7 @@ function createPropsCompiler(): Ajv { * was handed and never evicted, so a single instance would hold one entry per * schema per run for the life of the process — and a schema object mutated * between runs would get the first run's validator. The compiler therefore - * belongs to the run: created when a run installs it, reclaimed with everything + * belongs to the run: created when a run installs it, released with everything * it compiled when the run's scope ends. That `Map` is also the whole cache * this module needs, which is why there is no second one beside it. */ @@ -48,9 +48,9 @@ export function* usePropsCompiler(): Operation { /** * The run's compiler, or one that lives exactly as long as this call. * - * Compiling outside a run — a host describing a component, a test — has nothing - * to reclaim and nothing to share, so it gets an instance of its own rather - * than reaching for one that would outlive it. + * Compiling outside a run — a host describing a component, a test — has no + * run scope to own or share a compiler, so the call gets an instance of its + * own rather than reaching for one that would outlive it. */ function* compiler(): Operation { return (yield* PropsCompiler.get()) ?? createPropsCompiler(); diff --git a/packages/core/tests/agent-function-components.test.ts b/packages/core/tests/agent-function-components.test.ts index 44c533211..c9ef155e7 100644 --- a/packages/core/tests/agent-function-components.test.ts +++ b/packages/core/tests/agent-function-components.test.ts @@ -1066,8 +1066,9 @@ function recordedFailure(record: Record | undefined): string { * * The final routed session decides. An authentic use runs under its own * settings; a raw session or no session at all is an ordinary unconfigured - * route that reads and writes nothing; and a value that claims to be configured - * and was issued by nobody refuses rather than being read as either. + * route that reads and writes nothing; and a value that presents itself as + * configured and was issued by nobody refuses rather than being read as + * either. */ describe("Tier AF — the final routed Session decides", () => { it("AF37: routing the raw session a use names runs unconfigured", function* () { @@ -1344,7 +1345,7 @@ describe("Tier AF — the final routed Session decides", () => { * caller went on to mutate all stay out of the journal. * * Every journal here comes from a real turn through the real Prompt, because - * the audit's whole claim is about where in a turn the copy is taken. + * the audit verifies where in a turn the copy is taken. */ function permissionPlan( requests: readonly ScriptedPermission[], diff --git a/packages/core/tests/agent-session-launch.test.ts b/packages/core/tests/agent-session-launch.test.ts index 0f59b1879..2e7806617 100644 --- a/packages/core/tests/agent-session-launch.test.ts +++ b/packages/core/tests/agent-session-launch.test.ts @@ -1136,7 +1136,7 @@ describe("Tier FS — the final public launch surface", () => { * so nothing after the fact can tell them apart. The record has to say. This * tier is where that becomes true, and where the one compatibility inference — * a released format that could not have been client-allocated — is pinned to - * the weaker claim. + * the weaker provenance. */ const BINDING: ExecutableBuildBindingV1 = { schema: "executable-build.v1", diff --git a/packages/core/tests/agent-session-use-loaded-copy.test.ts b/packages/core/tests/agent-session-use-loaded-copy.test.ts index 78053085f..cc40c13b9 100644 --- a/packages/core/tests/agent-session-use-loaded-copy.test.ts +++ b/packages/core/tests/agent-session-use-loaded-copy.test.ts @@ -7,7 +7,7 @@ * value one of them issued arrives at the other looking exactly like something * it made itself. * - * It is not. The claim a use carries is a registered symbol, deliberately + * It is not. The marker a use carries is a registered symbol, deliberately * shared: any copy can see that a value presents itself as configured. The * authority is a private class field, and a private field belongs to the class * that declared it — so the copy that did not mint this value cannot read what diff --git a/packages/core/tests/agent-session-use.test.ts b/packages/core/tests/agent-session-use.test.ts index 74d38ed1a..790ed2eb1 100644 --- a/packages/core/tests/agent-session-use.test.ts +++ b/packages/core/tests/agent-session-use.test.ts @@ -4,8 +4,9 @@ * A configured `` says what a conversation runs under, and that fact * travels to the provider on the value that names the conversation. Every such * value travels the public Agent chain, where middleware may read it, copy it - * and route something else — so what these rows establish is which values carry - * an answer and which are refused for claiming to. + * and route something else — so what these rows establish is which values + * carry an answer and which are refused for presenting themselves as + * configured. * * The refusal is the point. A value that presents itself as configured and is * not one must not be read as an ordinary session and run unconfigured: that is diff --git a/packages/core/tests/all.test.ts b/packages/core/tests/all.test.ts index eeb35108e..5086a33c9 100644 --- a/packages/core/tests/all.test.ts +++ b/packages/core/tests/all.test.ts @@ -12,8 +12,9 @@ * Each test names the defect it kills: expanding the children in sequence, * emitting them in completion order, running them on the parent coroutine, * sharing one block counter, sharing the binding environment, leaving a held - * sibling alive after a failure, publishing one child's output before the join, - * and letting a `` or `` claim an owner outside the spawn. + * sibling alive after a failure, publishing one child's output before the + * join, and letting a `` or `` select an owner outside the + * spawn. */ import { beforeAll, describe, it } from "@executablemd/test-support/bdd"; diff --git a/packages/core/tests/answer-identity.test.ts b/packages/core/tests/answer-identity.test.ts index c793c0055..457c29f44 100644 --- a/packages/core/tests/answer-identity.test.ts +++ b/packages/core/tests/answer-identity.test.ts @@ -14,13 +14,14 @@ * installation is the right to be asked, and it is deliberately reusable: one * installation answers several admitted names and the same name resolved more * than once. A request is the right to answer one asking, and it is closed the - * moment that handler invocation ends. Only a request claims, which is what - * makes a statement provable — an installation handle can prove "some provider - * this host installed" and nothing about which invocation is speaking. + * moment that handler invocation ends. Only a request records an identity, + * which is what makes a statement provable — an installation handle can prove + * "some provider this host installed" and nothing about which invocation is + * speaking. * - * The rows read what `identify()` answers rather than what a refusal says: a - * claim that reported correctly while still identifying a substituted object - * would satisfy an error-shape assertion and none of these. + * The rows read what `identify()` answers rather than what a refusal says: an + * identity statement that reported correctly while still identifying a + * substituted object would satisfy an error-shape assertion and none of these. * * The owner is `CanonicalImports`, which already holds issuance and retention. * One owner asks one question about one table; a second registry would be a @@ -599,8 +600,8 @@ describe("Tier PA10b — one serial resolution window", () => { * That is the whole reason no scope takes part here: the execution asks for * each admitted name in turn, so there is one window at a time, and what a * request answers is the window object it captured when its handler was - * opened — not whichever window is open when it happens to claim, and not - * anything about where it is running. + * opened — not whichever window is open when it records the identity, and + * not anything about where it is running. */ it("PA10b: a request answers the window it captured, not the one open later", function* () { const imports = owner(); @@ -822,7 +823,7 @@ describe("Tier PA10c — one definition answering more than one import", () => { }); /** - * Claim one shared definition in a resolution of its own, and read it back. + * Identify one shared definition in a resolution of its own, and read it back. * * Written once because three rows need the same second import: a fresh window, * the same object, and the same provider saying the same thing about it. All of diff --git a/packages/core/tests/answers-component.test.ts b/packages/core/tests/answers-component.test.ts index cf9569c3b..2f425ed33 100644 --- a/packages/core/tests/answers-component.test.ts +++ b/packages/core/tests/answers-component.test.ts @@ -901,10 +901,11 @@ describe("Answers: reservation", () => { /** * Membership in the reserved set, which nothing above reaches. * - * Keeping a repository file out is the expansion loop's doing — it dispatches - * both names before resolution runs, and would go on doing so if they were - * dropped from the set. What the set uniquely decides is that a *registration* - * cannot claim either name, so this is the assertion that fails if they are. + * Keeping a repository file out is the expansion loop's doing — it + * dispatches both names before resolution runs, and would go on doing so if + * they were dropped from the set. What the set uniquely decides is that a + * *registration* cannot reserve either name, so this is the assertion that + * fails if they are. */ it("refuses a registration for either name", function* () { for (const name of ["Answers", "Answer"]) { diff --git a/packages/core/tests/capture-errors.test.ts b/packages/core/tests/capture-errors.test.ts index 910e789bf..1ff0a754f 100644 --- a/packages/core/tests/capture-errors.test.ts +++ b/packages/core/tests/capture-errors.test.ts @@ -216,10 +216,10 @@ function broke(n: number): string { } /** - * Claims `` and fails its expansion with the planted durability + * Intercepts `` and fails its expansion with the planted durability * failure. The journal no longer describes this run, so nothing between the - * projection and the document may translate it into a printed error or present it - * as a content failure. + * projection and the document may translate it into a printed error or present + * it as a content failure. */ function useStale(planted: StaleInputError): Operation { return Component.around({ diff --git a/packages/core/tests/component-returns.test.ts b/packages/core/tests/component-returns.test.ts index 068440651..38776379b 100644 --- a/packages/core/tests/component-returns.test.ts +++ b/packages/core/tests/component-returns.test.ts @@ -399,9 +399,10 @@ describe("Tier RV — component return values", () => { describe("definition-owned return flow", () => { /** - * A value component whose declaration is satisfied from inside `directive`. - * Each row is the same claim — the directive keeps the body that owns it — - * written in the four structural forms a document has today. + * A value component whose declaration is satisfied from inside + * `directive`. Each row is the same ownership rule — the directive keeps + * the body that owns it — written in the four structural forms a document + * has today. */ const OWNED = [ { name: "If", body: ["", '', ""] }, diff --git a/packages/core/tests/construct-error-observation.test.ts b/packages/core/tests/construct-error-observation.test.ts index da69dc5b8..d71fbe3f0 100644 --- a/packages/core/tests/construct-error-observation.test.ts +++ b/packages/core/tests/construct-error-observation.test.ts @@ -32,13 +32,13 @@ import type { * original segment objects — the ones `Component.raise` already returned. Their * identity is what proves the transport reports nothing a second time. * - * The constructs under test are the engine's, so nothing here claims a name. - * `` is a component that fails on its own terms, resolved through the - * `importComponent` middleware these install because they drive `expandSegments` - * directly — there is no registry in this harness. The printed error the engine - * builds for a failed invocation is the ErrorSegment they observe. See - * `error-observation.test.ts` for the same contract measured across the - * extension boundary instead. + * The constructs under test are the engine's, so nothing here reserves a name. + * `` is a component that fails on its own terms, resolved through + * the `importComponent` middleware these install because they drive + * `expandSegments` directly — there is no registry in this harness. The + * printed error the engine builds for a failed invocation is the ErrorSegment + * they observe. See `error-observation.test.ts` for the same contract measured + * across the extension boundary instead. */ const OPEN_SCHEMA: PropsSchema = { type: "object", properties: {}, additionalProperties: true }; diff --git a/packages/core/tests/declared-markdown-component.test.ts b/packages/core/tests/declared-markdown-component.test.ts index acaece7b6..f05d6d170 100644 --- a/packages/core/tests/declared-markdown-component.test.ts +++ b/packages/core/tests/declared-markdown-component.test.ts @@ -11,7 +11,7 @@ * the bytes say. A build that ships different bytes under the same name never * reaches a document. * - * **The name is claimed, not offered.** A declared component answers ahead of a + * **The name is reserved, not offered.** A declared component answers ahead of a * repository file, a workflow bundle and every registration, and * `Component.importComponent` middleware may observe, delegate and refuse an * import without being able to answer one. What a document expands is the @@ -93,8 +93,8 @@ const WITH_PRIVATE = ['', "", "policy says {answer}", ""]. /** * A private component, as a declaration carries it: an ordinary identity - * component whose implementation is built from the claimant this execution - * minted, and which nothing registers. + * component whose implementation is built from the identity authenticator this + * execution minted, and which nothing registers. */ function secret(name = "Secret", answer = "the private answer"): IdentityComponent { return { @@ -116,8 +116,9 @@ function secret(name = "Secret", answer = "the private answer"): IdentityCompone * * A tripwire rather than a fake: what a case about the closure has to show is * that the implementation did not run, and rendered output cannot show that on - * its own. It deliberately never calls its claimant — core promises the closure - * to a private component whether or not one names durable work. + * its own. It deliberately never calls its identity authenticator — core + * promises the closure to a private component whether or not one names durable + * work. */ function watching(entered: string[], name = "Secret"): IdentityComponent { return { @@ -215,7 +216,7 @@ function answering( }; } -/** A private component that names its own durable work, to prove the claimant works. */ +/** A private component that names its own durable work, to prove the identity authenticator works. */ function claiming(seen: string[], name = "Claiming"): IdentityComponent { return { name, @@ -1439,9 +1440,10 @@ function answeringOpenName(definition: ImportedDefinition): ExecutionInstallatio * The `{ text, exact }` runs one child's close retained, read rather than * asserted. * - * A row about what a durable value *is* cannot cast it into the shape it claims, - * so every member is parsed here and anything else throws — naming what it found — - * instead of arriving at the expectation as a plausible shape nobody checked. + * A row about what a durable value *is* cannot cast it into the shape it + * describes, so every member is parsed here and anything else throws — naming + * what it found — instead of arriving at the expectation as a plausible shape + * nobody checked. */ function retainedRuns(event: DurableEvent): { text: string; exact: boolean }[] { if (event.type !== "close" || event.result.status !== "ok") { @@ -2001,7 +2003,7 @@ describe("Tier MDK — the declaration states its kind", () => { * execution that could admit syntax it can never expand, and is refused before * the root document is read. * - * **One name, one answer.** A declared name is claimed across both arms and + * **One name, one answer.** A declared name is reserved across both arms and * across installations, ahead of a repository file and every ordinary * registration, and never over the engine's own syntax or a protected * component. @@ -2083,8 +2085,8 @@ function declaring( /** * What a run refused with, having read no root and imported nothing. * - * Both halves are the claim: a declaration set that cannot describe one - * environment is refused where it is installed, which is before the root + * Both halves establish the contract: a declaration set that cannot describe + * one environment is refused where it is installed, which is before the root * document is read and therefore before anything it says can happen. */ function* refusedBeforeRoot( diff --git a/packages/core/tests/document-target-execution.test.ts b/packages/core/tests/document-target-execution.test.ts index bb4481cb0..d30f000a4 100644 --- a/packages/core/tests/document-target-execution.test.ts +++ b/packages/core/tests/document-target-execution.test.ts @@ -1497,7 +1497,7 @@ describe("Tier TX — a terminal result needs its own root import", () => { /** * Tier TX — a detached retained value is still ordinary JSON. * - * Detaching is a claim against the journal, not against the document. A + * Detaching protects the journal; it does not restrict the document. A * replayed value a document goes on to update must behave as it did when the * run first produced it. */ diff --git a/packages/core/tests/document-targets.test.ts b/packages/core/tests/document-targets.test.ts index 0284e2832..fdfdc7e18 100644 --- a/packages/core/tests/document-targets.test.ts +++ b/packages/core/tests/document-targets.test.ts @@ -980,9 +980,9 @@ describe("Tier DT — structural recognition", () => { }); /** - * The reconstruction claim, made where it can fail. A boundary that returned - * the candidate would pass every field assertion above and still hand a - * caller arrays somebody else can rewrite. + * The reconstruction guarantee, made where it can fail. A boundary that + * returned the candidate would pass every field assertion above and still + * hand a caller arrays somebody else can rewrite. */ it("DT54: recognition returns a fresh local error, never the candidate", function* () { const foreign = foreignError(); diff --git a/packages/core/tests/eval-bindings.test.ts b/packages/core/tests/eval-bindings.test.ts index f0479e4ed..c11817c84 100644 --- a/packages/core/tests/eval-bindings.test.ts +++ b/packages/core/tests/eval-bindings.test.ts @@ -128,19 +128,19 @@ describe("Tier T5 — Binding environment", () => { * Every row drives the real trusted-host entrypoint with real installations. * The installations exist to *move* while the run is in flight — a preparation * and an `install()` that both rewrite the caller's record — because "copied - * before installations begin" is a claim about ordering that only something + * before installations begin" is an ordering guarantee that only something * mutating in between can disprove. */ /** * One initialization carrying whatever `initialBindings` is at runtime. * - * `initialBindings` is typed as JSON, and what has to hold is that the *parser* - * refuses a value the type already forbids — a host loading another copy of - * core, or reading its own record back from a file, is not type-checked against - * this one. The value is *defined* onto the record rather than asserted into the - * type, so nothing here claims the value is something it is not: a property - * descriptor carries an arbitrary value by design, which is exactly the - * untrusted shape the parser exists to meet. + * `initialBindings` is typed as JSON, and what has to hold is that the + * *parser* refuses a value the type already forbids — a host loading another + * copy of core, or reading its own record back from a file, is not + * type-checked against this one. The value is *defined* onto the record rather + * than asserted into the type, so nothing here asserts the value is something + * it is not: a property descriptor carries an arbitrary value by design, which + * is exactly the untrusted shape the parser exists to meet. */ function initialization(initialBindings: unknown): ExecutionInitialization { const given: ExecutionInitialization = {}; @@ -156,9 +156,9 @@ function initialization(initialBindings: unknown): ExecutionInitialization { /** * One installation that records which of its phases ran. * - * The sentinel a refusal row needs: "this input was rejected" and "this input was - * rejected *before anything was installed*" are different claims, and only - * something that would have been called can tell them apart. + * The sentinel a refusal row needs: "this input was rejected" and "this input + * was rejected *before anything was installed*" are different guarantees, and + * only something that would have been called can tell them apart. */ function watching(ran: string[]): ExecutionInstallation { return { diff --git a/packages/core/tests/evaluate-component.test.ts b/packages/core/tests/evaluate-component.test.ts index 14acee034..d3a8aaa74 100644 --- a/packages/core/tests/evaluate-component.test.ts +++ b/packages/core/tests/evaluate-component.test.ts @@ -2120,9 +2120,10 @@ describe("Tier FE34 — the shared read profile", () => { * * A `component-answer` entry is the one arm of a profile where the host does * not supply the body. It states a name and the exact structural identity a - * provider must have claimed, and canonical execution resolves that name once — - * before the root import, through the complete ordinary chain — reads the claim - * off the exact final answer, compares it whole, and seals what it retained. + * provider must have stated, and canonical execution resolves that name once — + * before the root import, through the complete ordinary chain — reads the + * identity off the exact final answer, compares it whole, and seals what it + * retained. * * So the rows here are about the two ways that could be weaker than it looks: * an answer nothing identified, and an answer that stopped being the thing that diff --git a/packages/core/tests/evaluate-loaded-copy.test.ts b/packages/core/tests/evaluate-loaded-copy.test.ts index b7e2828ce..32b90f293 100644 --- a/packages/core/tests/evaluate-loaded-copy.test.ts +++ b/packages/core/tests/evaluate-loaded-copy.test.ts @@ -1,7 +1,7 @@ /** * Tier FE — who answers for the name `Evaluate`, and what answering grants. * - * Two separate claims, and they are proved separately here because one is + * Two separate guarantees, and they are proved separately here because one is * routinely mistaken for the other. * * *Ownership* is that canonical core decides which implementation runs. A diff --git a/packages/core/tests/evaluate-provider-lifetime.test.ts b/packages/core/tests/evaluate-provider-lifetime.test.ts index 5502474f5..1cf2f5e81 100644 --- a/packages/core/tests/evaluate-provider-lifetime.test.ts +++ b/packages/core/tests/evaluate-provider-lifetime.test.ts @@ -47,7 +47,7 @@ const OPEN = `\\n'} as="answer" />\n\n { * A component whose invocation registers teardown before it returns. * * The cleanup pushes to the same log the fragment and the document push to, so - * the order of that one array is the whole claim: whether the projection's - * structured teardown finished before the parent's next element began. + * the order of that one array is the whole ordering check: whether the + * projection's structured teardown finished before the parent's next element + * began. */ function unwinding(log: string[]): FunctionComponentDefinition { return { diff --git a/packages/core/tests/generated-xmd.test.ts b/packages/core/tests/generated-xmd.test.ts index e127598ed..d702adf01 100644 --- a/packages/core/tests/generated-xmd.test.ts +++ b/packages/core/tests/generated-xmd.test.ts @@ -3,7 +3,7 @@ * (specs/workflow-workspace-spec.md §8.4). * * A trusted host hands the evaluator candidate source and the ceilings it may - * run under. Everything here is about one of three claims. + * run under. Everything here is about one of three guarantees. * * **The whole fragment is read before anything happens.** A refusal costs no * request, no observation, and no generated-XMD event — whether the construct @@ -2026,8 +2026,8 @@ describe("Tier GX — a resumed run is held to the ceilings it was admitted unde /** * One admission whose policy and result carry whatever members a case wants. * - * Built as a literal rather than by rewriting a real record, so a case states - * the exact shape it is claiming this build must refuse. + * Built as a literal rather than by rewriting a real record, so a case + * states the exact shape this build must refuse. */ function forgedAdmission(policy: JsonObject, extra: JsonObject = {}): DurableEvent { return { @@ -2875,8 +2875,8 @@ describe("Tier WGAC — the pinned read-only File", () => { * Tier GXC — the effect classes a fragment draws on * (specs/workflow-workspace-spec.md §8.4). * - * The host states two tables and the caller selects between them. Three claims - * follow from that, and everything here is one of them. + * The host states two tables and the caller selects between them. Three + * guarantees follow from that, and everything here is one of them. * * **A selection is not a grant.** `allow` chooses among identities the host * already installed. An empty, repeated or unavailable selection is the host's diff --git a/packages/core/tests/invocation-identity.test.ts b/packages/core/tests/invocation-identity.test.ts index 1d294ef36..3dc35383f 100644 --- a/packages/core/tests/invocation-identity.test.ts +++ b/packages/core/tests/invocation-identity.test.ts @@ -2,19 +2,21 @@ * Tier CIV — the identity a trusted host's component names its work after * (specs/executable-mdx-spec.md §5.6). * - * A component that names a durable operation after its own invocation is making - * an ownership claim: the name decides which retained record a replay restores, - * and an implementation running under somebody else's identity commits against - * its own storage under their expansion. Code Rule 15 says a decision like that - * never trusts replaceable state, so nothing here is read from one. + * A component that names a durable operation after its own invocation is + * asserting ownership: the name decides which retained record a replay + * restores, and an implementation running under somebody else's identity + * commits against its own storage under their expansion. Code Rule 15 says a + * decision like that never trusts replaceable state, so nothing here is read + * from one. * * The execution is told, before any installation runs, which components name - * durable work. It mints a domain for each, hands that domain's claimant - * straight to the host's factory, registers what comes back, and activates the - * claimant only once that registration has committed. What a document, a - * component or middleware can reach is the implementation — never the claimant, - * never the domain — and the claimant answers only for the invocation the - * engine is running at that moment. + * durable work. It mints a domain for each, hands that domain's identity + * authenticator straight to the host's factory, registers what comes back, and + * activates the identity authenticator only once that registration has + * committed. What a document, a component or middleware can reach is the + * implementation — never the identity authenticator, never the domain — and + * the identity authenticator answers only for the invocation the engine is + * running at that moment. */ import { describe, it } from "@executablemd/test-support/bdd"; @@ -83,8 +85,8 @@ function record(): Seen { /** * ``, as a host declares it: a factory the execution calls with the - * claimant it minted, and content-bearing so one probe can be another's live - * ancestor. + * identity authenticator it minted, and content-bearing so one probe can be + * another's live ancestor. */ function probe(seen: Seen, name = "Probe"): IdentityComponent { return { @@ -217,7 +219,8 @@ function rendered( function* nothing(): Operation {} /** - * One activated domain and its claimant, without an execution around them. + * One activated domain and its identity authenticator, without an execution + * around them. * * The engine expands one element at a time, so the cases that need two live * issuances — or one the engine has already ended — are stated here, at the @@ -1251,7 +1254,7 @@ describe("Tier CIV — two canonical imports live at the same time", () => { "", ].join("\n"); - /** A probe that says when it has claimed, so the failure lands after it. */ + /** A probe that says when it has authenticated its invocation, so the failure lands after it. */ function claiming(seen: Seen, done: { resolve(value: void): void }): IdentityComponent { return { name: "Probe", @@ -1273,7 +1276,7 @@ describe("Tier CIV — two canonical imports live at the same time", () => { }; } - /** The sibling that decides the run's outcome once the survivor claimed. */ + /** The sibling that decides the run's outcome once the survivor authenticated its invocation. */ function tripwire(waited: Operation, outcome: "fails" | "finishes"): IdentityComponent { return { name: "Boom", diff --git a/packages/core/tests/loaded-copy-files.test.ts b/packages/core/tests/loaded-copy-files.test.ts index 933c77df3..e16f18d88 100644 --- a/packages/core/tests/loaded-copy-files.test.ts +++ b/packages/core/tests/loaded-copy-files.test.ts @@ -12,10 +12,10 @@ * would arrive, imports the bundle as its own module, constructs a failure with * *that* copy's constructor, and asks the engine's own discovery about it. * - * Bundling is also the second half of a claim the smoke job makes: this module - * has to stay reachable without the runtime's host Apis, one of which carries a - * native addon no bundler can inline. A regression there fails here as a - * bundling error rather than as a mysterious CI break. + * Bundling is also the second half of a guarantee the smoke job makes: this + * module has to stay reachable without the runtime's host Apis, one of which + * carries a native addon no bundler can inline. A regression there fails here + * as a bundling error rather than as a mysterious CI break. * * Deno-only: `deno bundle` is Deno's. */ diff --git a/packages/core/tests/output-error-mode.test.ts b/packages/core/tests/output-error-mode.test.ts index acd6dd5bb..09bcaf13a 100644 --- a/packages/core/tests/output-error-mode.test.ts +++ b/packages/core/tests/output-error-mode.test.ts @@ -1683,10 +1683,10 @@ describe("Tier OM — caller content at a plain root leaves the printing compone /** * `` says what it did not write, which is a sentence about its own - * work. It is not a claim on the failure: the caller's region decided that - * one, so the account of it passes outward through ``'s own - * `printErrors(fn)` declaration and is settled where the element was written - * (§6.8.1, §6.13). At a plain root that ends the run. + * work. It does not confer ownership of the failure: the caller's region + * decided that one, so the account of it passes outward through ``'s + * own `printErrors(fn)` declaration and is settled where the element was + * written (§6.8.1, §6.13). At a plain root that ends the run. */ it("OM21: an ordinary failure in 's children writes nothing and ends the run", function* () { const result = yield* runRecordingWrites({ diff --git a/packages/core/tests/registered-printed-errors.test.ts b/packages/core/tests/registered-printed-errors.test.ts index c0b30e95a..a3bf400c5 100644 --- a/packages/core/tests/registered-printed-errors.test.ts +++ b/packages/core/tests/registered-printed-errors.test.ts @@ -2,11 +2,12 @@ * A function component's printed error, observed and settled exactly once * (spec §6.9). * - * Rescued from the expansion-hook suite, which pinned this against a claiming - * handler. The contract belongs to the component boundary rather than to that - * hook, so it is pinned here against a component instead — supplied through the - * `importComponent` seam, because this drives `expandSegments` directly and - * only `execute()` installs a provider that reads registrations. + * Rescued from the expansion-hook suite, which pinned this against an + * intercepting handler. The contract belongs to the component boundary rather + * than to that hook, so it is pinned here against a component instead — + * supplied through the `importComponent` seam, because this drives + * `expandSegments` directly and only `execute()` installs a provider that + * reads registrations. * * `raise()` is where settlement happens: it puts the segment through the * observation chain and applies the ambient error mode. What the component returns diff --git a/packages/core/tests/root-composition.test.ts b/packages/core/tests/root-composition.test.ts index f3aed525a..a209bac58 100644 --- a/packages/core/tests/root-composition.test.ts +++ b/packages/core/tests/root-composition.test.ts @@ -1,7 +1,7 @@ /** * Tier RC — the root a run executes, after `Document` and `RootMetadata`. * - * Two claims, and they pull against each other. A run with no Plugin + * Two guarantees, and they pull against each other. A run with no Plugin * middleware must be the run it always was — same body, same props, same * `returns`, same `` selection, same source positions, same expansion * identity — and a run with middleware must execute the envelope that diff --git a/packages/core/tests/secret-detection.test.ts b/packages/core/tests/secret-detection.test.ts index 3647d0270..c9b25f7d0 100644 --- a/packages/core/tests/secret-detection.test.ts +++ b/packages/core/tests/secret-detection.test.ts @@ -159,7 +159,7 @@ function label(event: DurableEvent): string { /** Every command answers with `output`, so no real shell runs. */ /** - * A stand-in child, which displays what it claims to have written. + * A stand-in child, which displays what it reports writing. * * Retention reads the same chain a reader does (#441), so a stub that returned * text without writing it would leave nothing for the journal to hold — and diff --git a/packages/core/tests/secret-rules.test.ts b/packages/core/tests/secret-rules.test.ts index 11deb343e..aaa94881e 100644 --- a/packages/core/tests/secret-rules.test.ts +++ b/packages/core/tests/secret-rules.test.ts @@ -550,8 +550,8 @@ describe("single-quoted fields after serialization", () => { * The earlier "one segment does not excuse the value" fixtures did not catch * this. They all carried mixed case or digits, so the word pattern rejected * them before the placeholder-word check ever ran — they passed for a reason - * unrelated to what they claimed to test. These are all lowercase, so the - * placeholder logic is the only thing standing between them and a finding. + * unrelated to what they were intended to test. These are all lowercase, so + * the placeholder logic is the only thing standing between them and a finding. */ describe("lowercase passphrases containing placeholder words", () => { const PASSPHRASES = [ diff --git a/packages/core/tests/shared-operation-permissions.test.ts b/packages/core/tests/shared-operation-permissions.test.ts index c7e78f65b..11b41ff14 100644 --- a/packages/core/tests/shared-operation-permissions.test.ts +++ b/packages/core/tests/shared-operation-permissions.test.ts @@ -10,8 +10,8 @@ * scope could see. * * Everything here drives the real host provider against a real directory, and - * every claim is checked twice: once in what the document reported, and once in - * what the filesystem actually holds afterwards. A refusal that printed the + * every outcome is checked twice: once in what the document reported, and once + * in what the filesystem actually holds afterwards. A refusal that printed the * right sentence and wrote the file anyway would pass the first and fail the * second. * diff --git a/packages/core/tests/state-ownership.test.ts b/packages/core/tests/state-ownership.test.ts index 0108e7a5c..f60e66377 100644 --- a/packages/core/tests/state-ownership.test.ts +++ b/packages/core/tests/state-ownership.test.ts @@ -2,10 +2,10 @@ * Tier SO — state belongs to the operation that owns it (architecture.md). * * Every table the engine keeps is created inside the run it describes and - * reclaimed when that run ends, so nothing one execution recorded is still - * answering questions during the next. The exception is a declaration an author - * writes at module evaluation about a function the author owns, which has no run - * to belong to and lives on the function itself. + * released when that run ends, so nothing one execution recorded is still + * answering questions during the next. The exception is a declaration an + * author writes at module evaluation about a function the author owns, which + * has no run to belong to and lives on the function itself. * * The evidence these tests accept is a second execution: what run 1 recorded * must not answer for run 2. @@ -228,10 +228,10 @@ describe("Tier SO — each run compiles with a compiler of its own", () => { }); /** - * The same claim where a host actually meets it: a component registered once - * and invoked by two executions, whose props schema object the host changed in - * between. A validator remembered from the first run would let the second run - * accept props its schema no longer allows. + * The same ownership guarantee where a host actually meets it: a component + * registered once and invoked by two executions, whose props schema object the + * host changed in between. A validator remembered from the first run would let + * the second run accept props its schema no longer allows. */ describe("Tier SO — two executions of a registered component", () => { function run(files: Record, schema: PropsSchema): Operation { diff --git a/packages/core/tests/support/answer-provider.ts b/packages/core/tests/support/answer-provider.ts index 7e4b11088..f3d1ed435 100644 --- a/packages/core/tests/support/answer-provider.ts +++ b/packages/core/tests/support/answer-provider.ts @@ -53,7 +53,7 @@ export function implementation( /** How one row wants its provider to differ from the honest one. */ export interface ProviderOptions { - /** The provider's own name for itself; the origin every claim carries. */ + /** The provider's own name for itself; the origin every identity statement carries. */ readonly origin?: string; /** The key and revision this provider states. */ readonly key?: string; @@ -64,9 +64,9 @@ export interface ProviderOptions { readonly asked?: string[]; /** Return the answer without stating an identity for it at all. */ readonly unclaimed?: boolean; - /** State the identity, then answer with a copy of the claimed object. */ + /** State the identity, then answer with a copy of the identified object. */ readonly copied?: boolean; - /** State the identity, then edit the claimed object. */ + /** State the identity, then edit the identified object. */ readonly mutated?: boolean; /** * Keep answering after the capture, rather than settling. @@ -77,51 +77,52 @@ export interface ProviderOptions { */ readonly keepsAnswering?: boolean; /** - * Keep *claiming* after the capture, rather than settling. + * Keep *stating identities* after the capture, rather than settling. * * The other half of the same refusal, one step earlier: the resolution this * provider answered has settled, so there is no open window to state an - * identity into and the claim refuses before the witness is ever consulted. + * identity into and recording the identity refuses before the witness is + * ever consulted. */ readonly reclaimsLater?: boolean; /** - * Delegate first, and answer with this provider's own claimed object. + * Delegate first, and answer with this provider's own identified object. * * What an *outer* provider does. The one installed first composes outermost, * so it sees the chain's answer before deciding, and returning its own - * claimed object is an honest substitution: the identity travels with the + * identified object is an honest substitution: the identity travels with the * object the chain finally gives back. */ readonly delegatesFirst?: boolean; /** - * Delegate and answer with whatever came back, claiming nothing. + * Delegate and answer with whatever came back, stating no identity. * * What a *repeated* bootstrap does. A package entered through an inherited * layer and again through a local one composes twice, and the outer entry - * cannot claim a second identity for the object the inner one already - * claimed — one implementation states what it is once. So it observes and + * cannot state a second identity for the object the inner one already + * identified — one implementation states what it is once. So it observes and * passes the answer through, which is what keeps the layering additive. */ readonly observesOnly?: boolean; /** What delegating answered with, for a row that has to prove it happened. */ readonly delegated?: unknown[]; /** - * Run this inside the live resolution, just before claiming. + * Run this inside the live resolution, just before stating the identity. * - * The one place a row can reach that is *during* an open claim window for - * this name — which is what a race between two resolutions has to be observed - * from, since there is no other way to be inside one. + * The one place a row can reach that is *during* an open identity-recording + * window for this name — which is what a race between two resolutions has to + * be observed from, since there is no other way to be inside one. */ readonly whileResolving?: (request: ComponentAnswerRequest) => void; /** * Answer with a value whose contract reads differently each time it is read. * * The check/use gap at execution scale. `[[Get]]` alternates between the - * claimed schema and a substitution; comparing own descriptors, which is how - * the claim is checked, does not run the trap. So a capture that checked the - * answer and then *read it again* to take its copy would seal the - * substitution — and a fragment would be validated against a contract the - * provider never claimed. + * identified schema and a substitution; comparing own descriptors, which is + * how the identity is checked, does not run the trap. So a capture that + * checked the answer and then *read it again* to take its copy would seal + * the substitution — and a fragment would be validated against a contract + * the provider never identified. */ readonly alternating?: { readonly substitute: PropsSchema; readonly reads: string[] }; /** Where this provider leaves each request its handler received, for a row to keep. */ @@ -129,8 +130,8 @@ export interface ProviderOptions { } /** - * One answer whose `props` alternates between what was claimed and something - * else, read by read. + * One answer whose `props` alternates between what was identified and + * something else, read by read. * * Only `[[Get]]` is trapped, because that is what taking a copy of a definition * uses and what comparing own descriptors does not. The schema is the member to diff --git a/packages/core/tests/syntax-component.test.ts b/packages/core/tests/syntax-component.test.ts index 8921e04d4..d4ef56982 100644 --- a/packages/core/tests/syntax-component.test.ts +++ b/packages/core/tests/syntax-component.test.ts @@ -16,8 +16,8 @@ * code ran, and it travels lexically on canonical core's own expansion * resolution — not through a context, where a name is not a secret. * - * **One occurrence renders once.** It claims the identity this execution minted - * and records a closed payload carrying exactly one member: + * **One occurrence renders once.** It authenticates the identity this execution + * minted and records a closed payload carrying exactly one member: * * ``` * { symbols: string } | { refused: non-empty string } @@ -992,8 +992,8 @@ describe("Tier SYN — the named form", () => { * The layering is the same shape as SYN25l.5 — the inner scope descends from * the outer, and both enter the same bootstrap. What the repeat means for a * provider is that the outer entry observes and delegates rather than - * claiming again: one implementation states what it is once, so an additive - * layering has exactly one claim behind the name. + * stating an identity again: one implementation states what it is once, so + * an additive layering has exactly one identity statement behind the name. * * These rows reuse #765's collector rather than adding one. The * documentation halves here are the same asks SYN25l.1/.2/.5 make, and what diff --git a/packages/core/tests/syntax-loaded-copy.test.ts b/packages/core/tests/syntax-loaded-copy.test.ts index 308c67e7e..a2a4f6204 100644 --- a/packages/core/tests/syntax-loaded-copy.test.ts +++ b/packages/core/tests/syntax-loaded-copy.test.ts @@ -2,10 +2,10 @@ * Tier SYN — a protected implementation from a second loaded copy answers for * nothing. * - * A component can be loaded from disk beside its own copy of core: that is what - * `--include` does, and what a middleware package holding its own copy is. So - * "another loaded copy cannot answer for ``" is a claim about ordinary - * arrangements rather than a hypothetical, and it has two halves. + * A component can be loaded from disk beside its own copy of core: that is + * what `--include` does, and what a middleware package holding its own copy + * is. So "another loaded copy cannot answer for ``" is a guarantee + * for ordinary arrangements rather than a hypothetical, and it has two halves. * * **The answer is refused.** Canonical execution issues a witness for the * definition it produced and verifies it where the component is invoked, keyed @@ -29,9 +29,9 @@ * in the protected tier. ``, `` and `` are answered * with one ordinary definition built once per loaded copy rather than a body * this execution built, so a second copy of that module supplies a complete, - * structurally identical definition — no claimant, no private table, nothing - * missing. That makes it the sharpest form of the question, and the only one a - * locally rebuilt definition cannot stand in for. + * structurally identical definition — no identity authenticator, no private + * table, nothing missing. That makes it the sharpest form of the question, and + * the only one a locally rebuilt definition cannot stand in for. */ import { describe, it } from "@executablemd/test-support/bdd"; diff --git a/packages/durable-streams/guard.ts b/packages/durable-streams/guard.ts index a7c18d0ad..82dbcac4a 100644 --- a/packages/durable-streams/guard.ts +++ b/packages/durable-streams/guard.ts @@ -68,7 +68,7 @@ export function establishJournalProvenance(stream: DurableStream): JournalProven /** * Carry an exact source stream's provenance onto a trusted wrapper of it. * - * Preservation is visible composition rather than a new claim: it transfers + * Preservation is visible composition rather than new evidence: it transfers * only the witness already associated with that exact source, so an unproven * source leaves the target unproven. The target is returned so the wrapping * site reads as one expression. diff --git a/packages/durable-streams/replay-index.ts b/packages/durable-streams/replay-index.ts index 65e850866..a35a1f79c 100644 --- a/packages/durable-streams/replay-index.ts +++ b/packages/durable-streams/replay-index.ts @@ -180,7 +180,7 @@ export class ReplayIndex { * Return the first retained coroutine not aligned with the current subtree. * * `entry` is the first unmatched retained protocol entry itself — the Yield - * at the cursor, or for an unclaimed completed child its first Yield when it + * at the cursor, or for an unmatched completed child its first Yield when it * has one and otherwise its Close — so a terminal diagnostic can name what * the terminating subtree did not reach, not just where it stopped. */ diff --git a/packages/durable-streams/retained.ts b/packages/durable-streams/retained.ts index 84b12af49..f07d18bbe 100644 --- a/packages/durable-streams/retained.ts +++ b/packages/durable-streams/retained.ts @@ -65,8 +65,8 @@ function resolve(settled: Settled): T { * another to the next, and no later mutation of the source changes what replay * used. * - * The copy is ordinary JSON. Detaching is the claim against the *stream*; - * making the copy immutable would be a claim against the *consumer*, and + * The copy is ordinary JSON. Detaching is the guarantee for the *stream*; + * making the copy immutable would be a restriction on the *consumer*, and * replayed values are legitimately mutable — an eval binding restored from a * journal is pushed to by the iteration that resumes on it. Members are * therefore writable and configurable like any other JSON. @@ -114,8 +114,8 @@ export function detachJson(value: Json, seen: Set = new Set()): Json { * * The authoritative retained graph is what admission validated and what replay * consumes, so nothing that reaches a caller may write to it. Freezing is the - * claim against *policy*, not against a workflow: what a document finally - * receives is a fresh mutable copy taken from this, never this. + * restriction on *policy*, not on a workflow: what a document finally receives + * is a fresh mutable copy taken from this, never this. */ function sealJson(value: Json): Json { const detached = detachJson(value); diff --git a/packages/git/src/composition/api.ts b/packages/git/src/composition/api.ts index 4ddd1e619..a87686a58 100644 --- a/packages/git/src/composition/api.ts +++ b/packages/git/src/composition/api.ts @@ -17,9 +17,9 @@ * be refused; it cannot reach one. * * The default handler throws. There is no in-memory fallback: a Repository that - * "starts" without a provider would retain nothing while claiming it had, and a - * host that installs none must be distinguishable from one whose repository is - * merely not there. + * "starts" without a provider would retain nothing while reporting that it had, + * and a host that installs none must be distinguishable from one whose + * repository is merely not there. */ import { type Api, createApi } from "@effectionx/context-api"; diff --git a/packages/git/src/composition/git-api.ts b/packages/git/src/composition/git-api.ts index 1dbd27107..63bbb82ab 100644 --- a/packages/git/src/composition/git-api.ts +++ b/packages/git/src/composition/git-api.ts @@ -12,7 +12,7 @@ * completed one restores from the journal and moves no branch. The ordinary * `xmd run` provider performs them directly against the selected checkout: * there is no transaction to enclose a person's own repository in, and none is - * claimed. + * promised. * * The default handler throws. There is no host-less fallback, because a Git * operation that "ran" without a provider would report a branch this run never diff --git a/packages/git/src/composition/git-push-records.ts b/packages/git/src/composition/git-push-records.ts index 05aed92a7..6c500f3db 100644 --- a/packages/git/src/composition/git-push-records.ts +++ b/packages/git/src/composition/git-push-records.ts @@ -270,11 +270,11 @@ export function parseGitPushNaturalKey(value: unknown): GitPushNaturalKey | unde /** * The pre-state this value describes, or `undefined` when it describes none. * - * The two variants are read separately so each stays closed. A relation is a - * claim about a commit, so it means nothing beside a destination proven absent; - * a word other than `ancestor` is a relation this version cannot account for; - * and either variant carrying a member it does not declare describes something - * else entirely. + * The two variants are read separately so each stays closed. A relation is an + * ancestry assertion about a commit, so it means nothing beside a destination + * proven absent; a word other than `ancestor` is a relation this version cannot + * account for; and either variant carrying a member it does not declare + * describes something else entirely. */ export function parseGitPushPreState( value: unknown, diff --git a/packages/git/src/composition/installation.ts b/packages/git/src/composition/installation.ts index 6598d2d71..6ac35fcc4 100644 --- a/packages/git/src/composition/installation.ts +++ b/packages/git/src/composition/installation.ts @@ -5,9 +5,9 @@ * Repository, Worktree, the four Git operations, PullRequest and its three * evidence reads, IssueTracker and Issue are ordinary registered defaults — not * reserved and not structural — so a repository-local component may shadow one - * for its own scope. `` is not among them: canonical core claims that name - * (`core/src/components/fixed-filesystem.ts`), and a document reaches it with or - * without this package. + * for its own scope. `` is not among them: canonical core reserves that + * name (`core/src/components/fixed-filesystem.ts`), and a document reaches it + * with or without this package. * * One array, three consumers, because three descriptions of one vocabulary * would drift. `useCompositionComponents()` registers it inside a workflow diff --git a/packages/git/src/composition/parse.ts b/packages/git/src/composition/parse.ts index a4228cbc4..87d44eced 100644 --- a/packages/git/src/composition/parse.ts +++ b/packages/git/src/composition/parse.ts @@ -1,5 +1,5 @@ /** - * Reading a value that arrived from outside as the shape it claims to be. + * Reading a value that arrived from outside as the shape it reports. * * Every record these components retain comes back through the journal or a * database column, so nothing about it is this package's own word by the time it diff --git a/packages/git/src/composition/pull-request-read-records.ts b/packages/git/src/composition/pull-request-read-records.ts index 6b878cd6f..dddbc86d6 100644 --- a/packages/git/src/composition/pull-request-read-records.ts +++ b/packages/git/src/composition/pull-request-read-records.ts @@ -11,7 +11,7 @@ * * `id` is a decimal string. Provider identifiers already exceed what a JSON * number holds exactly, and a value that silently loses its last digits is - * worse than one that never claimed to be arithmetic. + * worse than one that was never presented as arithmetic. * * Timestamps are the provider's own RFC 3339 strings, unparsed. What a reader * needs is what the host said, and reformatting is a second contract to get diff --git a/packages/git/src/composition/pull-request-records.ts b/packages/git/src/composition/pull-request-records.ts index adb58c173..42cb45539 100644 --- a/packages/git/src/composition/pull-request-records.ts +++ b/packages/git/src/composition/pull-request-records.ts @@ -739,7 +739,7 @@ function mutableFieldsAgree(before: PullRequestSnapshot, after: PullRequestSnaps /** * Whether two snapshots describe the same pull request in the same state. * - * What an adoption claims is that the pull request that was already there is + * What adoption establishes is that the pull request that was already there is * the one this record retains — every member, not merely the ones the request * named. A pre-state naming another number, another URL or another base commit * describes a pull request the observations are not about. diff --git a/packages/git/src/deno/composition/authentication.ts b/packages/git/src/deno/composition/authentication.ts index 8ed69df40..fc21f176b 100644 --- a/packages/git/src/deno/composition/authentication.ts +++ b/packages/git/src/deno/composition/authentication.ts @@ -305,11 +305,11 @@ export function credentialRequest(locator: string): CredentialRequest | undefine /** * What a session did with host resources, for a suite that has to prove it. * - * A claim that nothing survives teardown needs something that counted, and - * counting by scanning the temporary directory for a name prefix is a claim - * about the whole machine rather than about this invocation — two concurrent - * ones would each see the other's. So a session reports its own working - * directories, and a suite watches the invocation it started. + * Proving that nothing survives teardown needs something that counted, and + * counting by scanning the temporary directory for a name prefix measures the + * whole machine rather than this invocation — two concurrent ones would each + * see the other's. So a session reports its own working directories, and a + * suite watches the invocation it started. */ export interface GitAuthenticationObserver { opened?: (directory: string) => void; diff --git a/packages/git/src/deno/composition/commit.ts b/packages/git/src/deno/composition/commit.ts index 8d18dd712..21f4e6276 100644 --- a/packages/git/src/deno/composition/commit.ts +++ b/packages/git/src/deno/composition/commit.ts @@ -69,7 +69,7 @@ export interface GitCommitMessageEvidence { * UTF-8, because that is what Git receives and what a byte length has to be * counted in for the two to describe the same thing. Derived once, from the * admitted bytes, and then compared against everything: what Git read back, and - * what a retained result claims. + * what a retained result records. */ export function gitCommitMessageEvidence(message: string): GitCommitMessageEvidence { const bytes = new TextEncoder().encode(message); diff --git a/packages/git/src/deno/composition/git.ts b/packages/git/src/deno/composition/git.ts index 0a1594cb4..e0e9fc5ae 100644 --- a/packages/git/src/deno/composition/git.ts +++ b/packages/git/src/deno/composition/git.ts @@ -444,9 +444,9 @@ export function* switchBranch(git: GitSession, request: BranchSwitch): Operation * savepoint takes back the attempt — so the Workspace never holds a partial * staging, and the failed result describes a root that did not move. * - * Four conditions are refusals a document can act on, and the set is closed. Any - * other nonzero exit is infrastructure: naming it the nearest refusal would - * publish a durable result claiming this run knows what happened. + * Four conditions are refusals a document can act on, and the set is closed. + * Any other nonzero exit is infrastructure: an unsupported refusal + * classification must not become a durable outcome. */ export function* addPaths( git: GitSession, @@ -542,9 +542,8 @@ function addFailure(outcome: GitOutcome, paths: readonly string[]): GitFailureRe * The message selects a word and is then discarded, on the same terms as every * other reading here; `LC_ALL=C` is what makes it stable. A condition this * cannot recognize is *not* given a word. The set of refusals is closed because - * each of them is something a document can act on, and calling an unrecognized - * exit the nearest one would publish a durable result claiming this run knows - * what happened. + * each of them is something a document can act on, and classifying an + * unrecognized exit as one would falsely establish a durable refusal. */ function switchFailure(outcome: GitOutcome): GitFailureReason | undefined { if (checkedOutElsewhere(outcome)) { @@ -577,7 +576,7 @@ export function* checkoutReadable( * * `remote.origin.url` is what a clone writes and what this provider's clone * wrote. Reading it back is how the bytes in the Workspace are tied to the - * identity the record claims for them: a checkout of another repository sitting + * identity the record assigns to them: a checkout of another repository sitting * at the retained path answers with another locator, and no amount of HEAD * being readable would have said so. */ @@ -597,10 +596,10 @@ export function* commitPresent( /** * The shared `.git` directory a checkout belongs to. * - * For a primary checkout this is its own `.git`; for a linked worktree it is the - * repository the worktree is a worktree *of*. Comparing it with the place the - * enclosing Repository was materialized is what proves a retained worktree - * belongs to the retained Repository it claims, rather than to some other + * For a primary checkout this is its own `.git`; for a linked worktree it is + * the repository the worktree is a worktree *of*. Comparing it with the place + * the enclosing Repository was materialized is what proves a retained worktree + * belongs to the retained Repository it names, rather than to some other * repository whose administration happens to resolve. */ export function* commonDirectory( diff --git a/packages/git/src/deno/composition/github-pull-request.ts b/packages/git/src/deno/composition/github-pull-request.ts index 56c1dd83d..25735537b 100644 --- a/packages/git/src/deno/composition/github-pull-request.ts +++ b/packages/git/src/deno/composition/github-pull-request.ts @@ -46,7 +46,7 @@ function unusable(reason: string): never { } /** - * A pre-state that claims nothing. + * A pre-state that asserts no prior remote state. * * The three refusing observations publish no record — the engine journals a * conflict, an ambiguity and an unavailability as the effect's failed result diff --git a/packages/git/src/deno/composition/operations.ts b/packages/git/src/deno/composition/operations.ts index 59388c5fb..67c951837 100644 --- a/packages/git/src/deno/composition/operations.ts +++ b/packages/git/src/deno/composition/operations.ts @@ -45,7 +45,7 @@ * Between materialization and native Git, the retained identity is proven * against what was exported: placement, origin, object format, creation commit, * and — for a linked worktree — that it really is a worktree of the Repository - * it claims. Then the checkout's branch, commit, HEAD tree and index tree are + * it names. Then the checkout's branch, commit, HEAD tree and index tree are * read, the operation runs, and they are read again. What the run retains is * those two readings rather than a summary of what changed, because a history * that says only "switched" cannot be checked against anything. @@ -438,10 +438,10 @@ export function* exportCheckoutFamily( * localized first, because until it is, a linked worktree's pointers still name * Workspace paths and native Git can answer nothing about it. The working * directory is then proven to be a real directory inside the export. And the - * creation identity the record claims is read back out of the bytes — where the - * checkout came from, how it names objects, that the commit it was created at - * is present, and for a linked worktree that it is a worktree of the Repository - * it belongs to. + * creation identity the record describes is read back out of the bytes — where + * the checkout came from, how it names objects, that the commit it was created + * at is present, and for a linked worktree that it is a worktree of the + * Repository it belongs to. * * Everything here reads the host tree rather than the Workspace, so it belongs * outside the transaction that produced the export. diff --git a/packages/git/src/deno/composition/provider.ts b/packages/git/src/deno/composition/provider.ts index 3ceb2203d..4348eb742 100644 --- a/packages/git/src/deno/composition/provider.ts +++ b/packages/git/src/deno/composition/provider.ts @@ -88,9 +88,9 @@ export { WORKSPACE_GIT_COMMIT } from "./commit.ts"; /** * What a provider may observe about itself, for suites that count. * - * A claim that replay performs no effect and reaches no remote is only worth - * making if something counted. This is how: the host counts Git invocations, - * and the provider counts the effects and attachments it performed. + * Proving replay performs no effect and reaches no remote requires counting + * those crossings. This is how: the host counts Git invocations, and the + * provider counts the effects and attachments it performed. */ export interface CompositionObserver { effect?: (kind: "repository" | "worktree" | "git", name: string) => void; diff --git a/packages/git/src/deno/composition/pull-request-evidence.ts b/packages/git/src/deno/composition/pull-request-evidence.ts index 552c9fc4a..ac3c23285 100644 --- a/packages/git/src/deno/composition/pull-request-evidence.ts +++ b/packages/git/src/deno/composition/pull-request-evidence.ts @@ -62,7 +62,7 @@ export type EvidenceReading = | { readonly state: "protocol-invalid" }; /** - * Something was read, and it was not what it claimed to be. + * Something was read, and it was not the expected representation. * * Told apart from unavailable because they mean opposite things about the host: * unavailable is a host that did not answer, and this is a host that answered diff --git a/packages/git/src/deno/composition/pull-request-reads.ts b/packages/git/src/deno/composition/pull-request-reads.ts index 5f2a6e82e..0333d315f 100644 --- a/packages/git/src/deno/composition/pull-request-reads.ts +++ b/packages/git/src/deno/composition/pull-request-reads.ts @@ -114,8 +114,8 @@ export function parseGitHubPullRequestUrl(url: string): GitHubPullRequestName | * * Public GitHub only. A self-hosted deployment wearing the same path shape is * reachable by naming `provider="github"` explicitly — implicit selection must - * not claim a host nobody said was GitHub, because a search is how a document - * that named one service quietly reaches a different one. + * not select a host nobody identified as GitHub, because a search is how a + * document that named one service quietly reaches a different one. */ export function recognizesGitHubPullRequestUrl(url: string): boolean { const parsed = parseGitHubPullRequestUrl(url); diff --git a/packages/git/src/deno/composition/push.ts b/packages/git/src/deno/composition/push.ts index 208477257..ecdd2e1ed 100644 --- a/packages/git/src/deno/composition/push.ts +++ b/packages/git/src/deno/composition/push.ts @@ -15,8 +15,9 @@ * contextual working directory select a retained checkout the way they do for * every other Git operation; the observed record is compared with the retained * row member for member, every row is held to the identity naming it, and the - * exported family is proven to be the checkout the record claims. Only then are - * the branch and the commit read — from the checkout, never from a document. + * exported family is proven to be the checkout the record describes. Only then + * are the branch and the commit read — from the checkout, never from a + * document. * * A checkout whose HEAD names no branch stops here. That is the one condition a * document can act on, and it is decided before a durable effect exists and diff --git a/packages/git/src/deno/composition/repository.ts b/packages/git/src/deno/composition/repository.ts index dabde882b..db60b9f6e 100644 --- a/packages/git/src/deno/composition/repository.ts +++ b/packages/git/src/deno/composition/repository.ts @@ -198,12 +198,12 @@ export function* prepareRepositoryAttachment( * carried on, restoring recorded reads that no longer describe what is there * while every later live effect ran against the substitute. * - * So the three things the record actually claims are read back out of the + * So the three things the record actually states are read back out of the * checkout: where it came from, how it names objects, and whether the commit it - * was created at is in it. Each is creation identity, and creation identity does - * not move. What is deliberately *not* asked is where HEAD or the current branch - * is: #294 moves those transactionally, and requiring them to equal creation - * state would make an ordinary commit look like corruption. + * was created at is in it. Each is creation identity, and creation identity + * does not move. What is deliberately *not* asked is where HEAD or the current + * branch is: #294 moves those transactionally, and requiring them to equal + * creation state would make an ordinary commit look like corruption. * * The origin is compared by fingerprint rather than by bytes. The fingerprint is * what every other comparison in this provider uses, and it is the one form of diff --git a/packages/git/src/deno/run-composition/operations.ts b/packages/git/src/deno/run-composition/operations.ts index b72eb87c3..916eb9ee0 100644 --- a/packages/git/src/deno/run-composition/operations.ts +++ b/packages/git/src/deno/run-composition/operations.ts @@ -10,7 +10,7 @@ * * What is different is everything around them. There is no Workspace * transaction to enclose a person's own repository in, so a failure rolls back - * nothing and this makes no such claim; there is no journal, so nothing is + * nothing and this promises no rollback; there is no journal, so nothing is * retained and nothing replays; and the commit lands in the checkout the person * is standing in rather than in a root the run owns. * diff --git a/packages/git/src/deno/run-composition/pull-request.ts b/packages/git/src/deno/run-composition/pull-request.ts index 204c967a3..25e53a348 100644 --- a/packages/git/src/deno/run-composition/pull-request.ts +++ b/packages/git/src/deno/run-composition/pull-request.ts @@ -17,7 +17,7 @@ * ## Interruption, said plainly * * Inside one execution an attempt is made at most once. Across a process - * interruption there is no exactly-once claim at all: GitHub may have accepted a + * interruption there is no exactly-once guarantee: GitHub may have accepted a * change for which this run recorded no result, and the next run observes what * is there and decides from that. Nothing pretends otherwise, and nothing is * retained that would let it. diff --git a/packages/git/src/deno/selections.ts b/packages/git/src/deno/selections.ts index a712b16ca..8612d4646 100644 --- a/packages/git/src/deno/selections.ts +++ b/packages/git/src/deno/selections.ts @@ -14,7 +14,7 @@ * be constructed — only reproduced from one the provider already handed out. * Reproducing one is enough to name a target, which is exactly as much as a * selection is meant to carry: the registry answers with what the provider - * itself recorded, never with what the caller's copy claims. + * itself recorded, never with what the caller's copy reports. * * The comparison is total, not a spot check. An identifier that matches while * a name, a checkout path or one member of the identity does not is a value diff --git a/packages/git/src/git-host/identities.ts b/packages/git/src/git-host/identities.ts index 726202eec..266c2d227 100644 --- a/packages/git/src/git-host/identities.ts +++ b/packages/git/src/git-host/identities.ts @@ -1,6 +1,6 @@ /** * Which run each Git-host record in a history was written under, established - * where nothing replaceable can reach it and claimed one position at a time. + * where nothing replaceable can reach it and consumed one position at a time. * * A Git-host effect is named by a digest that includes the run id, so a record * a fork inherited would compute a different name under the fork and replay @@ -43,7 +43,7 @@ * So the records are consumed **in order**. A call is offered the next one that * has not been taken, and only when that record asks exactly what the call * asks; anything else leaves the inherited prefix behind for good. Matching by - * shape alone was not enough: it let a call claim a *later* record while the + * shape alone was not enough: it let a call consume a *later* record while the * record actually at this position was a different one, so a mismatch there — * with public divergence policy choosing to run live — became live execution * under a source identity. diff --git a/packages/git/src/git.ts b/packages/git/src/git.ts index a8b1f0732..c01be4113 100644 --- a/packages/git/src/git.ts +++ b/packages/git/src/git.ts @@ -76,9 +76,9 @@ export interface GitQueryApi { /** * The bytes one path held in one commit, as text. * - * The semantics of `git cat-file blob :`. What comes back is the - * pinned object rather than whatever the working tree holds now, which is what - * lets a run claim a commit as its identity and mean it. + * The semantics of `git cat-file blob :`. What comes back is + * the pinned object rather than whatever the working tree holds now, which is + * what lets a run use a commit as its identity and mean it. */ read(commit: string, path: string): Operation; } diff --git a/packages/git/src/issue/identities.ts b/packages/git/src/issue/identities.ts index 1ed2d4e2a..ebe953b96 100644 --- a/packages/git/src/issue/identities.ts +++ b/packages/git/src/issue/identities.ts @@ -1,6 +1,6 @@ /** * Which run each Issue record in a history was written under, established where - * nothing replaceable can reach it and claimed one position at a time. + * nothing replaceable can reach it and consumed one position at a time. * * An upsert is named by a digest that includes the run id, and its idempotency * key is derived from the run id outright, so a record a fork inherited would diff --git a/packages/git/tests/ambient-authentication.test.ts b/packages/git/tests/ambient-authentication.test.ts index fd843b689..770941073 100644 --- a/packages/git/tests/ambient-authentication.test.ts +++ b/packages/git/tests/ambient-authentication.test.ts @@ -1,12 +1,13 @@ /** * Tier WA — the authentication a live provider invocation borrows from its host. * - * The claim is about two things that must stay apart: a run reaches a protected - * remote as whoever is standing at the host right now, and nothing about that - * identity survives into what the run retains. Rendered text proves neither, so - * every test here reads one of the places an answer actually lives — what the - * remote received, which locator a session was opened for, how many sessions one - * document opened, and what the journal and Workspace hold afterwards. + * The test distinguishes two facts that must stay apart: a run reaches a + * protected remote as whoever is standing at the host right now, and nothing + * about that identity survives into what the run retains. Rendered text proves + * neither, so every test here reads one of the places an answer actually lives + * — what the remote received, which locator a session was opened for, how many + * sessions one document opened, and what the journal and Workspace hold + * afterwards. * * Nothing here reads a developer's real credential or contacts a network host, * and nothing here injects one either. The provider is never handed a credential @@ -865,8 +866,8 @@ describe("workflow ambient authentication cancellation", () => { * The working directories this run's own sessions opened and released. * * Watched rather than scanned for: a prefix search of the temporary directory - * is a claim about the whole machine, and two concurrent invocations would - * each see the other's. + * observes the whole machine, and two concurrent invocations would each see + * the other's. */ function watching(sequence: string[] = []) { const opened: string[] = []; diff --git a/packages/git/tests/api-entrypoint.test.ts b/packages/git/tests/api-entrypoint.test.ts index f0a91d538..b7aff8997 100644 --- a/packages/git/tests/api-entrypoint.test.ts +++ b/packages/git/tests/api-entrypoint.test.ts @@ -24,7 +24,7 @@ * * Read through `Reflect.get` rather than a cast: what a module exported is * whatever it exported, and the members below are proven present rather than - * claimed. + * assumed. */ import { describe, it } from "@executablemd/test-support/bdd"; diff --git a/packages/git/tests/git-add-durability.test.ts b/packages/git/tests/git-add-durability.test.ts index d3f07092a..57a155594 100644 --- a/packages/git/tests/git-add-durability.test.ts +++ b/packages/git/tests/git-add-durability.test.ts @@ -1,10 +1,10 @@ /** * Tier WF — what a `` retains, replays and refuses to guess. * - * The claims here are about the run's database rather than about an index. A - * replay must stage nothing and append no second transition; a retained result - * that no longer describes the invocation it was recorded for must stop the run; - * a cancelled or unretainable staging must leave the frontier exactly as it was. + * These tests inspect the run's database rather than an index. A replay must + * stage nothing and append no second transition; a retained result that no + * longer describes the invocation it was recorded for must stop the run; a + * cancelled or unretainable staging must leave the frontier exactly as it was. * * Every replay happens after the remote is deleted, so what continues a run is * what the run retained or nothing does. diff --git a/packages/git/tests/git-add.test.ts b/packages/git/tests/git-add.test.ts index 1583c13f7..f8d2860fc 100644 --- a/packages/git/tests/git-add.test.ts +++ b/packages/git/tests/git-add.test.ts @@ -409,10 +409,10 @@ describe("workflow Git.Add invocation", () => { /** * A malformed `paths` is refused before anything is staged. * - * The schema refuses most of these on the engine's own terms, which is why the - * claim here is about the run rather than about which error arrives: nothing - * ran, and nothing was recorded. `canonicalPaths()` below is what holds the - * same line for a caller that reaches the Api directly. + * The schema refuses most of these on the engine's own terms, which is why + * the assertion here concerns the run rather than which error arrives: + * nothing ran, and nothing was recorded. `canonicalPaths()` below is what + * holds the same line for a caller that reaches the Api directly. */ const MALFORMED = [ { name: "omits paths", written: `` }, diff --git a/packages/git/tests/git-commit-durability.test.ts b/packages/git/tests/git-commit-durability.test.ts index 2157be7aa..d729fafd1 100644 --- a/packages/git/tests/git-commit-durability.test.ts +++ b/packages/git/tests/git-commit-durability.test.ts @@ -1,8 +1,8 @@ /** * Tier WF — what a `` retains, replays and refuses to guess. * - * The claims here are about the run's database rather than about a repository. A - * replay must write no object, read no clock and append no second transition; a + * These tests inspect the run's database rather than a repository. A replay + * must write no object, read no clock and append no second transition; a * retained result that no longer describes the invocation it was recorded for * must stop the run; a cancelled or unretainable commit must leave the frontier * exactly as it was. diff --git a/packages/git/tests/git-push-crash.test.ts b/packages/git/tests/git-push-crash.test.ts index 7fd569b81..dedd9f877 100644 --- a/packages/git/tests/git-push-crash.test.ts +++ b/packages/git/tests/git-push-crash.test.ts @@ -7,11 +7,11 @@ * appended; `SIGKILL` then runs no application cleanup, so the remote holds the * branch and the run's database holds no result for it. * - * What the next execution does with that is the whole claim: it reconstructs - * the same request, observes the destination, recognizes its own completion and - * adopts it. The remote is mutated once. A run that pushed again — or that - * refused because the destination was no longer absent — would be the two - * failures this design is built to avoid. + * What the next execution does with that is what this test verifies: it + * reconstructs the same request, observes the destination, recognizes its own + * completion and adopts it. The remote is mutated once. A run that pushed again + * — or that refused because the destination was no longer absent — would be the + * two failures this design is built to avoid. * * The handshake is a line of JSON on standard output, never a sleep. */ diff --git a/packages/git/tests/git-push-durability.test.ts b/packages/git/tests/git-push-durability.test.ts index 70fc8b398..0abb29db2 100644 --- a/packages/git/tests/git-push-durability.test.ts +++ b/packages/git/tests/git-push-durability.test.ts @@ -1,13 +1,13 @@ /** * Tier WF — what a `` retains, replays and refuses to guess. * - * The claims here are about the run's database and the remote together. A - * replayed push must reach no remote and append no second transition; a - * retained record that no longer describes the invocation it was recorded for - * must stop the run rather than be read around; a cancelled push must leave the - * journal, the frontier and the materializations exactly as it found them; and - * the request one invocation admitted must be the request it publishes for, - * however the caller edits its own objects afterwards. + * These tests inspect the run's database and the remote together. A replayed + * push must reach no remote and append no second transition; a retained record + * that no longer describes the invocation it was recorded for must stop the run + * rather than be read around; a cancelled push must leave the journal, the + * frontier and the materializations exactly as it found them; and the request + * one invocation admitted must be the request it publishes for, however the + * caller edits its own objects afterwards. */ import { describe, it } from "@executablemd/test-support/bdd"; @@ -397,10 +397,10 @@ describe("workflow Git.Push durability", () => { * * Containment is the live provider's first act, so a replay that performed it * anyway would fail here — the object graph is left in a state no push may - * read from before the replay runs. It succeeds, which is the claim: the - * shared engine hands back the retained record without reaching a provider, - * so no graph is walked, no control repository is built and no Git runs for - * the push. + * read from before the replay runs. It succeeds, which proves the intended + * isolation: the shared engine hands back the retained record without + * reaching a provider, so no graph is walked, no control repository is built + * and no Git runs for the push. */ it("replays a completed push over an object graph no live push would accept", function* () { const root = yield* useStorageRoot(); diff --git a/packages/git/tests/git-push.test.ts b/packages/git/tests/git-push.test.ts index e94e7eb33..160a18f9b 100644 --- a/packages/git/tests/git-push.test.ts +++ b/packages/git/tests/git-push.test.ts @@ -2,11 +2,11 @@ * Tier WF — `` as a document writes it. * * These drive the real component through a real run database, a real local bare - * remote and a real `git`, because the claim under test is about two places at - * once: what the other end of the transport holds afterwards, and what this - * run's journal says it published. Rendered text proves neither — a push - * renders nothing — so every test here reads the remote's refs and the retained - * reconciliation record. + * remote and a real `git`, because the test checks two places at once: what the + * other end of the transport holds afterwards, and what this run's journal says + * it published. Rendered text proves neither — a push renders nothing — so + * every test here reads the remote's refs and the retained reconciliation + * record. * * Nothing here reaches a network. A remote is a bare repository in a temporary * directory, and an unreachable host is one that has been deleted. diff --git a/packages/git/tests/git-switch-durability.test.ts b/packages/git/tests/git-switch-durability.test.ts index 3a5622629..282fb61db 100644 --- a/packages/git/tests/git-switch-durability.test.ts +++ b/packages/git/tests/git-switch-durability.test.ts @@ -1,13 +1,12 @@ /** * Tier WF — what a `` retains, replays and refuses to guess. * - * The claims here are about the run's database rather than about a checkout. A - * replay must move no branch and append no second transition; a retained result - * that no longer parses must stop the run rather than be read around; a - * cancelled switch must leave the frontier, the materialization and the journal - * exactly as it found them; and the retained rows a switch runs against must be - * the same rows afterwards, because creation identity does not move when HEAD - * does. + * These tests inspect the run's database rather than a checkout. A replay must + * move no branch and append no second transition; a retained result that no + * longer parses must stop the run rather than be read around; a cancelled + * switch must leave the frontier, the materialization and the journal exactly + * as it found them; and the retained rows a switch runs against must be the + * same rows afterwards, because creation identity does not move when HEAD does. * * Every replay happens after the remote is deleted, so what continues a run is * what the run retained or nothing does. @@ -603,12 +602,12 @@ describe("workflow Git.Switch durability", () => { /** * Cancellation reaches the child, not only the operation waiting on it. * - * Every claim above is about what the run's database holds, which a halt that - * left a Git process running would still satisfy. This one is about the process. - * A named pipe is what makes a real `git` block on demand — it opens the pipe - * for reading and waits — and the write end this test holds is what says whether - * it is still there: writing to a pipe nothing is reading fails with `EPIPE`, - * and writing to one a live child is reading does not. + * Every assertion above concerns what the run's database holds, which a halt + * that left a Git process running would still satisfy. This one is about the + * process. A named pipe is what makes a real `git` block on demand — it opens + * the pipe for reading and waits — and the write end this test holds is what + * says whether it is still there: writing to a pipe nothing is reading fails + * with `EPIPE`, and writing to one a live child is reading does not. * * The blocking `open` before the halt is the premise rather than a convenience: * it returns only once a reader has the pipe open, so the child is provably diff --git a/packages/git/tests/github-pull-requests.test.ts b/packages/git/tests/github-pull-requests.test.ts index 385d3aaef..8fcda9654 100644 --- a/packages/git/tests/github-pull-requests.test.ts +++ b/packages/git/tests/github-pull-requests.test.ts @@ -2,9 +2,9 @@ * Tier U — the GitHub adapter, on its own. * * Which locators it will act for, where its credential comes from, what it - * makes of an answer, and — the claim the whole reconciliation rests on — that - * nothing it cannot read ever becomes "there is no pull request here". Every - * test drives the real adapter; what is substituted is the transport and the + * makes of an answer, and — the prerequisite for reconciliation — that nothing + * it cannot read ever becomes "there is no pull request here". Every test + * drives the real adapter; what is substituted is the transport and the * environment, which is the whole of what it asks its host for. */ diff --git a/packages/git/tests/issue-records.test.ts b/packages/git/tests/issue-records.test.ts index d618bbb66..9fc4b50d4 100644 --- a/packages/git/tests/issue-records.test.ts +++ b/packages/git/tests/issue-records.test.ts @@ -2,7 +2,7 @@ * Tier WI — what a retained issue record is, and what names it. * * D1 lives here rather than in a scenario document, and the reason is that the - * claim is compositional. "A changed request cannot consume the result retained + * proof is compositional. "A changed request cannot consume the result retained * for a different one" is three facts stacked: * * 1. the request fingerprint covers every member of the request — the canonical @@ -22,7 +22,7 @@ * second execution whose request differs. That is worth having and is not what * the scenario documents do today: a scenario that swapped root documents * between attempts did not exercise the mismatch path in this suite's fixture, - * so the claim is recorded as proven compositionally rather than end to end. + * so the property is recorded as proven compositionally rather than end to end. */ import { describe, it } from "@executablemd/test-support/bdd"; diff --git a/packages/git/tests/materialization.test.ts b/packages/git/tests/materialization.test.ts index 12d96e368..5e8f50c98 100644 --- a/packages/git/tests/materialization.test.ts +++ b/packages/git/tests/materialization.test.ts @@ -3,9 +3,9 @@ * * The Workspace is a database and native Git is a program that reads * directories, so every native operation happens in a disposable host tree - * exported from one. Everything the rest of #293 claims rests on that export - * being a faithful copy of what the database holds, and on it staying inside - * the directory this provider owns. + * exported from one. Every other guarantee in #293 depends on that export being + * a faithful copy of what the database holds, and on it staying inside the + * directory this provider owns. * * These drive the exporter directly rather than through a component, because * the properties are the exporter's own and no component exists to reach them diff --git a/packages/git/tests/module-partition.test.ts b/packages/git/tests/module-partition.test.ts index 051a9988f..da0dd3189 100644 --- a/packages/git/tests/module-partition.test.ts +++ b/packages/git/tests/module-partition.test.ts @@ -194,10 +194,10 @@ function misclassified(counted: Map): [string, number][] { * The subpaths a manifest's `exports` declares, or nothing when it declares no * readable map. * - * Narrowed by asking the value what it is rather than telling the compiler. - * The distinction matters here: this case's claim is about what the export map - * admits, and a manifest this could not read would otherwise answer "no - * subpaths" and satisfy the claim by accident. + * Narrowed by asking the value what it is rather than telling the compiler. The + * distinction matters here: this case verifies what the export map admits, and + * a manifest this could not read would otherwise answer "no subpaths" and pass + * the test by accident. */ function subpaths(declared: unknown): string[] | undefined { if (typeof declared !== "object" || declared === null) { diff --git a/packages/git/tests/plugin.test.ts b/packages/git/tests/plugin.test.ts index 89b2ba977..97b7c247d 100644 --- a/packages/git/tests/plugin.test.ts +++ b/packages/git/tests/plugin.test.ts @@ -62,7 +62,7 @@ function run(runId: string): WorkflowRun { const SOURCE_A = run("run-plugin-source-a"); const SOURCE_B = run("run-plugin-source-b"); -/** What one execution saw, at the boundaries a claim can be made about. */ +/** What one execution saw, at the observable boundaries. */ interface Seen { readonly gitHost: (readonly { runId: string; claimed: boolean }[] | undefined)[]; readonly issue: (readonly unknown[] | undefined)[]; diff --git a/packages/git/tests/pull-request-crash.test.ts b/packages/git/tests/pull-request-crash.test.ts index 4b368b948..1f38e3697 100644 --- a/packages/git/tests/pull-request-crash.test.ts +++ b/packages/git/tests/pull-request-crash.test.ts @@ -7,11 +7,11 @@ * so the pull request is open at the host and the run's database holds no * result for it. * - * What the next execution does with that is the whole claim: it reconstructs - * the same request, observes the branch pair, recognizes its own pull request - * and adopts it. One pull request exists. A run that created another — or that - * refused because one was already there — would be the two failures this design - * is built to avoid. + * What the next execution does with that is what this test verifies: it + * reconstructs the same request, observes the branch pair, recognizes its own + * pull request and adopts it. One pull request exists. A run that created + * another — or that refused because one was already there — would be the two + * failures this design is built to avoid. * * The GitHub the child talks to is a real HTTP listener over the same store the * test reads afterwards, because the child is a second process and cannot share diff --git a/packages/git/tests/pull-request-durability.test.ts b/packages/git/tests/pull-request-durability.test.ts index 3d5a2337d..667c923b2 100644 --- a/packages/git/tests/pull-request-durability.test.ts +++ b/packages/git/tests/pull-request-durability.test.ts @@ -1,10 +1,10 @@ /** * Tier WF — what a `` retains, replays and refuses to guess. * - * The claims here are about the run's database and the Git host together. A - * replayed pull request must reach no host, read no credential and append no - * second record; a retained record that no longer describes the invocation it - * was recorded for must stop the run rather than be read around; a cancelled + * These tests inspect the run's database and the Git host together. A replayed + * pull request must reach no host, read no credential and append no second + * record; a retained record that no longer describes the invocation it was + * recorded for must stop the run rather than be read around; a cancelled * creation must leave the journal exactly as it found it; and what public * routing middleware sees must be the frozen request and nothing that can * answer for it. @@ -70,9 +70,9 @@ function isHostProtocolFailure(value: unknown): value is GitHostProtocolError { /** * A Git host that refuses to be reached at all. * - * What a completed replay is claimed to need: no adapter, no credential and no - * request. Reaching for any of the three fails the run here rather than - * quietly succeeding against a host that happens to still hold the answer. + * A completed replay needs no adapter, credential or request. Reaching for any + * of the three fails the run here rather than quietly succeeding against a host + * that happens to still hold the answer. */ function unreachable(): GitHubAccess { return { diff --git a/packages/git/tests/pull-request-read.test.ts b/packages/git/tests/pull-request-read.test.ts index 3f786e72a..9889ae97b 100644 --- a/packages/git/tests/pull-request-read.test.ts +++ b/packages/git/tests/pull-request-read.test.ts @@ -1,10 +1,10 @@ /** * Tier PRR — the evidence a network-denied reviewer is given. * - * The claim these cases defend is a negative one: this surface never answers - * "there is nothing there" on the strength of something it could not read. So - * every refusal case asserts that the read *fails* rather than binding a - * shorter list, and the one case that binds `[]` proves the provider said so. + * These cases defend a refusal boundary: this surface never answers "there is + * nothing there" on the strength of something it could not read. So every + * refusal case asserts that the read *fails* rather than binding a shorter + * list, and the one case that binds `[]` proves the provider said so. * * The adapter runs against a transport this suite supplies. Nothing here * contacts a network host, and no case reads a developer's real credential. diff --git a/packages/git/tests/pull-request-records.test.ts b/packages/git/tests/pull-request-records.test.ts index be1d6d3a8..6a214bf4e 100644 --- a/packages/git/tests/pull-request-records.test.ts +++ b/packages/git/tests/pull-request-records.test.ts @@ -1,12 +1,12 @@ /** * Tier U — what a pull-request record is, and what authorizes one. * - * Two claims live here and neither needs a Git host, a database or a document. - * The first is that the retained shapes are exact: a record is read back for - * the request that produced it, and a value carrying more, fewer or different - * members than the contract declares describes something else. The second is - * the admission scan — the closed reading of this run's own journal that - * decides whether the branch a pull request would name is one the run + * Two invariants are checked here and neither needs a Git host, a database or a + * document. The first is that the retained shapes are exact: a record is read + * back for the request that produced it, and a value carrying more, fewer or + * different members than the contract declares describes something else. The + * second is the admission scan — the closed reading of this run's own journal + * that decides whether the branch a pull request would name is one the run * published. */ diff --git a/packages/git/tests/repository-components.test.ts b/packages/git/tests/repository-components.test.ts index 0cfa067b4..1ad082f8b 100644 --- a/packages/git/tests/repository-components.test.ts +++ b/packages/git/tests/repository-components.test.ts @@ -765,9 +765,9 @@ function fatalCause(error: unknown, seen = new Set()): unknown { * that the component shipped here really does make that call, first, and that a * document stops at it. * - * Together they are the whole claim. Neither is sufficient alone: the stand-in - * could pass while `` called something else or called nothing, and this - * could pass while the operation quietly answered instead of refusing. + * Together they are the complete proof. Neither is sufficient alone: the + * stand-in could pass while `` called something else or called nothing, + * and this could pass while the operation quietly answered instead of refusing. */ describe("Dir without a Files provider", () => { it("stops at ensureDirectory, and no directory, content or sibling follows", function* () { diff --git a/packages/git/tests/repository-materialization.test.ts b/packages/git/tests/repository-materialization.test.ts index c837a744b..9add31ded 100644 --- a/packages/git/tests/repository-materialization.test.ts +++ b/packages/git/tests/repository-materialization.test.ts @@ -1,11 +1,12 @@ /** * Tier WF — the export native Git is allowed to see. * - * The materialization is a copy of what the database holds, and every claim this - * provider makes rests on that: deleting one costs time and nothing else. These - * are the rules about the checkout root itself — that it is a real retained - * directory and that the export lands where it was aimed — and the control that - * says ordinary tracked symbolic links inside a checkout are still content. + * The materialization is a copy of what the database holds, and every guarantee + * this provider offers rests on that: deleting one costs time and nothing else. + * These are the rules about the checkout root itself — that it is a real + * retained directory and that the export lands where it was aimed — and the + * control that says ordinary tracked symbolic links inside a checkout are still + * content. */ import { describe, it } from "@executablemd/test-support/bdd"; import { expect } from "@executablemd/test-support/expect"; @@ -70,8 +71,8 @@ import { * Native Git may only operate on the provider-owned export of the retained * checkout. * - * The materialization is a copy of what the database holds, and every claim this - * provider makes rests on that: deleting one costs time and nothing else, + * The materialization is a copy of what the database holds, and every guarantee + * this provider offers rests on that: deleting one costs time and nothing else, * because the database is where the run's Git state is. A checkout root that is * a symbolic link breaks it in a way no identity check would notice — the * operating system resolves a working directory before Git ever sees it, so Git diff --git a/packages/git/tests/run-composition-ambient.test.ts b/packages/git/tests/run-composition-ambient.test.ts index 423a769ef..770eb72a2 100644 --- a/packages/git/tests/run-composition-ambient.test.ts +++ b/packages/git/tests/run-composition-ambient.test.ts @@ -6,7 +6,7 @@ * and does not authorize, lexical working directories, and the local Git * operations that write to the caller's own tree. * - * The claims here are about a filesystem rather than a database. There is no + * These assertions concern a filesystem rather than a database. There is no * WorkflowRun, no Workspace, no journal and nothing to replay. Every repository * is real, every Git command is real, and the managed root is a temporary * directory of the suite's own — no test ever touches the user's diff --git a/packages/git/tests/run-composition-lazy.test.ts b/packages/git/tests/run-composition-lazy.test.ts index 3dc754e6d..d878e820a 100644 --- a/packages/git/tests/run-composition-lazy.test.ts +++ b/packages/git/tests/run-composition-lazy.test.ts @@ -5,7 +5,7 @@ * Installing it must cost nothing at all, and a document that writes no * repository component must keep costing nothing. Proving that by looking for * an absent managed root proves only one of six things — so each capability is - * counted separately here, and the claim is that *every* count is zero. + * counted separately here, and *every* count must be zero. * * Counted rather than forbidden, because these are not all refusable: a Git * session is a temporary directory, an invocation identity is a random string, diff --git a/packages/git/tests/run-composition-managed.test.ts b/packages/git/tests/run-composition-managed.test.ts index 2ae2e1d4e..e4c8ccd96 100644 --- a/packages/git/tests/run-composition-managed.test.ts +++ b/packages/git/tests/run-composition-managed.test.ts @@ -280,10 +280,10 @@ describe("ORC10 — a conflict changes nothing", () => { /** * One refusal, fingerprinted on both sides. * - * The claim is not "it failed" but "it failed and changed nothing", so the - * slot's complete byte fingerprint and the checkout's own Git state are taken - * before the refusal and compared after it. A reset, a fetch, a switch or a - * rewritten sidecar would all show up here. + * The required outcome is not "it failed" but "it failed and changed + * nothing", so the slot's complete byte fingerprint and the checkout's own + * Git state are taken before the refusal and compared after it. A reset, a + * fetch, a switch or a rewritten sidecar would all show up here. */ function* refusesWithoutMutating( slot: ReturnType, diff --git a/packages/git/tests/support/composition.ts b/packages/git/tests/support/composition.ts index 8937a531f..6a2dba5ee 100644 --- a/packages/git/tests/support/composition.ts +++ b/packages/git/tests/support/composition.ts @@ -79,7 +79,7 @@ export function* gitPluginAdmissions(): Operation { return { admissions: [...(installed?.admissions ?? [])] }; } -/** What one execution did, at the boundaries a claim can be made about. */ +/** What one execution did, at the observable boundaries. */ export interface CompositionCounters { /** Every Git command, in order, as its argument list. */ readonly commands: string[][]; @@ -452,9 +452,9 @@ export function* workspaceTree( /** * What the index of one retained checkout holds staged, as native Git reads it. * - * The direct observation a staging claim needs. Index trees say *that* something - * changed; this says *what*, by exporting the retained family into a disposable - * host tree — the same way the provider does — and asking Git. + * The direct observation staging verification needs. Index trees say *that* + * something changed; this says *what*, by exporting the retained family into a + * disposable host tree — the same way the provider does — and asking Git. */ export function* stagedPaths( database: WorkflowRunDatabase, @@ -568,9 +568,10 @@ export function* checkoutConfig( /** * The commit one retained checkout is on, read out of the object itself. * - * `cat-file commit` rather than a pretty format: what a message claim is about - * is the bytes in the object, and reading them through the same formatting the - * provider uses would prove only that one command agrees with itself. + * `cat-file commit` rather than a pretty format: what message verification + * checks is the bytes in the object, and reading them through the same + * formatting the provider uses would prove only that one command agrees with + * itself. */ export interface CheckoutCommit { readonly commit: string; diff --git a/packages/git/tests/support/git-remotes.ts b/packages/git/tests/support/git-remotes.ts index a1bc4e37e..73d98675f 100644 --- a/packages/git/tests/support/git-remotes.ts +++ b/packages/git/tests/support/git-remotes.ts @@ -78,9 +78,9 @@ function environment(home: string): Record { * * Untrimmed, because a fixture that reads a committed file back out of Git is * reading bytes: a trailing newline is part of the document, and a helper that - * removed it would make "these are the exact bytes" a claim about something - * else. `git()` trims, for the object ids and branch names every other caller - * asks for. + * removed it would make "these are the exact bytes" an assertion about + * something else. `git()` trims, for the object ids and branch names every + * other caller asks for. */ export function gitOutput(args: readonly string[], cwd: string, home: string): string { const output = spawnSync("git", [...args], { diff --git a/packages/git/tests/support/github.ts b/packages/git/tests/support/github.ts index 97e16ca4d..bd7cb12a5 100644 --- a/packages/git/tests/support/github.ts +++ b/packages/git/tests/support/github.ts @@ -2,7 +2,7 @@ * A GitHub that answers pull-request and issue calls, without a network. * * One store, two ways to reach it. Most suites install {@link fakeGitHubAccess} - * and drive the adapter directly, which keeps every claim deterministic and + * and drive the adapter directly, which keeps every assertion deterministic and * lets a test count exactly how many requests were made and refuse the ones it * wants to fail. The crash suite needs a second process to reach the same * GitHub, so {@link useGitHubServer} puts the identical handler behind a real diff --git a/packages/git/tests/support/issue-providers.ts b/packages/git/tests/support/issue-providers.ts index be2ba51df..333fddf8a 100644 --- a/packages/git/tests/support/issue-providers.ts +++ b/packages/git/tests/support/issue-providers.ts @@ -230,7 +230,7 @@ export function useProviderComponents(log: ProviderLog): Operation { props: { type: "object", properties: { - /** The URL it claims. Anything else it delegates untouched. */ + /** The URL it handles. Anything else it delegates untouched. */ handles: { type: "string", minLength: 1 }, /** The URL it answers with. */ answers: { type: "string", minLength: 1 }, diff --git a/packages/git/tests/support/replay.ts b/packages/git/tests/support/replay.ts index ed58ea271..c69f8f890 100644 --- a/packages/git/tests/support/replay.ts +++ b/packages/git/tests/support/replay.ts @@ -1,11 +1,11 @@ /** * What every Repository and Worktree replay suite needs to see. * - * These reach past the adapter on purpose. A replay claim is about what another - * process would find, so the observations here open their own connection to the - * run's database — a row written inside an open transaction is invisible to one - * until that transaction commits, which is what makes these say whether a commit - * happened rather than whether a row is there afterwards. + * These reach past the adapter on purpose. Replay verification concerns what + * another process would find, so the observations here open their own + * connection to the run's database — a row written inside an open transaction + * is invisible to one until that transaction commits, which is what makes these + * say whether a commit happened rather than whether a row is there afterwards. * * The fixtures that damage a run are here for the same reason: no supported * operation can produce the states these suites replay from, so they are written @@ -201,9 +201,9 @@ export function isStale(candidate: unknown): candidate is RepositoryStaleStateEr /** * What one composition effect recorded, as the journal holds it. * - * The status is the whole point of these claims. A refusal that the run reports - * to the document and records as a success is a history that disagrees with - * itself, and only the retained result says which one happened. + * The status is the outcome these assertions check. A refusal that the run + * reports to the document and records as a success is a history that disagrees + * with itself, and only the retained result says which one happened. */ export function* compositionResults( database: WorkflowRunDatabase, diff --git a/packages/git/tests/support/run-composition-child.ts b/packages/git/tests/support/run-composition-child.ts index fade190d2..f894dbea5 100644 --- a/packages/git/tests/support/run-composition-child.ts +++ b/packages/git/tests/support/run-composition-child.ts @@ -1,7 +1,7 @@ /** * A second process asking for the same managed checkout. * - * Exclusive ownership is a claim about two operating-system processes, so it is + * Exclusive ownership must hold across two operating-system processes, so it is * proved by two operating-system processes. This one constructs its own * ordinary repository provider — its own leases, its own invocation identity — * against a managed root and a starting directory the parent names, selects diff --git a/packages/git/tests/support/run-composition-tier.ts b/packages/git/tests/support/run-composition-tier.ts index 36b0a819e..97291cf29 100644 --- a/packages/git/tests/support/run-composition-tier.ts +++ b/packages/git/tests/support/run-composition-tier.ts @@ -26,7 +26,7 @@ export const HEAD = "a".repeat(40); * The routes one modeled pull request answers a reviews read on. * * The pull request itself is one of them: an answer is authenticated against - * the subject it claims, so a collection with no pull request behind it is + * the subject it names, so a collection with no pull request behind it is * refused rather than bound. */ export function reviewRoutes(endpoint: string): Record { diff --git a/packages/git/tests/support/run-composition.ts b/packages/git/tests/support/run-composition.ts index b6b2d5a04..aa9f53f5d 100644 --- a/packages/git/tests/support/run-composition.ts +++ b/packages/git/tests/support/run-composition.ts @@ -3,10 +3,10 @@ * * Everything here is real: a real bare remote, a real working checkout the * command is "run in", real `git`, real advisory locks and a real managed root - * in a temporary directory. What is substituted is only what a claim needs to - * be deterministic about — the managed root, so no suite ever touches the - * user's own `~/.xmd/repositories`, and the Git subprocess where a suite counts - * invocations. + * in a temporary directory. What is substituted is only what the assertion + * needs to be deterministic about — the managed root, so no suite ever touches + * the user's own `~/.xmd/repositories`, and the Git subprocess where a suite + * counts invocations. * * There is no database, no journal and no WorkflowRun anywhere in this file. * That is the point of the profile: an ordinary run has none of them. @@ -108,7 +108,7 @@ export function* useManagedRoot(): Operation { return root; } -/** What one ordinary execution reached, at the boundaries a claim is made at. */ +/** What one ordinary execution reached, at the observed boundaries. */ export interface OrdinaryCounters { /** Every Git command, in order, as its argument list. */ readonly commands: string[][]; @@ -220,9 +220,9 @@ export interface RunOptions extends Omit * A fixed identity, because the production default reads the *host's* Git * configuration — and a machine with no `user.name` set makes `` * refuse. Every CI runner is such a machine, so leaving it to the host turns - * "this document committed" into a claim about who ran the suite: green on a - * developer's laptop, red on every shard. A case that is *about* identity - * resolution passes its own `identity` and overrides this. + * "this document committed" into an outcome dependent on who ran the suite: + * green on a developer's laptop, red on every shard. A case that is *about* + * identity resolution passes its own `identity` and overrides this. */ export function runOrdinaryDocument(source: string, options: RunOptions): Operation { return scoped(function* () { @@ -325,7 +325,7 @@ export function causedBy(error: unknown, is: (value: unknown) => value is T): /** * Everything a directory holds, as one comparable value. * - * Paths, kinds and content digests, sorted. A refusal that claims to change + * Paths, kinds and content digests, sorted. A refusal that promises to change * nothing has to survive this: a comparison of "the checkout is still there" * would pass while a file inside it had been rewritten. */ @@ -390,7 +390,7 @@ export function gateComponent(reached: () => void): ComponentRegistration { /** * Run a document that reaches ``, then halt it there. * - * The halt is the cancellation every persistence claim is made against: the + * The halt is the cancellation every persistence guarantee must survive: the * execution is torn down from outside, mid-document, with a component still in * flight. */ diff --git a/packages/runtime/apis.ts b/packages/runtime/apis.ts index 6854680d0..693a1995f 100644 --- a/packages/runtime/apis.ts +++ b/packages/runtime/apis.ts @@ -228,7 +228,7 @@ function detachHeaders(headers: Iterable): ResponseHe * * Read rather than asserted: `catch` gives back `unknown`, and what arrives * there is only conventionally an `ErrnoException`. Narrowing says what is - * actually known about the value instead of claiming a shape it may not have. + * actually known about the value instead of asserting a shape it may not have. */ function errorCode(error: unknown): string | undefined { if (typeof error !== "object" || error === null || !("code" in error)) { @@ -247,9 +247,9 @@ function errorCode(error: unknown): string | undefined { * redirects, or consumes output upstream of this call is trusted preprocessing, * and its result is what a caller is told the command produced. * - * What this does not promise is the tail. The record is read when the `Process` - * operation settles, and that can happen before the pumps have finished, so - * this claims no pump-complete delivery (effectionx #244). + * What this does not promise is the tail. The record is read when the + * `Process` operation settles, and that can happen before the pumps have + * finished, so this does not guarantee pump-complete delivery (effectionx #244). */ function* retaining(): Operation<{ stdout: () => string; stderr: () => string }> { let stdout = ""; diff --git a/packages/runtime/files.ts b/packages/runtime/files.ts index fdaf87a11..db5cc3a26 100644 --- a/packages/runtime/files.ts +++ b/packages/runtime/files.ts @@ -619,8 +619,8 @@ export function asFilesFatal(error: unknown): FilesFatalFailure | undefined { /** * What a write phase is allowed to say, which is the whole validity rule. * - * The phase decides the target claim: nothing selects `committed` except a - * cleanup that failed after the commit returned, and nothing claims + * The phase decides the reported target state: nothing selects `committed` + * except a cleanup that failed after the commit returned, and nothing reports * `commit-unknown` except a commit that threw. Keeping the table here rather * than at each construction site makes an invalid combination unconstructable * instead of merely unwritten. @@ -762,9 +762,9 @@ export function parseFilesFailure(error: unknown): FilesFailureData | undefined * The write failure data this error carries, if it carries valid data. * * Unlike a non-write failure, malformed data here has no safe reading: every - * sentence a consumer could print makes a claim about whether the file was - * replaced. A caller treats `undefined` from a write as a protocol invariant - * rather than inventing a commit state. + * sentence a consumer could print reports whether the file was replaced. A + * caller treats `undefined` from a write as a protocol invariant rather than + * inventing a commit state. */ export function parseFileWriteFailure(error: unknown): FileWriteFailureData | undefined { return attempt(() => { diff --git a/packages/runtime/tests/fetch.test.ts b/packages/runtime/tests/fetch.test.ts index 72eacd302..b63315fdb 100644 --- a/packages/runtime/tests/fetch.test.ts +++ b/packages/runtime/tests/fetch.test.ts @@ -2,7 +2,7 @@ * Tier FR — the runtime Fetch adapter (spec §Runtime Context APIs). * * The adapter is what turns a live host response into something a caller can - * keep. Two claims are under test and they pull against each other: the + * keep. Two guarantees are under test and they pull against each other: the * response must be *detached*, so nothing a caller holds depends on a socket * that has since closed, and the seams callers already use — `headers.get()` * and `text()` — must keep meaning exactly what they meant. diff --git a/packages/runtime/tests/host-files.test.ts b/packages/runtime/tests/host-files.test.ts index c6b40709e..6abef2564 100644 --- a/packages/runtime/tests/host-files.test.ts +++ b/packages/runtime/tests/host-files.test.ts @@ -9,10 +9,10 @@ * * The replacement cases are the last of those. The host contract holds while * the pathname namespace is stable, and the adapter's test-only observer is - * what makes "stable" falsifiable: it swaps part of the tree between the moment - * the adapter observes a path and the moment it uses one, synchronously, with - * no sleeping and no racing. What they prove is the documented weakness, not a - * containment claim. + * what makes "stable" falsifiable: it swaps part of the tree between the + * moment the adapter observes a path and the moment it uses one, + * synchronously, with no sleeping and no racing. What they prove is the + * documented weakness, not a containment guarantee. * * `mkdtemp`, `realpath`, `symlink`, `lstat`, and `readdir` have no * `@effectionx/fs` equivalent; everything else goes through it. @@ -1345,11 +1345,11 @@ describe("host Files — making a directory exist", () => { * Permission, asked by the provider. * * These drive `hostFilesHandler()` directly rather than the installed Api, - * because that is the stronger claim: a host holding the handler — and the + * because that is the stronger guarantee: a host holding the handler — and the * forwarding middleware `useHostFiles` installs is one — gets the same - * restriction as a document reaching it through `API.Files`. If the check lived - * in that middleware instead, every one of these would still pass through the - * Api and none of them would pass here. + * restriction as a document reaching it through `API.Files`. If the check + * lived in that middleware instead, every one of these would still pass + * through the Api and none of them would pass here. */ describe("host Files — permission", () => { /** Every low-level reach a refused operation must not make. */ diff --git a/packages/test-agent/src/worker/acp-server.ts b/packages/test-agent/src/worker/acp-server.ts index e8dddf16e..a332afb36 100644 --- a/packages/test-agent/src/worker/acp-server.ts +++ b/packages/test-agent/src/worker/acp-server.ts @@ -31,9 +31,9 @@ export interface WorkerAgent { * * The returned id is deliberately not the ACP session id. A native id is * something an agent asserts about its own durable state; a client that - * guessed one from the ACP id would be inferring an identity nobody claimed, - * and a test agent that returned the same string for both would make that - * mistake untestable. + * guessed one from the ACP id would be inferring an identity the provider + * never asserted, and a test agent that returned the same string for both + * would make that mistake untestable. */ startSession(instructions: string | undefined): Operation; runTurn(text: string): Operation; diff --git a/packages/test-agent/tests/cross-package-resolution.test.ts b/packages/test-agent/tests/cross-package-resolution.test.ts index c2bb57433..e22391e60 100644 --- a/packages/test-agent/tests/cross-package-resolution.test.ts +++ b/packages/test-agent/tests/cross-package-resolution.test.ts @@ -8,7 +8,7 @@ * * **The runtime path is the evidence.** XP1 and XP2 execute documents and read * what was rendered, because that is what a resolution defect cannot hide from: - * the retired expansion hook could claim a name and preempt execution while + * the retired expansion hook could intercept a name and preempt execution while * `inspectComponent` went on reporting the repository file it had overridden, * so an inspection-only suite would have passed against exactly the arrangement * it appeared to be testing. XP3 and XP4 add inspection on top, for origins @@ -41,9 +41,9 @@ import { installTestAgentComponents } from "../src/components.ts"; /** * Every name the three packages register. All are non-reserved defaults. * - * Written out rather than derived, so the coverage each test claims is visible - * in the file — and checked against the live registry by XP0, which is what - * keeps the two from drifting apart as packages gain components. + * Written out rather than derived, so the coverage each test requires is + * visible in the file — and checked against the live registry by XP0, which is + * what keeps the two from drifting apart as packages gain components. */ const AGENT = [ "AgentProvider", @@ -221,7 +221,8 @@ describe("Tier XP — cross-package resolution", () => { /** * The inventory below is what every other case iterates, so a name missing * from it is coverage silently not taken. Comparing against the live registry - * is what makes "every registered name" a checked claim rather than a comment. + * is what makes "every registered name" verified coverage rather than a + * comment. */ it("XP0: the names under test are exactly the ones the three packages register", function* () { const installed = yield* scoped(function* () { diff --git a/packages/test-support/journal.ts b/packages/test-support/journal.ts index a82e58033..f1930c4d1 100644 --- a/packages/test-support/journal.ts +++ b/packages/test-support/journal.ts @@ -41,7 +41,7 @@ export type RetainedOutcome = }; /** - * The effect types replay bookkeeping writes, which no ordered claim is about. + * Replay bookkeeping effect types, excluded from ordered assertions. * * Fixed and private. A caller-configurable list would let two suites disagree * about what this repository considers bookkeeping, which is the disagreement @@ -54,7 +54,7 @@ const BOOKKEEPING = new Set(["import_component", "loop", "loop_iteration", "work * * The position is where the event sits in *this* selection — not a durable * event id and not a SQLite sequence — so it stays the coordinate a reader can - * use to say which one a claim is about. + * use to say which one an assertion is about. */ export function selectYields( events: readonly DurableEvent[], @@ -75,7 +75,7 @@ export function selectYields( * The meaningful effect order, as values that diff readably. * * Numbering happens after the bookkeeping types are dropped, so adding or - * removing one of them does not renumber everything a claim is about. + * removing one of them does not renumber everything an assertion is about. */ export function effectSequence(events: readonly DurableEvent[]): readonly string[] { const sequence: string[] = []; diff --git a/packages/testing/src/activation.ts b/packages/testing/src/activation.ts index 6a0eed92b..5e037eddf 100644 --- a/packages/testing/src/activation.ts +++ b/packages/testing/src/activation.ts @@ -72,12 +72,11 @@ export class IncompleteTestingActivationError extends Error { } /** - * One ``'s claim on a complete activation. + * One ``'s ownership of a complete activation. * - * Accepted means delivered exactly once, to this claim, carrying a live + * Accepted means delivered exactly once, to this owner, carrying a live * boundary credential. Delivering the same request a second time is a protocol - * violation rather than a second proof, so it withdraws the claim instead of - * confirming it. + * violation rather than a second proof, so it invalidates confirmation. */ class Claim { deliveries = 0; @@ -116,7 +115,7 @@ class ActivationCredential { } } -/** One ``'s request for proof, carrying a claim only its terminal holds. */ +/** One ``'s request for proof, carrying an ownership handle only its terminal holds. */ class ActivationRequest { readonly #claim: Claim; @@ -128,9 +127,10 @@ class ActivationRequest { /** * Deliver `request` to `claim`, with whatever credential arrived beside it. * - * The expected claim is supplied by the caller rather than read off the + * The expected owner is supplied by the caller rather than read off the * request: a request another `` issued is also canonical, and settling - * it on its own claim would let one invocation's proof answer another's. + * it against its own owner would let one invocation's proof answer + * another's. */ static deliver(request: unknown, claim: Claim, credential: unknown): void { if (!ActivationRequest.own(request) || request.#claim !== claim) { diff --git a/packages/testing/tests/test-component.test.ts b/packages/testing/tests/test-component.test.ts index 5f72c29a8..d4ffa61a7 100644 --- a/packages/testing/tests/test-component.test.ts +++ b/packages/testing/tests/test-component.test.ts @@ -1,8 +1,9 @@ /** * `` as a registered function component (specs/testing-spec.md). * - * These pin the properties the migration off the `Component.expand` claim had - * to preserve, each of which broke at least once while it was being made. + * These pin the properties the migration off the `Component.expand` + * interception had to preserve, each of which broke at least once while it was + * being made. */ import { beforeAll, describe, it } from "@executablemd/test-support/bdd"; diff --git a/packages/web/src/declaration.ts b/packages/web/src/declaration.ts index 6da3327a2..e7d3a8eba 100644 --- a/packages/web/src/declaration.ts +++ b/packages/web/src/declaration.ts @@ -43,7 +43,7 @@ export interface Declaration { * `schema` is required; `uiSchema` is optional and `undefined` means absent. * * `label` names the component the author actually wrote, so a diagnostic from a - * form served for `` does not claim to come from ``. It mirrors + * form served for `` does not report that it comes from ``. It mirrors * `compileParseSchema(componentName, …)` in core. */ export function parseDeclaration(label: string, schema: unknown, uiSchema?: unknown): Declaration { @@ -122,7 +122,7 @@ function rejectAsyncSchema(label: string, schema: JsonObject): void { * a document could see or work around. * * Supporting the name would mean reimplementing what Ajv does with schema keys, - * so this slice refuses it and says so, rather than claiming a support it does + * so this slice refuses it and says so, rather than advertising support it does * not have. The same string as *data* — a `const`, an `enum` member, a title, a * default — is untouched, because nothing reads it as a key. */ diff --git a/packages/web/tests/component-support.ts b/packages/web/tests/component-support.ts index 0bbf059af..22b645ad5 100644 --- a/packages/web/tests/component-support.ts +++ b/packages/web/tests/component-support.ts @@ -1,9 +1,9 @@ /** * Driving `` the way a document does, and counting what it caused. * - * The claims this package makes hardest are negative — a failing body prints no + * The hardest behaviors to verify in this package are negative — a failing body prints no * URL, opens no browser, binds no port, journals nothing; a replay does none of - * it either. A test can only make those claims if something observes each effect, + * it either. A test can only verify those behaviors if something observes each effect, * so every seam is instrumented and the counters are read after the run. */ diff --git a/packages/web/tests/declaration.test.ts b/packages/web/tests/declaration.test.ts index 64096b215..3544251e8 100644 --- a/packages/web/tests/declaration.test.ts +++ b/packages/web/tests/declaration.test.ts @@ -251,7 +251,7 @@ describe("declaration: __proto__ in a schema position", () => { * name does not survive. `properties: { "__proto__": … }` compiles and then a * submission carrying that key is judged as though the property were never * declared; `dependencies` compiles and never applies; `required` is refused by - * strict mode. Rather than claim a support that is not there, the declaration is + * strict mode. Rather than advertise support that is not there, the declaration is * refused before anything compiles. */ it("refuses __proto__ wherever a schema declares it as a name", function* () { diff --git a/packages/web/tests/markdown.test.ts b/packages/web/tests/markdown.test.ts index a09277eb7..be5f37967 100644 --- a/packages/web/tests/markdown.test.ts +++ b/packages/web/tests/markdown.test.ts @@ -234,8 +234,7 @@ describe("markdown: sanitization is last", () => { /** * The policy denies what the page would do on its own, not what a person - * chooses to do. A safe link keeps its destination, so the threat model claims - * no more than "cannot *automatically* navigate or issue external requests". + * chooses to do. A safe link keeps its destination, so the threat model guarantees no more than "cannot *automatically* navigate or issue external requests". */ it("still preserves a link a person can choose to follow", function* () { const html = renderBody("[docs](https://example.test/guide)\n"); diff --git a/packages/workflow/deno.ts b/packages/workflow/deno.ts index fa94ba4e8..f277535ed 100644 --- a/packages/workflow/deno.ts +++ b/packages/workflow/deno.ts @@ -132,7 +132,8 @@ export { /** * What a host declares to the execution so an authored workflow document has * ``: its implementation names durable work after its own invocation, - * so canonical execution builds it from the claimant it minted. + * so canonical execution builds it from the invocation identity function it + * minted. */ export { evaluationProfile } from "./src/deno/workspace/evaluate.ts"; export type { GeneratedEvaluationOptions } from "./src/deno/workspace/evaluate.ts"; diff --git a/packages/workflow/src/bundle.ts b/packages/workflow/src/bundle.ts index deb8215d2..42e41f5a8 100644 --- a/packages/workflow/src/bundle.ts +++ b/packages/workflow/src/bundle.ts @@ -131,8 +131,8 @@ function importedValue(event: DurableEvent): { value: unknown } | undefined | ty * Every branch is a decision about what the record *is*, taken before anything * is replayed from it. A declared name must have been recorded as a bundled * component, with this bundle's exact path, hash, and source; an undeclared - * name must not claim to be one; and a repository selection is admitted only - * for the root, which core holds to the run's own root source. + * name must not report itself as one; and a repository selection is admitted + * only for the root, which core holds to the run's own root source. */ function admitImport( event: DurableEvent, diff --git a/packages/workflow/src/deno/advisory-lock.ts b/packages/workflow/src/deno/advisory-lock.ts index e2b7e85a9..726f2c0e4 100644 --- a/packages/workflow/src/deno/advisory-lock.ts +++ b/packages/workflow/src/deno/advisory-lock.ts @@ -53,10 +53,11 @@ interface LockingRuntime { * Whether the global this host found is one that opens files. * * Asked rather than assumed. Describing the global's type at the point of use - * would be this module telling its own typechecker what is out there — a claim - * the compiler accepts and nothing verifies, which is exactly backwards for a - * value that arrives from outside every module in this project. So the one - * property this adapter depends on is checked, and the answer is what narrows. + * would be this module telling its own typechecker what is out there — an + * assertion the compiler accepts and nothing verifies, which is exactly + * backwards for a value that arrives from outside every module in this project. + * So the one property this adapter depends on is checked, and the answer is + * what narrows. * * It cannot check further than one call deep: what `openSync` returns is only * knowable by calling it. That is the honest boundary of a runtime reached diff --git a/packages/workflow/src/deno/artifact/records.ts b/packages/workflow/src/deno/artifact/records.ts index 036adfda2..272174880 100644 --- a/packages/workflow/src/deno/artifact/records.ts +++ b/packages/workflow/src/deno/artifact/records.ts @@ -442,7 +442,7 @@ class Inventory { } /** - * Refuse any entry nothing declared has claimed. + * Refuse any entry no declaration has consumed. * * The other half of completeness. `take()` catches a record that should be * there and is not; this catches one that is there and should not be, which @@ -643,7 +643,7 @@ function ordered( /** * The snapshot one accepted inventory describes. * - * Total: every declared record is claimed and parsed, and anything left over + * Total: every declared record is consumed and parsed, and anything left over * refuses the file. A reader that stopped once it had what a caller asked for * would be reporting a status whose journal it had never looked at. */ @@ -1212,7 +1212,7 @@ function decodeAgentSessions(inventory: Inventory, path: string): readonly Agent * The source closure this artifact carries. * * Driven by the definition already decoded rather than by which entries happen - * to be present, so the descriptor decides which kinds are claimed and + * to be present, so the descriptor decides which kinds are consumed and * `requireNothingLeftOver` refuses anything else the file carried. */ function decodeDefinitionSources( @@ -1227,7 +1227,7 @@ function decodeDefinitionSources( * The retained bytes this artifact carries, one pair per logical path. * * Each pair's natural identity is the canonical JSON string of its path, and - * both halves are claimed under it: an entry whose own `path` is not the + * both halves are consumed under it: an entry whose own `path` is not the * identity it was stored under would let one source be read as another's. * * The declared hash and length are read out with the path rather than skipped @@ -1375,7 +1375,7 @@ function verifyLifecycle( * * Sizes and hashes are recomputed rather than believed: the manifest already * proved the bytes are the ones that were sealed, and this proves the bytes are - * the ones the DOFS records claim to be about. + * the ones the DOFS records describe. */ function verifyContentStore( contents: XmdArtifactContents, @@ -1529,7 +1529,8 @@ interface AnswerPublication { } /** - * Every retained answer, authenticated against the history it claims to answer. + * Every retained answer, authenticated against the retained history of its + * corresponding request. * * A row naming an event the journal holds proves nothing on its own. What has * to be true is that the named event *is* the wait, that it is *this* wait, that @@ -1749,7 +1750,7 @@ function* judgeRetainedAnswer( } } -/** One retained record, as the durable event it claims to be. */ +/** One retained record, as the durable event it describes. */ function parseJournalEvent(record: string, path: string): DurableEvent { const parsed = parseDurableEvent(record); if (!parsed.ok) { diff --git a/packages/workflow/src/deno/artifact/schema.ts b/packages/workflow/src/deno/artifact/schema.ts index d5aa35ca2..e1d557cb7 100644 --- a/packages/workflow/src/deno/artifact/schema.ts +++ b/packages/workflow/src/deno/artifact/schema.ts @@ -13,9 +13,9 @@ * is **XMD's own writable run state** offered where evidence was expected, and * says so in its own sentence rather than as a confusing foreign refusal. A * version this build does not implement is **unsupported**: a later build may - * read it, and this one must not touch it. A file that claims version 1 and is - * not shaped like one is **damage** — the header says the tables are there, so - * their absence or their wrong shape is the file disagreeing with itself. + * read it, and this one must not touch it. A file that declares version 1 and + * is not shaped like one is **damage** — the header says the tables are there, + * so their absence or their wrong shape is the file disagreeing with itself. * * The stored `sqlite_schema` definitions are compared with the definitions this * build creates, so a dropped constraint, an added trigger, a view somebody @@ -66,8 +66,8 @@ interface DeclaredObject { * Version 1, one declaration at a time. * * Two tables and nothing else. The header is a singleton carrying what the - * container claims to be and what it claims to hold; the content table is a - * generic store keyed by an entry's kind and its canonical logical identity. + * container declares as its format and contents; the content table is a generic + * store keyed by an entry's kind and its canonical logical identity. * * The content table is `WITHOUT ROWID`, so its primary key *is* the table and * SQLite creates no automatic index beside it. That matters because version 1 @@ -77,7 +77,7 @@ interface DeclaredObject { * `identity` holds the entry's canonical JSON identity as text rather than a * joined key, because two different natural keys can join to one string and a * container whose primary key merged them would hold fewer records than its - * manifest claims. + * manifest lists. */ const OBJECTS: ReadonlyMap = new Map([ [ diff --git a/packages/workflow/src/deno/artifact/source.ts b/packages/workflow/src/deno/artifact/source.ts index 67214eed1..5a19bd1b4 100644 --- a/packages/workflow/src/deno/artifact/source.ts +++ b/packages/workflow/src/deno/artifact/source.ts @@ -4,7 +4,7 @@ * A workflow definition pins a commit and a path; it does not retain the * document. So a closure's blob identity is computed from the bytes somebody * read back out of that commit, and compared with it — which is what makes - * "these are the bytes the definition names" a checkable claim rather than an + * "these are the bytes the definition names" a verifiable fact rather than an * assertion by whoever did the reading. * * One function, because the exporter that produces a closure and the verifier diff --git a/packages/workflow/src/deno/artifact/types.ts b/packages/workflow/src/deno/artifact/types.ts index f45d216dc..0532b2e4a 100644 --- a/packages/workflow/src/deno/artifact/types.ts +++ b/packages/workflow/src/deno/artifact/types.ts @@ -94,8 +94,8 @@ export interface XmdArtifactAgentCheckpoint { * A durable session identity a provider asserted, and what kind of thing it is. * * Tagged for the same reason the live mapping's assertion is: "an ACP session - * id" and "a record id in some store" are different claims that happen to be - * strings. + * id" and "a record id in some store" are different identity assertions that + * happen to be strings. */ export interface XmdArtifactProviderSessionIdentity { readonly kind: string; diff --git a/packages/workflow/src/deno/artifact/write.ts b/packages/workflow/src/deno/artifact/write.ts index ab589bb30..4952367d7 100644 --- a/packages/workflow/src/deno/artifact/write.ts +++ b/packages/workflow/src/deno/artifact/write.ts @@ -22,10 +22,10 @@ * * ## Cleanup * - * An incomplete file is removed inside the operation's own `scoped()` - * ownership boundary, so a failure and a cancellation are cleaned up the same - * way. Cleanup that fails is reported and never reports a successful artifact: - * a file nobody could finish writing is not evidence, and claiming one was + * An incomplete file is removed inside the operation's own `scoped()` ownership + * boundary, so a failure and a cancellation are cleaned up the same way. + * Cleanup that fails is reported and never reports a successful artifact: a + * file nobody could finish writing is not evidence, and reporting one was * published would leave an operator with a path they believe is good. */ @@ -81,7 +81,7 @@ const SIDECARS = ["-journal", "-wal", "-shm"]; * artifact. * * Adapter-private, and installed only by this package's own suites. It exists - * because "the identity ignores physical layout" is a claim about two files + * because "the identity ignores physical layout" is a property of two files * that genuinely differ, and the only way to assert it is to produce two. */ export interface XmdArtifactLayout { diff --git a/packages/workflow/src/deno/definition-source.ts b/packages/workflow/src/deno/definition-source.ts index aed5d3527..c4d67f7fc 100644 --- a/packages/workflow/src/deno/definition-source.ts +++ b/packages/workflow/src/deno/definition-source.ts @@ -6,7 +6,7 @@ * reading it is a total re-derivation: every retained length, every source hash * and the bundle hash itself are recomputed from the BLOBs before anything is * handed back. A retained identity nobody can reproduce is not evidence of the - * definition it claims. + * definition it names. * * ## Missing and corrupt are different answers * diff --git a/packages/workflow/src/deno/delivery.ts b/packages/workflow/src/deno/delivery.ts index 040bcfe67..5f175ec3f 100644 --- a/packages/workflow/src/deno/delivery.ts +++ b/packages/workflow/src/deno/delivery.ts @@ -295,7 +295,7 @@ function* judgeAnswer( * in the framing each will have. A credential that reached a run's file has * already leaked, whatever the resume that would have published it does next. * - * The scanner is created for this delivery and reclaimed with it, so its + * The scanner is created for this delivery and released with it, so its * fingerprints mean nothing outside this call and are not reported. */ function* scanDelivery( diff --git a/packages/workflow/src/deno/provider-sessions.ts b/packages/workflow/src/deno/provider-sessions.ts index a0bc8daf5..a4153e904 100644 --- a/packages/workflow/src/deno/provider-sessions.ts +++ b/packages/workflow/src/deno/provider-sessions.ts @@ -81,9 +81,9 @@ export function* useEmptyDirectory(path: string): Operation { * Own this run's provider-session sidecar for one attachment. * * It creates nothing. A run whose document never prompts an Agent allocates no - * sidecar at all, which is what keeps "this run had no agent" a fact about the - * filesystem rather than a claim: the directories below appear when a session is - * placed and a record is written, and not before. + * sidecar at all, which is what keeps "this run had no agent" observable in the + * filesystem rather than merely asserted: the directories below appear when a + * session is placed and a record is written, and not before. * * What it does own is the end. The retained half — the mapping records and the * provider's own session store — outlives the attachment, because that is what a diff --git a/packages/workflow/src/deno/schema.ts b/packages/workflow/src/deno/schema.ts index d302a5d1c..ed6cd923c 100644 --- a/packages/workflow/src/deno/schema.ts +++ b/packages/workflow/src/deno/schema.ts @@ -8,9 +8,9 @@ * that belongs to another program is a **format** failure: nothing here will * ever read it. A schema version this build does not implement is a **version** * failure: a later build might read it, and this one must not touch it. A file - * that claims to be a version-1 workflow database and is not shaped like one is - * **damage** — the header says the tables are there, so their absence or their - * wrong shape is the file disagreeing with itself. + * that declares itself a version-1 workflow database and is not shaped like one + * is **damage** — the header says the tables are there, so their absence or + * their wrong shape is the file disagreeing with itself. * * Recognizing it is not the same as reading its table names. The stored * definition of every table is compared with the definition this build creates, @@ -19,7 +19,7 @@ * * Nothing in this module writes to a database it did not just create. An * incompatible or damaged file is described and left exactly as it was found: a - * host that silently replaced it would be claiming to continue a run whose + * host that silently replaced it would be reporting continuation of a run whose * history it had just deleted. */ @@ -764,7 +764,7 @@ export function verifyRecognizedSchema( /** * Hold a recognized database to the schema this build writes for its version. * - * The header already claims a version, so anything missing or differently + * The header already declares a version, so anything missing or differently * shaped is the file disagreeing with itself rather than a version this build * has not learned yet. A version-1 object inside a version-2 file — the * `workflow_run` table with a `base` column, say — fails here as a shape that diff --git a/packages/workflow/src/deno/workspace/agent-checkpoints.ts b/packages/workflow/src/deno/workspace/agent-checkpoints.ts index 3cffd0de4..56190d4c1 100644 --- a/packages/workflow/src/deno/workspace/agent-checkpoints.ts +++ b/packages/workflow/src/deno/workspace/agent-checkpoints.ts @@ -71,7 +71,7 @@ const INSERT = `INSERT INTO ${AGENT_PROMPT_CHECKPOINTS} * * The join is the ordering. `journal_events.sequence` is the run's own physical * order, and reading through it is what makes two associations comparable - * without this table claiming to know which Prompt came first. + * without this table asserting which Prompt came first. */ const SELECT_ALL = `SELECT c.event_id, c.session_key, c.provider, c.token_kind, c.token_value FROM ${AGENT_PROMPT_CHECKPOINTS} c diff --git a/packages/workflow/src/deno/workspace/agent-sessions.ts b/packages/workflow/src/deno/workspace/agent-sessions.ts index ff55877b3..8f73c9a39 100644 --- a/packages/workflow/src/deno/workspace/agent-sessions.ts +++ b/packages/workflow/src/deno/workspace/agent-sessions.ts @@ -49,8 +49,8 @@ export class WorkflowAgentSessionError extends Error { * One durable identity a provider asserted, and what kind of thing it is. * * Tagged, because "the adapter's own session id" and "an ACP session id" and "a - * record id in some store" are different claims that happen to be strings. A - * host comparing them without the tag would accept one for another. + * record id in some store" are different identity assertions that happen to be + * strings. A host comparing them without the tag would accept one for another. */ export interface ProviderAssertion { readonly kind: string; diff --git a/packages/workflow/src/deno/workspace/files.ts b/packages/workflow/src/deno/workspace/files.ts index 2576c79de..7e4377fa6 100644 --- a/packages/workflow/src/deno/workspace/files.ts +++ b/packages/workflow/src/deno/workspace/files.ts @@ -286,8 +286,8 @@ function* fileEffect( * The same path serves a live effect and a replayed one: live execution * publishes the outcome and hands it back, replay hands back the outcome that * was published. Neither branch is written twice here, which is what makes - * "replay restores the recorded result" a property of the code rather than a - * claim about it. + * "replay restores the recorded result" a property of the code rather than an + * assertion about it. */ function* performed( database: WorkflowRunDatabase, @@ -349,7 +349,7 @@ function* readOutcome( * What the target already is, when that decides the write before it starts. * * A directory cannot become a file, and saying so before anything is attempted - * is what keeps the target claim `unchanged` rather than `rolled-back`. A path + * is what keeps the target state `unchanged` rather than `rolled-back`. A path * that does not exist yet is the ordinary case and answers `undefined`. */ function* classifyWriteTarget( @@ -428,7 +428,7 @@ function* ensureOutcome( * The parents and the replacement share one savepoint, so a write that creates * two directories and then cannot be written leaves neither behind. The refusal * that comes back therefore describes a Workspace that is exactly what it was, - * which is the `rolled-back` target claim the write vocabulary already has. + * which is the `rolled-back` target state the write vocabulary already has. */ function* writeOutcome( filesystem: DenoWorkspaceFilesystem, diff --git a/packages/workflow/src/journal.ts b/packages/workflow/src/journal.ts index 026788b46..0d671a117 100644 --- a/packages/workflow/src/journal.ts +++ b/packages/workflow/src/journal.ts @@ -23,8 +23,8 @@ import type { DurableEvent, EffectDescription } from "@executablemd/durable-stre * One workflow run. * * No base and no pinned commit: a run starts from exact retained bytes rather - * than from a repository state, and a member naming one would be a claim about - * a repository the run never had. The bundle hash is what the retained + * than from a repository state, and a member naming one would be an assertion + * about a repository the run never had. The bundle hash is what the retained * definition is, and the exact target is what distinguishes two runs over it. * * The value a journal records, and the value `getWorkflowRun()` answers with. @@ -152,14 +152,14 @@ export function readWorkflowRun(value: unknown): WorkflowRun | undefined { return Object.freeze({ runId, bundleHash, targetPath }); } -/** What one retained event claims about the run, when it claims anything. */ +/** What one retained event records about the run, when it records anything. */ interface RunClaim { readonly settled: boolean; readonly value: unknown; } /** - * The claim this event makes, read totally and fail-closed. + * The workflow-run identity this event records, read totally and fail-closed. * * Every member a decision rests on is forced here — the discriminator, the * coroutine, both halves of the description, the settlement and a successful @@ -169,7 +169,8 @@ interface RunClaim { * absent, and a recorded terminal result be reused on the difference. * * A Yield that reads cleanly but is not the root coroutine's, or is not under - * both the canonical type and the canonical name, makes no claim at all. + * both the canonical type and the canonical name, records no workflow-run + * identity. */ function runClaim(event: DurableEvent): RunClaim | undefined { try { diff --git a/packages/workflow/src/lifecycle/api.ts b/packages/workflow/src/lifecycle/api.ts index d728cb4fe..5e213e551 100644 --- a/packages/workflow/src/lifecycle/api.ts +++ b/packages/workflow/src/lifecycle/api.ts @@ -113,8 +113,8 @@ export interface WorkflowLifecycleSnapshot extends WorkflowInspectionSnapshot { /** * What deletion actually removed. * - * Categories, not a claim about the world: a push that happened is not undone - * by removing the record of it, and nothing here says otherwise. + * Categories, not a determination of external state: a push that happened is + * not undone by removing the record of it, and nothing here says otherwise. */ export interface WorkflowDeletion { readonly removed: readonly ("run-storage" | "provider-sessions")[]; diff --git a/packages/workflow/src/lifecycle/source.ts b/packages/workflow/src/lifecycle/source.ts index b7cc18b8d..eb43f7ed5 100644 --- a/packages/workflow/src/lifecycle/source.ts +++ b/packages/workflow/src/lifecycle/source.ts @@ -8,7 +8,7 @@ * * The retained lifecycle reads that store and holds what it finds to the * descriptor it asked about, which is what makes "these are the bytes this run - * is a run of" a checkable claim rather than an assertion by whoever did the + * is a run of" a verifiable fact rather than an assertion by whoever did the * reading. */ diff --git a/packages/workflow/src/run.ts b/packages/workflow/src/run.ts index 3430a6413..72ba7041f 100644 --- a/packages/workflow/src/run.ts +++ b/packages/workflow/src/run.ts @@ -108,7 +108,7 @@ const CurrentWorkflowRun: Context = createContext): Operation { const prepared = yield* prepareElicitation(props.schema); diff --git a/packages/workflow/src/suspension/suspend.ts b/packages/workflow/src/suspension/suspend.ts index 2e27b0744..e5cd110ab 100644 --- a/packages/workflow/src/suspension/suspend.ts +++ b/packages/workflow/src/suspension/suspend.ts @@ -125,7 +125,7 @@ export function* suspendFor(request: WorkflowSuspensionRequest): Operation } /** - * The answer, restored or claimed. + * The answer, restored or consumed. * * A durable operation of its own, directly behind the request, so an execution * that already received its answer replays it instead of asking again. Its live diff --git a/packages/workflow/tests/generated-agent-component.test.ts b/packages/workflow/tests/generated-agent-component.test.ts index 08594b03f..8f1593619 100644 --- a/packages/workflow/tests/generated-agent-component.test.ts +++ b/packages/workflow/tests/generated-agent-component.test.ts @@ -2,15 +2,15 @@ * Tier WGAC — ``, the registered generated-XMD boundary * (specs/workflow-workspace-spec.md §8.4). * - * The claim under test is the split between availability and permission. - * Registering the component is what makes the operation reachable from a - * trusted workflow document; it carries none of the ceilings the operation runs - * under, and nothing a document writes can supply or widen one. + * The test verifies the split between availability and permission. Registering + * the component is what makes the operation reachable from a trusted workflow + * document; it carries none of the ceilings the operation runs under, and + * nothing a document writes can supply or widen one. * * So these drive the real component through a real attachment against a real * run database. A stand-in for the run's storage would be a stand-in for the - * exact thing being claimed: that the roots come from the run rather than from - * the element. + * exact boundary being verified: that the roots come from the run rather than + * from the element. */ import { describe, it } from "@executablemd/test-support/bdd"; diff --git a/packages/workflow/tests/support/artifact-fixture.ts b/packages/workflow/tests/support/artifact-fixture.ts index 1b36a1eb7..7a78bd1fb 100644 --- a/packages/workflow/tests/support/artifact-fixture.ts +++ b/packages/workflow/tests/support/artifact-fixture.ts @@ -534,8 +534,8 @@ function agentSession( * * What a bundle may hold is a provider's business — transcripts, tool state, a * secret a conversation repeated, the exporting host's own paths — and the - * claim these prove is that the container returns those bytes exactly and that - * no ordinary presentation renders them. A literal that looked like a real + * property these prove is that the container returns those bytes exactly and + * that no ordinary presentation renders them. A literal that looked like a real * credential would be the same evidence and would also arrive in every diff of * this file. */ diff --git a/packages/workflow/tests/support/restart-child.ts b/packages/workflow/tests/support/restart-child.ts index ee03cfa0a..7f30827f7 100644 --- a/packages/workflow/tests/support/restart-child.ts +++ b/packages/workflow/tests/support/restart-child.ts @@ -1,11 +1,11 @@ /** * A whole workflow run, in a process of its own. * - * A scope closing inside one process is not the same claim as a process - * ending: the connection, the page cache and every value the first run put in - * memory go away together only in the second. Two of the acceptances need - * that, so both run here, through the production Deno adapter, and the test - * observes them from outside. + * A scope closing inside one process is not the same proof as a process ending: + * the connection, the page cache and every value the first run put in memory go + * away together only in the second. Two of the acceptances need that, so both + * run here, through the production Deno adapter, and the test observes them + * from outside. * * ```sh * deno run -A restart-child.ts [channel] diff --git a/packages/workflow/tests/workflow-agent-checkpoints.test.ts b/packages/workflow/tests/workflow-agent-checkpoints.test.ts index dd0423a3c..4fa7c03f3 100644 --- a/packages/workflow/tests/workflow-agent-checkpoints.test.ts +++ b/packages/workflow/tests/workflow-agent-checkpoints.test.ts @@ -3,11 +3,11 @@ * (specs/workflow-workspace-spec.md §8.6). * * A retained Agent session says which conversation this run is having. A - * checkpoint says where in that conversation one Prompt landed. The claim under - * test is that the second fact commits with the Prompt it describes and with - * nothing else — so these drive the real publisher, the real transaction and the - * real table against a real run database. A stand-in for any of them would be a - * stand-in for exactly what is being claimed. + * checkpoint says where in that conversation one Prompt landed. These tests + * verify that the second fact commits with the Prompt it describes and with + * nothing else — so these drive the real publisher, the real transaction and + * the real table against a real run database. A stand-in for any of them would + * be a stand-in for exactly what is being verified. * * The provider here is a fake, and deliberately so: what an adapter puts on a * response is `packages/acp`'s question, and it is answered under Tier APC and diff --git a/packages/workflow/tests/workflow-checkpoint.test.ts b/packages/workflow/tests/workflow-checkpoint.test.ts index dff526b77..b151a296c 100644 --- a/packages/workflow/tests/workflow-checkpoint.test.ts +++ b/packages/workflow/tests/workflow-checkpoint.test.ts @@ -1,12 +1,12 @@ /** * Tier CK — what `` becomes under a workflow run. * - * The claim is a substitution, so every case here is about which of two - * registrations answered, and the discriminator is what each leaves behind: - * core's `` wraps the asking in a durable `elicit` record, and the - * workflow's does not. A suite that only checked "the answer bound" could not - * tell them apart, and the whole point of the substitution is the record that - * is missing — a durable wait cannot sit inside one. + * The behavior under test is a substitution, so every case here is about which + * of two registrations answered, and the discriminator is what each leaves + * behind: core's `` wraps the asking in a durable `elicit` record, and + * the workflow's does not. A suite that only checked "the answer bound" could + * not tell them apart, and the whole point of the substitution is the record + * that is missing — a durable wait cannot sit inside one. * * The attachment is the production `withWorkflowWorkspace`, not a hand-built * install, so what these cases prove is that the host wires it rather than that diff --git a/packages/workflow/tests/workflow-definition.test.ts b/packages/workflow/tests/workflow-definition.test.ts index 286a900fa..890841d4b 100644 --- a/packages/workflow/tests/workflow-definition.test.ts +++ b/packages/workflow/tests/workflow-definition.test.ts @@ -699,8 +699,8 @@ function sourceAt(path: unknown): Record[] { * The members one serialized descriptor wrote, in the order it wrote them. * * Narrowed rather than asserted: presentation order is what these cases are - * about, and a cast would make the claim hold for a serializer that answered - * with an array or a scalar. + * about, and a cast would make the assertion pass for a serializer that + * answered with an array or a scalar. */ function jsonMembers(value: Json): string[] { if (value === null || typeof value !== "object" || Array.isArray(value)) { diff --git a/packages/workflow/tests/workflow-lifecycle-authority.test.ts b/packages/workflow/tests/workflow-lifecycle-authority.test.ts index 330495c17..11fb23d7b 100644 --- a/packages/workflow/tests/workflow-lifecycle-authority.test.ts +++ b/packages/workflow/tests/workflow-lifecycle-authority.test.ts @@ -2,8 +2,9 @@ * Tier WLA — who may advance a run. * * The subject is an operating-system lock, so these tests take it for real and, - * where exclusion across processes is the claim, from a real second process. - * An in-process stand-in would prove that this module agrees with itself. + * where the test requires exclusion across processes, from a real second + * process. An in-process stand-in would prove that this module agrees with + * itself. * * The lock's whole value is that the workflow executor cannot retain it beyond * its scope. Every test that acquires one also says what happens after that diff --git a/packages/workflow/tests/workflow-lifecycle-inspection.test.ts b/packages/workflow/tests/workflow-lifecycle-inspection.test.ts index 94fa31cf7..70058982d 100644 --- a/packages/workflow/tests/workflow-lifecycle-inspection.test.ts +++ b/packages/workflow/tests/workflow-lifecycle-inspection.test.ts @@ -2,10 +2,10 @@ * Tier WLI — immutable lifecycle inspection. * * These suites are about what reading a run may and may not do. The provider - * under test is the real Deno one against real SQLite files, because the claim - * is physical: a command that reports a run must leave its bytes, its rows and - * its file mode exactly as it found them, and must never reach the connection - * pool execution uses. + * under test is the real Deno one against real SQLite files, because the + * invariant is physical: a command that reports a run must leave its bytes, its + * rows and its file mode exactly as it found them, and must never reach the + * connection pool execution uses. * * A snapshot is checked as one reading rather than field by field. "The record * says completed" and "the frontier is this event" are only worth anything diff --git a/packages/workflow/tests/workflow-run-storage.test.ts b/packages/workflow/tests/workflow-run-storage.test.ts index 6cbab1645..d78feeef7 100644 --- a/packages/workflow/tests/workflow-run-storage.test.ts +++ b/packages/workflow/tests/workflow-run-storage.test.ts @@ -1616,7 +1616,7 @@ describe("Tier WS — version 1 amended in place", () => { } /** - * One shape that once claimed to be a complete version 1. + * One shape that once declared itself a complete version 1. * * Built by leaving out whichever amendments had not been made yet, so a new * amendment adds one name here and one prior shape rather than silently diff --git a/packages/workflow/tests/workflow-suspension-answer.test.ts b/packages/workflow/tests/workflow-suspension-answer.test.ts index 32b9cef7f..acee243c5 100644 --- a/packages/workflow/tests/workflow-suspension-answer.test.ts +++ b/packages/workflow/tests/workflow-suspension-answer.test.ts @@ -9,8 +9,8 @@ * wait, publishes one durable answer event and consumes the retained value in * one transaction, and the document continues from the value. * - * The claims worth stating carefully are the ones a weaker implementation would - * also seem to satisfy. A value correlates to *this* wait and no other. A + * The invariants worth stating carefully are the ones a weaker implementation + * would also seem to satisfy. A value correlates to *this* wait and no other. A * refusal writes nothing at all. And the consume and the publication are one * transaction, so a failure between them leaves the answer pending rather than * a run whose history says it was answered and whose delivery state says it was diff --git a/packages/workflow/tests/workflow-suspension.test.ts b/packages/workflow/tests/workflow-suspension.test.ts index 059766718..dc8376d3b 100644 --- a/packages/workflow/tests/workflow-suspension.test.ts +++ b/packages/workflow/tests/workflow-suspension.test.ts @@ -7,7 +7,7 @@ * wait — teardown, settlement, exit code, released lock — is the CLI's, and * Tier WFS proves that against real processes. * - * The identity claim is the one worth stating carefully. A suspension ID is + * The identity invariant is the one worth stating carefully. A suspension ID is * derived from the run and the durable coroutine position, so it is stable for * the same wait across executions and different for two waits in one procedure. * Both halves are asserted: an identity that is only stable is one that diff --git a/packages/workflow/tests/workspace-effect-transaction.test.ts b/packages/workflow/tests/workspace-effect-transaction.test.ts index 0dd5ab433..f7c8ee14d 100644 --- a/packages/workflow/tests/workspace-effect-transaction.test.ts +++ b/packages/workflow/tests/workspace-effect-transaction.test.ts @@ -2038,10 +2038,10 @@ describe("Tier WAR — read-only Workspace inspection", () => { * inspection *succeeds*, the transaction commits, and only that savepoint * stands between a historical read and a run left on a root it never * published. Here the transaction itself ends without committing, so the - * rollback is over-determined — which is the point. The claim is the outcome - * the caller is owed on every exit, and the case also proves the run is still - * usable afterwards rather than poisoned by a materialization that was - * interrupted half way through. + * rollback is over-determined — which is the point. The invariant is the + * outcome the caller is owed on every exit, and the case also proves the run + * is still usable afterwards rather than poisoned by a materialization that + * was interrupted half way through. */ it("WAR3: a failure and a cancellation each leave the run where they found it", function* () { const root = yield* useStorageRoot(); diff --git a/packages/workflow/tests/workspace-files.test.ts b/packages/workflow/tests/workspace-files.test.ts index 6f9fb6776..2d57d46fd 100644 --- a/packages/workflow/tests/workspace-files.test.ts +++ b/packages/workflow/tests/workspace-files.test.ts @@ -207,7 +207,7 @@ function* workspaceEvents(database: WorkflowRunDatabase): Operation { /** * Everything that breaks version lockstep in the workspace at `repoRoot`, as - * messages naming the manifest at fault. An empty list is the whole claim: the + * messages naming the manifest at fault. An empty list is the required result: the * release publishes one version, and every manifest and the lockfile declare * it. * diff --git a/scripts/main-green.ts b/scripts/main-green.ts index c8ea21079..7f8e3f62c 100644 --- a/scripts/main-green.ts +++ b/scripts/main-green.ts @@ -1,5 +1,5 @@ /** - * Decide whether this pull request may claim `green`, and say why either way. + * Decide whether this pull request may pass `green`, and say why either way. * * What this decides lives in `lib/main-green.ts`; what it parses lives in * `lib/github.ts`. What is left here is the one thing neither can hold: the diff --git a/scripts/measure-test-weights.ts b/scripts/measure-test-weights.ts index e576bd2be..1216eacd0 100644 --- a/scripts/measure-test-weights.ts +++ b/scripts/measure-test-weights.ts @@ -12,7 +12,7 @@ * * Provenance is supplied, never inferred. A local run could read its own commit * from Git and its own versions from the executables on `PATH`, and would then - * produce a file claiming to describe the runner while describing a laptop. So + * produce a file reporting provenance for the runner while describing a laptop. So * every provenance value arrives in the environment, and a missing one is a * refusal. */ diff --git a/scripts/oxlint-rules/no-module-scoped-registry.js b/scripts/oxlint-rules/no-module-scoped-registry.js index d52948760..9bc8370fb 100644 --- a/scripts/oxlint-rules/no-module-scoped-registry.js +++ b/scripts/oxlint-rules/no-module-scoped-registry.js @@ -9,7 +9,7 @@ * scope-local inheritance the rest of the engine is built on. * * State belongs to the operation that owns it: create the table inside that - * operation and hand it down through context, so it is reclaimed when the scope + * operation and hand it down through context, so it is released when the scope * that made it ends. * * export function* useSegmentCauses() { diff --git a/scripts/smoke-documentation.ts b/scripts/smoke-documentation.ts index 0205b4a83..e27298fa1 100644 --- a/scripts/smoke-documentation.ts +++ b/scripts/smoke-documentation.ts @@ -33,7 +33,7 @@ import { useTempDirectory } from "./lib/temp-directory.ts"; const MISSING_ASSET = "packaged component documentation is missing"; /** - * Report the claim that did not hold and shut the program down. + * Report the failed assertion and shut the program down. * * Through Effection's `exit` rather than `Deno.exit`, which returns to the host * without unwinding anything: the temporary directory below belongs to this diff --git a/scripts/smoke-fetch.ts b/scripts/smoke-fetch.ts index 4db587632..133a4fd7e 100644 --- a/scripts/smoke-fetch.ts +++ b/scripts/smoke-fetch.ts @@ -6,7 +6,7 @@ * response before binding it — three things that live in the module graph, and * only the binary shows that `deno compile` kept them. * - * The server is this script's own, so the claim is observed from outside the + * The server is this script's own, so the behavior is observed from outside the * run: one request reached it, and the document bound what it answered. */ diff --git a/scripts/smoke-foreground.ts b/scripts/smoke-foreground.ts index 356bcbcdb..4efe9a3f5 100644 --- a/scripts/smoke-foreground.ts +++ b/scripts/smoke-foreground.ts @@ -2,7 +2,7 @@ * Foreground execution through the compiled binary (#441). * * The contract is about what a caller sees and what status they get, and only - * the binary proves both survived `deno compile`. Two claims, each observed + * the binary proves both survived `deno compile`. Two behaviors, each observed * from outside the process: * * 1. a command's output arrives while the run is still going, not at the end; diff --git a/scripts/smoke-run-composition.ts b/scripts/smoke-run-composition.ts index b312da4dd..b64570df3 100644 --- a/scripts/smoke-run-composition.ts +++ b/scripts/smoke-run-composition.ts @@ -7,7 +7,7 @@ * those is a fact about the program that is running, so only the binary shows * they survived `deno compile`. * - * Five claims, each observed from outside the process: + * Five behaviors, each observed from outside the process: * * 1. a root-level `` belongs to the repository the binary was run in, * and a command inside it runs there; diff --git a/scripts/tests/adapter-distribution.test.ts b/scripts/tests/adapter-distribution.test.ts index 61e03720e..578ce29ad 100644 --- a/scripts/tests/adapter-distribution.test.ts +++ b/scripts/tests/adapter-distribution.test.ts @@ -3,7 +3,7 @@ * * The snapshots travel as a module in the graph rather than as files on disk, * precisely so that one mechanism serves the source tree, the dnt npm artifact - * and the compiled binary. That claim is only worth making if it is checked: + * and the compiled binary. That distribution guarantee is only useful if it is checked: * a compiled `xmd` that resolved no snapshot module would launch nothing, and * an npm package missing it would fail at a customer's first workflow Prompt. * @@ -17,7 +17,7 @@ * * This file itself runs under Deno only (`scripts/runtime-test-exclusions.ts`). * It asks for a module graph through `deno info`, and both distributions it - * inspects are Deno's own build outputs; the portable half of the claim is Tier + * inspects are Deno's own build outputs; the portable half of the contract is Tier * EA and Tier AM, which do run under all three. */ import { describe, it } from "@executablemd/test-support/bdd"; diff --git a/scripts/tests/build-web-client.test.ts b/scripts/tests/build-web-client.test.ts index 414fdbfbb..e209de677 100644 --- a/scripts/tests/build-web-client.test.ts +++ b/scripts/tests/build-web-client.test.ts @@ -130,7 +130,7 @@ describe("build-web-client", () => { }); /** - * The function above is only half the claim: `deno task build:web` is a + * The function above is only half the verification: `deno task build:web` is a * preflight plus a `deno run`, and `deno task build` adds a `deno compile` — * each its own process, each with its own node-modules mode. Automatic * management creates `node_modules/.deno` before a process reaches its own diff --git a/scripts/tests/ci-workflow.test.ts b/scripts/tests/ci-workflow.test.ts index 8837cf447..d3bec6185 100644 --- a/scripts/tests/ci-workflow.test.ts +++ b/scripts/tests/ci-workflow.test.ts @@ -262,7 +262,7 @@ describe("the CI smoke job", () => { /** * Each of these proves something about the compiled binary that no source - * run can: a claim that only holds if `deno compile` kept what the claim is + * run can: a requirement satisfied only if `deno compile` kept what the requirement is * about. A script removed from the job is a proof silently withdrawn, so the * job is held to naming them. */ diff --git a/scripts/tests/cli-npm-bin.test.ts b/scripts/tests/cli-npm-bin.test.ts index abe5fbb8d..0e9da78c8 100644 --- a/scripts/tests/cli-npm-bin.test.ts +++ b/scripts/tests/cli-npm-bin.test.ts @@ -438,7 +438,7 @@ describe("npm CLI package", { sanitizeOps: false, sanitizeResources: false }, () * `` is packaged Markdown rather than a module, so what a build ships * under that name is exactly the kind of thing a module-graph emitter can * lose. Asking the built bin what it would let a document write is what makes - * "the same Component in every distribution" a checked claim: the origin names + * "the same Component in every distribution" a verified guarantee: the origin names * the asset, the digest names the bytes, and a build that shipped different * ones — or none — answers differently here rather than at a person's first * `xmd plan`. diff --git a/scripts/tests/filesystem-contract-workflow.test.ts b/scripts/tests/filesystem-contract-workflow.test.ts index a65e599d9..6a87affd9 100644 --- a/scripts/tests/filesystem-contract-workflow.test.ts +++ b/scripts/tests/filesystem-contract-workflow.test.ts @@ -1,10 +1,10 @@ /** * The five-target filesystem contract job, held to the release matrix. * - * The claim `xmd run` makes about containment is per-platform: path arithmetic + * The containment guarantee `xmd run` provides is per-platform: path arithmetic * and `realpath` are the host's, and Windows brings drive letters, UNC paths, * junctions, and reparse points that POSIX does not. A job that covered four of - * the five triples would leave the fifth's claim asserted and unproven, and + * the five triples would leave the fifth's guarantee asserted and unproven, and * nothing about adding a release target would notice. * * So the matrix is held to `RELEASE_TARGETS` by set equality, the same way diff --git a/scripts/tests/jsr-consumer-documentation.test.ts b/scripts/tests/jsr-consumer-documentation.test.ts index a10628792..228d09642 100644 --- a/scripts/tests/jsr-consumer-documentation.test.ts +++ b/scripts/tests/jsr-consumer-documentation.test.ts @@ -1,7 +1,7 @@ /** * Tier SYN — a JSR consumer's named lookup. * - * Two claims, and they are different. That `components.md` appears in + * Two checks, and they are different. That `components.md` appears in * `deno publish --dry-run` says the asset is *selected into the payload* — the * publish filter keeps it, rather than dropping it as tooling. That a consumer * can render it says the asset is *reachable from the published layout*, which diff --git a/scripts/tests/main-green.test.ts b/scripts/tests/main-green.test.ts index 626ae0467..6805f599b 100644 --- a/scripts/tests/main-green.test.ts +++ b/scripts/tests/main-green.test.ts @@ -73,8 +73,7 @@ interface Script { /** * A `main` that behaves as scripted, one `Poll` per iteration. * - * Reading past the last poll throws, so a case that converges later than it - * claims fails rather than quietly reading a repeated state. `endless` repeats + * Reading past the last poll throws, so a case that converges later than expected fails rather than quietly reading a repeated state. `endless` repeats * the final poll instead, which is the only way to reach the wait's own bound. */ function world(polls: Poll[], options: { endless?: boolean } = {}): Script { diff --git a/scripts/tests/plan-component-compiled.test.ts b/scripts/tests/plan-component-compiled.test.ts index d42326795..ee89011a4 100644 --- a/scripts/tests/plan-component-compiled.test.ts +++ b/scripts/tests/plan-component-compiled.test.ts @@ -14,8 +14,7 @@ * environment costs nothing, which is exactly why it is the right probe. * * It runs against `dist/xmd`, so `deno task build` has to have happened. A - * missing binary is reported as the setup it is rather than as a failure of the - * claim. + * missing binary is reported as the setup it is rather than as a failed assertion. */ import { describe, it } from "@executablemd/test-support/bdd"; @@ -374,7 +373,7 @@ describe( * pass this case for the wrong reason. * * The unrelated `CustomProbe.md` in the same directory is the other half: - * claiming forty-one names is not the same as turning discovery off, and a + * reserving forty-one names is not the same as turning discovery off, and a * change that secured the review by disabling `--include` would be a * regression this would catch. * diff --git a/scripts/tests/plugin-compiled.test.ts b/scripts/tests/plugin-compiled.test.ts index 541c1c2ea..687fc9ab9 100644 --- a/scripts/tests/plugin-compiled.test.ts +++ b/scripts/tests/plugin-compiled.test.ts @@ -12,8 +12,7 @@ * depended on it would be testing this machine rather than the product. * * It runs against `dist/xmd`, so `deno task build` has to have happened. A - * missing binary is reported as the setup it is rather than as a failure of the - * claim. + * missing binary is reported as the setup it is rather than as a failed assertion. */ import { describe, it } from "@executablemd/test-support/bdd"; diff --git a/scripts/tests/prepared-state.test.ts b/scripts/tests/prepared-state.test.ts index 2ec637352..011cf80d0 100644 --- a/scripts/tests/prepared-state.test.ts +++ b/scripts/tests/prepared-state.test.ts @@ -277,8 +277,7 @@ describe("cancelling a fingerprint", () => { * itself says when it has begun a known number of files, so the test halts at * the same point on a fast disk and a slow one. Counting starts rather than * completions is what makes "begins no further read" observable: `until()` - * does not cancel the host call already in flight, and this seam never - * claimed it did. + * does not cancel the host call already in flight, and this seam never promised it did. */ it("begins no further read once its task is halted", function* () { const files = 4000; diff --git a/scripts/tests/runtime-tests.test.ts b/scripts/tests/runtime-tests.test.ts index fcb803e78..7bbe8be75 100644 --- a/scripts/tests/runtime-tests.test.ts +++ b/scripts/tests/runtime-tests.test.ts @@ -4,8 +4,8 @@ * These drive the shard through an injected runner rather than a real one, so * they can assert the exact argument vector and the exact ordering without * paying for hundreds of processes. That a real child's output survives, and - * that halting a shard halts its child, are claims an injected runner cannot - * make — `shard-execution.test.ts` makes those against real processes. + * that halting a shard halts its child, are behaviors an injected runner cannot + * establish — `shard-execution.test.ts` verifies those against real processes. */ import { describe, it } from "@executablemd/test-support/bdd"; import { expect } from "@executablemd/test-support/expect"; diff --git a/scripts/tests/shard-execution.test.ts b/scripts/tests/shard-execution.test.ts index a84f36cd0..b2256fb99 100644 --- a/scripts/tests/shard-execution.test.ts +++ b/scripts/tests/shard-execution.test.ts @@ -1,5 +1,5 @@ /** - * What a shard does with real child processes: the claims an injected runner + * What a shard does with real child processes: the behaviors an injected runner * cannot make. * * The corpus here is a temporary Deno workspace of its own — three tiny test diff --git a/scripts/tests/verify-clean.test.ts b/scripts/tests/verify-clean.test.ts index 875fe4e70..4b5a918a3 100644 --- a/scripts/tests/verify-clean.test.ts +++ b/scripts/tests/verify-clean.test.ts @@ -205,7 +205,7 @@ describe("CP11 — the offline build phases are unchanged", () => { /** * The release phase compiles what a release compiles, argv for argv. * - * Equality rather than containment: this phase's whole claim is that what a + * Equality rather than containment: this phase's required guarantee is that what a * release does fetches nothing and moves no dependency state, and a compile * embedding fewer assets walks fewer module graphs than the one it stands * for. It used to embed neither the packaged documents nor any diff --git a/scripts/verify-clean.ts b/scripts/verify-clean.ts index b588b5440..5653660a5 100644 --- a/scripts/verify-clean.ts +++ b/scripts/verify-clean.ts @@ -4,19 +4,19 @@ * Usage: * deno task verify:clean * - * The chain is the claim this repository makes: + * The chain is the preparation and build sequence this repository verifies: * * deno task setup → deps:target → build:web → build → the release compile * → resolution probe → the interference proof * - * Two claims, because a build and a check are different things. + * Two guarantees, because a build and a check are different things. * * **A build is cache-pure.** `build:web`, `build`, and the release compile run * offline and must leave `node_modules`, the Deno cache's dependency content, * and `deno.lock` byte-identical — a build that fetches has installed * something. * - * **The interference proof is not, and does not claim to be.** It resolves + * **The interference proof is not, and does not purport to be.** It resolves * modules no build walks, so it adds to the Deno cache, which the runtime owns. * What it may never move is what this repository owns: `node_modules` and * `deno.lock`. That is the comparison its phases make. What it proves beyond diff --git a/site/components/Prose.tsx b/site/components/Prose.tsx index a31cda188..7bede44bc 100644 --- a/site/components/Prose.tsx +++ b/site/components/Prose.tsx @@ -15,7 +15,7 @@ export const P_MD = "margin:0;max-width:74ch;font-size:0.9375rem;line-height:1.6;color:var(--body);"; export const P_MEASURED = `${P_SM}max-width:74ch;`; -/** A claim set at the weight of a heading, opening a panel or closing a list. */ +/** A statement set at the weight of a heading, opening a panel or closing a list. */ export const CLAIM = "margin:0;font-size:1.0625rem;line-height:1.45;color:var(--ink);font-weight:800;letter-spacing:-0.01em;"; From 312754689527010ffe8f468e1beda2d48845e2ef Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Wed, 14 Oct 2026 07:44:05 -0400 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=93=9D=20Enforce=20banned=20words=20i?= =?UTF-8?q?n=20architecture=20and=20JSDoc=20prose?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .oxlint-prose.json | 11 ++ .oxlintrc.json | 1 + AGENTS.md | 6 + package.json | 2 +- scripts/banned-words.js | 13 ++ scripts/lib/banned-words.js | 25 +++ scripts/lint-architecture.js | 20 ++ scripts/oxlint-plugin.js | 2 + scripts/oxlint-rules/no-banned-jsdoc-words.js | 110 +++++++++++ scripts/tests/banned-words.test.ts | 173 ++++++++++++++++++ scripts/tests/oxlint-policy.test.ts | 17 ++ 11 files changed, 379 insertions(+), 1 deletion(-) create mode 100644 .oxlint-prose.json create mode 100644 scripts/banned-words.js create mode 100644 scripts/lib/banned-words.js create mode 100644 scripts/lint-architecture.js create mode 100644 scripts/oxlint-rules/no-banned-jsdoc-words.js create mode 100644 scripts/tests/banned-words.test.ts diff --git a/.oxlint-prose.json b/.oxlint-prose.json new file mode 100644 index 000000000..1f8bacf39 --- /dev/null +++ b/.oxlint-prose.json @@ -0,0 +1,11 @@ +{ + "ignorePatterns": [ + "**/node_modules/**", + "site/_fresh/**", + "site/vendor/**", + "site/*.timestamp-*.mjs" + ], + "categories": { "correctness": "off" }, + "jsPlugins": [{ "name": "local", "specifier": "./scripts/oxlint-plugin.js" }], + "rules": { "local/no-banned-jsdoc-words": "error" } +} diff --git a/.oxlintrc.json b/.oxlintrc.json index e92294a55..33d689707 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -14,6 +14,7 @@ "rules": { "eslint/curly": "error", + "local/no-banned-jsdoc-words": "error", "local/no-module-scoped-registry": "error", "local/no-section-divider-comments": "error", "local/no-sync-filesystem": "error", diff --git a/AGENTS.md b/AGENTS.md index 0547cf27b..1be3b2f02 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -503,6 +503,12 @@ the corpus or enabling in-shard concurrency is not an answer to a miss. alternatives, defensive qualifications, and exhaustive detail that does not help a reader understand or use the design. +### Banned words + +Avoid words in the canonical [banned-words list](scripts/banned-words.js) when +writing architecture prose or JSDoc. Choose wording for the specific meaning; +keep literal code references intact. `deno task lint` enforces the list. + ### Component descriptions Write a component description for an author deciding what to type. Lead with an diff --git a/package.json b/package.json index cd4a9cd5d..754c8c650 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "test:node": "tsx scripts/runtime-tests.ts node", "test:bun": "bun scripts/runtime-tests.ts bun", "test:deno": "deno task test", - "lint": "oxlint -c .oxlintrc.json --ignore-pattern 'scripts/tests/fixtures/**' --ignore-pattern '**/npm/**' --ignore-pattern 'packages/workflow/vendor/cloudflare-computer-dofs/**' --ignore-pattern 'packages/acp/vendor/acpx/**' --ignore-pattern 'packages/cli/src/repl/vendor/freedom/**' packages scripts && oxfmt --check packages scripts && pnpm run lint:dead-code", + "lint": "oxlint -c .oxlintrc.json --ignore-pattern 'scripts/tests/fixtures/**' --ignore-pattern '**/npm/**' --ignore-pattern 'packages/workflow/vendor/cloudflare-computer-dofs/**' --ignore-pattern 'packages/acp/vendor/acpx/**' --ignore-pattern 'packages/cli/src/repl/vendor/freedom/**' packages scripts && oxlint -c .oxlint-prose.json site smoke-test && node scripts/lint-architecture.js && oxfmt --check packages scripts && pnpm run lint:dead-code", "lint:dead-code": "knip --config knip.json --no-progress --no-config-hints --include files,exports,types", "fmt": "oxfmt --write packages scripts" }, diff --git a/scripts/banned-words.js b/scripts/banned-words.js new file mode 100644 index 000000000..d1c79a867 --- /dev/null +++ b/scripts/banned-words.js @@ -0,0 +1,13 @@ +export const BANNED_WORDS = [ + "claim", + "claims", + "claimed", + "claiming", + "claimant", + "claimants", + "unclaimed", + "reclaim", + "reclaims", + "reclaimed", + "reclaiming", +]; diff --git a/scripts/lib/banned-words.js b/scripts/lib/banned-words.js new file mode 100644 index 000000000..22acbf0bd --- /dev/null +++ b/scripts/lib/banned-words.js @@ -0,0 +1,25 @@ +import { remark } from "remark"; +import { BANNED_WORDS } from "../banned-words.js"; + +export function bannedProseWords(source) { + const forbidden = new Set(BANNED_WORDS.map((word) => word.toLowerCase())); + const findings = []; + + function visit(node) { + if (node.type === "text") { + const start = node.position.start.offset; + const text = source.slice(start, node.position.end.offset); + for (const match of text.matchAll(/[\p{L}\p{N}_$]+/gu)) { + if (forbidden.has(match[0].toLowerCase())) { + findings.push({ word: match[0], offset: start + match.index }); + } + } + } + for (const child of node.children ?? []) { + visit(child); + } + } + + visit(remark().parse(source)); + return findings; +} diff --git a/scripts/lint-architecture.js b/scripts/lint-architecture.js new file mode 100644 index 000000000..c2d3debb9 --- /dev/null +++ b/scripts/lint-architecture.js @@ -0,0 +1,20 @@ +import { readTextFile } from "@effectionx/fs"; +import { exit, main } from "effection"; +import { bannedProseWords } from "./lib/banned-words.js"; + +main(function* () { + const file = process.argv[2] ?? new URL("../architecture.md", import.meta.url); + const source = yield* readTextFile(file); + const findings = bannedProseWords(source); + for (const { word, offset } of findings) { + const before = source.slice(0, offset); + const line = before.split("\n").length; + const column = offset - before.lastIndexOf("\n"); + console.error( + `${file}:${line}:${column}: forbidden prose word "${word}" (scripts/banned-words.js)`, + ); + } + if (findings.length > 0) { + yield* exit(1); + } +}); diff --git a/scripts/oxlint-plugin.js b/scripts/oxlint-plugin.js index 1ee11cd75..7629037e1 100644 --- a/scripts/oxlint-plugin.js +++ b/scripts/oxlint-plugin.js @@ -10,6 +10,7 @@ import { requireScopeBoundEventRegistration } from "./oxlint-rules/require-scope export default { meta: { name: "executablemd" }, rules: { + "no-banned-jsdoc-words": noBannedJsdocWords, "no-module-scoped-registry": noModuleScopedRegistry, "no-section-divider-comments": noSectionDividerComments, "no-redundant-test-scope": noRedundantTestScope, @@ -20,3 +21,4 @@ export default { "require-scope-bound-event-registration": requireScopeBoundEventRegistration, }, }; +import { noBannedJsdocWords } from "./oxlint-rules/no-banned-jsdoc-words.js"; diff --git a/scripts/oxlint-rules/no-banned-jsdoc-words.js b/scripts/oxlint-rules/no-banned-jsdoc-words.js new file mode 100644 index 000000000..871e731ea --- /dev/null +++ b/scripts/oxlint-rules/no-banned-jsdoc-words.js @@ -0,0 +1,110 @@ +import { bannedProseWords } from "../lib/banned-words.js"; + +function annotationEnd(text, start) { + let cursor = start; + while (/\s/.test(text[cursor] ?? "") && cursor < text.length) { + cursor++; + } + if (text[cursor] !== "{") { + return start; + } + let depth = 0; + let quote; + for (; cursor < text.length; cursor++) { + const character = text[cursor]; + if (quote) { + if (character === "\\") { + cursor++; + } else if (character === quote) { + quote = undefined; + } + } else if (character === '"' || character === "'" || character === "`") { + quote = character; + } else if (character === "{") { + depth++; + } else if (character === "}") { + if (--depth === 0) { + return cursor + 1; + } + } + } + return start; +} + +function prose(comment) { + const characters = []; + const offsets = []; + const body = comment.value.slice(1); + let offset = comment.range[0] + 3; + + for (const line of body.matchAll(/[^\n]*(?:\n|$)/g)) { + const margin = /^\s*\* ?/.exec(line[0])?.[0].length ?? 0; + for (let index = margin; index < line[0].length; index++) { + characters.push(line[0][index]); + offsets.push(offset + index); + } + offset += line[0].length; + } + + // Annotation syntax and link targets name code; their descriptions remain prose. + let text = characters.join(""); + text = text.replace(/\{@(?:link|linkcode|linkplain)\s+[^\s|}]+/g, (value) => + " ".repeat(value.length), + ); + text = text.replace(/^[ \t]*@example\b[^]*?(?=^[ \t]*@[\w-]+|$(?![^]))/gm, (value) => + value.replace(/[^\r\n]/g, " "), + ); + const original = text; + for (const tag of original.matchAll(/^[ \t]*@([\w-]+)/gm)) { + let end = annotationEnd(original, tag.index + tag[0].length); + if ( + /^(?:param|arg|argument|property|prop|typedef|callback|template|typeParam|extends|implements|see)$/.test( + tag[1], + ) + ) { + const name = /^[ \t]+(?:\[[^\]\n]*\]|[\w.$]+(?:[ \t]*,[ \t]*[\w.$]+)*)/.exec( + original.slice(end), + ); + end += name?.[0].length ?? 0; + } + text = + text.slice(0, tag.index) + + text.slice(tag.index, end).replace(/[^\r\n]/g, " ") + + text.slice(end); + } + return { text, offsets }; +} + +export const noBannedJsdocWords = { + meta: { + type: "suggestion", + messages: { + forbidden: + 'Avoid "{{word}}" in prose; choose wording for its meaning (scripts/banned-words.js).', + }, + }, + create(context) { + const source = context.sourceCode; + return { + Program() { + for (const comment of source.getAllComments()) { + if (comment.type !== "Block" || !source.text.startsWith("/**", comment.range[0])) { + continue; + } + const { text, offsets } = prose(comment); + for (const { word, offset } of bannedProseWords(text)) { + const start = offsets[offset]; + context.report({ + loc: { + start: source.getLocFromIndex(start), + end: source.getLocFromIndex(start + word.length), + }, + messageId: "forbidden", + data: { word }, + }); + } + } + }, + }; + }, +}; diff --git a/scripts/tests/banned-words.test.ts b/scripts/tests/banned-words.test.ts new file mode 100644 index 000000000..a67e20d2b --- /dev/null +++ b/scripts/tests/banned-words.test.ts @@ -0,0 +1,173 @@ +import { describe, it } from "@executablemd/test-support/bdd"; +import { expect } from "@executablemd/test-support/expect"; +import { copyFile, ensureDir, readTextFile, writeTextFile } from "@effectionx/fs"; +import { exec } from "@effectionx/process"; +import { until } from "effection"; +import type { Operation } from "effection"; +import { useTempDirectory } from "@executablemd/test-support/temp"; +import { symlink } from "node:fs/promises"; +import path from "node:path"; +import { ROOT, runOxlint } from "./oxlint.ts"; +import { BANNED_WORDS } from "../banned-words.js"; + +const RULE = "local(no-banned-jsdoc-words)"; + +interface Diagnostic { + code: string; + message: string; + filename: string; + labels: { span: { line: number; column: number; length: number; offset: number } }[]; +} + +function diagnostics(source: string): Diagnostic[] { + const report: { diagnostics: Diagnostic[] } = JSON.parse(source); + return report.diagnostics.filter((item) => item.code === RULE); +} + +function* subject(source: string, name = "subject.ts"): Operation { + const directory = yield* useTempDirectory("banned-words-"); + const file = path.join(directory, name); + yield* writeTextFile(file, source); + return file; +} + +function architecture(file: string, script = path.join(ROOT, "scripts/lint-architecture.js")) { + return exec("node", { arguments: [script, file], cwd: ROOT }).join(); +} + +describe("banned prose words", () => { + it("rejects every explicit variant through the repository Oxlint config", function* () { + const source = + BANNED_WORDS.map((word) => `/** ${word.toUpperCase()}. */`).join("\n") + "\nexport {};\n"; + const file = yield* subject(source); + const run = yield* runOxlint(".oxlintrc.json", ["--format=json", file]); + const found = diagnostics(run.stdout); + expect(run.code).not.toBe(0); + expect(found.map((item) => item.labels[0].span)).toEqual( + BANNED_WORDS.map((word, index) => ({ + line: index + 1, + column: 5, + length: word.length, + offset: source.indexOf(word.toUpperCase()), + })), + ); + expect(found.every((item) => item.filename === file)).toBe(true); + for (let index = 0; index < BANNED_WORDS.length; index++) { + expect(found[index].message).toContain(BANNED_WORDS[index].toUpperCase()); + } + }); + + it("maps multiline CRLF prose back to exact source columns", function* () { + const file = yield* subject( + "/**\r\n * Intro.\r\n * A CLAIM, then claimed.\r\n * @returns claims remain prose.\r\n */\r\nexport {};\r\n", + ); + const run = yield* runOxlint(".oxlintrc.json", ["--format=json", file]); + expect(diagnostics(run.stdout).map((item) => item.labels[0].span)).toEqual([ + { line: 3, column: 6, length: 5, offset: 21 }, + { line: 3, column: 18, length: 7, offset: 33 }, + { line: 4, column: 13, length: 6, offset: 55 }, + ]); + }); + + it("preserves code, annotations, other comments and containing words", function* () { + const file = yield* subject( + [ + "// claim claims", + "/* claim */", + 'export const claim = "claimed";', + "/** A disclaimer and claimsConfiguration remain ordinary names.", + " * Literal `claim(invocation)` and ``claims `claim` `` are references.", + " * {@link IdentityClaimant} and {@link claim|the operation} name code.", + " *", + " * ```ts", + ' * const claimed = "claim";', + " * ```", + " *", + ' * claim("claims");', + " *", + " * @param {IdentityClaimant} claim the callback", + " * @type {claim}", + " * @type {{", + ' * claim: "}",', + " * claimed: string", + " * }}", + " * @template Claim, Claimant", + " * @example", + ' * claim("claimed");', + " */", + "export function use(claim: unknown) { return claim; }", + ].join("\n"), + ); + const run = yield* runOxlint(".oxlintrc.json", ["--format=json", file]); + expect(diagnostics(run.stdout)).toEqual([]); + }); + + it("rejects architectural prose with locations while preserving Markdown code", function* () { + const bad = yield* subject("# Design\r\n\r\nA Claim remains.\r\n", "architecture.md"); + const rejected = yield* architecture(bad); + expect(rejected.code).not.toBe(0); + expect(rejected.stderr).toContain(`${bad}:3:3: forbidden prose word "Claim"`); + + const good = yield* subject( + [ + "# Design", + "A disclaimer beside `claim(carrier)`.", + "", + "```ts", + 'const claim = "claimed";', + "```", + "", + " reclaim();", + ].join("\n"), + "architecture.md", + ); + expect((yield* architecture(good)).code).toBe(0); + }); + + it("takes an added list entry through both consumers without shared mutation", function* () { + const directory = yield* useTempDirectory("banned-words-list-"); + const copies = [ + "scripts/banned-words.js", + "scripts/lib/banned-words.js", + "scripts/oxlint-rules/no-banned-jsdoc-words.js", + "scripts/lint-architecture.js", + ]; + for (const file of copies) { + yield* ensureDir(path.dirname(path.join(directory, file))); + yield* copyFile(path.join(ROOT, file), path.join(directory, file)); + } + yield* writeTextFile(path.join(directory, "package.json"), '{"type":"module"}\n'); + yield* until( + symlink(path.join(ROOT, "node_modules"), path.join(directory, "node_modules"), "junction"), + ); + yield* writeTextFile( + path.join(directory, "plugin.js"), + [ + 'import { noBannedJsdocWords } from "./scripts/oxlint-rules/no-banned-jsdoc-words.js";', + 'export default { rules: { "no-banned-jsdoc-words": noBannedJsdocWords } };', + ].join("\n"), + ); + const config = path.join(directory, "oxlint.json"); + yield* writeTextFile( + config, + JSON.stringify({ + categories: { correctness: "off" }, + jsPlugins: [{ name: "local", specifier: "./plugin.js" }], + rules: { "local/no-banned-jsdoc-words": "error" }, + }), + ); + const source = yield* subject("/** jargonprobe */\nexport {};\n"); + const document = yield* subject("jargonprobe\n", "architecture.md"); + const script = path.join(directory, "scripts/lint-architecture.js"); + expect((yield* runOxlint(config, ["--format=json", source])).code).toBe(0); + expect((yield* architecture(document, script)).code).toBe(0); + + const list = path.join(directory, "scripts/banned-words.js"); + const original = yield* readTextFile(list); + yield* writeTextFile(list, original.replace("];", ' "JARGONPROBE",\n];')); + const linted = yield* runOxlint(config, ["--format=json", source]); + expect(linted.code).not.toBe(0); + expect(diagnostics(linted.stdout)[0].message).toContain("jargonprobe"); + expect((yield* architecture(document, script)).code).not.toBe(0); + }); +}); diff --git a/scripts/tests/oxlint-policy.test.ts b/scripts/tests/oxlint-policy.test.ts index 886e48dfe..aa0e9c16e 100644 --- a/scripts/tests/oxlint-policy.test.ts +++ b/scripts/tests/oxlint-policy.test.ts @@ -51,6 +51,7 @@ const DENIED = [ const GATE_RULES = [ "eslint/curly", + "local/no-banned-jsdoc-words", "local/no-module-scoped-registry", "local/no-section-divider-comments", "local/no-sync-filesystem", @@ -192,6 +193,22 @@ function parseReport(source: string, origin: string): Report { } describe("Oxlint policy", () => { + it("checks prose beyond packages/scripts without widening other rules or formatting", function* () { + const manifest = JSON.parse(yield* readTextFile(path.join(ROOT, "package.json"))); + expect(manifest.scripts.lint).toContain("oxlint -c .oxlint-prose.json site smoke-test"); + expect(manifest.scripts.lint).toContain("node scripts/lint-architecture.js"); + expect(manifest.scripts.lint).toContain("oxfmt --check packages scripts"); + const prose = yield* config(".oxlint-prose.json"); + expect(prose.rules).toEqual({ "local/no-banned-jsdoc-words": "error" }); + expect(prose.categories).toEqual({ correctness: "off" }); + const directory = yield* scratch("oxlint-prose-policy"); + const file = path.join(directory, "surface.ts"); + yield* writeTextFile(file, "export function probe() { if (true) return 1; }\n"); + expect((yield* runOxlint(".oxlint-prose.json", [file])).code).toBe(0); + yield* writeTextFile(file, "/** Claim */\nexport {};\n"); + expect((yield* runOxlint(".oxlint-prose.json", [file])).code).not.toBe(0); + }); + it("extends one canonical shared policy from both profiles", function* () { const gate = yield* config(GATE); const sensor = yield* config(SENSOR); From 6ebcceb22352a400d5694e150d3cdb5d04b19fcb Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Wed, 14 Oct 2026 07:50:13 -0400 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=A7=AA=20Keep=20banned-word=20regress?= =?UTF-8?q?ions=20in=20the=20existing=20policy=20suite?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/tests/banned-words.test.ts | 173 ---------------------------- scripts/tests/oxlint-policy.test.ts | 168 ++++++++++++++++++++++++++- 2 files changed, 167 insertions(+), 174 deletions(-) delete mode 100644 scripts/tests/banned-words.test.ts diff --git a/scripts/tests/banned-words.test.ts b/scripts/tests/banned-words.test.ts deleted file mode 100644 index a67e20d2b..000000000 --- a/scripts/tests/banned-words.test.ts +++ /dev/null @@ -1,173 +0,0 @@ -import { describe, it } from "@executablemd/test-support/bdd"; -import { expect } from "@executablemd/test-support/expect"; -import { copyFile, ensureDir, readTextFile, writeTextFile } from "@effectionx/fs"; -import { exec } from "@effectionx/process"; -import { until } from "effection"; -import type { Operation } from "effection"; -import { useTempDirectory } from "@executablemd/test-support/temp"; -import { symlink } from "node:fs/promises"; -import path from "node:path"; -import { ROOT, runOxlint } from "./oxlint.ts"; -import { BANNED_WORDS } from "../banned-words.js"; - -const RULE = "local(no-banned-jsdoc-words)"; - -interface Diagnostic { - code: string; - message: string; - filename: string; - labels: { span: { line: number; column: number; length: number; offset: number } }[]; -} - -function diagnostics(source: string): Diagnostic[] { - const report: { diagnostics: Diagnostic[] } = JSON.parse(source); - return report.diagnostics.filter((item) => item.code === RULE); -} - -function* subject(source: string, name = "subject.ts"): Operation { - const directory = yield* useTempDirectory("banned-words-"); - const file = path.join(directory, name); - yield* writeTextFile(file, source); - return file; -} - -function architecture(file: string, script = path.join(ROOT, "scripts/lint-architecture.js")) { - return exec("node", { arguments: [script, file], cwd: ROOT }).join(); -} - -describe("banned prose words", () => { - it("rejects every explicit variant through the repository Oxlint config", function* () { - const source = - BANNED_WORDS.map((word) => `/** ${word.toUpperCase()}. */`).join("\n") + "\nexport {};\n"; - const file = yield* subject(source); - const run = yield* runOxlint(".oxlintrc.json", ["--format=json", file]); - const found = diagnostics(run.stdout); - expect(run.code).not.toBe(0); - expect(found.map((item) => item.labels[0].span)).toEqual( - BANNED_WORDS.map((word, index) => ({ - line: index + 1, - column: 5, - length: word.length, - offset: source.indexOf(word.toUpperCase()), - })), - ); - expect(found.every((item) => item.filename === file)).toBe(true); - for (let index = 0; index < BANNED_WORDS.length; index++) { - expect(found[index].message).toContain(BANNED_WORDS[index].toUpperCase()); - } - }); - - it("maps multiline CRLF prose back to exact source columns", function* () { - const file = yield* subject( - "/**\r\n * Intro.\r\n * A CLAIM, then claimed.\r\n * @returns claims remain prose.\r\n */\r\nexport {};\r\n", - ); - const run = yield* runOxlint(".oxlintrc.json", ["--format=json", file]); - expect(diagnostics(run.stdout).map((item) => item.labels[0].span)).toEqual([ - { line: 3, column: 6, length: 5, offset: 21 }, - { line: 3, column: 18, length: 7, offset: 33 }, - { line: 4, column: 13, length: 6, offset: 55 }, - ]); - }); - - it("preserves code, annotations, other comments and containing words", function* () { - const file = yield* subject( - [ - "// claim claims", - "/* claim */", - 'export const claim = "claimed";', - "/** A disclaimer and claimsConfiguration remain ordinary names.", - " * Literal `claim(invocation)` and ``claims `claim` `` are references.", - " * {@link IdentityClaimant} and {@link claim|the operation} name code.", - " *", - " * ```ts", - ' * const claimed = "claim";', - " * ```", - " *", - ' * claim("claims");', - " *", - " * @param {IdentityClaimant} claim the callback", - " * @type {claim}", - " * @type {{", - ' * claim: "}",', - " * claimed: string", - " * }}", - " * @template Claim, Claimant", - " * @example", - ' * claim("claimed");', - " */", - "export function use(claim: unknown) { return claim; }", - ].join("\n"), - ); - const run = yield* runOxlint(".oxlintrc.json", ["--format=json", file]); - expect(diagnostics(run.stdout)).toEqual([]); - }); - - it("rejects architectural prose with locations while preserving Markdown code", function* () { - const bad = yield* subject("# Design\r\n\r\nA Claim remains.\r\n", "architecture.md"); - const rejected = yield* architecture(bad); - expect(rejected.code).not.toBe(0); - expect(rejected.stderr).toContain(`${bad}:3:3: forbidden prose word "Claim"`); - - const good = yield* subject( - [ - "# Design", - "A disclaimer beside `claim(carrier)`.", - "", - "```ts", - 'const claim = "claimed";', - "```", - "", - " reclaim();", - ].join("\n"), - "architecture.md", - ); - expect((yield* architecture(good)).code).toBe(0); - }); - - it("takes an added list entry through both consumers without shared mutation", function* () { - const directory = yield* useTempDirectory("banned-words-list-"); - const copies = [ - "scripts/banned-words.js", - "scripts/lib/banned-words.js", - "scripts/oxlint-rules/no-banned-jsdoc-words.js", - "scripts/lint-architecture.js", - ]; - for (const file of copies) { - yield* ensureDir(path.dirname(path.join(directory, file))); - yield* copyFile(path.join(ROOT, file), path.join(directory, file)); - } - yield* writeTextFile(path.join(directory, "package.json"), '{"type":"module"}\n'); - yield* until( - symlink(path.join(ROOT, "node_modules"), path.join(directory, "node_modules"), "junction"), - ); - yield* writeTextFile( - path.join(directory, "plugin.js"), - [ - 'import { noBannedJsdocWords } from "./scripts/oxlint-rules/no-banned-jsdoc-words.js";', - 'export default { rules: { "no-banned-jsdoc-words": noBannedJsdocWords } };', - ].join("\n"), - ); - const config = path.join(directory, "oxlint.json"); - yield* writeTextFile( - config, - JSON.stringify({ - categories: { correctness: "off" }, - jsPlugins: [{ name: "local", specifier: "./plugin.js" }], - rules: { "local/no-banned-jsdoc-words": "error" }, - }), - ); - const source = yield* subject("/** jargonprobe */\nexport {};\n"); - const document = yield* subject("jargonprobe\n", "architecture.md"); - const script = path.join(directory, "scripts/lint-architecture.js"); - expect((yield* runOxlint(config, ["--format=json", source])).code).toBe(0); - expect((yield* architecture(document, script)).code).toBe(0); - - const list = path.join(directory, "scripts/banned-words.js"); - const original = yield* readTextFile(list); - yield* writeTextFile(list, original.replace("];", ' "JARGONPROBE",\n];')); - const linted = yield* runOxlint(config, ["--format=json", source]); - expect(linted.code).not.toBe(0); - expect(diagnostics(linted.stdout)[0].message).toContain("jargonprobe"); - expect((yield* architecture(document, script)).code).not.toBe(0); - }); -}); diff --git a/scripts/tests/oxlint-policy.test.ts b/scripts/tests/oxlint-policy.test.ts index aa0e9c16e..17628c9e4 100644 --- a/scripts/tests/oxlint-policy.test.ts +++ b/scripts/tests/oxlint-policy.test.ts @@ -1,11 +1,15 @@ import { describe, it } from "@executablemd/test-support/bdd"; import { expect } from "@executablemd/test-support/expect"; -import { ensureDir, readTextFile, writeTextFile } from "@effectionx/fs"; +import { copyFile, ensureDir, readTextFile, writeTextFile } from "@effectionx/fs"; +import { exec } from "@effectionx/process"; +import { until } from "effection"; +import { symlink } from "node:fs/promises"; import type { Operation } from "effection"; import path from "node:path"; import { useTempDirectory } from "@executablemd/test-support/temp"; import { ROOT, runOxlint } from "./oxlint.ts"; +import { BANNED_WORDS } from "../banned-words.js"; import { categorizeRule, SENSOR_RULES, @@ -443,3 +447,165 @@ describe("Oxlint policy", () => { expect(output).not.toContain('"rules"'); }); }); + +const RULE = "local(no-banned-jsdoc-words)"; + +interface Diagnostic { + code: string; + message: string; + filename: string; + labels: { span: { line: number; column: number; length: number; offset: number } }[]; +} + +function diagnostics(source: string): Diagnostic[] { + const report: { diagnostics: Diagnostic[] } = JSON.parse(source); + return report.diagnostics.filter((item) => item.code === RULE); +} + +function* subject(source: string, name = "subject.ts"): Operation { + const directory = yield* useTempDirectory("banned-words-"); + const file = path.join(directory, name); + yield* writeTextFile(file, source); + return file; +} + +function architecture(file: string, script = path.join(ROOT, "scripts/lint-architecture.js")) { + return exec("node", { arguments: [script, file], cwd: ROOT }).join(); +} + +describe("banned prose words", () => { + it("rejects every explicit variant through the repository Oxlint config", function* () { + const source = + BANNED_WORDS.map((word) => `/** ${word.toUpperCase()}. */`).join("\n") + "\nexport {};\n"; + const file = yield* subject(source); + const run = yield* runOxlint(".oxlintrc.json", ["--format=json", file]); + const found = diagnostics(run.stdout); + expect(run.code).not.toBe(0); + expect(found.map((item) => item.labels[0].span)).toEqual( + BANNED_WORDS.map((word, index) => ({ + line: index + 1, + column: 5, + length: word.length, + offset: source.indexOf(word.toUpperCase()), + })), + ); + expect(found.every((item) => item.filename === file)).toBe(true); + for (let index = 0; index < BANNED_WORDS.length; index++) { + expect(found[index].message).toContain(BANNED_WORDS[index].toUpperCase()); + } + }); + + it("maps multiline CRLF prose back to exact source columns", function* () { + const file = yield* subject( + "/**\r\n * Intro.\r\n * A CLAIM, then claimed.\r\n * @returns claims remain prose.\r\n */\r\nexport {};\r\n", + ); + const run = yield* runOxlint(".oxlintrc.json", ["--format=json", file]); + expect(diagnostics(run.stdout).map((item) => item.labels[0].span)).toEqual([ + { line: 3, column: 6, length: 5, offset: 21 }, + { line: 3, column: 18, length: 7, offset: 33 }, + { line: 4, column: 13, length: 6, offset: 55 }, + ]); + }); + + it("preserves code, annotations, other comments and containing words", function* () { + const file = yield* subject( + [ + "// claim claims", + "/* claim */", + 'export const claim = "claimed";', + "/** A disclaimer and claimsConfiguration remain ordinary names.", + " * Literal `claim(invocation)` and ``claims `claim` `` are references.", + " * {@link IdentityClaimant} and {@link claim|the operation} name code.", + " *", + " * ```ts", + ' * const claimed = "claim";', + " * ```", + " *", + ' * claim("claims");', + " *", + " * @param {IdentityClaimant} claim the callback", + " * @type {claim}", + " * @type {{", + ' * claim: "}",', + " * claimed: string", + " * }}", + " * @template Claim, Claimant", + " * @example", + ' * claim("claimed");', + " */", + "export function use(claim: unknown) { return claim; }", + ].join("\n"), + ); + const run = yield* runOxlint(".oxlintrc.json", ["--format=json", file]); + expect(diagnostics(run.stdout)).toEqual([]); + }); + + it("rejects architectural prose with locations while preserving Markdown code", function* () { + const bad = yield* subject("# Design\r\n\r\nA Claim remains.\r\n", "architecture.md"); + const rejected = yield* architecture(bad); + expect(rejected.code).not.toBe(0); + expect(rejected.stderr).toContain(`${bad}:3:3: forbidden prose word "Claim"`); + + const good = yield* subject( + [ + "# Design", + "A disclaimer beside `claim(carrier)`.", + "", + "```ts", + 'const claim = "claimed";', + "```", + "", + " reclaim();", + ].join("\n"), + "architecture.md", + ); + expect((yield* architecture(good)).code).toBe(0); + }); + + it("takes an added list entry through both consumers without shared mutation", function* () { + const directory = yield* useTempDirectory("banned-words-list-"); + const copies = [ + "scripts/banned-words.js", + "scripts/lib/banned-words.js", + "scripts/oxlint-rules/no-banned-jsdoc-words.js", + "scripts/lint-architecture.js", + ]; + for (const file of copies) { + yield* ensureDir(path.dirname(path.join(directory, file))); + yield* copyFile(path.join(ROOT, file), path.join(directory, file)); + } + yield* writeTextFile(path.join(directory, "package.json"), '{"type":"module"}\n'); + yield* until( + symlink(path.join(ROOT, "node_modules"), path.join(directory, "node_modules"), "junction"), + ); + yield* writeTextFile( + path.join(directory, "plugin.js"), + [ + 'import { noBannedJsdocWords } from "./scripts/oxlint-rules/no-banned-jsdoc-words.js";', + 'export default { rules: { "no-banned-jsdoc-words": noBannedJsdocWords } };', + ].join("\n"), + ); + const config = path.join(directory, "oxlint.json"); + yield* writeTextFile( + config, + JSON.stringify({ + categories: { correctness: "off" }, + jsPlugins: [{ name: "local", specifier: "./plugin.js" }], + rules: { "local/no-banned-jsdoc-words": "error" }, + }), + ); + const source = yield* subject("/** jargonprobe */\nexport {};\n"); + const document = yield* subject("jargonprobe\n", "architecture.md"); + const script = path.join(directory, "scripts/lint-architecture.js"); + expect((yield* runOxlint(config, ["--format=json", source])).code).toBe(0); + expect((yield* architecture(document, script)).code).toBe(0); + + const list = path.join(directory, "scripts/banned-words.js"); + const original = yield* readTextFile(list); + yield* writeTextFile(list, original.replace("];", ' "JARGONPROBE",\n];')); + const linted = yield* runOxlint(config, ["--format=json", source]); + expect(linted.code).not.toBe(0); + expect(diagnostics(linted.stdout)[0].message).toContain("jargonprobe"); + expect((yield* architecture(document, script)).code).not.toBe(0); + }); +});