@plurnk/plurnk-contracts 1.21.1 → 1.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/SPEC.md CHANGED
@@ -11,7 +11,7 @@ runtime-neutral wire envelopes; `@plurnk/plurnk-parser` implements the language
11
11
  | ------------------------------------------------------------------------------- | --------------------------------------------------- |
12
12
  | AST, validators, Problems, results, Notices, text regions and extents | `@plurnk/plurnk-contracts` |
13
13
  | Capability and loop policies | `CapabilityPolicy`, `LoopPolicy`, `LoopPolicyRequest`, `PROPOSAL_POLICIES` |
14
- | Durable reasoning intent | `ReasoningPolicy`, `REASONING_POLICIES` |
14
+ | Durable effort | `Effort`, `EFFORTS` |
15
15
  | Model route and catalog discovery | `ModelRoute`, `ModelCatalogQuery`, `ModelCatalogPage`, `ModelReadiness` |
16
16
  | Stopped-world client contract | `ProposalDisposition`, `ProposalProjection` |
17
17
  | Client-owned interaction contract | `ClientInteractionRequest`, `ClientInteractionProjection`, `ClientInteractionResolution` |
@@ -177,7 +177,7 @@ Contracts hold no default for the rest: the daemon's panel supplies it
177
177
  vocabulary of `proposals`. Capability admission precedes effect
178
178
  classification and proposal settlement.
179
179
 
