@plurnk/plurnk-contracts 3.0.0 → 3.1.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/README.md +3 -5
- package/SPEC.md +131 -143
- package/dist/conformance/agui-v1.json +4 -1
- package/dist/schema/Notice.json +6 -1
- package/dist/schema/OperationResult.json +2 -3
- package/dist/schema/PlurnkStatement.json +8 -18
- package/dist/schema/WorkerOwner.json +6 -2
- package/dist/src/ApplicationPort.d.ts +1 -7
- package/dist/src/ApplicationPort.d.ts.map +1 -1
- package/dist/src/Functionality.d.ts +2 -1
- package/dist/src/Functionality.d.ts.map +1 -1
- package/dist/src/PlurnkParseError.d.ts +3 -1
- package/dist/src/PlurnkParseError.d.ts.map +1 -1
- package/dist/src/PlurnkParseError.js +5 -1
- package/dist/src/PlurnkParseError.js.map +1 -1
- package/dist/src/TurnDisposition.d.ts +1 -8
- package/dist/src/TurnDisposition.d.ts.map +1 -1
- package/dist/src/TurnDisposition.js +0 -10
- package/dist/src/TurnDisposition.js.map +1 -1
- package/dist/src/types.generated.d.ts +14 -12
- package/dist/src/types.generated.d.ts.map +1 -1
- package/package.json +2 -2
- package/plurnk.md +59 -53
package/README.md
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
# @plurnk/plurnk-contracts
|
|
2
2
|
|
|
3
3
|
The single authority for PLURNK's model-facing language contract, its AST,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
{§root-value-api}.
|
|
4
|
+
shared schemas and types, runtime-neutral Problems, operation results,
|
|
5
|
+
Notices, and text coordinates. See SPEC {§root-value-api}.
|
|
7
6
|
|
|
8
7
|
## Install
|
|
9
8
|
|
|
@@ -27,8 +26,7 @@ Requires Node.js 26 or newer.
|
|
|
27
26
|
JSON Schema owns shared wire shapes, generated TypeScript projects those
|
|
28
27
|
shapes, and ANTLR owns accepted model-language syntax. See SPEC
|
|
29
28
|
{§contract-representations}. An operator who wants constrained sampling on a
|
|
30
|
-
llama-server route writes their own GBNF and points `PLURNK_PROVIDERS_GBNF` at
|
|
31
|
-
it; this package ships no grammar profile.
|
|
29
|
+
llama-server route writes their own GBNF and points `PLURNK_PROVIDERS_GBNF` at it.
|
|
32
30
|
|
|
33
31
|
## Parser
|
|
34
32
|
|
package/SPEC.md
CHANGED
|
@@ -28,8 +28,8 @@ runtime-neutral wire envelopes; `@plurnk/plurnk-parser` implements the language
|
|
|
28
28
|
|
|
29
29
|
§contract-representations JSON Schema is authoritative for shared data shapes. TypeScript types are
|
|
30
30
|
generated from the schemas; ANTLR is authoritative for accepted model-language
|
|
31
|
-
syntax.
|
|
32
|
-
|
|
31
|
+
syntax. An operator's own GBNF is carried verbatim to a llama-server route by
|
|
32
|
+
the providers package.
|
|
33
33
|
|
|
34
34
|
§agui-discovery-contract `AguiDiscovery` is the complete installed AG-UI+
|
|
35
35
|
surface at one instant. `schemaVersion` identifies its discovery shape;
|
|
@@ -128,7 +128,7 @@ meaning, including registered scheme resolution, target existence, tag
|
|
|
128
128
|
selection, text-region bounds, result ordering, full-text ranking, mutation
|
|
129
129
|
effects, and executor behavior.
|
|
130
130
|
|
|
131
|
-
### §contract-proposal-projection
|
|
131
|
+
### §contract-proposal-projection Admission policy and stopped-world projection
|
|
132
132
|
|
|
133
133
|
The schemas own the runtime-neutral shapes; core owns their stateful values.
|
|
134
134
|
|
|
@@ -137,7 +137,7 @@ The schemas own the runtime-neutral shapes; core owns their stateful values.
|
|
|
137
137
|
| `CapabilityDescriptor` | One routed operation demand with its operation, access class, resource/runtime/tool coordinates, and declared traits | Derive every demand before dispatch |
|
|
138
138
|
| `CapabilityPolicy` | Exact `only`/`deny` selectors; omitted `only` is unrestricted and present empty `only` denies all | Intersect service and workspace layers |
|
|
139
139
|
| `CapabilityProjection` | Exact service, workspace, and normalized effective policies | Expose the resolver's workspace cascade without claiming one layer is effective authority |
|
|
140
|
-
| `WorkerOwner` | Nonempty address
|
|
140
|
+
| `WorkerOwner` | Nonempty address, unique client-tool names, and whether it is interactive | Persist by workspace; inherit through worker creation |
|
|
141
141
|
| `ProposalPolicy` | `review`, `accept`, or `reject` | Read the server's disposition knob at the proposal boundary |
|
|
142
142
|
| `ProposalDisposition` | Review, or automatic accept/reject with optional outcome | Select once for the pending gate |
|
|
143
143
|
| `ProposalProjection` | Identity, review target, body/attrs, owner, stale signal, disposition | One validated projection for live delivery and reconnect |
|
|
@@ -164,13 +164,16 @@ than hidden policy behavior.
|
|
|
164
164
|
|
|
165
165
|
§capability-policy-projection A `CapabilityProjection` reports every durable
|
|
166
166
|
workspace layer and their normalized intersection: `service`, `workspace`, and
|
|
167
|
-
`effective`. Only `workspace` is client-mutable. Workers and loops
|
|
168
|
-
capability policy
|
|
169
|
-
policy.
|
|
167
|
+
`effective`. Only `workspace` is client-mutable. Workers and loops store no
|
|
168
|
+
capability policy and inherit no bound; every actor uses the same live workspace
|
|
169
|
+
policy. Core derives one further ring per asking worker from its owner, and it only
|
|
170
|
+
removes interaction runtimes ({§owner-interaction-ring}). A client never derives
|
|
171
|
+
effective authority from the mutable layer alone.
|
|
170
172
|
|
|
171
173
|
§proposal-policy `ProposalPolicy` names one server disposition; `PROPOSAL_POLICIES`
|
|
172
|
-
is its schema-owned vocabulary. `WorkerOwner` carries an address
|
|
173
|
-
names that recipient implements
|
|
174
|
+
is its schema-owned vocabulary. `WorkerOwner` carries an address, the client-tool
|
|
175
|
+
names that recipient implements, and `interactive`: whether a person attends it. Neither
|
|
176
|
+
contains resource permissions or
|
|
174
177
|
message-carried authority. Core owns persistence, inheritance and settlement
|
|
175
178
|
({§worker-ownership}, {§proposal-disposition}); capability admission precedes approval.
|
|
176
179
|
|
|
@@ -311,15 +314,14 @@ column-zero line outside any block containing a native operation's name and at m
|
|
|
311
314
|
`<!-- aside -->`, with only horizontal whitespace otherwise, opens that operation as if it were
|
|
312
315
|
fenced with the taught three backticks. The aside retains its ordinary meaning: no target or
|
|
313
316
|
modifiers are inferred. Its body runs to a line that is exactly the name
|
|
314
|
-
again, to the next heading ({§fence-heading-in-body}), or to the end of the turn
|
|
315
|
-
parameterless KILL always takes the remaining answer region ({§terminal-kill}). A fence inside
|
|
317
|
+
again, to the next heading ({§fence-heading-in-body}), or to the end of the turn. A fence inside
|
|
316
318
|
naming nothing known is body; the block expects no closer, so its body is never cut
|
|
317
|
-
back ({§closer-fallback}).
|
|
318
|
-
`` `
|
|
319
|
+
back ({§closer-fallback}). One warning-severity receipt follows a recovered statement —
|
|
320
|
+
`` `NOTE` opened with no fence; the taught form is three backticks. `` One rule for every native
|
|
319
321
|
operation: a naked `WAIT` parks, a naked `NOTE` takes its text, a naked `READ` meets the ordinary
|
|
320
322
|
missing-target refusal. A closer the author wrote anyway is still not body: when the body's last line is
|
|
321
323
|
a bare backtick fence that no other fence line in the body pairs with (an odd count of fence lines), that
|
|
322
|
-
line is the block's closer and leaves the body, so `
|
|
324
|
+
line is the block's closer and leaves the body, so `SEND`, then the answer, then a closing fence delivers
|
|
323
325
|
the answer alone. An aside-bearing name inside a body is not a closer. An incomplete or repeated
|
|
324
326
|
aside, an operand, or other heading text does not qualify and remains the unfenced form
|
|
325
327
|
({§unfenced-operation}). Executors are runtimes rather than operations, and reasoning is never
|
|
@@ -329,10 +331,9 @@ read this way.
|
|
|
329
331
|
line of three or more backticks and a name that is a native operation or a known executor
|
|
330
332
|
is a heading. Inside an open block it either ends that block without closing it and opens the
|
|
331
333
|
next statement, or it is a literal example held by the block. {§fence-pairing} chooses between
|
|
332
|
-
the two
|
|
334
|
+
the two. Fence lines of
|
|
333
335
|
fewer than three backticks are never headings ({§operation-fences}). Known executors are `sh`
|
|
334
|
-
plus what the host names in `ParseOptions.executors`.
|
|
335
|
-
heading never ends the block ({§terminal-kill}).
|
|
336
|
+
plus what the host names in `ParseOptions.executors`.
|
|
336
337
|
|
|
337
338
|
§closer-fallback A block that ends at a heading or at the end of the input has no closer of its
|
|
338
339
|
own; its body is the whole span less one terminating line ending. Where a same-character fence
|
|
@@ -443,17 +444,9 @@ heading. An operation example quoted in a body of its own width therefore reads
|
|
|
443
444
|
closing and the example running; the wider outer fence or the tab offset quotes it
|
|
444
445
|
({§operation-fences}).
|
|
445
446
|
|
|
446
|
-
§terminal-kill **A parameterless KILL starts the final answer region.** Once its heading is
|
|
447
|
-
recognized as an operation, the rest of the input is its literal body. A fence cannot return
|
|
448
|
-
that region to executable operations or outside text. Apparent operations, receipts and malformed
|
|
449
|
-
fences within it are answer text. An actual enclosing closer at the end is framing, not body;
|
|
450
|
-
an earlier fence remains body. Compact and recovered naked spellings obey the same boundary.
|
|
451
|
-
Quoted KILL examples do not open this region; targeted KILL retains ordinary statement framing.
|
|
452
|
-
Earlier operations still execute and completion remains subject to {§kill-conclusion}.
|
|
453
|
-
|
|
454
447
|
§prose-code-blocks **A message or a prompt shows code.** Inside a `SEND`, `WORK`, `FORK` or `BARE`
|
|
455
448
|
body, at any depth, a heading that names an executor (` ```sh `, ` ```python3 `) is a code block the
|
|
456
|
-
text shows
|
|
449
|
+
text shows: it never ends the block and never runs. A native
|
|
457
450
|
operation's heading still ends such a block, since a message is often followed by the author's next
|
|
458
451
|
operation. In the distinct recorded benchmark emissions an executor heading ended an unclosed
|
|
459
452
|
`WORK` body 14 times, a `BARE` body 9 times and a `SEND` body twice; every one inspected (qflash
|
|
@@ -470,10 +463,6 @@ operations the author wrote than the best repaired reading, the repaired reading
|
|
|
470
463
|
inner fence keep what followed it (the qflash run192, run90 and run210 deliverables regain their last
|
|
471
464
|
sections), one echoed transcript (glm run155) runs one more operation, and none loses one.
|
|
472
465
|
|
|
473
|
-
§naked-kill **A naked KILL obeys the same answer boundary.** A parameterless `KILL` opened without
|
|
474
|
-
a fence ({§naked-operation}), with or without an aside, takes the remaining input under
|
|
475
|
-
{§terminal-kill}. A repeated name can close it only at the end; it never exposes later operations.
|
|
476
|
-
|
|
477
466
|
§pairing-witness **Witnesses.**
|
|
478
467
|
|
|
479
468
|
| Witness | Result |
|
|
@@ -558,9 +547,8 @@ opening fence, OP, parameters, and aside share one line. `` Saying that it ran k
|
|
|
558
547
|
issuing it again. Inside a body the same lines stay literal. Measured: of 2,308 naked fences in
|
|
559
548
|
12,797 recorded emissions, 51 open that way and 2,238 hold code or quoted output, which is why a
|
|
560
549
|
bare fence alone draws nothing; in the 10,486-emission fence corpus every one of the 12 that open
|
|
561
|
-
that way was an operation the model meant to run.
|
|
562
|
-
|
|
563
|
-
in a body.
|
|
550
|
+
that way was an operation the model meant to run. An example the model means only to show
|
|
551
|
+
belongs in a properly nested body ({§balanced-fences}) or a quotation ({§quotation}).
|
|
564
552
|
So a model may show plurnk's own operations in an answer. Two exceptions keep programs whole:
|
|
565
553
|
CommonMark's own rule that a backtick opener's line carries no further backtick, so
|
|
566
554
|
```` ```READ (x)``` ```` is inline code and quotes nothing after it; and a bare fence directly under
|
|
@@ -679,12 +667,12 @@ beside owner metadata, not only a matcher carried inside its `pattern` option.
|
|
|
679
667
|
by one ASCII space. Target and scope form one resource selection; COPY/MOVE
|
|
680
668
|
repeat the complete selection/metadata group per operand. ANTLR accepts
|
|
681
669
|
adjacent slots and scope/metadata permutations within a selection without
|
|
682
|
-
changing ownership or making them distinct canonical forms.
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
670
|
+
changing ownership or making them distinct canonical forms. Metadata may also
|
|
671
|
+
precede the first target, belonging to that first selection. Between targets it
|
|
672
|
+
belongs to the preceding selection, never the following one. Single-target
|
|
673
|
+
scope-first tolerance remains valid with metadata before or after that scope.
|
|
674
|
+
Each selection has at most one scope; its metadata blocks retain their authored order. A second scope
|
|
675
|
+
is refused; the recovery is the scope's working form ({§parse-recovery}).
|
|
688
676
|
|
|
689
677
|
§lifecycle-slots NOTE accepts no target, scope, or metadata. WAIT retains its
|
|
690
678
|
optional target and duration under {§send-wait-scope}. Their literal bodies begin
|
|
@@ -714,14 +702,11 @@ are never split. Each URI inherits its slot's scope and metadata and compiles th
|
|
|
714
702
|
BARE and NOTE take no scope, and neither does a SEND without a recipient; a `<…>` slot on such a
|
|
715
703
|
heading, in any position, is skipped and the operation runs, with one warning-severity advisory
|
|
716
704
|
naming the operation's slots and the dropped scope — `` `WORK` takes a target only; the scope
|
|
717
|
-
`<1,-1>` was ignored.
|
|
705
|
+
`<1,-1>` was ignored. `` (`` `NOTE` takes no target or
|
|
718
706
|
scope; … ``, `` `SEND` without a recipient takes no scope; … ``). An aside is never a scope, a
|
|
719
707
|
recipient SEND keeps its scope for the recipient ({§send-directed-scope}), and WAIT follows
|
|
720
708
|
{§send-wait-scope}. There is no ambiguity: the operation has one reading with or without
|
|
721
|
-
the slot.
|
|
722
|
-
dead; in the distinct recorded emissions one heading carried the form (zai run426,
|
|
723
|
-
```` ```WORK (worker://deprecation-implementer) <1,-1> ````), beside two recipient SENDs whose scope
|
|
724
|
-
the recipient refuses at runtime.
|
|
709
|
+
the slot.
|
|
725
710
|
|
|
726
711
|
§heading-inline-body Nonempty body text belongs below the fence header. Text after the slots
|
|
727
712
|
on the heading line is read by the operation's shape, by the builder that reads that operation,
|
|
@@ -753,9 +738,8 @@ written on the heading line — under {§heading-inline-body}. The host names th
|
|
|
753
738
|
(`ParseOptions.jsonBodyExecutors`). A heading that already carries a block keeps the object as
|
|
754
739
|
inline body. On FIND, READ and KILL the same text is the matcher
|
|
755
740
|
({§naked-pattern}), because a search for JSON text is legitimate; a bare matcher
|
|
756
|
-
that parses as a JSON object draws one advisory
|
|
757
|
-
|
|
758
|
-
learned in the turn it happens.
|
|
741
|
+
that parses as a JSON object draws one advisory saying so: "`{…}` was read as the
|
|
742
|
+
matcher." ({§diagnostic-observation}).
|
|
759
743
|
|
|
760
744
|
§operation-aside The final header modifier may be one single-line HTML
|
|
761
745
|
comment. AstBuilder removes its delimiters and surrounding whitespace into
|
|
@@ -764,7 +748,7 @@ routing, timing, or body input. Comments inside a body remain literal except
|
|
|
764
748
|
for the narrowly owned {§misplaced-aside-advisory}.
|
|
765
749
|
|
|
766
750
|
§scheme-metadata-modifier A target may carry one single-line `[metadata]`
|
|
767
|
-
block
|
|
751
|
+
block, placed under {§slot-order}; executor and SEND fences also admit it without a target.
|
|
768
752
|
The block belongs to the selected scheme or executor, which owns its shape,
|
|
769
753
|
interpretation, validation and authority. The language assigns no meaning to
|
|
770
754
|
the content and stores each block's exact inner text: balanced brackets inside
|
|
@@ -777,7 +761,9 @@ or multiline metadata loses its boundary.
|
|
|
777
761
|
**House policy, not a language rule:** every first-party scheme and executor
|
|
778
762
|
reads its block through the shared `MetadataOptions` reader, which takes the
|
|
779
763
|
block with its brackets as a JSON array of option objects, merged left to
|
|
780
|
-
right with later keys winning.
|
|
764
|
+
right with later keys winning. Reply SEND additionally owns a numeric completion
|
|
765
|
+
element ({§message-completion}); WAIT owns its numeric duration ({§send-wait-scope}).
|
|
766
|
+
A third-party owner may read its block any way
|
|
781
767
|
it likes — the language guarantees only the exact inner text. Documentation
|
|
782
768
|
for a first-party owner therefore shows the bracketed array form.
|
|
783
769
|
|
|
@@ -788,8 +774,8 @@ Worker; the shared reader withholds both from the owner's options.
|
|
|
788
774
|
|
|
789
775
|
§matcher-option **`pattern` is the matcher, and it lives in the heading.** On
|
|
790
776
|
FIND, READ, KILL, EDIT, and each COPY/MOVE operand, the option
|
|
791
|
-
`[{"pattern": "<matcher>"}]` carries the matcher string
|
|
792
|
-
|
|
777
|
+
`[{"pattern": "<matcher>"}]` carries the matcher string: the leading prefix
|
|
778
|
+
claims its dialect under {§matcher-prefix-claims}, and
|
|
793
779
|
AstBuilder lifts it into the statement's `matcher` (`MatcherBody | null`),
|
|
794
780
|
positioned dialect errors included. A block that carries only `pattern`
|
|
795
781
|
leaves `metadata: null` for the owner; beside other keys the block stays with
|
|
@@ -798,10 +784,9 @@ language lifts only from one block that parses as a JSON array of objects;
|
|
|
798
784
|
anything else lifts nothing and reaches the owner's `400` untouched. A
|
|
799
785
|
`pattern` that is present but not a string is the language's own positioned
|
|
800
786
|
diagnostic, as is a matcher of a claimed dialect that fails admission. FIND,
|
|
801
|
-
READ, and targeted KILL take no body: a body beneath their heading is
|
|
802
|
-
the operation still runs, with one warning-severity advisory naming the
|
|
803
|
-
|
|
804
|
-
on the opening fence line after the path.`); it is never silently read as a
|
|
787
|
+
READ, and targeted KILL take no body: a body beneath their heading is not used and
|
|
788
|
+
the operation still runs, with one warning-severity advisory naming the lines not
|
|
789
|
+
used (`FIND takes no body; lines 4–6 were not used.`); it is never silently read as a
|
|
805
790
|
matcher, and it never strikes ({§matcher-body-redirect}). The heading line itself
|
|
806
791
|
is the matcher's home ({§naked-pattern}). A body that is only an HTML comment is
|
|
807
792
|
still the aside under {§misplaced-aside-advisory}. EDIT keeps its literal body:
|
|
@@ -838,10 +823,10 @@ governed by {§canonical-statement}; runtime conditions remain explicit below.
|
|
|
838
823
|
| BARE | optional prompt resource | none | prompt; optional with a path |
|
|
839
824
|
| WORK | optional fresh `worker://name`, or a prompt resource ({§worker-spawn-prompt-resource}) | none | prompt; optional with a resource |
|
|
840
825
|
| FORK | optional context-inheriting `worker://name`, or a prompt resource | none | prompt; optional with a resource |
|
|
841
|
-
| KILL |
|
|
826
|
+
| KILL | required target | optional text region on a target ({§kill-scope}) | the distillation of what a `log:///` target retires ({§kill-scope}); none for other targets |
|
|
842
827
|
| SEND | optional recipient | recipient-defined; none for workers ({§send-directed-scope}) | message |
|
|
843
828
|
| NOTE | none | none | literal working memory |
|
|
844
|
-
| WAIT | optional label ({§send-wait-scope}) |
|
|
829
|
+
| WAIT | optional label ({§send-wait-scope}) | none; duration is `[seconds]` metadata | explanation of the wait |
|
|
845
830
|
|
|
846
831
|
§note-value NOTE retains its literal body as ordinary model-owned working memory.
|
|
847
832
|
It has no target, scope, metadata, or lifecycle effect. Its full body participates
|
|
@@ -851,10 +836,10 @@ repetition and strike rules still apply.
|
|
|
851
836
|
|
|
852
837
|
§reasoning-operations The shared fence parser admits complete, line-leading NOTE,
|
|
853
838
|
FIND and READ statements from exposed provider reasoning. Admission is part of
|
|
854
|
-
the language
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
839
|
+
the language. Other backtick or tilde code blocks are opaque; heading and
|
|
840
|
+
missing-closer recovery cannot escape them or complete an unfinished reasoning
|
|
841
|
+
operation. Blockquoted and inline examples are not headings. Other reasoned
|
|
842
|
+
operations never execute.
|
|
858
843
|
|
|
859
844
|
Operations are admitted only after the provider response completes; their
|
|
860
845
|
presence never interrupts generation. Selected operations precede the content
|
|
@@ -883,19 +868,18 @@ The path names a program or tool and is never split. Metadata such as
|
|
|
883
868
|
|
|
884
869
|
§turn-disposition WAIT requests parking; its literal body does not control
|
|
885
870
|
scheduling, and its optional target is the label the row keeps, never a join;
|
|
886
|
-
the AST
|
|
871
|
+
the AST retains the normalized metadata duration as `seconds`, separate from text coordinates.
|
|
887
872
|
A turn admits any number of WAITs, all deferred until its other operations
|
|
888
873
|
settle and together one park. End-of-program adjudication owns continuation, joining and completion
|
|
889
|
-
under {§wait-obligation-matrix}.
|
|
890
|
-
under {§
|
|
891
|
-
SEND delivers messages and NOTE retains memory, neither declaring an outcome.
|
|
874
|
+
under {§wait-obligation-matrix}. SEND carries optional message-completion metadata
|
|
875
|
+
under {§message-completion}. KILL requires a target; NOTE retains memory.
|
|
892
876
|
|
|
893
|
-
§send-wait-scope WAIT's optional
|
|
877
|
+
§send-wait-scope WAIT's optional `[seconds]` metadata is a non-negative finite scalar bounding
|
|
894
878
|
this park, not the lifetime of its work. Without it, the service supplies its
|
|
895
879
|
configured bound ({§worker-wait-timing}). Repeated duration slots select the
|
|
896
880
|
smallest valid scalar. Zero continues without parking or a diagnostic. Invalid
|
|
897
|
-
duration
|
|
898
|
-
bound applies.
|
|
881
|
+
duration metadata is ignored with a terse warning; when none is valid, the configured
|
|
882
|
+
bound applies. A text scope cannot supply a duration and receives the same warning.
|
|
899
883
|
The optional target is a label, never a selected wake source;
|
|
900
884
|
the body is the wait's explanation. Neither creates a schedule or restricts ordinary
|
|
901
885
|
wake events. Ordinary malformed-header rules still apply. Multiple WAITs request
|
|
@@ -903,8 +887,7 @@ one park with the earliest bound, including the configured bound for each bare W
|
|
|
903
887
|
|
|
904
888
|
§send-directed-scope A recipient SEND carries an optional numeric scope after
|
|
905
889
|
its target and metadata through to the addressed owner, which assigns its
|
|
906
|
-
semantics or refuses it; worker actors refuse one (`scope-unsupported`, 400)
|
|
907
|
-
because later and recurring delivery belong to the schedule family. A
|
|
890
|
+
semantics or refuses it; worker actors refuse one (`scope-unsupported`, 400). A
|
|
908
891
|
targetless message takes no scope. A scope never changes the message body or
|
|
909
892
|
disposition.
|
|
910
893
|
|
|
@@ -914,7 +897,7 @@ anchored (```` ```KILL (log:///**/READ) <17,-1>``` ```` or
|
|
|
914
897
|
selects rows or lines (```` ```KILL (log:///**) [{"pattern": "~stale"}]``` ````, {§matcher-option}).
|
|
915
898
|
Each operand becomes an ordinary KILL statement with its own `target`, `lineMarker` and
|
|
916
899
|
`matcher`; no grouped AST reaches execution ({§target-group}).
|
|
917
|
-
|
|
900
|
+
KILL requires a target. Its body is retained on a `log:///` target, where
|
|
918
901
|
it is the model's distillation of what the KILL retires and lands as its own NOTE row
|
|
919
902
|
({§log-kill-distillation}); every other targeted KILL has `body: null`, and a body beneath one
|
|
920
903
|
draws the advisory ({§matcher-body-redirect}). Beneath a `log:///` KILL the body is never read as
|
|
@@ -923,12 +906,10 @@ Without a scope, KILL retires or deletes the whole target; with one, it removes
|
|
|
923
906
|
that span — of a log body's packet projection or of an entry's content. Core owns the
|
|
924
907
|
one-way semantics: there is no operation that restores a scoped-away log body.
|
|
925
908
|
|
|
926
|
-
§
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
and is refused there; a bracket before the target of a non-executor OP is one
|
|
931
|
-
bounded header diagnostic that selects nothing.
|
|
909
|
+
§bracket-metadata-slot Brackets are the owner's metadata modifier: the runtime
|
|
910
|
+
or MCP service is the fence name, and tool input belongs in the body. A bracket
|
|
911
|
+
block is metadata before or after the target, with ownership under {§slot-order};
|
|
912
|
+
its position does not select an executor or change its interpretation.
|
|
932
913
|
|
|
933
914
|
The `<scope>` slot is optional where admitted and its domain is OP-specific. FIND
|
|
934
915
|
scopes ordered results. Executions and SEND scope owner-defined timing. READ, EDIT, COPY,
|
|
@@ -985,7 +966,7 @@ same bare spelling the receipt used: a model that appends the channel to the pat
|
|
|
985
966
|
shown addresses the same entry, and so does one that writes it after the parenthesis,
|
|
986
967
|
`(page.html) #readable`, which {§naked-pattern} reads as the channel. `raw` is therefore always the path alone; a
|
|
987
968
|
bare path never contains a literal `#`, and `PlurnkParser.stringify` renders the channel back.
|
|
988
|
-
Without a `#` the field is absent
|
|
969
|
+
Without a `#` the field is absent.
|
|
989
970
|
|
|
990
971
|
§read-exact-target READ targets one exact resource (a local path or scheme
|
|
991
972
|
URL, with optional `#channel` fragment or `[metadata]`) and has no body. A
|
|
@@ -1203,7 +1184,7 @@ The operation column names the canonical AST operation after
|
|
|
1203
1184
|
| COPY/MOVE destination | 0/1/2/4 text coordinates after target | Region replaced or insertion point at the destination |
|
|
1204
1185
|
| KILL | 0/1/2 text coordinates | Whole target when absent; one physical line or inclusive range when present ({§kill-scope}) |
|
|
1205
1186
|
| execution | None | Lifetime uses metadata; observation cadence belongs to the daemon ({§exec-lifetime}) |
|
|
1206
|
-
| WAIT |
|
|
1187
|
+
| WAIT | None | Maximum park duration uses metadata ({§send-wait-scope}) |
|
|
1207
1188
|
| Directed SEND | Owner-defined numeric scope | Carried to the addressed owner; worker actors refuse it ({§send-directed-scope}) |
|
|
1208
1189
|
|
|
1209
1190
|
Text coordinates use the algebra in {§text-scope-semantics}: one integer is a
|
|
@@ -1278,27 +1259,26 @@ rule protects code examples in SEND, WORK, FORK, BARE and every other body.
|
|
|
1278
1259
|
|
|
1279
1260
|
## 9. Turn dispositions
|
|
1280
1261
|
|
|
1281
|
-
The runtime adjudicates
|
|
1262
|
+
The runtime adjudicates each admitted turn against actual message resolutions,
|
|
1282
1263
|
results and live obligations ({§wait-obligation-matrix}). A response with no
|
|
1283
|
-
operation
|
|
1264
|
+
operation resolves no message and creates no new observation obligation ({§empty-turn}).
|
|
1284
1265
|
|
|
1285
1266
|
| Intent | Nominal status | Meaning |
|
|
1286
1267
|
|---|---|---|
|
|
1287
1268
|
| Unobserved messages or results | 102 | Continue silently |
|
|
1288
|
-
| No
|
|
1289
|
-
| WAIT | 202 | Park
|
|
1290
|
-
|
|
|
1291
|
-
|
|
|
1292
|
-
| Other admitted program | 102 | Continue regardless of earlier replies or live work |
|
|
1269
|
+
| No operations while messages remain unresolved, or fresh operation/parser failure, without WAIT | 102 | Recover before automatic parking |
|
|
1270
|
+
| WAIT with live obligations | 202 | Park with the supplied or configured duration |
|
|
1271
|
+
| Resolved messages, observed results, live work remains | 202 | Join the held work; replies remain delivered |
|
|
1272
|
+
| Resolved messages, observed results, no held work | 200 or 499 | Settle under {§loop-completion}, retaining the aggregate message outcome |
|
|
1293
1273
|
| KILL own worker | 499 | Cancel unfinished work in that worker and its descendants |
|
|
1294
1274
|
| Runtime or infrastructure failure | 5xx | Not a model-authored task status |
|
|
1295
1275
|
|
|
1296
1276
|
### The terminal contract (waitpid)
|
|
1297
1277
|
|
|
1298
|
-
The model may supply WAIT or
|
|
1278
|
+
The model may supply WAIT or complete message obligations with SEND metadata. The host, not the grammar, owns
|
|
1299
1279
|
turn boundaries and adjudicates the loop's actual obligations. Asking
|
|
1300
|
-
the human uses the native `question` executor tool when
|
|
1301
|
-
disposition. The shape rules ARE structural:
|
|
1280
|
+
the human uses the native `question` executor tool, offered only when a person attends the
|
|
1281
|
+
worker's owner ({§owner-interaction-ring}), not a disposition. The shape rules ARE structural:
|
|
1302
1282
|
|
|
1303
1283
|
- §send-mid-reservation WAIT is reserved ({§turn-disposition}).
|
|
1304
1284
|
A turn admits any number of lifecycle declarations, anywhere among its
|
|
@@ -1309,19 +1289,17 @@ disposition. The shape rules ARE structural:
|
|
|
1309
1289
|
dispositions until the other admitted operations settle
|
|
1310
1290
|
({§op-execution-order}). Nothing is dropped and no diagnostic is raised for
|
|
1311
1291
|
position. Omission does not synthesize a disposition ({§turn-shape}).
|
|
1312
|
-
This applies to WAIT, not to the literal answer region opened by parameterless KILL
|
|
1313
|
-
({§terminal-kill}).
|
|
1314
1292
|
- SEND is communication: an optional recipient path and an optional body.
|
|
1315
1293
|
- §park-202-only WAIT joins live work: an open stream or a live
|
|
1316
|
-
child. With none, it
|
|
1294
|
+
child. With none, it does not park. Its optional duration bounds parking ({§send-wait-scope});
|
|
1317
1295
|
a future message is scheduled through the schedule family.
|
|
1318
1296
|
- §lifecycle-only-turn A WAIT-, SEND-, NOTE-, or KILL-only turn is valid.
|
|
1319
1297
|
NOTE does not request parking or acknowledge messages.
|
|
1320
1298
|
Ordinary repetition, strike and execution limits still apply.
|
|
1321
1299
|
|
|
1322
|
-
SEND with no `(path)`
|
|
1323
|
-
message to that recipient.
|
|
1324
|
-
|
|
1300
|
+
SEND with no `(path)` replies to open messages. SEND with `(path)` directs the
|
|
1301
|
+
message to that recipient. Completion metadata resolves message obligations
|
|
1302
|
+
({§message-completion}); dispatch still executes the whole program.
|
|
1325
1303
|
|
|
1326
1304
|
### §send-body SEND body projection
|
|
1327
1305
|
|
|
@@ -1394,7 +1372,7 @@ the executor's own spelling. Quoted blocks, offset lines and names inside a sent
|
|
|
1394
1372
|
§recorded-emissions **The parser is regressed against emissions models actually produced,
|
|
1395
1373
|
not fixtures we wrote.** `test/fixtures/recorded-emissions.jsonl` holds one real exemplar
|
|
1396
1374
|
of every distinct parse shape observed across the live and demo drills — the operations
|
|
1397
|
-
authored, whether outside text appeared,
|
|
1375
|
+
authored, whether outside text appeared, and
|
|
1398
1376
|
the status the engine recorded at the time. A fixture encodes what we believe a model
|
|
1399
1377
|
emits; a recording encodes what one did, so only recordings test the shapes models actually
|
|
1400
1378
|
produce (#802, #809).
|
|
@@ -1562,12 +1540,19 @@ schema, this suffix invariant, and Problem status equality.
|
|
|
1562
1540
|
| 100–399 | `problem` is forbidden |
|
|
1563
1541
|
| 400–599 | One RFC 9457 `problem` object is required |
|
|
1564
1542
|
|
|
1565
|
-
|
|
1566
|
-
|
|
1543
|
+
Producer-specific success fields and Problem Details extension members remain
|
|
1544
|
+
open. A malformed result is
|
|
1567
1545
|
an internal producer contract violation; it is not converted into a second
|
|
1568
1546
|
model-facing failure envelope.
|
|
1569
1547
|
|
|
1570
|
-
### 13.5 Problem Details
|
|
1548
|
+
### 13.5 Diagnostics and Problem Details
|
|
1549
|
+
|
|
1550
|
+
§diagnostic-observation **A diagnostic says what happened, never why.** Every Problem `detail`
|
|
1551
|
+
and `recovery`, parse diagnostic and notice names what was read, what was done with it, and
|
|
1552
|
+
where, and may show the working form of the construct it read or refused. It never names a cause
|
|
1553
|
+
or an intent the input does not establish: no likely mistake, no reconstruction of what the author
|
|
1554
|
+
meant, no alternative the producer did not apply, and no form the language no longer has. Each
|
|
1555
|
+
sentence presupposes only what the producer itself decided.
|
|
1571
1556
|
|
|
1572
1557
|
§problem-details `ProblemDetails` requires `type`, `title`, `status`, and `detail`;
|
|
1573
1558
|
`instance` is optional until a durable host can attach the occurrence URI.
|
|
@@ -1585,8 +1570,8 @@ model-facing failure envelope.
|
|
|
1585
1570
|
| extensions | Factual producer-known operands or constraints |
|
|
1586
1571
|
|
|
1587
1572
|
`detail` is failure truth; `recovery` is not a second explanation. Producers do
|
|
1588
|
-
not
|
|
1589
|
-
|
|
1573
|
+
not blame the model, restate status, or expose an implementation accident as the
|
|
1574
|
+
cause ({§diagnostic-observation}). General syntax and workflow teaching remain in the model
|
|
1590
1575
|
packet rather than being repeated in every Problem.
|
|
1591
1576
|
|
|
1592
1577
|
`Problems.create(owner, code, status, detail, extensions?, options?)` derives a
|
|
@@ -1630,6 +1615,12 @@ complete RFC 9457 object.
|
|
|
1630
1615
|
failure truth, lifecycle, scheduling, or recovery. Sharing a renderer with
|
|
1631
1616
|
Problems does not merge their semantics.
|
|
1632
1617
|
|
|
1618
|
+
§notice-directive A Notice's `message` states what happened ({§diagnostic-observation}).
|
|
1619
|
+
When the observation concerns the model's own output, the producer may attach one
|
|
1620
|
+
`directive`: `YOU MUST`, `YOU MUST NOT`, `YOU MUST ONLY`, `YOU SHOULD` or
|
|
1621
|
+
`YOU SHOULD NOT`, then the rule. An observation of the environment carries none.
|
|
1622
|
+
Clients display the message; the model packet leads with the directive.
|
|
1623
|
+
|
|
1633
1624
|
### §client-display-capabilities 13.7 Client display capabilities
|
|
1634
1625
|
|
|
1635
1626
|
`ClientDisplayCapabilities` is the transport-neutral installed-capability
|
|
@@ -1760,21 +1751,25 @@ class PlurnkParseError extends Error {
|
|
|
1760
1751
|
readonly source: ErrorSource;
|
|
1761
1752
|
readonly severity: Severity;
|
|
1762
1753
|
readonly recovery: string | undefined;
|
|
1754
|
+
readonly operationOmitted: boolean;
|
|
1763
1755
|
}
|
|
1764
1756
|
```
|
|
1765
1757
|
|
|
1758
|
+
§parse-admission **A diagnostic's severity does not describe whether an operation ran.**
|
|
1759
|
+
`operationOmitted` identifies unexecuted unfenced operations, unknown operation-shaped
|
|
1760
|
+
tags and unrecovered native calls. A warning about a retained operation or a quoted
|
|
1761
|
+
example does not set it. This fact survives serialization when true; consumers do
|
|
1762
|
+
not infer it from diagnostic wording. It does not independently prescribe a strike.
|
|
1763
|
+
|
|
1766
1764
|
§parse-recovery **Every hard diagnostic carries its working form.** A `severity: "error"`
|
|
1767
|
-
diagnostic names, in `recovery`, the form
|
|
1768
|
-
carries the operation's canonical line (`` `READ (path) <L,M>? pattern? <!-- aside -->?`
|
|
1769
|
-
opening fence line; READ takes no body. ``), a refused
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
carries none, since its statement ran. A refused matcher carries the same pair into its own
|
|
1776
|
-
operation's Problem ({§matcher-refusal}). Before this, a refused regex (`/*url*/`, DeepSeek run429)
|
|
1777
|
-
reported `Nothing to repeat` with no way forward and the turn was spent.
|
|
1765
|
+
diagnostic names, in `recovery`, the form of the construct it refused, in the model's terms: a
|
|
1766
|
+
refused heading carries the operation's canonical line (`` `READ (path) <L,M>? pattern? <!-- aside -->?`
|
|
1767
|
+
on the opening fence line; READ takes no body. ``), a refused scope the scope's form, and a refused
|
|
1768
|
+
matcher its dialect's form with an example (`` A pattern is a regex written `/pattern/flags`, such
|
|
1769
|
+
as `/timeout/i`. ``). The working form is the language's, never a reconstruction of the input
|
|
1770
|
+
({§diagnostic-observation}). The runtime projects `recovery` as the Problem's `recovery` beside the
|
|
1771
|
+
verbatim `message`; an advisory carries none. A refused matcher carries
|
|
1772
|
+
the same pair into its own operation's Problem ({§matcher-refusal}).
|
|
1778
1773
|
|
|
1779
1774
|
§parser-position Parser source locations are points, not text regions. An AST
|
|
1780
1775
|
statement's `position` identifies the first backtick of its header; a diagnostic
|
|
@@ -1837,9 +1832,8 @@ diagnostics are:
|
|
|
1837
1832
|
refusal ({§matcher-refusal}).
|
|
1838
1833
|
- §regex-sed-range **A sed line range is named as one.** A regex matcher written as a sed
|
|
1839
1834
|
address range — `/a/,/b/` or `/a/,+N` — is refused ({§matcher-refusal}) as a range, never as invalid flags: the
|
|
1840
|
-
diagnostic
|
|
1841
|
-
|
|
1842
|
-
(`<first,last>`, or `<N,M>` with M being N plus the range's count).
|
|
1835
|
+
diagnostic names the range suffix and gives the regex matcher's working form.
|
|
1836
|
+
It does not synthesize a different selector or a workflow ({§diagnostic-observation}).
|
|
1843
1837
|
- §unclosed-regex **A regex that never closes.** A `/pattern` matcher with no closing
|
|
1844
1838
|
`/` is read as the whole pattern with no flags, with one warning-severity advisory
|
|
1845
1839
|
naming the closing slash and the flag position. The reading is deterministic because
|
|
@@ -1870,15 +1864,9 @@ diagnostics are:
|
|
|
1870
1864
|
`FIND (src/parser.ts) [{"pattern": "/\\bparse\\w+\\b/"}]`. `^` claims the regex
|
|
1871
1865
|
dialect without slashes or flags: the whole text is the pattern, so
|
|
1872
1866
|
`READ (notes.md) ^Decision:.*` selects lines beginning with `Decision:`.
|
|
1873
|
-
`^` is deliberately absent from `plurnk.md`'s dialect table
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
was taught to, and the engine honours what it will reach for anyway. Teaching it would
|
|
1877
|
-
spend hot-path weight on a line that changes no behaviour. The omission is therefore not
|
|
1878
|
-
drift between the teaching and the engine, and closing it in either direction is a
|
|
1879
|
-
regression: restoring the row pays for nothing, and retiring the prefix makes the
|
|
1880
|
-
pretrained spelling a glob that matches a literal caret — silence in place of the
|
|
1881
|
-
selection the model asked for.
|
|
1867
|
+
`^` is deliberately absent from `plurnk.md`'s dialect table: a model writes the anchor
|
|
1868
|
+
whether or not it is taught, so the engine honours it without spending hot-path teaching
|
|
1869
|
+
on it. The omission is not drift between the teaching and the engine.
|
|
1882
1870
|
- §trailing-slots **Slots after the matcher peel off the right.** The heading text after
|
|
1883
1871
|
the matcher is read backwards: a trailing `<!-- aside -->`, a trailing `<scope>` in the
|
|
1884
1872
|
shapes the lexer admits (result positions on FIND, text coordinates elsewhere) and a
|
|
@@ -1916,9 +1904,9 @@ diagnostics are:
|
|
|
1916
1904
|
- §bare-target **A target written without its parentheses is refused with the line that runs.**
|
|
1917
1905
|
A FIND, READ or EDIT heading with no target whose heading text opens with a word that is no
|
|
1918
1906
|
matcher sigil, `READ a.py <1,4>`, cannot run: the word stands where the target goes, but on FIND it
|
|
1919
|
-
could as well be a pattern. The statement is one hard diagnostic
|
|
1920
|
-
`` `READ` has no target: `a.py` stands where the target goes.
|
|
1921
|
-
|
|
1907
|
+
could as well be a pattern. The statement is one hard diagnostic,
|
|
1908
|
+
`` `READ` has no target: `a.py` stands where the target goes. ``, whose recovery is the operation's
|
|
1909
|
+
working form ({§parse-recovery}).
|
|
1922
1910
|
- §bare-anchor-scope **An EDIT's anchor without its angle brackets is its scope.** On an EDIT
|
|
1923
1911
|
heading, `@abcde` or `@abcde,@fghij` standing alone where the scope goes — nothing but an aside, a
|
|
1924
1912
|
closer or the line end after it — is the scope `<@abcde>`, with one warning-severity advisory:
|
|
@@ -1927,10 +1915,10 @@ diagnostics are:
|
|
|
1927
1915
|
marker (14 distinct recorded headings). On READ and KILL the same text stays a literal matcher,
|
|
1928
1916
|
since `@patch` is a search a model means.
|
|
1929
1917
|
- §matcher-body-redirect **Unread body text on bodyless operations.** FIND, READ and bodyless
|
|
1930
|
-
KILL keep the statement but
|
|
1931
|
-
`READ takes no body;
|
|
1932
|
-
|
|
1933
|
-
|
|
1918
|
+
KILL keep the statement but do not use text the matcher did not consume, with one warning
|
|
1919
|
+
naming where it stands: `READ takes no body; lines 4–38 were not used.`, or `the text after its
|
|
1920
|
+
heading on line 3` when it shares the heading's line. KILL's advisory says `This KILL`, limiting the claim to that invocation:
|
|
1921
|
+
log distillation bodies remain valid. Delivered like
|
|
1934
1922
|
{§misplaced-aside-advisory} as a `parse_advisory` notice (a warning, never an error).
|
|
1935
1923
|
One sigil line beneath a bodyless heading is the bare form written a line low and still lifts;
|
|
1936
1924
|
nothing else is promoted into a matcher from below the heading. An option block's `pattern`
|
|
@@ -1960,33 +1948,33 @@ diagnostics are:
|
|
|
1960
1948
|
with any other content is ignored under the same advisory path
|
|
1961
1949
|
({§matcher-body-redirect}).
|
|
1962
1950
|
|
|
1963
|
-
§error-shape The diagnostic class determines
|
|
1964
|
-
|
|
1951
|
+
§error-shape The diagnostic class determines the parts of a message; every class says what
|
|
1952
|
+
happened, never why ({§diagnostic-observation}). Advisories belong to one successfully built statement. A rejected
|
|
1965
1953
|
statement emits its hard diagnostic, not normalization advisories; neither a
|
|
1966
1954
|
rejection nor an internal exception carries advisories into another statement
|
|
1967
1955
|
or parser invocation.
|
|
1968
1956
|
|
|
1969
|
-
| Class
|
|
1970
|
-
|
|
1971
|
-
| Hard fact
|
|
1972
|
-
|
|
|
1973
|
-
|
|
|
1974
|
-
| Boundary loss | `unparsedTail` | Where trust ends, which header slot remains open, and why later input is undefined. |
|
|
1957
|
+
| Class | Surface | Message contract |
|
|
1958
|
+
|---------------|-----------------------|-------------------------------------------------------------------------------------------------------------------|
|
|
1959
|
+
| Hard fact | `severity: "error"` | What was read, where, and the constraint it violates, in PLURNK vocabulary; `recovery` is the construct's working form ({§parse-recovery}). |
|
|
1960
|
+
| Advisory | `severity: "warning"` | What was read and what was done with it, read as a named construct or not used, and where; the statement remains admitted. |
|
|
1961
|
+
| Boundary loss | `unparsedTail` | Where trust ends and which header slot remains open; later input is undefined. |
|
|
1975
1962
|
|
|
1976
1963
|
All messages use PLURNK protocol vocabulary: opening fence, closing fence, target,
|
|
1977
1964
|
scope, line marker, body, section boundary, or space between slots. They never
|
|
1978
1965
|
expose ANTLR rule or token names. They refer to a slot or
|
|
1979
|
-
feature rather than an implementation rule. Generic tutoring,
|
|
1980
|
-
|
|
1966
|
+
feature rather than an implementation rule. Generic tutoring, coordinate
|
|
1967
|
+
restatement and multiple repair strategies are forbidden, and no message names an
|
|
1968
|
+
intent ({§diagnostic-observation}).
|
|
1981
1969
|
Unexpected top-level text immediately after a closed operation identifies that
|
|
1982
1970
|
operation's opening line, closing line, and matching backtick count.
|
|
1983
1971
|
|
|
1984
1972
|
Examples of canonical hard facts:
|
|
1985
1973
|
|
|
1986
1974
|
- `unrecognized character '<' in target`
|
|
1987
|
-
- `
|
|
1975
|
+
- `unrecognized character '[' in the sh header`
|
|
1988
1976
|
- `unrecognized character 'X' in statement header`
|
|
1989
|
-
- `
|
|
1977
|
+
- `unrecognized character '[' in the WAIT header`
|
|
1990
1978
|
- `expected ')'; got ':'`
|
|
1991
1979
|
|
|
1992
1980
|
Each malformed statement produces at most one hard error. The first recorded
|