@plurnk/plurnk-contracts 1.20.0 → 1.21.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 +125 -109
- package/dist/src/types.d.ts +1 -1
- package/dist/src/types.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 +37 -60
package/SPEC.md
CHANGED
|
@@ -267,58 +267,52 @@ input
|
|
|
267
267
|
`````
|
|
268
268
|
|
|
269
269
|
§section-boundary Every statement is one backtick block. Its header occupies one
|
|
270
|
-
physical line: a fence of at least three backticks ({§operation-fences}),
|
|
271
|
-
|
|
270
|
+
physical line: a fence of at least three backticks ({§operation-fences}), then the name
|
|
271
|
+
and its slots. A closer is shown by
|
|
272
272
|
convention and never demanded ({§fence-closer}, {§closer-fallback}). There are no
|
|
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
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
and a delimited fence never closes a bare one. The compact one-line form closes on
|
|
283
|
-
its heading line after the modifiers under the same rule.
|
|
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.
|
|
284
282
|
|
|
285
283
|
§balanced-fences A complete nested interpretation takes precedence over missing-closer
|
|
286
|
-
recovery. Within
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
fences inside a body are never promoted to operations ({§fence-heading-in-body}). `plurnk.md`
|
|
310
|
-
teaches exactly four; other accepted widths are not taught. Every producer of a statement — the
|
|
311
|
-
parser, a client composing `/look`, a client's tab-completion — writes `PLURNK_FENCE` rather than
|
|
312
|
-
its own literal (plurnk/plurnk#92).
|
|
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.
|
|
296
|
+
|
|
297
|
+
§operation-fences **Accept three or more backticks; teach and render three.** A line-start fence
|
|
298
|
+
of three or more backticks naming a native operation or registered executor opens that
|
|
299
|
+
operation ({§indented-fences}), and no width draws a receipt. Three is the taught form and the
|
|
300
|
+
rendered form; a wider fence is the same statement, and it is how a body holding fence lines of
|
|
301
|
+
its own is held: an opener wider than any of them ({§balanced-fences}). Enclosing quotations
|
|
302
|
+
remain inert ({§quotation}), and a fence inside an intact block is never promoted to an
|
|
303
|
+
operation ({§fence-heading-in-body}). `plurnk.md` teaches exactly three and shows the wider
|
|
304
|
+
fence only as the nesting form. Every producer of a statement — the parser, a client composing
|
|
305
|
+
`/look`, a client's tab-completion — writes `PLURNK_FENCE` rather than its own literal
|
|
306
|
+
(plurnk/plurnk#92).
|
|
313
307
|
|
|
314
308
|
§naked-operation **A native operation's name alone on a line opens it without a fence.** A
|
|
315
309
|
column-zero line outside any block that is exactly an operation's name, with nothing but
|
|
316
|
-
horizontal whitespace after it, opens that operation as if it were fenced with the taught
|
|
310
|
+
horizontal whitespace after it, opens that operation as if it were fenced with the taught three
|
|
317
311
|
backticks: no target, no modifiers, and a body that runs to a line that is exactly the name
|
|
318
|
-
again, to the next
|
|
319
|
-
|
|
312
|
+
again, to the next heading ({§fence-heading-in-body}), or to the end of the turn. A fence inside
|
|
313
|
+
naming nothing known is body; the block expects no closer, so its body is never cut
|
|
320
314
|
back ({§closer-fallback}). It runs, and one warning-severity receipt follows its statement —
|
|
321
|
-
`` `KILL` opened with no fence; the taught form is
|
|
315
|
+
`` `KILL` opened with no fence; the taught form is three backticks. `` One rule for every native
|
|
322
316
|
operation: a naked `WAIT` parks, a naked `NOTE` takes its text, a naked `READ` meets the ordinary
|
|
323
317
|
missing-target refusal. Only the bare name qualifies; a name with anything else on its line is
|
|
324
318
|
the unfenced form and still refuses ({§unfenced-operation}), executors are runtimes rather than
|
|
@@ -327,54 +321,49 @@ operations, and reasoning is never read this way. Measured before it was accepte
|
|
|
327
321
|
three loops lost to the refusal at the strike threshold.
|
|
328
322
|
|
|
329
323
|
§fence-heading-in-body Outside a complete nested block ({§balanced-fences}), a fence
|
|
330
|
-
line of three or more backticks
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
({§closer-fallback}) and opens the next statement. Fence lines of fewer than three
|
|
324
|
+
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
|
|
335
328
|
backticks are never headings ({§operation-fences}). Known executors are `sh` plus what
|
|
336
|
-
the host names in `ParseOptions.executors`. Consequences: a
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
when their own fences are incomplete.
|
|
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.
|
|
340
332
|
|
|
341
333
|
§closer-fallback A block that ends at a heading or at the end of the input has no
|
|
342
|
-
closer of its own. Its body is cut back to its last bare fence line (any count,
|
|
343
|
-
|
|
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
|
|
344
336
|
ending goes with it; when no bare fence line exists the body is the whole span less
|
|
345
337
|
one terminating line ending. This carries no diagnostic: a missing closer is never
|
|
346
338
|
an admission failure, and {§unparsed-tail-boundary} is not involved.
|
|
347
339
|
|
|
348
|
-
`plurnk.md`
|
|
349
|
-
immediately after a newline"*; this recovery is not taught. It sits at the quiet end of
|
|
340
|
+
`plurnk.md` shows every operation closed; this recovery is not taught. It sits at the quiet end of
|
|
350
341
|
the scale {§response-text-note} describes: the model opened the operation correctly
|
|
351
342
|
and only failed to close it, so the harness reads what it plainly meant and says nothing.
|
|
352
343
|
A departure that small earns no correction — telling a model its closer was missing costs
|
|
353
344
|
a sentence in every future packet to fix something already fixed.
|
|
354
345
|
|
|
355
346
|
§fence-boundary Balanced nesting is resolved before local recovery. Otherwise,
|
|
356
|
-
fences are read by count
|
|
347
|
+
fences are read by count, except for the heading rule above:
|
|
357
348
|
|
|
358
349
|
| Fence encountered inside a body | Meaning |
|
|
359
350
|
|---|---|
|
|
360
351
|
| Part of a complete nested block | Literal body, including its openers and closers |
|
|
352
|
+
| Indented four spaces or more, or by a tab | Body ({§indented-fences}) |
|
|
361
353
|
| Fewer backticks than the block's own | Body |
|
|
362
|
-
| At least the block's backticks, bare
|
|
363
|
-
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
is correct by construction and there is no mistake to report (operator, 2026-09-21). The parser
|
|
376
|
-
presumes nothing about why a fence is offset. Outside an operation, that quotation is
|
|
377
|
-
response text under {§response-text}; inside a body, it stays literal body content.
|
|
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 |
|
|
356
|
+
|
|
357
|
+
§indented-fences **CommonMark's indentation, everywhere.** A fence line may follow at most three
|
|
358
|
+
spaces; four or more, or a tab, make it indented code. That one rule reads every fence purpose the
|
|
359
|
+
same way: an opener within three spaces opens, a closer within three closes, a heading within
|
|
360
|
+
three ends an unclosed block, and a body keeps its own lines' indentation. A fence indented
|
|
361
|
+
further is literal wherever it stands — prose outside a block, body inside one — and draws no
|
|
362
|
+
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
|
|
366
|
+
{§response-text}; inside a body, it stays literal body content.
|
|
378
367
|
|
|
379
368
|
§inline-chain A closer on a heading line, or on a body's closing line, may be
|
|
380
369
|
followed on that same line by the next opener; the closer still closes, and the
|
|
@@ -386,7 +375,7 @@ text there is the heading's own and is read under {§transparent-inline-closer}.
|
|
|
386
375
|
closing fence on a heading line followed by more of that heading — a `<scope>`, an
|
|
387
376
|
`[option block]`, a `<!-- aside -->`, or a naked matcher — does not end the reading: the
|
|
388
377
|
heading keeps taking its slots under {§trailing-slots} and {§naked-pattern}, exactly as though
|
|
389
|
-
the closer were absent, so
|
|
378
|
+
the closer were absent, so ```` ```READ (a.md)``` ```` `<1,2>` is the same operation as `READ (a.md) <1,2>`.
|
|
390
379
|
The closer is still a closer: the block ends with that physical line and never reaches down for
|
|
391
380
|
the next operation, which is what a bare heading carrying a matcher would do. A closer followed
|
|
392
381
|
by the next opener is {§inline-chain}, and by nothing is the ordinary {§fence-closer}. There is
|
|
@@ -413,7 +402,7 @@ identity; absent `node`, the shorthand grants no executable capability.
|
|
|
413
402
|
line: prose, then heading after heading with no line ending anywhere. Two
|
|
414
403
|
rules absorb it. The next opener on a heading's own line, after the heading's
|
|
415
404
|
slots, ends that heading's block bodyless and opens ({§empty-section}), so
|
|
416
|
-
|
|
405
|
+
````EDIT (a.rs) <60,66> <!-- drop --> ```EDIT (b.rs) <31,38>` is two scoped
|
|
417
406
|
deletions. Literal inline bodies follow {§heading-inline-body}.
|
|
418
407
|
|
|
419
408
|
§anchor-digits In a text scope, `@` followed by one to four digits cannot be a
|
|
@@ -425,28 +414,33 @@ line takes the rest of the line as the aside, with one warning-severity advisory
|
|
|
425
414
|
A closed aside followed by more text is unchanged.
|
|
426
415
|
|
|
427
416
|
§quotation **A fence that opens no operation quotes.** Outside a body, a line-start fence that
|
|
428
|
-
is not an operation heading — unlabeled, tagged like a code block (`ts`, `json`),
|
|
429
|
-
|
|
417
|
+
is not an operation heading — unlabeled, tagged like a code block (`ts`, `json`), or naming
|
|
418
|
+
nothing registered — opens a
|
|
430
419
|
quotation that runs to its matching closer (same character, width at least the opener's) or to
|
|
431
420
|
the end of the input. Everything inside is data: no operation runs there and native tool-call
|
|
432
421
|
markup is not read ({§native-tool-calls}). An operation fenced inside an unlabeled code block
|
|
433
|
-
draws one warning that it was shown, not run
|
|
434
|
-
|
|
435
|
-
|
|
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.
|
|
428
|
+
So a model may show plurnk's own operations in an answer. Two exceptions keep programs whole:
|
|
436
429
|
CommonMark's own rule that a backtick opener's line carries no further backtick, so
|
|
437
|
-
```` ```READ (x)``` ```` is inline code and quotes nothing after it; a bare fence directly under
|
|
438
|
-
line carrying a fence run, which is an orphaned closer and quotes nothing
|
|
439
|
-
|
|
440
|
-
|
|
430
|
+
```` ```READ (x)``` ```` is inline code and quotes nothing after it; and a bare fence directly under
|
|
431
|
+
a line carrying a fence run, which is an orphaned closer and quotes nothing. An unknown tag at
|
|
432
|
+
any width is a code block and draws nothing, unless its line carries a target slot, `(…)`: that
|
|
433
|
+
is an operation the model missed by its tag, and it draws one warning — `` `OP` is not an
|
|
434
|
+
operation or a known executor here. `` An offset example draws nothing either
|
|
435
|
+
({§indented-fences}). Quotation outside an operation is
|
|
441
436
|
response text under {§response-text}, not an executable program or a completion envelope.
|
|
442
437
|
|
|
443
|
-
`plurnk.md`
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
too. Each is a shape a model reaches for from ordinary Markdown rather than from this
|
|
438
|
+
`plurnk.md` names the tab offset as the form for an example, in the aside of its nesting
|
|
439
|
+
example, and shows its own examples offset; the other quoting fences are untaught: a tilde
|
|
440
|
+
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
|
|
447
441
|
teaching, so honouring it protects an example the model already believed was safe
|
|
448
|
-
({§response-text-note} places the scale). The
|
|
449
|
-
|
|
442
|
+
({§response-text-note} places the scale). The offset is the one form that survives every
|
|
443
|
+
fence style.
|
|
450
444
|
|
|
451
445
|
§interstitial-fence Superseded by {§quotation}: an unlabeled fence no longer opens nothing, it
|
|
452
446
|
quotes. (It in turn replaced the retired unlabeled-fence SEND of the fences chapter, whose
|
|
@@ -471,15 +465,24 @@ reading, with no diagnostic and no teaching (#758):
|
|
|
471
465
|
Tokens keep their source positions; only their order in the stream changes.
|
|
472
466
|
|
|
473
467
|
§native-tool-calls An emission that yields no operation may be a model's native
|
|
474
|
-
tool-call markup
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
468
|
+
tool-call markup naming a plurnk operation or a known executor, and every popular
|
|
469
|
+
family is read the same way: DeepSeek's `<||DSML|| calls>` and Anthropic-style
|
|
470
|
+
`<function_calls>` blocks of `invoke` elements with `parameter` children; the
|
|
471
|
+
`<tool_call>` family as `<function=NAME>` with `<parameter=key>` children (Qwen,
|
|
472
|
+
MiMo), as a JSON object with `name` and `arguments` (Hermes and kin), or as a name
|
|
473
|
+
followed by `<arg_key>`/`<arg_value>` pairs (GLM); a bare `<function=NAME>` element
|
|
474
|
+
(Llama); Mistral's `[TOOL_CALLS]` JSON array; Llama's `<|python_tag|>` JSON object; and
|
|
475
|
+
Kimi's `<|tool_call_begin|>` sections. Each call is read as that operation's
|
|
476
|
+
canonical fence: `path`/`target`/`file_path`/`file`/`resource`/`uri` fill the target,
|
|
477
|
+
`scope`/`range`/`lines` the scope, as do `start`/`end` written apart and `offset`/`limit`
|
|
478
|
+
(a first line and a count), `pattern`/`regex`/`query` a matcher option, `aside`
|
|
479
|
+
the aside, and `body`/`content`/`command`/`text`/`input` or plain text inside the
|
|
480
|
+
call the body; plurnk slots written after the name are kept, a trailing scope's own
|
|
481
|
+
bracket may close the tag. A block keeps its line count where its lines allow, so
|
|
482
|
+
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).
|
|
483
486
|
|
|
484
487
|
§empty-section Both the compact bodyless form and an empty multiline block
|
|
485
488
|
normalize optional bodies to null. Closing fences are conventional, never required
|
|
@@ -489,10 +492,9 @@ normalize optional bodies to null. Closing fences are conventional, never requir
|
|
|
489
492
|
runtime fences from the shared AST, with one blank line between operations.
|
|
490
493
|
Every closing fence occupies its own line, including bodyless operations;
|
|
491
494
|
inline fences remain accepted input, not generated examples.
|
|
492
|
-
It chooses at least
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
delimiter are syntax, not AST or persistence state. Core-authored programs use
|
|
495
|
+
It chooses at least three backticks and more than any run within the body
|
|
496
|
+
({§balanced-fences}), preserving body bytes on reparse. Fence length is syntax,
|
|
497
|
+
not AST or persistence state. Core-authored programs use
|
|
496
498
|
this serializer and the ordinary admission parser. Rendering preserves a matcher
|
|
497
499
|
beside owner metadata, not only a matcher carried inside its `pattern` option.
|
|
498
500
|
|
|
@@ -1090,7 +1092,8 @@ under {§turn-ops-log-curation}; body bytes and source positions are unchanged.
|
|
|
1090
1092
|
The model-turn entry point returns each non-whitespace text span outside operation
|
|
1091
1093
|
regions as an ordered `text` item with its exact content and source position.
|
|
1092
1094
|
Quoted blocks remain literal text, including every nested operation-looking line.
|
|
1093
|
-
Operation bodies, asides
|
|
1095
|
+
Operation bodies, asides, malformed operation regions and unfenced operation lines
|
|
1096
|
+
({§unfenced-operation}) are not response text;
|
|
1094
1097
|
nothing at or beyond a lost boundary is recovered as text. The statement and client
|
|
1095
1098
|
tiers ignore outside text. Core alone owns filing it as a NOTE ({§response-text-note})
|
|
1096
1099
|
and no-operation strikes ({§empty-turn}); parsing never infers delivery or completion
|
|
@@ -1099,12 +1102,17 @@ intent.
|
|
|
1099
1102
|
§unfenced-operation **An operation written without its fence did not run, and the parser says
|
|
1100
1103
|
so.** An outside-text line that opens at column zero with an operation's name and anything else
|
|
1101
1104
|
— `KILL The answer…`, `READ (a.md)`, `KILL (notes.md)` — draws one warning: `` `KILL` has no
|
|
1102
|
-
fence, so it did not run. `` The line
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
({§
|
|
1106
|
-
|
|
1107
|
-
|
|
1105
|
+
fence, so it did not run. `` The line is not response text ({§response-text}): it is neither filed as
|
|
1106
|
+
a NOTE nor echoed into the next packet, and the exact emission remains at `ops://` (operator,
|
|
1107
|
+
2026-09-23); the bare name alone
|
|
1108
|
+
opens the operation instead ({§naked-operation}). A registered executor's name followed by an
|
|
1109
|
+
operand slot — `gitea (list_issues)`, `sh(build.sh)` — draws the same warning under the executor's
|
|
1110
|
+
own spelling; quoted blocks, offset lines and names inside a sentence draw nothing, since `sh`,
|
|
1111
|
+
`env` and `members` are ordinary words. The model that wrote it believes it ran: while the line was
|
|
1112
|
+
still filed as a NOTE ({§response-text-note}), an unfenced KILL read back as an answer already given,
|
|
1113
|
+
and the model repeated it until the cycle detector ended the loop (`demo-overflow-recovery-AC4Ul4`;
|
|
1114
|
+
the same shape defeated SEND recovery and a count of invalid characters; operator, 2026-09-22). The
|
|
1115
|
+
warning and the exclusion together end that echo.
|
|
1108
1116
|
|
|
1109
1117
|
§recorded-emissions **The parser is regressed against emissions models actually produced,
|
|
1110
1118
|
not fixtures we wrote.** `test/fixtures/recorded-emissions.jsonl` holds one real exemplar
|
|
@@ -1540,6 +1548,14 @@ diagnostics are:
|
|
|
1540
1548
|
diagnostic, with or without flags, without assuming what the extra text was
|
|
1541
1549
|
intended to represent. Invalid patterns or flags retain the native
|
|
1542
1550
|
regex failure; no branch silently removes or executes trailing content.
|
|
1551
|
+
- §unclosed-regex **A regex that never closes.** A `/pattern` matcher with no closing
|
|
1552
|
+
`/` is read as the whole pattern with no flags, with one warning-severity advisory
|
|
1553
|
+
naming the closing slash and the flag position. The reading is deterministic because
|
|
1554
|
+
the heading's own boundaries bound it ({§naked-pattern}: the matcher runs to the end
|
|
1555
|
+
of the heading, and an aside is lexed apart from it). A bare `/` with nothing after
|
|
1556
|
+
it has no pattern to read and is refused as `invalid-operation-syntax` naming what
|
|
1557
|
+
is missing. A matcher with a second unescaped `/` is not unclosed: it is
|
|
1558
|
+
`/pattern/flags`, and invalid flags keep their native failure with the escape hint.
|
|
1543
1559
|
- §naked-pattern **The matcher rides the heading bare.** After the path, and any
|
|
1544
1560
|
scope or option block, the rest of a FIND, READ or KILL heading line is the
|
|
1545
1561
|
matcher, in whichever dialect its first characters claim
|
|
@@ -1679,6 +1695,6 @@ runtime constructs this; the parser provides the fields):
|
|
|
1679
1695
|
"column": 12,
|
|
1680
1696
|
"source": "parser",
|
|
1681
1697
|
"severity": "error",
|
|
1682
|
-
"message": "READ block opened at line 1 but was not closed with
|
|
1698
|
+
"message": "READ block opened at line 1 but was not closed with 3 backticks"
|
|
1683
1699
|
}
|
|
1684
1700
|
```
|
package/dist/src/types.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export * from "./types.generated.ts";
|
|
|
2
2
|
import type { ClientStatement, LoopPolicy, Position, PlurnkStatement, ProviderRequestAccounting, ReasoningPolicy } from "./types.generated.ts";
|
|
3
3
|
import type PlurnkParseError from "./PlurnkParseError.ts";
|
|
4
4
|
export declare const PLURNK_OPS: readonly ["FIND", "READ", "EDIT", "COPY", "MOVE", "SEND", "BARE", "WORK", "FORK", "KILL", "NOTE", "WAIT"];
|
|
5
|
-
export declare const PLURNK_FENCE = "
|
|
5
|
+
export declare const PLURNK_FENCE = "```";
|
|
6
6
|
export type PlurnkOp = (typeof PLURNK_OPS)[number];
|
|
7
7
|
export type RuntimeTag = Lowercase<string>;
|
|
8
8
|
export declare const RUNTIME_TAG: RegExp;
|
package/dist/src/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAEA,cAAc,sBAAsB,CAAC;AAKrC,OAAO,KAAK,EACR,eAAe,EACf,UAAU,EACV,QAAQ,EACR,eAAe,EACf,yBAAyB,EACzB,eAAe,EAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,gBAAgB,MAAM,uBAAuB,CAAC;AAM1D,eAAO,MAAM,UAAU,YACnB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAC9E,MAAM,EAAE,MAAM,CACR,CAAC;AAGX,eAAO,MAAM,YAAY,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAEA,cAAc,sBAAsB,CAAC;AAKrC,OAAO,KAAK,EACR,eAAe,EACf,UAAU,EACV,QAAQ,EACR,eAAe,EACf,yBAAyB,EACzB,eAAe,EAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,gBAAgB,MAAM,uBAAuB,CAAC;AAM1D,eAAO,MAAM,UAAU,YACnB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAC9E,MAAM,EAAE,MAAM,CACR,CAAC;AAGX,eAAO,MAAM,YAAY,QAAQ,CAAC;AAElC,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAKnD,MAAM,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;AAC3C,eAAO,MAAM,WAAW,QAAwB,CAAC;AACjD,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAmC,CAAC;AACrF,eAAO,MAAM,aAAa,OAAQ,MAAM,GAAG,IAAI,GAAG,SAAS,KAAG,EAAE,IAAI,UAAyF,CAAC;AAC9J,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS;IAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,aAAa,CAAC,KAAG,SAAS,IAAI,OAAO,CAAC,CAAC,EAAE;IAAE,OAAO,EAAE,UAAU,CAAA;CAAE,CAChH,CAAC;AAG3B,eAAO,MAAM,SAAS,GAAI,CAAC,SAAS,eAAe,GAAG,eAAe,aAAa,CAAC,KAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,GAAG,UACT,CAAC;AAK5G,MAAM,WAAW,uBAAuB;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,yBAAyB,GAAG,CACpC,UAAU,EAAE,yBAAyB,KACpC,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB,MAAM,MAAM,uBAAuB,GAAG,CAClC,QAAQ,EAAE,uBAAuB,KAChC,OAAO,CAAC,yBAAyB,CAAC,CAAC;AAIxC,eAAO,MAAM,kBAAkB,EAE1B,SAAS,eAAe,EAAE,CAAC;AAGhC,eAAO,MAAM,iBAAiB,EAEzB,SAAS,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;AAGxC,eAAO,MAAM,WAAW,QAAqC,CAAC;AAG9D,eAAO,MAAM,UAAU,QAAiE,CAAC;AAGzF,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,QAAQ,CAAyC,CAAC;AAI1F,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAI9B,MAAM,MAAM,SAAS,CAAC,CAAC,GAAG,eAAe,IACnC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,CAAC,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAEjD,MAAM,MAAM,WAAW,CAAC,CAAC,GAAG,eAAe,IAAI;IAC3C,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;IACtB,YAAY,CAAC,EAAE;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACrD,CAAC"}
|
package/dist/src/types.js
CHANGED
|
@@ -12,7 +12,7 @@ export const PLURNK_OPS = [
|
|
|
12
12
|
"NOTE", "WAIT",
|
|
13
13
|
];
|
|
14
14
|
// {§operation-fences} — canonical teaching/rendering width; ingestion also accepts three.
|
|
15
|
-
export const PLURNK_FENCE = "
|
|
15
|
+
export const PLURNK_FENCE = "```";
|
|
16
16
|
export const RUNTIME_TAG = /^[a-z][a-z0-9+.-]*$/;
|
|
17
17
|
export const INTERNAL_ROW_OPS = new Set(["extension", "error"]);
|
|
18
18
|
export const isExecutionOp = (op) => typeof op === "string" && !INTERNAL_ROW_OPS.has(op) && RUNTIME_TAG.test(op);
|
package/dist/src/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,oFAAoF;AACpF,cAAc,sBAAsB,CAAC;AAErC,OAAO,gBAAgB,MAAM,2BAA2B,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAC/E,OAAO,qBAAqB,MAAM,gCAAgC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACzF,OAAO,qBAAqB,MAAM,gCAAgC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAWzF,0EAA0E;AAC1E,6CAA6C;AAE7C,4FAA4F;AAC5F,MAAM,CAAC,MAAM,UAAU,GAAG;IACtB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAC9E,MAAM,EAAE,MAAM;CACR,CAAC;AAEX,0FAA0F;AAC1F,MAAM,CAAC,MAAM,YAAY,GAAG,
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,oFAAoF;AACpF,cAAc,sBAAsB,CAAC;AAErC,OAAO,gBAAgB,MAAM,2BAA2B,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAC/E,OAAO,qBAAqB,MAAM,gCAAgC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACzF,OAAO,qBAAqB,MAAM,gCAAgC,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAWzF,0EAA0E;AAC1E,6CAA6C;AAE7C,4FAA4F;AAC5F,MAAM,CAAC,MAAM,UAAU,GAAG;IACtB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAC9E,MAAM,EAAE,MAAM;CACR,CAAC;AAEX,0FAA0F;AAC1F,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,CAAC;AAQlC,MAAM,CAAC,MAAM,WAAW,GAAG,qBAAqB,CAAC;AACjD,MAAM,CAAC,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;AACrF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAA6B,EAAoB,EAAE,CAAC,OAAO,EAAE,KAAK,QAAQ,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC9J,MAAM,CAAC,MAAM,WAAW,GAAG,CAAiD,SAAY,EAAoD,EAAE,CAC1I,SAAS,IAAI,SAAS,CAAC;AAC3B,6FAA6F;AAC7F,kBAAkB;AAClB,MAAM,CAAC,MAAM,SAAS,GAAG,CAA8C,SAAY,EAA4C,EAAE,CAC7H,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAA6C,CAAC;AAkB5G,2EAA2E;AAC3E,uEAAuE;AACvE,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAC3C,qBAAqB,CAAC,IAAyB,CACpB,CAAC;AAEhC,oEAAoE;AACpE,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,CAC1C,gBAAgB,CAAC,UAAU,CAAC,SAAS,CAAC,IAAiC,CACpC,CAAC;AAExC,wFAAwF;AACxF,MAAM,CAAC,MAAM,WAAW,GAAG,kCAAkC,CAAC;AAE9D,mFAAmF;AACnF,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,MAAM,CAAC,qBAAqB,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AAEzF,sFAAsF;AACtF,MAAM,CAAC,MAAM,gBAAgB,GAAuB,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC"}
|
package/package.json
CHANGED
package/plurnk.md
CHANGED
|
@@ -1,95 +1,81 @@
|
|
|
1
1
|
# Plurnk Harness
|
|
2
2
|
|
|
3
|
-
Pattern Lookup Universal Resource NetworK: find anything by pattern, read it by address, change it by operation.
|
|
4
|
-
|
|
5
3
|
## Plurnk OP Syntax
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
```OP (path)? <scope|range>? [metadata]? pattern? <!-- aside -->?
|
|
8
6
|
body?
|
|
9
|
-
|
|
7
|
+
```
|
|
10
8
|
|
|
11
9
|
> [!IMPORTANT]
|
|
12
|
-
> YOU MUST use valid Plurnk OPs.
|
|
13
|
-
|
|
14
|
-
> [!TIP]
|
|
15
|
-
> YOU SHOULD tab offset any example OP you do not intend to execute.
|
|
16
|
-
|
|
17
|
-
* `[metadata]`: optional one-line special configuration.
|
|
18
|
-
* `<!-- aside -->`: optional terse explanation.
|
|
19
|
-
* Parameters and the aside stay on the OP line; the body starts on the next.
|
|
10
|
+
> YOU MUST ONLY use valid Plurnk OPs, with all parameters and the optional terse aside on the fenced OP line.
|
|
20
11
|
|
|
21
12
|
## Core Plurnk OPs
|
|
22
13
|
|
|
23
|
-
* NOTE: Reasoning scratchpad for
|
|
14
|
+
* NOTE: Reasoning scratchpad for recording conclusions, decisions, and facts.
|
|
24
15
|
* FIND: List matching paths, or the match locations inside one path.
|
|
25
16
|
* READ: Read files, entries, streams, or only the lines a pattern selects.
|
|
26
17
|
* EDIT: Create a file or entry; replace existing text by scope or by pattern.
|
|
27
18
|
* COPY: (path) <scope>? (path) <scope>? - Copy files, entries, streams, or text regions.
|
|
28
19
|
* MOVE: (path) <scope>? (path) <scope>? - Move files, entries, streams, or text regions.
|
|
29
|
-
* KILL: End things — delete an entry, stop a process, retire log items, or end the loop
|
|
20
|
+
* KILL: End things — delete an entry, stop a process, retire log items, or end the loop.
|
|
30
21
|
* WORK: Deploy a child worker (fresh log).
|
|
31
22
|
* FORK: Deploy a forked worker (forked log).
|
|
32
|
-
* BARE: Deploy an isolated inference
|
|
23
|
+
* BARE: Deploy an isolated inference on the fence body (no log or tools).
|
|
33
24
|
* WAIT: Yield until the next wake: a child worker's result or a stream's end.
|
|
34
25
|
* SEND: Message endpoints or workers.
|
|
35
26
|
|
|
36
27
|
## Workflow Management
|
|
37
28
|
|
|
38
29
|
> [!IMPORTANT]
|
|
39
|
-
>
|
|
40
|
-
|
|
41
|
-
> [!WARNING]
|
|
42
|
-
> YOU MAY NOT end the loop with KILL before all other OPs, child workers, and streams are resolved and reviewed.
|
|
30
|
+
> YOU MUST deliver the final response as a turn with ONLY a single parameterless KILL with the response in the body:
|
|
43
31
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
> [!TIP]
|
|
49
|
-
> Free text, NOTEs, and other messages are not the final deliverable response.
|
|
32
|
+
```KILL
|
|
33
|
+
This is an example final deliverable response. It's alone. All child workers and streams are resolved and reviewed.
|
|
34
|
+
```
|
|
50
35
|
|
|
51
36
|
## Workspace Navigation
|
|
52
37
|
|
|
53
|
-
|
|
54
|
-
|
|
38
|
+
```FIND (src/**/*.ts) /TODO/ <!-- paths with matches -->
|
|
39
|
+
```
|
|
55
40
|
|
|
56
|
-
|
|
57
|
-
|
|
41
|
+
```READ (belfry.md) /\bbats?\b/i <!-- only the lines matching "bat" or "bats" -->
|
|
42
|
+
```
|
|
58
43
|
|
|
59
|
-
* `(path)` may be a glob, permitting bulk operations.
|
|
60
|
-
* Log item paths nest: `log:///1/2/3/READ` is loop/turn/item/
|
|
44
|
+
* `(path)` may be a glob/extglob, permitting bulk operations.
|
|
45
|
+
* Log item paths nest: `log:///1/2/3/READ` is loop/turn/item/OP.
|
|
61
46
|
* FIND results hold one inner array per path: its channels, default first; append `#channel` to select another.
|
|
62
|
-
* Percent-encode `(` as `%28` and `)` as `%29`.
|
|
47
|
+
* Percent-encode in paths `(` as `%28` and `)` as `%29`.
|
|
63
48
|
|
|
64
49
|
## File Editing
|
|
65
50
|
|
|
66
|
-
|
|
51
|
+
```EDIT (example.md) <@abcde>
|
|
67
52
|
literal replacement text
|
|
68
|
-
|
|
53
|
+
```
|
|
69
54
|
|
|
70
|
-
|
|
71
|
-
|
|
55
|
+
```EDIT (books.xml) //book[price > 35.00] <!-- an empty body removes each match -->
|
|
56
|
+
```
|
|
72
57
|
|
|
73
|
-
````
|
|
74
|
-
|
|
75
|
-
|
|
58
|
+
````EDIT (edit-example.md) <!-- Nesting can be resolved with increased outer fences. Examples can use tabbed offset. -->
|
|
59
|
+
```EDIT (create-example.md)
|
|
60
|
+
When representing markdown, `~~~` notation can disambiguate nested content.
|
|
61
|
+
```
|
|
76
62
|
````
|
|
77
|
-
````42
|
|
78
63
|
|
|
79
64
|
> [!TIP]
|
|
80
65
|
> The EDIT body is literal text. YOU SHOULD address lines by `<@hash>` or `<@start,@end>`; stale targets are rejected.
|
|
81
66
|
|
|
82
|
-
> [!TIP]
|
|
83
|
-
> Creating a file creates missing parent directories.
|
|
84
|
-
|
|
85
67
|
## Delegation
|
|
86
68
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
69
|
+
```WORK (worker://alice) <!-- the child's result lands in your log -->
|
|
70
|
+
The child's complete task.
|
|
71
|
+
```
|
|
90
72
|
|
|
91
|
-
|
|
92
|
-
|
|
73
|
+
```BARE
|
|
74
|
+
A self-contained prompt.
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
```KILL (sh:///ab3d5678) <!-- stops a running command -->
|
|
78
|
+
```
|
|
93
79
|
|
|
94
80
|
> [!TIP]
|
|
95
81
|
> `SEND (worker://name)` messages a live worker.
|
|
@@ -99,11 +85,8 @@ Pattern Lookup Universal Resource NetworK: find anything by pattern, read it by
|
|
|
99
85
|
> [!CAUTION]
|
|
100
86
|
> logTokensTotal must not exceed logTokensMax. Successful log KILL receipts are not shown.
|
|
101
87
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
````KILL (log:///**/READ) <17,-1> <!-- trims each item's log lines from 17 on, recovering context -->
|
|
106
|
-
````
|
|
88
|
+
```KILL (log:///1/[1-7]/*/{NOTE,READ}) <17, -1> <!-- trims matching log items, recovering context -->
|
|
89
|
+
```
|
|
107
90
|
|
|
108
91
|
## `<scope|range>`
|
|
109
92
|
|
|
@@ -117,12 +100,6 @@ Pattern Lookup Universal Resource NetworK: find anything by pattern, read it by
|
|
|
117
100
|
| `<SL,SC,EL,EC>` | start included, end excluded — `<2,3,3,6>` is line 2 column 3 through line 3 column 5 |
|
|
118
101
|
| `<0>`, `<-1>` | prepend / append on mutations; as an end line, `-1` is the last line |
|
|
119
102
|
|
|
120
|
-
> [!CAUTION]
|
|
121
|
-
> The hash anchor and line number (`@abcde 42:`) shown on editable text are not content.
|
|
122
|
-
|
|
123
|
-
> [!TIP]
|
|
124
|
-
> Log items often present partial preview ranges. READ more if it's relevant and you have the logTokensMax room for it.
|
|
125
|
-
|
|
126
103
|
## `pattern`
|
|
127
104
|
|
|
128
105
|
> [!TIP]
|
|
@@ -135,4 +112,4 @@ Pattern Lookup Universal Resource NetworK: find anything by pattern, read it by
|
|
|
135
112
|
| `$` | jsonpath (RFC 9535) | `$.items[?(@.price>500)]` |
|
|
136
113
|
| `~` | full-text (SQLite FTS5) | `~retry` |
|
|
137
114
|
| `&` | graph (treesitter symbols) | `&sym`, `&<sym`, `&>sym` |
|
|
138
|
-
| none | literal or extglob
|
|
115
|
+
| none | literal or glob/extglob | `?(export )?(async )function *` |
|