180
- §reasoning-policy-wire `ReasoningPolicy` is exactly `off | adaptive | low |
180
+ §effort-wire `Effort` is exactly `off | adaptive | low |
181
181
  medium | high`. The schema owns this shared wire vocabulary. Providers own the
182
182
  supported subset and native projection for a selected route; core owns the
183
183
  durable worker value.
@@ -190,8 +190,8 @@ physical limits, capabilities, and local `ModelReadiness`. A readiness cause
190
190
  contains alternative environment-variable sets—every name within a set is
191
191
  required and any set may satisfy the cause. It carries names only, never values,
192
192
  and asserts neither credential validity nor endpoint reachability.
193
- `capabilities.reasoningPolicies` lists the route's admitted members of
194
- {§reasoning-policy-wire}, including supported activation policies; clients do
193
+ `capabilities.efforts` lists the route's admitted members of
194
+ {§effort-wire}, including supported activation policies; clients do
195
195
  not infer fixed efforts from the `reasoning` capability bit. It is not a
196
196
  worker's model/spawn intersection or an alias-specific tuning projection.
197
197
 
@@ -273,26 +273,21 @@ convention and never demanded ({§fence-closer}, {§closer-fallback}). There are
273
273
  operation suffixes or heading levels. Complete nested matches take precedence
274
274
  over local recovery ({§balanced-fences}).
275
275
 
276
- §fence-closer A block opened with N backticks closes at the first unclaimed line made of
277
- at least N backticks and nothing else but horizontal whitespace, within three spaces of
278
- its line start ({§indented-fences}). Count follows CommonMark: a shorter fence inside the
279
- body is body; an equal or longer bare fence closes the block unless {§balanced-fences}
280
- claims it for a nested block. The compact one-line form closes on its heading line after
281
- the modifiers under the same rule.
276
+ §fence-closer A block opened with N backticks closes at a line made of at least N backticks and
277
+ nothing else but horizontal whitespace, within three spaces of its line start
278
+ ({§indented-fences}). Count follows CommonMark: a shorter fence inside the body is body; an equal
279
+ or longer bare fence may close the block or open a nested one, and {§fence-pairing} decides
280
+ which. The compact one-line form closes on its heading line after the modifiers under the same
281
+ rule.
282
282
 
283
283
  §balanced-fences A complete nested interpretation takes precedence over missing-closer
284
- recovery. Within a body, line-leading labeled fences open literal blocks. A bare fence
285
- closes the innermost open block of exactly its width, otherwise the outermost open block
286
- narrower than it; the narrower blocks it steps over are literal body, and a wider or
287
- differently fenced block inside stops it. So a wider outer fence holds any narrower body,
288
- finished or not, and equal widths nest when every inner block closes. The enclosing block
289
- and its nested blocks must all
290
- close under {§fence-closer}; equal opener/closer totals alone are insufficient, and a
291
- complete inline block is already closed. Preserve every nested body byte, including
292
- apparent OPs and known executors, without dispatching them. If no complete enclosing
293
- interpretation exists, retain {§fence-heading-in-body} and {§closer-fallback}. These
294
- rules apply equally to model programs, stored programs, client operations, and
295
- reasoning quotations.
284
+ recovery. Within a body, a line-leading labeled fence opens a literal block, and an equal or
285
+ wider bare fence nests where closing there would cost the reading more
286
+ ({§fence-pairing}). A nested block ends at its first valid closer, as a CommonMark code block
287
+ does. So a wider outer fence holds any narrower body, finished or not, and equal widths nest
288
+ when every inner block closes. Preserve every nested body byte, including apparent operations
289
+ and known executors, without dispatching them. These rules apply equally to model programs,
290
+ stored programs, client operations, and reasoning quotations.
296
291
 
297
292
  §operation-fences **Accept three or more backticks; teach and render three.** A line-start fence
298
293
  of three or more backticks naming a native operation or registered executor opens that
@@ -311,48 +306,176 @@ horizontal whitespace after it, opens that operation as if it were fenced with t
311
306
  backticks: no target, no modifiers, and a body that runs to a line that is exactly the name
312
307
  again, to the next heading ({§fence-heading-in-body}), or to the end of the turn. A fence inside
313
308
  naming nothing known is body; the block expects no closer, so its body is never cut
314
- back ({§closer-fallback}). It runs, and one warning-severity receipt follows its statement —
309
+ back ({§closer-fallback}). A naked `KILL` alone holds every fence inside it as text ({§naked-kill}). It runs, and one warning-severity receipt follows its statement —
315
310
  `` `KILL` opened with no fence; the taught form is three backticks. `` One rule for every native
316
311
  operation: a naked `WAIT` parks, a naked `NOTE` takes its text, a naked `READ` meets the ordinary
317
- missing-target refusal. Only the bare name qualifies; a name with anything else on its line is
312
+ missing-target refusal. A closer the author wrote anyway is still not body: when the body's last line is
313
+ a bare backtick fence that no other fence line in the body pairs with (an odd count of fence lines), that
314
+ line is the block's closer and leaves the body, so `KILL`, then the answer, then a closing fence delivers
315
+ the answer alone. Only the bare name qualifies; a name with anything else on its line is
318
316
  the unfenced form and still refuses ({§unfenced-operation}), executors are runtimes rather than
319
- operations, and reasoning is never read this way. Measured before it was accepted (2026-09-22):
320
- 48 naked `KILL` lines in 9,196 recorded emissions, every one followed by the deliverable, and
321
- three loops lost to the refusal at the strike threshold.
317
+ operations, and reasoning is never read this way. In 9,196 recorded emissions, all 48 naked
318
+ `KILL` lines were followed by the deliverable.
322
319
 
323
320
  §fence-heading-in-body Outside a complete nested block ({§balanced-fences}), a fence
324
321
  line of three or more backticks and a name that is a native operation or a known executor
325
- is a heading. Inside an open block of any width it ends that block without closing it
326
- ({§closer-fallback}) and opens the next statement: a wider fence holds the narrower headings
327
- inside it only while it closes ({§balanced-fences}). Fence lines of fewer than three
328
- backticks are never headings ({§operation-fences}). Known executors are `sh` plus what
329
- the host names in `ParseOptions.executors`. Consequences: a closer glued to the next opener
330
- (six backticks then `READ`) can never swallow an unbalanced turn, and no unclosed block, however
331
- wide, swallows the operations after it.
332
-
333
- §closer-fallback A block that ends at a heading or at the end of the input has no
334
- closer of its own. Its body is cut back to its last bare fence line (any count, within
335
- three spaces of its line start), which is the closer the author meant, and one terminating line
336
- ending goes with it; when no bare fence line exists the body is the whole span less
337
- one terminating line ending. This carries no diagnostic: a missing closer is never
338
- an admission failure, and {§unparsed-tail-boundary} is not involved.
322
+ is a heading. Inside an open block it either ends that block without closing it and opens the
323
+ next statement, or it is a literal example held by the block; the block holds it only while
324
+ the block ends at a real closer, and {§fence-pairing} chooses between the two. Fence lines of
325
+ fewer than three backticks are never headings ({§operation-fences}). Known executors are `sh`
326
+ plus what the host names in `ParseOptions.executors`. Inside a parameterless `KILL` a
327
+ heading never ends the block ({§terminal-kill}).
328
+
329
+ §closer-fallback A block that ends at a heading or at the end of the input has no closer of its
330
+ own; its body is the whole span less one terminating line ending. Where a same-character fence
331
+ narrower than an outermost block stands where its closer belongs, {§fence-pairing} may read it
332
+ as that closer, at the cost of one repair; an unclosed EDIT yields to the native heading after it
333
+ ({§unclosed-mutation-yields}). This carries no diagnostic: a missing closer is
334
+ never an admission failure, and {§unparsed-tail-boundary} is not involved.
339
335
 
340
336
  `plurnk.md` shows every operation closed; this recovery is not taught. It sits at the quiet end of
341
- the scale {§response-text-note} describes: the model opened the operation correctly
337
+ the scale {§outside-text} describes: the model opened the operation correctly
342
338
  and only failed to close it, so the harness reads what it plainly meant and says nothing.
343
339
  A departure that small earns no correction — telling a model its closer was missing costs
344
340
  a sentence in every future packet to fix something already fixed.
345
341
 
346
- §fence-boundary Balanced nesting is resolved before local recovery. Otherwise,
347
- fences are read by count, except for the heading rule above:
342
+ §fence-boundary Every fence line inside a body takes one of these meanings, chosen for the whole
343
+ input at once by {§fence-pairing}:
348
344
 
349
345
  | Fence encountered inside a body | Meaning |
350
346
  |---|---|
351
- | Part of a complete nested block | Literal body, including its openers and closers |
352
347
  | Indented four spaces or more, or by a tab | Body ({§indented-fences}) |
353
- | Fewer backticks than the block's own | Body |
354
- | At least the block's backticks, bare | The block's closer |
355
- | Three or more backticks naming a native operation or known executor | A heading: ends the block, opens the next statement |
348
+ | Fewer backticks than the block's own, or another character | Body, or the opener of a nested block |
349
+ | At least the block's backticks, bare | The block's closer, or the opener of a nested block |
350
+ | Labeled, naming nothing known | The opener of a nested block, or body |
351
+ | Three or more backticks naming a native operation or known executor | A heading that ends the block, or a literal example |
352
+
353
+ ### §fence-pairing Fence pairing
354
+
355
+ A whole-input pass, `FencePairing`, decides where every block ends before the lexer reads a
356
+ token; the lexer's semantic predicates consult its decision, and ANTLR keeps framing, slots and
357
+ statement composition ({§parser-architecture}). The pass is a least-cost parse of the fence
358
+ lines as a bracket language, in the manner of Aho and Peterson's least-errors parser
359
+ (SIAM J. Comput. 1(4), 1972): every reading of the fences is a derivation, and the pass returns
360
+ the cheapest.
361
+
362
+ §pairing-need **Why a pass ahead of the grammar.** Whether a bare fence closes a block or opens a
363
+ nested one depends on every fence after it, unboundedly. Measured on 10,486 distinct recorded
364
+ emissions:
365
+
366
+ | Alternative | Result |
367
+ |---|---|
368
+ | The fence structure as an ANTLR grammar under SLL prediction | 10,000 accepted, 0.2 ms mean; 486 not: 119 valid only under full LL, 243 needing repair, 113 unrepairable |
369
+ | The same grammar under full LL | A 267 KB packet echo took 4.8 s. Full-context results are not cached: the runtime records that caching them "was slower than interpreting and much more complicated" (`ParserATNSimulator`) |
370
+ | ANTLR's error recovery for the 356 that need repair | `DefaultErrorStrategy` repairs only at the point of detection, by single-token insertion or deletion; it has no least-cost repair over the input |
371
+ | Nongreedy lexer loops | A lexer decision is local, not "globally correct" (ANTLR `doc/wildcard.md`), so a nongreedy body ends at the first closer even when a later one is the block's |
372
+ | CommonMark's rule alone | The first closer of sufficient width closes (CommonMark 0.31.2 §4.5), and CommonMark declines to backtrack because it "would require backtracking… much less efficient". It cuts 110 recorded bodies at an inner bare block |
373
+ | A budgeted depth-first search over stacks | Exhausted its step budget on 20 recorded emissions of 188 to 3,501 fence lines |
374
+
375
+ The ALL(*) paper (Parr, Harwell, Fisher, OOPSLA 2014) states the limits relied on here: SLL either
376
+ behaves like LL or reports an error (Theorem 6.5, §3.2), and an ambiguity resolves to the lowest
377
+ alternative (§4.2), so neither mode chooses among complete readings by cost. The grammars-v4
378
+ Python (`INDENT`/`DEDENT`) and PHP (heredoc) grammars settle block structure the same way:
379
+ outside the grammar, then hand the lexer tokens.
380
+
381
+ §pairing-algorithm **Algorithm.** Each line is classified by the lexer's line-start rules: text, a
382
+ bare fence, a labeled fence, a heading, a closer glued to a heading, or a naked operation name.
383
+ A block's contents read the same whatever lies beneath it on the stack, so the pass summarizes
384
+ each (position, block, what the block holds so far) once. For a nested block, the summary maps
385
+ every place the block could end to its cheapest reading up to there; parents compose their
386
+ children's summaries. An outermost block is evaluated in the root's frame, where only the cost
387
+ to the end of the input matters, so it holds one entry. Evaluation runs on an explicit work
388
+ stack. Candidates are taken in preference order and replace one another only by costing
389
+ strictly less, so each entry is the reading a preference-ordered exhaustive search returns.
390
+ Inside a quotation or a nested block the first valid closer closes, CommonMark's rule, applied
391
+ as a disambiguation filter (Klint and Visser, 1994); an operation body keeps the choice between
392
+ nesting and closing. A block opened by a bare fence must hold a line, except a quotation at the
393
+ top level: two stray fences in a row there are an empty quotation, shown and harmless, rather
394
+ than two repairs that a reading could avoid only by hiding an operation.
395
+
396
+ §pairing-objective **Objective.** A complete reading, one that needs no repair, wins over every
397
+ repaired reading: a complete nested interpretation takes precedence. Each class has its own order.
398
+
399
+ | Counted | Complete readings | Repaired readings | Why |
400
+ |---|---|---|---|
401
+ | Hidden operations: a heading that will not run, written at its block's width or wider | 1, together with the next row | 1 | Every operation the author wrote should run |
402
+ | Repairs: a supplied closer (except a message's run to the end of the input, {§message-run-on}), a fence read as a stray, a narrower closer accepted, a body under an operation that takes none (FIND, READ, COPY, MOVE, targeted KILL), a body not well-formed in the media type its runtime declares ({§executor-invocation}) | none by definition | 2 | The least-errors distance |
403
+ | Literal by declaration: a heading narrower than its block, or no wider than the labeled block or example holding it, or inside a quotation or a KILL, or an executor heading inside a SEND, WORK, FORK or BARE body ({§prose-code-blocks}); a labeled fence in a body read as text | 1, together with the row above | 3 | Every code block the author declared should stand |
404
+ | Supplied closers | 2 | 4 | A block the author opened should end at a fence the author wrote |
405
+ | Other fences read as text | 3 | 5 | The least departure from the fences as written |
406
+
407
+ Complete readings compare exactly as a single least-errors order would. Once every reading of an
408
+ emission needs a repair, its shape is already broken, and saving a repair is not worth an operation
409
+ the author wrote: across the corpus, readings that traded operations for repairs held a WORK in a
410
+ BARE behind two stray fences, wrote 11,485 characters of operation text into a file as an EDIT
411
+ body, and ended a turn's KILL inside a WAIT. A summary keeps, for every place a block could end, the
412
+ best complete reading under each order and the best repaired reading, so the search stays exact:
413
+ a repaired total may take either class for any of its parts.
414
+
415
+ §unclosed-mutation-yields **A mutation body never swallows a native operation.** An example
416
+ inside an EDIT is written with a wider outer fence ({§operation-fences}); a heading narrower than
417
+ the EDIT's fence is literal by declaration and stays text. At the EDIT's own width a native
418
+ operation heading runs, closed or not: read as the body's example it would be a *swallowed*
419
+ operation, and a swallowed operation outranks any number of repairs — a reading that swallows one
420
+ is never complete, and among repaired readings the fewest swallowed wins before every other class.
421
+ So where ```` ```EDIT (b.py) ```` follows ```` ```EDIT (a.py) ```` with no closer between, the
422
+ reading that supplies `a.py`'s closer before that heading wins, both EDITs run, and no operation
423
+ heading is written into a file; the same shape with a closer after the example is fence-identical
424
+ and reads the same way. Of 67 recorded EDIT bodies holding a native heading, 66 use the wider fence
425
+ and read unchanged, and the one at equal width (glm run158) had written a test EDIT's heading and
426
+ body into `functional.py` and never run it. Only EDIT mutates from its body, so only EDIT carries
427
+ the rule: an executor heading inside an EDIT keeps the ordinary reading, and SEND, WORK, FORK and
428
+ BARE bodies keep {§prose-code-blocks}.
429
+
430
+ Equal cost goes to the earlier alternative: nesting before closing in an operation body,
431
+ closing before nesting in a quotation, and a supplied closer before a literal example at a
432
+ heading. An operation example quoted in a body of its own width therefore reads as the body
433
+ closing and the example running; the wider outer fence or the tab offset quotes it
434
+ ({§operation-fences}).
435
+
436
+ §terminal-kill **A KILL body is the deliverable.** Inside a parameterless `KILL`, at any depth, a
437
+ heading is a literal example or text and never ends the block; the block ends at its closer or
438
+ the end of the input. Of 796 recorded parameterless KILLs, 9 were followed by any other
439
+ operation, while 62 of 120 SENDs were, so the rule is KILL's alone. It keeps a final report whole
440
+ and never runs a command the report only shows.
441
+
442
+ §prose-code-blocks **A message or a prompt shows code.** Inside a `SEND`, `WORK`, `FORK` or `BARE`
443
+ body, at any depth, a heading that names an executor (` ```sh `, ` ```python3 `) is a code block the
444
+ text shows, exactly as under {§terminal-kill}: it never ends the block and never runs. A native
445
+ operation's heading still ends such a block, since a message is often followed by the author's next
446
+ operation. In the distinct recorded benchmark emissions an executor heading ended an unclosed
447
+ `WORK` body 14 times, a `BARE` body 9 times and a `SEND` body twice; every one inspected (qflash
448
+ run218, run114 and run118, deepdumb run44) was the child's task, the prompt's code or code quoted in
449
+ a report, and reading it as an operation truncated the task and ran the example in the parent.
450
+
451
+ §message-run-on **A message runs to the end of the turn.** A parameterless `KILL`, or a `SEND`,
452
+ `WORK`, `FORK` or `BARE`, whose block reaches the end of the input without its closer takes it
453
+ there with no repair: the text after its last inner block is still the deliverable, the message
454
+ or the task, never outside text. The run counts as a supplied closer, so a reading that closes at
455
+ a real fence still wins, and it never costs an operation: when the reading that runs on hides more
456
+ operations the author wrote than the best repaired reading, the repaired reading stands. Across the
457
+ 11,235 distinct recorded benchmark emissions this changes 26 readings: bodies that had ended at an
458
+ inner fence keep what followed it (the qflash run192, run90 and run210 deliverables regain their last
459
+ sections), one echoed transcript (glm run155) runs one more operation, and none loses one.
460
+
461
+ §naked-kill **A naked KILL is the whole rest of the turn.** A parameterless `KILL` opened by its
462
+ name alone ({§naked-operation}) is a completion, and nothing can follow a completion: every fenced
463
+ block inside it, a native operation heading included, is text the deliverable shows, exactly as
464
+ inside a fenced KILL ({§terminal-kill}), and the block ends only at its name alone on a line or at
465
+ the end of the input. No operation the deliverable shows runs. In the rtx5070 demo
466
+ `demo-show-dont-run-sJU8zO` the model, asked to show a deletion without doing it, answered with a
467
+ naked `KILL` whose deliverable quoted ```` ```KILL (notes.md) ````; read as a heading that ended
468
+ the deliverable, the quoted KILL ran and deleted the file. The fenced form of the same answer had
469
+ already read as quotation; this rule makes the two forms one.
470
+
471
+ §pairing-witness **Witnesses.**
472
+
473
+ | Witness | Result |
474
+ |---|---|
475
+ | Every input up to six lines over eleven line shapes, against a forward exhaustive search over explicit stacks under the same moves and class orders | 1,948,716 inputs, 0 differences in chosen cost; the same harness reports 37 differences at four lines when a summary keeps one entry per end regardless of class |
476
+ | The generated matrix: six operations × widths 3–5 × twelve body shapes × four tails | 864 of 864 (`fence-matrix.test.ts`); the four `EDIT · outer 3 · labeled quoted operation` cells read the example as an operation ({§unclosed-mutation-yields}), and in the `next operation` cell the EDIT's written closer, now a stray top-level fence, quotes the operation after it ({§quotation}) |
477
+ | 10,486 recorded emissions | All parse; 0.9 ms mean, 267 ms at most (3,501 fence lines). The work is polynomial in fence lines, cubic at worst, so no step bound is needed |
478
+ | The same, against the single-order objective | 10,466 identical; 19 read more operations, where headings follow unclosed blocks or a closer is glued to the next opener; 1 echoed transcript reads a different operation; none reads fewer |
356
479
 
