@plurnk/plurnk-contracts 1.14.2 → 1.16.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 +106 -123
- package/dist/plurnk.gemma.gbnf +62 -87
- package/dist/plurnk.qwen.gbnf +62 -87
- package/dist/schema/ClientStatement.json +114 -40
- package/dist/schema/PlurnkStatement.json +29 -199
- package/dist/schema/RangeExtent.json +1 -1
- package/dist/src/AstBuilder.d.ts +2 -2
- package/dist/src/AstBuilder.d.ts.map +1 -1
- package/dist/src/AstBuilder.js +68 -146
- package/dist/src/AstBuilder.js.map +1 -1
- package/dist/src/PlurnkErrorStrategy.d.ts +0 -1
- package/dist/src/PlurnkErrorStrategy.d.ts.map +1 -1
- package/dist/src/PlurnkErrorStrategy.js +72 -61
- package/dist/src/PlurnkErrorStrategy.js.map +1 -1
- package/dist/src/PlurnkParser.d.ts +1 -2
- package/dist/src/PlurnkParser.d.ts.map +1 -1
- package/dist/src/PlurnkParser.js +15 -104
- package/dist/src/PlurnkParser.js.map +1 -1
- package/dist/src/generated/plurnkLexer.d.ts +42 -69
- package/dist/src/generated/plurnkLexer.d.ts.map +1 -1
- package/dist/src/generated/plurnkLexer.js +495 -647
- package/dist/src/generated/plurnkLexer.js.map +1 -1
- package/dist/src/generated/plurnkParser.d.ts +76 -215
- package/dist/src/generated/plurnkParser.d.ts.map +1 -1
- package/dist/src/generated/plurnkParser.js +643 -1829
- package/dist/src/generated/plurnkParser.js.map +1 -1
- package/dist/src/generated/plurnkParserVisitor.d.ts +3 -87
- package/dist/src/generated/plurnkParserVisitor.d.ts.map +1 -1
- package/dist/src/generated/plurnkParserVisitor.js +2 -74
- package/dist/src/generated/plurnkParserVisitor.js.map +1 -1
- package/dist/src/index.d.ts +0 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +0 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/types.d.ts +1 -1
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.generated.d.ts +18 -50
- package/dist/src/types.generated.d.ts.map +1 -1
- package/dist/src/types.js +1 -1
- package/dist/src/types.js.map +1 -1
- package/package.json +1 -1
- package/plurnk.md +67 -73
- package/dist/src/TagSignal.d.ts +0 -15
- package/dist/src/TagSignal.d.ts.map +0 -1
- package/dist/src/TagSignal.js +0 -53
- package/dist/src/TagSignal.js.map +0 -1
package/SPEC.md
CHANGED
|
@@ -147,7 +147,7 @@ order-independent: a descriptor is admitted only when every layer admits it.
|
|
|
147
147
|
No Worker or loop can restore service, workspace, or parent authority. A
|
|
148
148
|
composed operation is admitted only when every routed demand survives. These
|
|
149
149
|
descriptors govern routed external authority, not every grammar statement:
|
|
150
|
-
log/program control such as PLAN,
|
|
150
|
+
log/program control such as PLAN, log KILL, and label or targetless SEND
|
|
151
151
|
creates no capability demand. A known interactive runtime is represented by
|
|
152
152
|
access class `interact`; scheme and runtime manifests contribute traits rather
|
|
153
153
|
than hidden policy behavior.
|
|
@@ -267,7 +267,7 @@ back onto the sampled text so the complete pre-projection response can be graded
|
|
|
267
267
|
Either body may be empty and cannot contain its profile's opener or closer.
|
|
268
268
|
`sep` is zero through seven whitespace characters. The projected PLURNK content
|
|
269
269
|
is either bare or enclosed once in a paired `plurnk` Markdown fence; the turn
|
|
270
|
-
begins with
|
|
270
|
+
begins with `## PLAN0`, and every following operation is a same-lane `## OP0`
|
|
271
271
|
section.
|
|
272
272
|
`tail-0` admits zero through fourteen internal operations followed by exactly
|
|
273
273
|
one terminal SEND under the existing terminal-eligibility rules.
|
|
@@ -303,19 +303,18 @@ lane. This makes both the canonical delimiter and section boundary structurally
|
|
|
303
303
|
available during constrained generation; ANTLR remains the wider language and
|
|
304
304
|
accepts intentional alternate-lane literals during ingestion.
|
|
305
305
|
|
|
306
|
-
§gbnf-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
target resolution.
|
|
306
|
+
§gbnf-kill-shaping The rail shapes KILL as one required target, an optional
|
|
307
|
+
text-coordinate scope (numeric or anchored), and an optional one-line matcher body,
|
|
308
|
+
without proving that the selection resolves; ANTLR and AstBuilder own the statement's
|
|
309
|
+
shape, and runtime owns target resolution ({§kill-scope}).
|
|
311
310
|
|
|
312
311
|
## §canonical-statement 2. Canonical statement form
|
|
313
312
|
|
|
314
313
|
```text
|
|
315
|
-
|
|
314
|
+
## PLANdelimiter
|
|
316
315
|
body
|
|
317
316
|
|
|
318
|
-
## OPdelimiter
|
|
317
|
+
## OPdelimiter (path)? {metadata}* <scope>? <!-- annotation -->?
|
|
319
318
|
body?
|
|
320
319
|
```
|
|
321
320
|
|
|
@@ -334,10 +333,9 @@ under {§plan-value}.
|
|
|
334
333
|
|
|
335
334
|
| Element | Canonical contract |
|
|
336
335
|
|--------------|---------------------------------------------------------------------------|
|
|
337
|
-
|
|
|
336
|
+
| `## PLAN` | Required level-one turn anchor |
|
|
338
337
|
| `## OP` | Level-two protocol operation |
|
|
339
338
|
| `delimiter` | Heading lane, joined directly to PLAN or OP |
|
|
340
|
-
| `[signal]` | Optional operation-specific signal, preceded by one space |
|
|
341
339
|
| `(path)` | Optional target slot, preceded by one space |
|
|
342
340
|
| `{metadata}` | Optional repeatable scheme-metadata modifier after a target |
|
|
343
341
|
| `<scope>` | Optional numeric scope, preceded by one space |
|
|
@@ -371,8 +369,8 @@ spacing and permutation are not second canonical spellings.
|
|
|
371
369
|
|
|
372
370
|
§heading-inline-body Text that follows the last slot on a heading line — after
|
|
373
371
|
horizontal whitespace, beginning with a character that cannot open a slot (not `[`,
|
|
374
|
-
`(`, or `<`, nor `{` after a target) — is the first body line:
|
|
375
|
-
|
|
372
|
+
`(`, or `<`, nor `{` after a target) — is the first body line: `### EXEC0 [crm] (crm_query) SELECT Id FROM Case` and
|
|
373
|
+
`### FIND0 (src/**) /createCoder/i` parse as their canonical two-line forms. Nothing is
|
|
376
374
|
lost and the stored statement is canonical; the spelling is tolerated and announced:
|
|
377
375
|
one warning-severity advisory follows the statement, naming the heading and the rule
|
|
378
376
|
(body content goes immediately beneath the OP heading line), so the model learns
|
|
@@ -413,9 +411,8 @@ or safely execute understandable input:
|
|
|
413
411
|
|
|
414
412
|
| Element | Accepted shape or role |
|
|
415
413
|
|-------------|--------------------------------------------------------------------|
|
|
416
|
-
| `OP` | `FIND READ EDIT COPY MOVE
|
|
414
|
+
| `OP` | `FIND READ EDIT COPY MOVE SEND EXEC BARE WORK FORK KILL PLAN` |
|
|
417
415
|
| `delimiter` | `[A-Za-z0-9_]*`, adjacent to PLAN or OP |
|
|
418
|
-
| `[signal]` | Operation-specific tags, identifier, branch, or integer |
|
|
419
416
|
| `(path)` | Local path or scheme URL target; detailed in §5 |
|
|
420
417
|
| `{metadata}` | Repeatable opaque scheme modifier attached after a target |
|
|
421
418
|
| `<scope>` | One or more signed integers or decimals; detailed in §7 |
|
|
@@ -427,22 +424,20 @@ or safely execute understandable input:
|
|
|
427
424
|
The model-facing forms below are the canonical projection. Parser tolerance is
|
|
428
425
|
governed by {§canonical-statement}; runtime conditions remain explicit below.
|
|
429
426
|
|
|
430
|
-
| OP | `
|
|
431
|
-
|
|
432
|
-
| PLAN | none
|
|
433
|
-
| FIND |
|
|
434
|
-
| READ |
|
|
435
|
-
| EDIT |
|
|
436
|
-
| COPY |
|
|
437
|
-
| MOVE |
|
|
438
|
-
|
|
|
439
|
-
|
|
|
440
|
-
|
|
|
441
|
-
|
|
|
442
|
-
|
|
|
443
|
-
|
|
|
444
|
-
| KILL | optional target-specific code | required target, including a log item | none | empty |
|
|
445
|
-
| SEND | optional target-specific code | optional recipient | optional timeout, poll | message; terminal is nonempty |
|
|
427
|
+
| OP | `(path)` | `<scope>` | `body` |
|
|
428
|
+
|------|----------------------------------------------|---------------------------------|--------------------------------|
|
|
429
|
+
| PLAN | none | none | required Plurnk Plan JSON array |
|
|
430
|
+
| FIND | required target or glob | optional result range | optional matcher |
|
|
431
|
+
| READ | required target | optional text region | empty |
|
|
432
|
+
| EDIT | required file or entry | required for an existing target | literal text |
|
|
433
|
+
| COPY | required source and destination | optional region after each path | empty |
|
|
434
|
+
| MOVE | required source and destination | optional region after each path | empty |
|
|
435
|
+
| EXEC | optional `[executor]`, optional program path ({§exec-executor-slot}) | optional timeout, poll | optional program input |
|
|
436
|
+
| BARE | none | none | required prompt |
|
|
437
|
+
| WORK | required fresh `worker://name` | none | required prompt |
|
|
438
|
+
| FORK | required context-inheriting `worker://name` | none | required prompt |
|
|
439
|
+
| KILL | required target, including a log item | optional text region ({§kill-scope}) | optional matcher |
|
|
440
|
+
| SEND | a label `(NEXT\|WAIT\|TERM\|FAIL)` or an optional recipient ({§send-label}) | optional timeout, poll on WAIT | message; terminal is nonempty |
|
|
446
441
|
|
|
447
442
|
§operation-code-polymorphism SEND and KILL share a numeric wire slot, not one universal numeric vocabulary.
|
|
448
443
|
For pathless terminal SEND, the code is the loop disposition defined in §9.
|
|
@@ -481,26 +476,35 @@ to ACP v1
|
|
|
481
476
|
[`schema-v1.21.0`](https://github.com/agentclientprotocol/agent-client-protocol/tree/schema-v1.21.0)
|
|
482
477
|
commit `272bf799f35a258c6a4107a0410ed361e83683d3`.
|
|
483
478
|
|
|
484
|
-
§exec-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
479
|
+
§exec-executor-slot An EXEC heading takes an optional `[executor]` slot before its path: `### EXEC0 [python3] (tools/report.py)`. The executor may also trail the path (`### EXEC0 (tools/report.py) [python3]`); either position binds the same AST, since no other slot after a path uses `[...]`. Canonical rendering leads with the executor. Two executors are the one rejected shape. The bracket names the registered executor that runs the program — a tool family, a language runtime, or the shell — and lexes as one `EXECUTOR` token only on an EXEC heading. The path names the program: a registered tool of that family, or a script file or entry. A bare `### EXEC0` is the shell running its body; with a path the body is the program's input. The AST carries `executor` (null for the shell) and `target` separately; the path is never split. Each of the executor, the path, and the `<timeout,poll>` scope appears at most once. Tool teaching, not the grammar, spells the registered executors; a `{cwd=…}` metadata block, interpreted by the executor, names the working directory.
|
|
480
|
+
|
|
481
|
+
§send-label SEND's path slot carries either a turn label or a recipient. The four
|
|
482
|
+
labels `(NEXT)`, `(WAIT)`, `(TERM)`, and `(FAIL)` lex as one `SEND_LABEL` token
|
|
483
|
+
and make the SEND terminal: the AST `status` is 102, 202, 200, or 499 and `target`
|
|
484
|
+
is null. A label SEND names no recipient; a label beside a recipient path is one
|
|
485
|
+
error at the heading naming that rule. A SEND whose path is a recipient
|
|
486
|
+
(`### SEND0 (worker://recheck)`, `(https://…)`, `(a2a://…)`), or whose path slot is
|
|
487
|
+
empty (the user), is a mid-turn message with `status` null. The GBNF rail spells a
|
|
488
|
+
mid-turn recipient as a URL, so a constrained turn can never place a label mid-turn.
|
|
489
|
+
|
|
490
|
+
§send-wait-scope A `(WAIT)` SEND keeps its numeric `<scope>` — the park interval
|
|
491
|
+
and poll ({§park-202-only}); the dispatcher owns what it accepts. Every other label
|
|
492
|
+
takes no scope.
|
|
493
|
+
|
|
494
|
+
§kill-scope KILL takes an optional text-coordinate scope beside its target, numeric or
|
|
495
|
+
anchored (`### KILL0 (log:///**/READ) <17,-1>`, `### KILL0 (worker:///notes.md)
|
|
496
|
+
<@aB3dE,@0Aa9Z>`), and an optional one-line matcher body that selects rows. The AST
|
|
497
|
+
is `{ op: "KILL", target, lineMarker: TextLineMarker | null, body: MatcherBody | null }`.
|
|
498
|
+
Without a scope, KILL retires or deletes the whole target; with one, it removes exactly
|
|
499
|
+
that span — of a log body's packet projection or of an entry's content. Core owns the
|
|
500
|
+
one-way semantics: there is no operation that restores a scoped-away log body.
|
|
501
|
+
|
|
502
|
+
§legacy-bracket-slot The bracket slot carries no signal, tag, code, or status on any heading; EXEC alone takes `[executor]` ({§exec-executor-slot}). A `[` on any other heading is one bounded lexer diagnostic that names that rule and the OP's own `(path)` slot, and after PLAN states that PLAN takes no modifiers. The statement drops and its siblings run.
|
|
499
503
|
|
|
500
504
|
The `<scope>` slot is optional where admitted and its domain is OP-specific. FIND
|
|
501
|
-
scopes ordered results. EXEC and SEND scope timing. READ, EDIT, COPY,
|
|
502
|
-
MOVE use one universal text algebra independent of mimetype;
|
|
503
|
-
only its one- and two-line forms for canonical log-body visibility:
|
|
505
|
+
scopes ordered results. EXEC and a WAIT SEND scope timing. READ, EDIT, COPY,
|
|
506
|
+
MOVE, and KILL use one universal text algebra independent of mimetype; a log
|
|
507
|
+
KILL admits only its one- and two-line forms for canonical log-body visibility:
|
|
504
508
|
|
|
505
509
|
| Arity | Surface meaning | Endpoint rule |
|
|
506
510
|
|---------------|---------------------------------------------------------------------|------------------------------------------------------|
|
|
@@ -522,7 +526,7 @@ Producers never emit that form. Other arities and decimal text coordinates are
|
|
|
522
526
|
runtime 416 failures.
|
|
523
527
|
|
|
524
528
|
§bare-statement **BARE requests one isolated model inference.** Its required
|
|
525
|
-
body is the complete prompt
|
|
529
|
+
body is the complete prompt: no
|
|
526
530
|
target, scope, persistent worker identity, or output-language statement shape
|
|
527
531
|
is represented in the AST. Runtime provider selection, batching, accounting,
|
|
528
532
|
and observation timing belong to the consuming service.
|
|
@@ -560,8 +564,6 @@ Mutation semantics:
|
|
|
560
564
|
| EDIT | Status plus a bounded receipt for the effect that landed |
|
|
561
565
|
| COPY | Source and destination selections plus ordered destination effects |
|
|
562
566
|
| MOVE | Source and destination selections plus ordered destination and source effects |
|
|
563
|
-
| OPEN | Status and matched log-item count |
|
|
564
|
-
| FOLD | Status and matched log-item count |
|
|
565
567
|
| SEND | Status and recipient acknowledgement when applicable |
|
|
566
568
|
| EXEC | Spawn acknowledgement; output arrives through named stream channels |
|
|
567
569
|
| BARE | The one-shot model response |
|
|
@@ -652,7 +654,7 @@ ingestion restriction: the parser decomposes arbitrary URL authorities.
|
|
|
652
654
|
|
|
653
655
|
## §matcher-prefix-claims 6. Bulk pattern matching
|
|
654
656
|
|
|
655
|
-
FIND, authored READ,
|
|
657
|
+
FIND, authored READ, KILL, LOOK, and BUFF accept an optional body matcher.
|
|
656
658
|
The lexer preserves the body opaquely; AstBuilder assigns the dialect from its
|
|
657
659
|
leading characters, then normalizes matcher-bearing READ to FIND under
|
|
658
660
|
{§read-find-normalization}.
|
|
@@ -665,18 +667,15 @@ visitor error and never falls back to glob matching.
|
|
|
665
667
|
disposition signal, never by a whole-turn alternative), so one malformed heading costs one
|
|
666
668
|
diagnostic and every later statement, the terminal SEND included, stands on its own. Any
|
|
667
669
|
other second path slot names the one-slot rule.
|
|
668
|
-
- §scope-slot-tolerance A line scope written inside a path slot (
|
|
670
|
+
- §scope-slot-tolerance A line scope written inside a path slot (`### COPY0 (worker:///src.md<2,3>)`)
|
|
669
671
|
is read as `(worker:///src.md) <2,3>` — `<` and `>` are not URI characters, so a `<…>` right
|
|
670
672
|
before a slot's closing paren can only be a scope; every path slot of a statement is repaired
|
|
671
673
|
the same way — and the slip is one warning-severity advisory at the `<`, placed right after its
|
|
672
674
|
statement, stating the `(path) <scope>` form that was used. The statement runs; a warning is
|
|
673
675
|
never a strike. A `<` anywhere else in the slot remains the lexer's refusal.
|
|
674
|
-
- §
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
after its statement, stating the `[+diff]` correction and that it was used. The statement
|
|
678
|
-
runs with the tag. A heading that already carries a signal is not rewritten: its second path
|
|
679
|
-
slot is blamed at the first paren and the statement is dropped.
|
|
676
|
+
- §second-path-slot A second `(path)` on a heading that already closed one is a parser
|
|
677
|
+
error at the second paren stating the one-slot rule and that a pattern belongs in the body;
|
|
678
|
+
the statement is dropped and its siblings run.
|
|
680
679
|
|
|
681
680
|
| Prefix | Dialect | Canonical body | Typed admission | Runtime owner |
|
|
682
681
|
|-----------|----------|--------------------------------------|-----------------------------------|---------------------|
|
|
@@ -727,16 +726,16 @@ The operation column names the canonical AST operation after
|
|
|
727
726
|
| EDIT | 0/1/2/4 text coordinates | Text replacement, deletion, prepend, or append |
|
|
728
727
|
| COPY/MOVE source | 0/1/2/4 text coordinates | Region copied or moved from the selected source |
|
|
729
728
|
| COPY/MOVE destination | 0/1/2/4 text coordinates after target | Region replaced or insertion point at the destination |
|
|
730
|
-
|
|
|
729
|
+
| KILL | 0/1/2 text coordinates | Whole target when absent; one physical line or inclusive range when present ({§kill-scope}) |
|
|
731
730
|
| EXEC | `timeout[,poll]` | Spawn lifetime bound and poll cadence in minutes |
|
|
732
|
-
|
|
|
731
|
+
| `### SEND0 (WAIT)` | `timeout[,poll]` | Bounded or indefinite wait and optional poll cadence ({§send-wait-scope}) |
|
|
733
732
|
|
|
734
733
|
Text coordinates use the algebra in {§text-scope-semantics}: one integer is a
|
|
735
734
|
whole line, two integers are an inclusive whole-line range, and four integers
|
|
736
735
|
are an exact start-inclusive/end-exclusive region. Mutation scopes additionally
|
|
737
736
|
admit `0` as prepend and `-1` as append. A leading decimal on semantic FIND
|
|
738
737
|
is a similarity threshold; any remaining integers select result positions. READ
|
|
739
|
-
does not admit decimal scope components.
|
|
738
|
+
does not admit decimal scope components. A log KILL intersects a valid body-relative line
|
|
740
739
|
scope with each selected body; an absent line is a successful no-op for that
|
|
741
740
|
body, while unsupported arity is a runtime failure.
|
|
742
741
|
|
|
@@ -744,7 +743,7 @@ body, while unsupported arity is a runtime failure.
|
|
|
744
743
|
spelled `@` followed by exactly five Base62 characters (`0-9A-Za-z`) wherever
|
|
745
744
|
its `L`, `SL`, or `EL` position denotes a line. Columns, prepend `0`, and append
|
|
746
745
|
`-1` remain numeric. Exact READ, EDIT, COPY/MOVE source and destination,
|
|
747
|
-
|
|
746
|
+
KILL, and client LOOK preserve these positions in `TextLineMarker`; core resolves them
|
|
748
747
|
against the addressed current text before operation-specific numeric scope
|
|
749
748
|
semantics run. A matcher-bearing or path-glob READ normalizes to FIND, whose
|
|
750
749
|
result positions remain numeric and reject anchors. Numeric text scopes remain
|
|
@@ -759,7 +758,7 @@ shapes for runtime validation. An anchor-bearing text scope uses commas; ANTLR
|
|
|
759
758
|
tolerates one space after each comma.
|
|
760
759
|
|
|
761
760
|
Apart from the unadvertised three-coordinate text-scope tolerance in
|
|
762
|
-
{§text-scope-semantics} and
|
|
761
|
+
{§text-scope-semantics} and a log KILL's per-body empty intersection, the runtime rejects invalid arity, out-of-range or
|
|
763
762
|
inverted positions, and decimal text coordinates rather than rounding or
|
|
764
763
|
reinterpreting them. FIND owns a deterministic result order so the same
|
|
765
764
|
inclusive range selects the same positions from unchanged state. The parser
|
|
@@ -787,18 +786,18 @@ Delimiter rules:
|
|
|
787
786
|
|
|
788
787
|
Example — a lane-0 turn stored inside a lane-2 EDIT body:
|
|
789
788
|
|
|
790
|
-
```
|
|
791
|
-
|
|
789
|
+
```example
|
|
790
|
+
## PLAN2
|
|
792
791
|
[{"content":"Store the quoted turn.","status":"in_progress"}]
|
|
793
792
|
|
|
794
|
-
|
|
795
|
-
|
|
793
|
+
### EDIT2 (worker:///quoted.plurnk)
|
|
794
|
+
## PLAN0
|
|
796
795
|
[{"content":"Answer from memory.","status":"in_progress"}]
|
|
797
796
|
|
|
798
|
-
|
|
797
|
+
### SEND0 (TERM)
|
|
799
798
|
Paris.
|
|
800
799
|
|
|
801
|
-
|
|
800
|
+
### SEND2 (TERM)
|
|
802
801
|
Stored the quoted turn.
|
|
803
802
|
```
|
|
804
803
|
|
|
@@ -827,27 +826,26 @@ streams, pending retrievals); the grammar polices *shape* only. Asking
|
|
|
827
826
|
the human is the native `question` EXEC tool ({§question-tool}), not a
|
|
828
827
|
disposition. The shape rules ARE structural:
|
|
829
828
|
|
|
830
|
-
- §send-mid-reservation The four
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
mid-position SENDs (`status-mid` is their complement over `DDD`).
|
|
829
|
+
- §send-mid-reservation The four labels lex as one `SEND_LABEL` token
|
|
830
|
+
({§send-label}), making a label SEND **structurally terminal**: a
|
|
831
|
+
statement after it is a parse error (the mid-termination rule), and the
|
|
832
|
+
GBNF spells mid-position SEND recipients as URLs, which no label is.
|
|
835
833
|
This keeps the grammar's last-SEND model and the dispatcher's
|
|
836
|
-
first-
|
|
837
|
-
- A **mid** SEND (before the terminal) is comms:
|
|
838
|
-
|
|
834
|
+
first-label model coincident.
|
|
835
|
+
- A **mid** SEND (before the terminal) is comms: a recipient path or
|
|
836
|
+
none, no label, empty body allowed.
|
|
839
837
|
- §terminal-body-nonempty The GBNF rail requires a non-empty terminal SEND body — a constrained
|
|
840
838
|
turn cannot end empty-handed. ANTLR remains tolerant during ingestion.
|
|
841
|
-
- §park-202-only The **park** rides `
|
|
839
|
+
- §park-202-only The **park** rides `(WAIT)` only: `<T>` (wait up to T minutes),
|
|
842
840
|
`<T,P>` (adds a poll cadence, mirroring EXEC's slot), `<-1>`
|
|
843
841
|
(indefinite; the join's own liveness bounds it). See §7 for the
|
|
844
842
|
GBNF-strict / ANTLR-tolerant split.
|
|
845
|
-
- §no-idle-102 A **zero-statement turn may not conclude `
|
|
843
|
+
- §no-idle-102 A **zero-statement turn may not conclude `(NEXT)`** — "continue"
|
|
846
844
|
with nothing submitted is a spin. The GBNF's `tail-0` exits through
|
|
847
|
-
a terminal trie without the `
|
|
848
|
-
straight into
|
|
849
|
-
the full
|
|
850
|
-
`
|
|
845
|
+
a terminal trie without the `(NEXT)` tail, so the idle turn (`PLAN`
|
|
846
|
+
straight into `### SEND0 (NEXT)`) is unemittable; one statement restores
|
|
847
|
+
the full label set. The other three stay legal bare (a zero-op
|
|
848
|
+
`(WAIT)` is the engine's obligation check). ANTLR stays tolerant
|
|
851
849
|
(ingest side). A dispatch-emptied turn — ops emitted but failing
|
|
852
850
|
downstream validation — survives the rail by nature; the engine's
|
|
853
851
|
idle-turn 409 backstops that class.
|
|
@@ -914,7 +912,7 @@ possible. EOF is a valid body boundary. An unfinished signal, target, or metadat
|
|
|
914
912
|
|
|
915
913
|
| Location | Canonical generation | Tolerant ANTLR ingestion |
|
|
916
914
|
|-----------------------------|---------------------------------------|-----------------------------------------------------------|
|
|
917
|
-
| Heading marker |
|
|
915
|
+
| Heading marker | `## PLAN0` or `## OP0` at column zero | The initial PLAN may directly follow leading TEXT; subsequent headings retain exact depth and column |
|
|
918
916
|
| Between OP and delimiter | Adjacent | Must remain adjacent |
|
|
919
917
|
| Before each modifier | One ASCII space | Zero or more horizontal whitespace characters |
|
|
920
918
|
| Inside signal | Adjacent values | Horizontal whitespace is ignored; newline is invalid |
|
|
@@ -947,13 +945,13 @@ types cover ordered parse items and `PlurnkParseError`, which JSON Schema cannot
|
|
|
947
945
|
express. Consumers never receive ANTLR parse-tree or token types.
|
|
948
946
|
|
|
949
947
|
§turn-shape `PlurnkParser.parse` accepts exactly one model turn containing at
|
|
950
|
-
least one parsed source operation. Canonical generation
|
|
951
|
-
ends with a
|
|
952
|
-
|
|
953
|
-
terminal SEND was parsed,
|
|
954
|
-
|
|
948
|
+
least one parsed source operation. Canonical generation may begin with H1 PLAN
|
|
949
|
+
(a SHOULD, never repeated mid-turn) and ends with a label H2 SEND. A turn without
|
|
950
|
+
a PLAN stands as written — no PLAN is synthesized and nothing is diagnosed. When
|
|
951
|
+
no valid terminal SEND was parsed, the parser appends a bodyless `### SEND0 (NEXT)`
|
|
952
|
+
carrying {§parser-position} `UNKNOWN_POSITION` and one exact hard diagnostic
|
|
955
953
|
stating the observed boundary failure and applied default. The source text
|
|
956
|
-
remains unchanged.
|
|
954
|
+
remains unchanged. The GBNF rail takes the same optional PLAN.
|
|
957
955
|
An authored terminal SEND still ends the source turn: a same-lane operation or
|
|
958
956
|
other hard error after it is outside the trustworthy boundary. Tolerated TEXT
|
|
959
957
|
may appear only before the first operation; after that point, nonstructural text
|
|
@@ -961,7 +959,7 @@ is section body content. `parseLog` remains strict canonical PLAN-through-SEND
|
|
|
961
959
|
input, and GBNF remains strict canonical generation.
|
|
962
960
|
|
|
963
961
|
§document-fence `PlurnkParser.parse` additionally admits one outer Markdown code
|
|
964
|
-
fence whose opening line is exactly ```` ```plurnk ```` and whose closing line,
|
|
962
|
+
fence whose opening line is exactly ```` ```example ```` (or the earlier ```` ```plurnk ````) and whose closing line,
|
|
965
963
|
when present, is ```` ``` ````. The fence encloses the complete
|
|
966
964
|
model turn and projects neither text nor body content into the AST. Its opener
|
|
967
965
|
commits the document to either that closer or EOF immediately after the turn.
|
|
@@ -972,7 +970,7 @@ no other parser tier admits it. GBNF continues to shape the paired form.
|
|
|
972
970
|
|
|
973
971
|
| Entry point | Accepted document | Result statement type |
|
|
974
972
|
|--------------------------------|----------------------------------------------------------------|-----------------------|
|
|
975
|
-
| `PlurnkParser.parse` | One operation-bearing model turn, bare with optional TEXT or inside one outer `plurnk` fence; omitted PLAN/SEND recover to defaults | `PlurnkStatement` |
|
|
973
|
+
| `PlurnkParser.parse` | One operation-bearing model turn, bare with optional TEXT or inside one outer `example` (or `plurnk`) fence; omitted PLAN/SEND recover to defaults | `PlurnkStatement` |
|
|
976
974
|
| `PlurnkParser.parseStatements` | Zero or more protocol statements and hidden whitespace | `PlurnkStatement` |
|
|
977
975
|
| `PlurnkParser.parseLog` | One or more consecutive same-lane PLAN-anchored turns | `PlurnkStatement` |
|
|
978
976
|
| `PlurnkParser.parseClient` | H2 protocol statements plus read-shaped LOOK/BUFF commands | `ClientStatement` |
|
|
@@ -1010,7 +1008,6 @@ than alternate consumer entry points:
|
|
|
1010
1008
|
|--------------------------------------------|---------------------------------------------------------------------------------------------------------------|
|
|
1011
1009
|
| `AstBuilder` | Consumes generated ANTLR contexts; `PlurnkParser` and `parsePath` own its API |
|
|
1012
1010
|
| `PlurnkErrorStrategy`, `RecordingListener` | Assemble parser recovery and diagnostics around `antlr4ng`; consumers receive `PlurnkParseError` values |
|
|
1013
|
-
| `Jsonplurnk` test helper | Independently checks the Core-owned {§jsonplurnk} renderer corpus; it is neither shipped code nor a root API |
|
|
1014
1011
|
|
|
1015
1012
|
### CLI
|
|
1016
1013
|
|
|
@@ -1062,7 +1059,10 @@ and no greater than `total`.
|
|
|
1062
1059
|
The transparent coordinates make completion and continuation derivable. The
|
|
1063
1060
|
shape has no separate `complete`, `next`, or all-results instruction. Exact
|
|
1064
1061
|
text-coordinate selections use {§text-region} instead. `Validator.assertRangeExtent`
|
|
1065
|
-
enforces both the schema and the relational endpoint invariants.
|
|
1062
|
+
enforces both the schema and the relational endpoint invariants. `unit: "byte"`
|
|
1063
|
+
names a selection of a binary resource's bytes, positions being 1-based byte
|
|
1064
|
+
offsets; the byte view is one octet per line, so the same positional algebra
|
|
1065
|
+
applies ({§read-bytes} in the core specification).
|
|
1066
1066
|
|
|
1067
1067
|
### §entry-read-result 13.3 Client entry reads
|
|
1068
1068
|
|
|
@@ -1307,17 +1307,11 @@ the sole and complete owner of syntax-error messaging because it holds the
|
|
|
1307
1307
|
parse state, lexer mode, and expected-token set that no consumer has. It
|
|
1308
1308
|
produces the final diagnostic message, deduplicated expected-token lists, and
|
|
1309
1309
|
turn-shape diagnostics. No valid leading PLAN yields ``No valid leading PLAN
|
|
1310
|
-
was parsed; an empty
|
|
1311
|
-
valid terminal SEND was parsed;
|
|
1310
|
+
was parsed; an empty `## PLAN0` was used.``; no valid terminal SEND yields ``No
|
|
1311
|
+
valid terminal SEND was parsed; `### SEND0 (NEXT)` was used.``; source with no
|
|
1312
1312
|
parsed operation yields `no valid Plurnk operation was found.` Targeted
|
|
1313
1313
|
diagnostics are:
|
|
1314
1314
|
|
|
1315
|
-
- §signal-scope-redirect **EXEC scope in the signal slot.** When EXEC's
|
|
1316
|
-
`[signal]` slot (executor-ident mode) hits a leading `-` or digit —
|
|
1317
|
-
mark-shaped `<timeout, poll>` scope content mistyped into the brackets — the
|
|
1318
|
-
lexer message becomes “timeout/poll ride the `<scope>` slot; try
|
|
1319
|
-
`## EXEC0 <-1,300>`” instead of a raw `unrecognized character`. The redirect is
|
|
1320
|
-
EXEC-scoped because its signal mode is exclusive; SEND/KILL are untouched.
|
|
1321
1315
|
- §matcher-body-redirect **Matcher body in the slot region.** When the
|
|
1322
1316
|
post-target modifier region begins with `$`, `~`, or `@` with no whitespace
|
|
1323
1317
|
before it, the lexer redirects the unambiguous matcher to body content below the
|
|
@@ -1325,8 +1319,8 @@ diagnostics are:
|
|
|
1325
1319
|
already the inline body, {§heading-inline-body}). Slash-led regex and XPath are
|
|
1326
1320
|
excluded because `/` can be target data.
|
|
1327
1321
|
- §bare-target-redirect **A `(target)` on BARE.** BARE takes no `(path)`; a model that
|
|
1328
|
-
writes its prompt, or the prompt's address, into a parenthesized slot (
|
|
1329
|
-
(What day is it?)`,
|
|
1322
|
+
writes its prompt, or the prompt's address, into a parenthesized slot (`### BARE0
|
|
1323
|
+
(What day is it?)`, `### BARE0 (prompt:///1/1)`) is told that the prompt is the body
|
|
1330
1324
|
line beneath the heading, with the heading's own opener, instead of the generic
|
|
1331
1325
|
slot list. Two operator sessions on 2026-08-26 produced exactly these shapes.
|
|
1332
1326
|
- §combined-anchor-line-redirect **Combined anchor and line number in a scope.**
|
|
@@ -1334,21 +1328,10 @@ diagnostics are:
|
|
|
1334
1328
|
error: `a scope position accepts one line coordinate; use the \`@hash\` anchor
|
|
1335
1329
|
without its displayed line number`. A malformed header scope is consumed as
|
|
1336
1330
|
one token at either COPY/MOVE operand; neither produces a punctuation cascade.
|
|
1337
|
-
- §
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
\`[…]\` tag slot; a target goes in \`(…)\`. Try \`## EDIT0 (path)\``). It is
|
|
1342
|
-
gated on a path-shaped signal so a genuine additive-tag signal is not mis-steered
|
|
1343
|
-
toward a path it lacks.
|
|
1344
|
-
- §matcher-in-signal-slot **Matcher in the signal slot.** A tag term whose name
|
|
1345
|
-
begins with a matcher prefix (`/`, `$`, `~`, `&`) is never a tag: `## FIND0
|
|
1346
|
-
[/require/] (**.go)` used to apply a folksonomic tag named `/require/` and
|
|
1347
|
-
return unsearched rows. The canonicalizer refuses the term, so the builder
|
|
1348
|
-
raises one heading-positioned error naming the body rule (`` `[/require/]` is not
|
|
1349
|
-
a tag - a matcher belongs in the body beneath the heading; `[+tag]` adds,
|
|
1350
|
-
`[tag]` filters ``); the statement drops and its siblings run. Matcher
|
|
1351
|
-
characters inside a name (`slash/inside`) stay legal.
|
|
1331
|
+
- §label-recipient-redirect **A label beside a recipient.** `### SEND0 (TERM)
|
|
1332
|
+
(worker://parent)` and `### SEND0 (worker://parent) (TERM)` are one parser error at
|
|
1333
|
+
the heading: `a (NEXT|WAIT|TERM|FAIL) SEND names no recipient; message a recipient
|
|
1334
|
+
with its own SEND first` ({§send-label}).
|
|
1352
1335
|
- §misplaced-annotation-advisory **Annotation in the body.** A READ or FIND whose
|
|
1353
1336
|
body is solely an HTML comment (`<!-- … -->`) can never carry a matcher: it is
|
|
1354
1337
|
the annotation the model put on the line below the heading. The builder takes
|
|
@@ -1379,7 +1362,7 @@ Examples of canonical hard facts:
|
|
|
1379
1362
|
- `unrecognized character '<' in target`
|
|
1380
1363
|
- `unrecognized character ':' in signal`
|
|
1381
1364
|
- `unrecognized character 'X' in statement header`
|
|
1382
|
-
- `a turn must begin with
|
|
1365
|
+
- `a turn must begin with \`## PLAN0\``
|
|
1383
1366
|
- `expected ')'; got ':'`
|
|
1384
1367
|
|
|
1385
1368
|
Each malformed statement produces at most one hard error. The first recorded
|
|
@@ -1414,6 +1397,6 @@ runtime constructs this; the parser provides the fields):
|
|
|
1414
1397
|
"column": 12,
|
|
1415
1398
|
"source": "parser",
|
|
1416
1399
|
"severity": "error",
|
|
1417
|
-
"message": "target slot of
|
|
1400
|
+
"message": "target slot of `### READ0` opened at line 1 but never closed - add `)`"
|
|
1418
1401
|
}
|
|
1419
1402
|
```
|