Conversation
`<All>` runs its direct `<Spawn>` children at the same time and waits for all of them. Both names are engine structural syntax, so no repository file, registration, bundle or Plugin can supply either, and they work in ordinary and admitted generated XMD alike. One shared pure rule decides the whole structure from source — paired forms, no props, at least two spawns, blank text only between them, no `<Spawn>` outside its `<All>`, and no `<Return>` or `<Break>` reaching past a spawn — and expansion, non-executing validation and the whole-fragment preflight read the same result, so a malformed construct starts no child anywhere. Each child is a durable coroutine of the one that reached the `<All>`, allocated in source order by the existing `durableAll()` join, with its own binding environment, live overlay, eval scope, block counter, output buffer, failure ledger, hide set and expansion path. Nothing merges back. `<All>` appends the renderings in authored order only after every child succeeds, so completion order may decide when records append and never what the document renders. The first failure cancels and joins the rest, publishes nothing, and fabricates no completion. Capability-backed identity becomes branch-local, which is what the Story's own `<All><Spawn><Session>` example needs. Canonical import frames and provider answer windows were kept as one execution-wide last-open stack, so two children resolving at once could have one child's selection land in the other's frame — an ordinary `<Session>` in each branch then named no durable identity at all. Both stacks are now owned per Effection scope: nesting inside one scope still hides its parent until it closes, sibling branches have independent tops, closing or cancelling one neither clears nor authorizes the other, and a provider installation may answer in two open windows while a second, different answer in either still refuses. The scope is a private key and reaches no document, component or provider. `All` and `Spawn` join the two frozen complete structural-vocabulary expectations, which is what failed the earlier weights run.
The artifact of run 36473005680, unchanged. `<All>` and `<Spawn>` add one test file and change what several others run, and a weight is only true of the runner that measured it.
`toSorted()` is ES2023 and the Node typecheck targets ES2022, so two rows of the `<All>` suite failed every `test-node` shard while Deno and Bun passed. `sort()` on the array `map` just made is the convention this repository already documents in `scripts/lib/verify.ts` and Git's remote-composition proof.
taras
force-pushed
the
agent/all-spawns
branch
from
September 28, 2026 22:34
f46cb57 to
37c4cea
Compare
…ced spawn once Three corrections to the reviewed `<All>` delivery. A claim was keyed by the answer object alone, which made the first resolution part of that object's permanent identity. A provider that owns one immutable definition and hands it to every import it answers was refused the second time — punished for not copying itself. The key is now the pair of answer and resolution window: what an object *is* stays settled by its first claim, so it cannot be renamed, re-originated or taken by another installation, while which import it answered is recorded per window. Each window keeps its own retained copy, so `identify()` still answers only for the window that claimed, and a second *different* answer in a window already spent still refuses. Reuse is of the definition, not merely of the reference. The first claim retains core's copy as the baseline the stated identity describes, and a later window may answer with that object only while it still describes it — so a provider cannot claim a definition, edit it, and have the next import record the edited one under the revision that described the original. An answer core could never retain does not become claimable because it changed. A `<Spawn>` written below an `<All>` but not directly inside it was reported twice during non-executing validation: once by the `<All>`'s own structure walk, which anchors the diagnostic at the misplaced element, and again by the element's own rule, whose guard only knew its immediate parent. The element's rule now owns exactly one case — a `<Spawn>` with no `<All>` above it at all — and the walk owns every other. And the vocabulary: work owned by a `<Spawn>` is a spawn, a spawned child, sibling spawns, spawned concurrency. It was described as branching, which is what an `<If>` arm and a `<Case>` are. Established meanings elsewhere are untouched.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A document could not run two pieces of work at the same time. Everything a
document does is sequential, so two
<Session>conversations, two long reads ortwo independent sub-documents run one after another even when neither needs the
other's result. #827's agent sessions need concurrent work, and #854's REPL needs
two live conversations at once, so this is the structural primitive they are
both waiting on.
What changes
Before:
Two conversations, one after the other. Nothing in the language can say they are
independent.
After:
Both run at the same time.
<All>waits for every<Spawn>child and renderstheir Markdown in authored order even when they finish in another order, so
the document reads the same however the work interleaved.
Each
<Spawn>is its own child: bindings made in one stay in it, and a<Return>or
<Break>inside one cannot target work outside it. A<Spawn>anywhere butdirectly inside
<All>is refused before the document runs, and so is an<All>with fewer than two
<Spawn>children.Under a durable run the children are joined through
durableAll(), so each childis a coroutine of its own in the Journal and a replay resumes them the same way.
How it works
Two identity mechanisms had to stop being execution-wide for this to work at
all, because concurrent children resolve components at the same time:
invocation-identity.ts) are now one LIFO stack perEffection scope rather than one per execution. Two children importing at once
no longer see each other's frame.
component-resolution.ts) are likewise per scope, anda provider's issuance is spent against the window that asked for it rather than
against whatever window happened to be innermost.
Both were found by measurement: two ordinary
<Session>invocations under<All>failed with
ComponentInvocationErroruntil ownership followed the scope.Review guide
Start with:
packages/core/tests/all.test.tsThen review:
packages/core/src/structural.tsandstructural-rules.ts— what the syntaxis, and what is refused before anything runs
packages/core/src/expand.ts—expandAll(),spawnChild(),spawnEnvironment(), and the live/durable joinpackages/core/src/invocation-identity.tsandcomponents/component-resolution.ts— per-scope ownershipspecs/executable-mdx-spec.mdandarchitecture.mdLook carefully at:
rendered output is authored order in both the live and the durable path.
<Return>/<Break>and its bindings stop at its ownboundary.
What must stay true
<All>renders in authored order — enforced by collecting each child's resultpositionally and checked by ALL6 and the
<All>-of-<Session>rows.<Spawn>outside<All>is a document error, not a runtime one — enforced byspawnElementViolations()/misplacedSpawnViolations()and checked inall.test.ts.and windows, checked by the concurrent rows in
answer-identity.test.tsandinvocation-identity.test.ts.syntax-catalog.test.tsSY4cand
syntax-cli.test.tsSX2b now includeAllandSpawn.How to verify it
deno task test packages/core/tests/all.test.tsproves the syntax, therefusals, isolation, ordering and the durable join, and fails if a child's
bindings escape or output follows finishing order.
their own answer, and fail if a frame or window is shared — which is exactly
what happened before this change.
Scope
Included
<All>/<Spawn>syntax, validation, expansion and durable jointest-weights.jsonfrom run 36473005680 atb14a2ba1Intentionally unchanged
already does: a child's failure raises into its owner as any task does.
<All>is not an iteration construct;<Loop>is unchanged.Generated or mechanical changes
test-weights.jsonis the artifact of Measure test weights run36473005680 at
b14a2ba1, committed unchanged. Nothing was hand-edited, and noshard recalibration is included.
Risks and limitations
It is targeted at
agent/issue-854-projectionso the diff here is Run spawned document work concurrently with<All>#855's ownwork; once ✨ Slice A of #854: retain a safe Agent permission audit and project Agent conversations #857 merges, this branch is rebased onto updated
main, its focuseddelivery evidence re-run, and this PR retargeted to
main. It closes Run spawned document work concurrently with<All>#855only — Run a Plan and follow its Agent sessions in the REPL #854 stays open.
Scope confirmation
Closes #855