357
480
  §indented-fences **CommonMark's indentation, everywhere.** A fence line may follow at most three
358
481
  spaces; four or more, or a tab, make it indented code. That one rule reads every fence purpose the
@@ -360,9 +483,8 @@ same way: an opener within three spaces opens, a closer within three closes, a h
360
483
  three ends an unclosed block, and a body keeps its own lines' indentation. A fence indented
361
484
  further is literal wherever it stands — prose outside a block, body inside one — and draws no
362
485
  advisory: `plurnk.md` shows its own examples offset, so an offset fence is the page's own form
363
- and there is no mistake to report (operator, 2026-09-21). The parser presumes nothing about why a fence is offset. This one
364
- rule replaces the column-zero opener (operator, 2026-09-18) and the lenient closer beside it
365
- (operator, 2026-09-23). Outside an operation, offset text is response text under
486
+ and there is no mistake to report. The parser presumes nothing about why a fence is offset.
487
+ Outside an operation, offset text is response text under
366
488
  {§response-text}; inside a body, it stays literal body content.
367
489
 
368
490
  §inline-chain A closer on a heading line, or on a body's closing line, may be
@@ -380,15 +502,13 @@ The closer is still a closer: the block ends with that physical line and never r
380
502
  the next operation, which is what a bare heading carrying a matcher would do. A closer followed
381
503
  by the next opener is {§inline-chain}, and by nothing is the ordinary {§fence-closer}. There is
382
504
  no ambiguity to resolve: a slot begins with `<` or `[` and an opener with a backtick run, so the
383
- shapes are disjoint (operator, 2026-09-13: "If there is no risk of ambiguity, then we add
384
- tolerance. Turning model soup into operations instead of errors is a cardinal imperative").
505
+ shapes are disjoint.
385
506
 
386
507
  §executor-case **An executor tag in any case.** A fence tag that matches a
387
508
  registered executor's name case-insensitively opens that executor (`SH` opens
388
509
  `sh`), and the statement's `executor` is the registered spelling, so a lookup
389
510
  by that name never misses. Operation names stay uppercase by teaching and were
390
- never written otherwise in 12,000 fences; one `SH` in 1,300 `sh` fences was
391
- (2026-09-13 census). An unregistered name without an accepted spelling
511
+ never written otherwise in 12,000 fences; one `SH` in 1,300 `sh` fences was. An unregistered name without an accepted spelling
392
512
  ({§executor-js-spelling}) is still prose ({§interstitial-fence}).
393
513
 
394
514
  §executor-js-spelling When `node` is registered and `js` is not, `js` names
@@ -419,12 +539,22 @@ nothing registered — opens a
419
539
  quotation that runs to its matching closer (same character, width at least the opener's) or to
420
540
  the end of the input. Everything inside is data: no operation runs there and native tool-call
421
541
  markup is not read ({§native-tool-calls}). An operation fenced inside an unlabeled code block
422
- draws one warning that it was shown, not run. An unlabeled fence whose first line is an operation
423
- heading is the operation with its tag forgotten, and draws one warning — `` `READ` inside an
424
- unlabeled fence did not run; the tag is the operation. `` — a native name alone or with a slot, an
425
- executor's name with its operand (of 2,308 naked fences in 12,797 recorded emissions, 51 open that
426
- way and 2,238 hold code or quoted output, which is why the fence itself draws nothing). A labeled
427
- block is an example by declaration, and nothing else inside draws an advisory.
542
+ draws one warning that it was shown, not run. At the top level, a bare fence whose next line is an
543
+ operation heading opens that operation instead ({§forgotten-tag}). A labeled block is an example by
544
+ declaration, and nothing else inside draws an advisory.
545
+
546
+ §forgotten-tag **A tag on the line under a bare fence is the operation.** At the top level, a bare
547
+ fence whose next line is an operation heading, a native name alone or with a slot or an executor's
548
+ name with its operand, opens that operation as if both were written on one line: the heading takes
549
+ its slots, the lines after it are its body, and it closes like any operation. It runs, and one
550
+ warning-severity receipt names the form — `` `READ` ran, though its fence was malformed: the
551
+ opening fence, OP, parameters, and aside share one line. `` Saying that it ran keeps the model from
552
+ issuing it again. Inside a body the same lines stay literal. Measured: of 2,308 naked fences in
553
+ 12,797 recorded emissions, 51 open that way and 2,238 hold code or quoted output, which is why a
554
+ bare fence alone draws nothing; in the 10,486-emission fence corpus every one of the 12 that open
555
+ that way was an operation the model meant to run. With the answer carried by the final KILL,
556
+ whose body shows and never runs ({§terminal-kill}), an example the model means only to show lives
557
+ in a body.
428
558
  So a model may show plurnk's own operations in an answer. Two exceptions keep programs whole:
429
559
  CommonMark's own rule that a backtick opener's line carries no further backtick, so
430
560
  ```` ```READ (x)``` ```` is inline code and quotes nothing after it; and a bare fence directly under
@@ -439,17 +569,16 @@ response text under {§response-text}, not an executable program or a completion
439
569
  example, and shows its own examples offset; the other quoting fences are untaught: a tilde
440
570
  fence, an unlabeled fence and an unknown tag all quote. Each is a shape a model reaches for from ordinary Markdown rather than from this
441
571
  teaching, so honouring it protects an example the model already believed was safe
442
- ({§response-text-note} places the scale). The offset is the one form that survives every
572
+ ({§outside-text} places the scale). The offset is the one form that survives every
443
573
  fence style.
444
574
 
445
- §interstitial-fence Superseded by {§quotation}: an unlabeled fence no longer opens nothing, it
446
- quotes. (It in turn replaced the retired unlabeled-fence SEND of the fences chapter, whose
447
- unlabeled fences turned displaced headings into silent messages.)
575
+ §interstitial-fence Only a native operation or a known executor opens a block. A fence naming
576
+ anything else, or nothing at all, opens no operation: outside a block it quotes under
577
+ {§quotation}, inside a body it is body.
448
578
 
449
579
  §closer-aside A closing fence followed on its line by one aside and nothing else
450
580
  is the closer; the aside is outside text. Read as body, that line would be written
451
- into the edited resource (#758: a recorded EDIT deleting a line wrote
452
- ```` ```` <!-- remove duplicated Result import --> ```` into a Python file). A
581
+ into the edited resource (#758). A
453
582
  closing fence followed by any other text is still body.
454
583
 
455
584
  §heading-slot-order A heading near-miss with exactly one reading is read as that
@@ -480,9 +609,42 @@ the aside, and `body`/`content`/`command`/`text`/`input` or plain text inside th
480
609
  call the body; plurnk slots written after the name are kept, a trailing scope's own
481
610
  bracket may close the tag. A block keeps its line count where its lines allow, so
482
611
  statement positions name the source line; an inline block grows to its fences.
483
- A call with an unknown name or parameter leaves the whole emission as it was. An
484
- emission that already yields an operation is never rewritten. No diagnostic, notice
485
- or teaching mentions the reading (#760).
612
+ DeepSeek writes the whole heading into the invoke's name — `<||DSML|| invoke name="FIND (docs/**)
613
+ /Http404/ <!-- docs mentions -->">`, or `name="sh` with no closing quote and the script on the lines
614
+ below — and the element's content is the body: the first word of the name is the operation, the rest
615
+ its slots, and `parameter` tags around the content are debris, as are a copied facts line
616
+ (`{"lines":6}`) under the heading, a `comment` attribute (the aside), and `<||DSML||tool_calls>`
617
+ spelled without spaces. An executor's unknown parameter is one of its options, `[{"maxTokens":
618
+ "2500"}]`, for its owner to accept or refuse; `bash` names `sh` when `sh` is the registered shell.
619
+ Of 69 distinct recorded emissions carrying DSML markup (the 11,500 distinct emissions recorded
620
+ through run429), 60 read this way and 9 draw the {§native-tool-call-receipt}: a bare
621
+ `<||DSML|| calls>` with nothing inside, and calls whose native operation carries a parameter
622
+ plurnk has no slot for.
623
+ Qwen's own shapes read the same way: a flat JSON call whose operation is the value
624
+ of an `op`, `action` or `cmd` key in any case (`{"op": "READ", "path": …, "range": …}`),
625
+ an XML element named by the operation (`<NOTE>…</NOTE>`, `<FIND (path) <1,3></FIND>`,
626
+ `<read path="…"/>`) or by a generic `op` element or function (`<op op="READ" …>`,
627
+ `<op verb="READ" …/>` in `<ops>`, `<op=READ (path) …>`, `<function=OP name="READ" …>`,
628
+ `<function=OP>` around such a JSON call or a plurnk heading), and a plurnk heading written
629
+ as the call's text (`<tool_call>READ (a.py) <60,120>`, `=READ (…)`). Closing tags left over
630
+ from another family (`</parameter>`, `</invoke>`, `</>`) after a call are markup noise;
631
+ `reason` and `description` are the aside; a scope may be a JSON array (`[500,530]`) or a
632
+ `{"start", "end"}` object; an executor's string `input` is its program. A call with an
633
+ unknown name or parameter, or a FIND, READ, EDIT, COPY or MOVE naming no target, leaves the
634
+ whole emission as it was. An emission that already yields an operation is never
635
+ rewritten. No diagnostic, notice or teaching mentions a successful reading (#760).
636
+
637
+ §native-tool-call-receipt **Markup that was not read is named.** When an emission yields no
638
+ operation and carries native tool-call markup that could not be read, the parse reports one
639
+ hard diagnostic at the markup, naming it and the fenced form that runs — `` `<tool_call>` is
640
+ tool-call markup, which plurnk does not run, so nothing ran. An operation is a fenced block:
641
+ three backticks and `READ (django/forms/widgets.py)` on the opening line. `` The form names
642
+ the operation and target the markup itself names where it names them (`sh` for a shell
643
+ command, `NOTE` for a note or narration), and otherwise the generic "the operation with its target,
644
+ such as `READ (path)`". The model believes it
645
+ acted; silence would let it wait on a result that never comes. Of 107 distinct recorded
646
+ no-operation qflash emissions carrying call-like markup, 63 read under {§native-tool-calls}, 42 draw
647
+ this receipt, and 2, a bare JSON object of narration with no tool-call marker, draw neither.
486
648
 
487
649
  §empty-section Both the compact bodyless form and an empty multiline block
488
650
  normalize optional bodies to null. Closing fences are conventional, never required
@@ -519,19 +681,35 @@ has at most one scope; its metadata blocks retain their authored order.
519
681
  optional target and ignores syntactically valid scope and metadata without diagnostics
520
682
  ({§send-wait-scope}). Their literal bodies begin below the header.
521
683
 
684
+ §scope-on-scopeless **A scope on an operation that takes none is dropped, and named.** WORK, FORK,
685
+ BARE and NOTE take no scope, and neither does a SEND without a recipient; a `<…>` slot on such a
686
+ heading, in any position, is skipped and the operation runs, with one warning-severity advisory
687
+ naming the operation's slots and the dropped scope — `` `WORK` takes a target only; the scope
688
+ `<1,-1>` was ignored. A scope selects lines in READ, EDIT and KILL. `` (`` `NOTE` takes no target or
689
+ scope; … ``, `` `SEND` without a recipient takes no scope; … ``). An aside is never a scope, a
690
+ recipient SEND keeps its scope for the recipient ({§send-directed-scope}), and WAIT's is skipped
691
+ unread ({§send-wait-scope}). There is no ambiguity: the operation has one reading with or without
692
+ the slot. Before this, the heading drew the grammar's expected-token diagnostic and the turn was
693
+ dead; in the distinct recorded emissions one heading carried the form (zai run426,
694
+ ```` ```WORK (worker://deprecation-implementer) <1,-1> ````), beside two recipient SENDs whose scope
695
+ the recipient refuses at runtime.
696
+
522
697
  §heading-inline-body Nonempty body text belongs below the fence header.
523
698
  The ingester tolerates body text after horizontal whitespace on the header,
524
699
  preserves it, and emits one warning stating that normalization. This does not
525
700
  change the meaning of a compact empty block or permit unmatched fences.
526
701
 
527
- §bare-option-object A bare option object is the option block. On an
528
- operation that takes an option block and no bare matcher — SEND, BARE, WORK,
529
- FORK and every executor fence — heading text after the slots that is exactly
530
- one JSON object `{…}` is read as `[{…}]`: the AST carries the array form, the
531
- written heading renders it, every consumer sees the taught shape, and one
532
- warning-severity receipt names the indulgence in place of the
533
- {§heading-inline-body} advisory: "`SEND` took a bare option object; the taught
534
- form is `[{…}]`." A heading that already carries a block keeps the object as
702
+ §bare-option-object A bare option object is the option block, where the house option array owns the
703
+ block. On an operation that takes an option block and no bare matcher — SEND, BARE, WORK, FORK and
704
+ every executor fence — heading text after the slots that is exactly one JSON object `{…}` is read
705
+ as `[{…}]`: the AST carries the array form, the written heading renders it, and one
706
+ warning-severity receipt names the indulgence in place of the {§heading-inline-body} advisory:
707
+ "`SEND` took a bare option object; the taught form is `[{…}]`." The option array is a house
708
+ convention, not a language rule ({§scheme-metadata-modifier}): an executor whose declared body is
709
+ JSON ({§executor-invocation}), an MCP tool, reads the object as its body instead — its arguments,
710
+ written on the heading line — with one warning: "`gitea` took its body on the heading line; the
711
+ body belongs on the lines below it." The host names those executors to the parse
712
+ (`ParseOptions.jsonBodyExecutors`). A heading that already carries a block keeps the object as
535
713
  inline body. On FIND, READ and KILL the same text is the matcher
536
714
  ({§naked-pattern}), because a search for JSON text is legitimate; a bare matcher
537
715
  that parses as a JSON object draws one advisory naming the option form ("`{…}`
@@ -731,9 +909,9 @@ accounting, and observation timing belong to the consuming service.
731
909
  §read-find-normalization An authored READ is never rewritten into a FIND. A
732
910
  glob target on READ keeps its glob, and the runtime fans it out into one exact
733
911
  READ per matching path, with the authored scope and matcher ({§read-fan-out}
734
- in the core SPEC; operator, 2026-09-13: "give it what it asked for" — a model
912
+ in the core SPEC). A model
735
913
  that asks to read every file under a glob gets those files, bounded by the
736
- FIND page and the preview scope, not a catalog it did not ask for). A matcher
914
+ FIND page and the preview scope, not a catalog it did not ask for. A matcher
737
915
  never changes the operation either: READ with a `pattern` on an exact target
738
916
  stays READ and renders the selected lines ({§read-pattern}). The survey of
739
917
  paths is FIND, and only FIND.
@@ -927,7 +1105,7 @@ statements remain recoverable when their boundaries are trustworthy.
927
1105
 
928
1106
  ## §scope-slot 7. Scope markers
929
1107
 
930
- The model-facing slot is `<scope>`; the AST field remains the historical
1108
+ The model-facing slot is `<scope>`; the AST field is
931
1109
  `lineMarker`. Numeric scopes preserve ordered components in `LineMarker`;
932
1110
  text-coordinate operations use `TextLineMarker`, whose line positions may also
933
1111
  carry rendered anchors. The operation owner assigns every component's role.
@@ -1058,7 +1236,8 @@ The implementation this section describes lives in `@plurnk/plurnk-parser`
1058
1236
  ({§parser-consumers}); this section remains the contract it implements.
1059
1237
 
1060
1238
  ANTLR owns framing, slots and statement composition; AstBuilder produces the
1061
- schema-owned AST. Registration, effects and authority remain runtime concerns.
1239
+ schema-owned AST. Where each block ends is decided first, over the whole input, by
1240
+ {§fence-pairing}; the lexer's fence predicates consult that decision and never decide it. Registration, effects and authority remain runtime concerns.
1062
1241
 
1063
1242
  ```mermaid
1064
1243
  stateDiagram-v2
@@ -1097,41 +1276,37 @@ Quoted blocks remain literal text, including every nested operation-looking line
1097
1276
  Operation bodies, asides, malformed operation regions and unfenced operation lines
1098
1277
  ({§unfenced-operation}) are not response text;
1099
1278
  nothing at or beyond a lost boundary is recovered as text. The statement and client
1100
- tiers ignore outside text. Core alone owns filing it as a NOTE ({§response-text-note})
1279
+ tiers ignore outside text. Core alone owns storing it as the turn's outside source ({§outside-text})
1101
1280
  and no-operation strikes ({§empty-turn}); parsing never infers delivery or completion
1102
1281
  intent.
1103
1282
 
1104
1283
  §unfenced-operation **An operation written without its fence did not run, and the parser says
1105
1284
  so.** An outside-text line that opens at column zero with an operation's name and anything else
1106
1285
  — `KILL The answer…`, `READ (a.md)`, `KILL (notes.md)` — draws one warning: `` `KILL` has no
1107
- fence, so it did not run. `` The line is not response text ({§response-text}): it is neither filed as
1108
- a NOTE nor echoed into the next packet, and the exact emission remains at `ops://` (operator,
1109
- 2026-09-23); the bare name alone
1286
+ fence, so it did not run. `` The line is not response text ({§response-text}): it is neither stored
1287
+ as outside text nor echoed into the next packet, and the exact emission remains at `ops://`; the bare name alone
1110
1288
  opens the operation instead ({§naked-operation}). A registered executor's name followed by an
1111
1289
  operand slot — `gitea (list_issues)`, `sh(build.sh)` — draws the same warning under the executor's
1112
1290
  own spelling; quoted blocks, offset lines and names inside a sentence draw nothing, since `sh`,
1113
- `env` and `members` are ordinary words. The model that wrote it believes it ran: while the line was
1114
- still filed as a NOTE ({§response-text-note}), an unfenced KILL read back as an answer already given,
1115
- and the model repeated it until the cycle detector ended the loop (`demo-overflow-recovery-AC4Ul4`;
1116
- the same shape defeated SEND recovery and a count of invalid characters; operator, 2026-09-22). The
1117
- warning and the exclusion together end that echo.
1291
+ `env` and `members` are ordinary words. The model that wrote it believes it ran: stored as
1292
+ outside text ({§outside-text}), an unfenced KILL would sit in the record as an answer never given,
1293
+ and only the warning tells the model otherwise. The warning and the exclusion together keep the
1294
+ line out of the record.
1118
1295
 
1119
1296
  §recorded-emissions **The parser is regressed against emissions models actually produced,
1120
1297
  not fixtures we wrote.** `test/fixtures/recorded-emissions.jsonl` holds one real exemplar
1121
1298
  of every distinct parse shape observed across the live and demo drills — the operations
1122
1299
  authored, whether outside text appeared, how many parameterless KILLs appeared, and
1123
1300
  the status the engine recorded at the time. A fixture encodes what we believe a model
1124
- emits; a recording encodes what one did, and the difference is not academic: the
1125
- regressions in #802 and #809 both shipped through a fully green suite, because every
1126
- fixture in it was ours.
1301
+ emits; a recording encodes what one did, so only recordings test the shapes models actually
1302
+ produce (#802, #809).
1127
1303
  Shape coverage, not volume, is the point — 120 exemplars are ~60 KB against ~88 MB for
1128
1304
  every emission ever recorded. The recorded status is **provenance, never an assertion**:
1129
1305
  the contract has changed under these turns and will again, so the replay asserts only that
1130
1306
  today's parser still reads each emission the way the corpus says it does. Regenerate with
1131
1307
  `scriptify/extract-emission-corpus.ts --write` after a drill; a changed shape is the
1132
1308
  contract moving and the diff names every shape that moved with it. The extractor also
1133
- reports how many recorded turns concluded under a contract that no longer would, which is
1134
- the drift between what the harness once accepted and what it accepts now.
1309
+ reports how many recorded turns concluded in a way the current contract would reject.
1135
1310
 
1136
1311
  ## 12. Public API
1137
1312
 
@@ -1150,9 +1325,9 @@ An explicit disposition may sit anywhere in it
1150
1325
  ({§disposition-anywhere}). An omitted WAIT produces no synthesized statement, diagnostic, receipt,
1151
1326
  warning, or strike. The authored operations and source remain unchanged.
1152
1327
  Unfinished blocks never receive inferred closers.
1153
- Bounded operation errors retain valid siblings, and so does a lost boundary:
1154
- the statements that closed before `unparsedTail.from` are facts, and only what
1155
- follows is undefined ({§unparsed-tail-boundary}).
1328
+ A bounded operation error leaves its siblings' facts intact, and a lost boundary
1329
+ leaves the facts before it ({§unparsed-tail-boundary}); running them is the
1330
+ consumer's admission ({§emission-admission}).
1156
1331
 
1157
1332
  The host records programs per turn; no operation acts as a separator between
1158
1333
  saved programs. There is no outer Markdown program wrapper; the executable
@@ -1193,7 +1368,7 @@ among them: the parser is `@plurnk/plurnk-parser`'s ({§parser-consumers}).
1193
1368
  The remaining values are small pure helpers over those contracts (`isExecution`, `writtenOp`,
1194
1369
  `lifecycleOfLoopStatus`, `selectWorkerLoop`, `renderJsonResult`, `formatJsonDocument`,
1195
1370
  `aguiConformanceReport`) and the closed name patterns and vocabularies (`RUNTIME_TAG`,
1196
- `SKILL_NAME`, `REASONING_POLICIES`).
1371
+ `SKILL_NAME`, `EFFORTS`).
1197
1372
 
1198
1373
  §parser-construction-boundary Parser construction components are internal rather
1199
1374
  than alternate consumer entry points:
@@ -1490,9 +1665,22 @@ class PlurnkParseError extends Error {
1490
1665
  readonly column: number;
1491
1666
  readonly source: ErrorSource;
1492
1667
  readonly severity: Severity;
1668
+ readonly recovery: string | undefined;
1493
1669
  }
1494
1670
  ```
1495
1671
 
1672
+ §parse-recovery **Every hard diagnostic carries its working form.** A `severity: "error"`
1673
+ diagnostic names, in `recovery`, the form that runs, in the model's terms: a refused heading
1674
+ carries the operation's canonical line (`` `READ (path) <L,M>? pattern? <!-- aside -->?` on the
1675
+ opening fence line; READ takes no body. ``), a refused matcher the dialect's form with an example,
1676
+ and a refused regex the regex that matches the words the model wrote — `` A pattern is a regex:
1677
+ write `/url/` to match lines containing url; `*` repeats what precedes it. To select files by
1678
+ name, put the glob in the target: `FIND (tests/*url*)`. `` — where the glob suggestion is derived
1679
+ from the pattern only when it is glob-shaped, and the regex sentence stands alone otherwise. The
1680
+ runtime projects `recovery` as the Problem's `recovery` beside the verbatim `message`; an advisory
1681
+ carries none, since its statement ran. Before this, a refused regex (`/*url*/`, DeepSeek run429)
1682
+ reported `Nothing to repeat` with no way forward and the turn was spent.
1683
+
1496
1684
  §parser-position Parser source locations are points, not text regions. An AST
1497
1685
  statement's `position` identifies the first backtick of its header; a diagnostic
1498
1686
  identifies the offending or recovery point; `unparsedTail.from` identifies where
@@ -1540,7 +1728,7 @@ diagnostics are:
1540
1728
  position after the closing `/`. Only a leading group of `i`, `m` and `s` lifts;
1541
1729
  `(?i:…)` scoped modifiers are valid ECMAScript and pass through untouched.
1542
1730
  `plurnk.md` teaches one regex spelling, `/\btimeout\b/i`, with flags after the closing
1543
- slash; the lift is not taught. Unlike the tolerances on the {§response-text-note}
1731
+ slash; the lift is not taught. Unlike the tolerances on the {§outside-text}
1544
1732
  scale, this one forgives a departure the model did not choose: `(?i)` is the spelling
1545
1733
  a great many models were trained on, so refusing it would punish an instinct rather
1546
1734
  than a mistake ({§naked-pattern} carries `^` for the same reason). The advisory still
@@ -1550,6 +1738,11 @@ diagnostics are:
1550
1738
  diagnostic, with or without flags, without assuming what the extra text was
1551
1739
  intended to represent. Invalid patterns or flags retain the native
1552
1740
  regex failure; no branch silently removes or executes trailing content.
1741
+ - §regex-sed-range **A sed line range is named as one.** A regex matcher written as a sed
1742
+ address range — `/a/,/b/` or `/a/,+N` — is refused as a range, never as invalid flags: the
1743
+ diagnostic says a matcher selects only the lines it matches, gives the one regex that
1744
+ locates the ends (`/a|b/`, or `/a/`) and the scope that then addresses the span
1745
+ (`<first,last>`, or `<N,M>` with M being N plus the range's count).
1553
1746
  - §unclosed-regex **A regex that never closes.** A `/pattern` matcher with no closing
1554
1747
  `/` is read as the whole pattern with no flags, with one warning-severity advisory
1555
1748
  naming the closing slash and the flag position. The reading is deterministic because
@@ -1577,7 +1770,7 @@ diagnostics are:
1577
1770
  dialect without slashes or flags: the whole text is the pattern, so
1578
1771
  `READ (notes.md) ^Decision:.*` selects lines beginning with `Decision:`.
1579
1772
  `^` is deliberately absent from `plurnk.md`'s dialect table and belongs here instead
1580
- (operator, 2026-09-21, #804). It is carried because `^` meaning "anchor" is among the
1773
+ (#804). It is carried because `^` meaning "anchor" is among the
1581
1774
  strongest instincts a model arrives with: it will write `^Decision:.*` whether or not it
1582
1775
  was taught to, and the engine honours what it will reach for anyway. Teaching it would
1583
1776
  spend hot-path weight on a line that changes no behaviour. The omission is therefore not
@@ -1597,23 +1790,49 @@ diagnostics are:
1597
1790
  itself ends in one of those shapes takes the option escape.
1598
1791
  `plurnk.md` teaches one order — `OP (path)? <scope|range>? [metadata]? pattern?
1599
1792
  <!-- aside -->?` — and free ordering is not taught. Small departure, small
1600
- reinterpretation ({§response-text-note}): every slot the model wrote is present and
1793
+ reinterpretation ({§outside-text}): every slot the model wrote is present and
1601
1794
  unambiguous, so only their sequence differs from the taught form, and nothing is
1602
1795
  invented to read it. The advisory names the canonical order rather than refusing,
1603
1796
  because the operation the model meant is never in doubt.
1797
+ - §log-heading-notation **The log's heading notation, copied as syntax, is read as the slot it
1798
+ stands for.** A packet's log row heading is `### log:///L/T/S/OP → path pattern · N`
1799
+ ({§log-wire-format} in the core SPEC); models copy its notation onto their own headings. Each
1800
+ piece has one reading, so each is read and named with one warning-severity advisory after its
1801
+ statement:
1802
+
1803
+ | Written | Read as | Advisory |
1804
+ |---|---|---|
1805
+ | `READ → sh:///x#stdout <1,50>` | the target, `READ (sh:///x#stdout) <1,50>`; COPY/MOVE take one arrow per operand | `` `→ sh:///x#stdout` is how the log shows an address; it was read as the target. Write the target in parentheses: `READ (sh:///x#stdout) <1,50>`. `` |
1806
+ | `READ (a.py) <1,50> · 900`, `· 320 tokens`, a bare `·` | nothing: the token charge is dropped, on the heading or after a matcher | `` `· 900` is the token charge the log shows on a heading; it is not part of an operation and was ignored. `` |
1807
+ | `FIND (x) /re/ · locate the sign handling` | the aside | `` `· locate the sign handling` was read as the aside; a note on an operation is written `<!-- locate the sign handling -->`. `` |
1808
+
1809
+ The arrow's path runs to the next space, `<` or `[`; a `·` never begins a heading matcher. In
1810
+ distinct recorded benchmark emissions the arrow form opened 40 headings and the charge ended 52,
1811
+ where they drew a missing-target 400 or a false-empty glob match.
1812
+ - §bare-target **A target written without its parentheses is refused with the line that runs.**
1813
+ A FIND, READ or EDIT heading with no target whose heading text opens with a word that is no
1814
+ matcher sigil, `READ a.py <1,4>`, cannot run: the word stands where the target goes, but on FIND it
1815
+ could as well be a pattern. The statement is one hard diagnostic that writes the corrected line —
1816
+ `` `READ` has no target: `a.py` stands where the target goes. Write the target in parentheses:
1817
+ `READ (a.py) <1,4>`. `` A targetless KILL's heading text remains its inline deliverable.
1818
+ - §bare-anchor-scope **An EDIT's anchor without its angle brackets is its scope.** On an EDIT
1819
+ heading, `@abcde` or `@abcde,@fghij` standing alone where the scope goes — nothing but an aside, a
1820
+ closer or the line end after it — is the scope `<@abcde>`, with one warning-severity advisory:
1821
+ `` `@abcde` was read as the scope `<@abcde>`; a scope is written in angle brackets. `` Read as
1822
+ body instead, the anchor would be written into the file, or the EDIT refused for want of a line
1823
+ marker (14 distinct recorded headings). On READ and KILL the same text stays a literal matcher,
1824
+ since `@patch` is a search a model means.
1604
1825
  - §matcher-body-redirect **A body beneath those headings.** Text below the heading
1605
1826
  of a FIND, READ or targeted KILL is a body, and those operations take none: the builder
1606
1827
  keeps the statement without it and raises one warning-severity advisory (`READ
1607
1828
  takes no body; the body was ignored. A pattern belongs on the opening fence line
1608
1829
  after the path.`), delivered like {§misplaced-aside-advisory} as a
1609
- `parse_advisory` notice (operator, 2026-09-12: a gentle warning, never an error
1610
- the model must recover from). One sigil line beneath the heading is the bare form
1830
+ `parse_advisory` notice (a warning, never an error). One sigil line beneath the heading is the bare form
1611
1831
  written a line low and still lifts; nothing else is promoted into a matcher from
1612
1832
  below the heading, and the advisory never echoes the body.
1613
- - §combined-anchor-tolerance **Combined anchor and line number in a scope.** A
1614
- text-coordinate scope position written `@hash:L` or `@hash L` is the displayed
1615
- `@abcde 42:` prefix copied whole (a koota-entity turn refused nine of them in a
1616
- row, 2026-09-12): the position is the anchor, the number is dropped, and one
1833
+ - §combined-anchor-tolerance **Combined line number and anchor in a scope.** A
1834
+ text-coordinate scope written `L<@hash>` — digits immediately before the opener — is the
1835
+ displayed `42<@abcde>` row prefix copied whole: the scope is the anchor, the number is dropped, and one
1617
1836
  warning-severity advisory names the anchor-only form. The scope lexes as one
1618
1837
  ordinary marker at any text-coordinate operation, either COPY/MOVE operand
1619
1838
  included; nothing cascades.
@@ -1684,7 +1903,7 @@ author the tail's reason.
1684
1903
  |--------------------|----------------------------------------------------------------------------------------------------------------|
1685
1904
  | Diagnostic text | Project `message` verbatim; do not strip prefixes, restate coordinates, or synthesize generic syntax recovery. |
1686
1905
  | Structured context | Preserve `line`, `column`, `source`, and `severity` as separate fields. |
1687
- | Runtime recovery | Attach only a separately owned fact, such as Core knowing that bounded sibling operations were retained. |
1906
+ | Runtime recovery | Project the parser's `recovery` ({§parse-recovery}) and attach only a separately owned fact, such as Core knowing that bounded sibling operations were retained. |
1688
1907
  | Durable projection | Map bounded hard errors to failed operation results; warnings may become Notices with `level: "warn"`. |
1689
1908
  | Presentation | Normalize or bound the diagnostic only when the surface requires it, without changing its meaning. |
1690
1909