@plurnk/plurnk-contracts 1.9.1 → 1.10.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 +43 -14
- package/dist/conformance/agui-v1.json +32 -1
- package/dist/plurnk.gemma.gbnf +2 -1
- package/dist/plurnk.qwen.gbnf +2 -1
- package/dist/schema/Plan.json +29 -20
- package/dist/schema/PlurnkStatement.json +611 -161
- package/dist/src/AcpPlanValue.d.ts.map +1 -1
- package/dist/src/AcpPlanValue.js +4 -1
- package/dist/src/AcpPlanValue.js.map +1 -1
- package/dist/src/ApplicationPort.d.ts +7 -0
- package/dist/src/ApplicationPort.d.ts.map +1 -1
- package/dist/src/AstBuilder.d.ts +2 -0
- package/dist/src/AstBuilder.d.ts.map +1 -1
- package/dist/src/AstBuilder.js +57 -13
- package/dist/src/AstBuilder.js.map +1 -1
- package/dist/src/PlanValue.d.ts +0 -1
- package/dist/src/PlanValue.d.ts.map +1 -1
- package/dist/src/PlanValue.js +8 -7
- package/dist/src/PlanValue.js.map +1 -1
- package/dist/src/PlurnkErrorStrategy.js +8 -8
- package/dist/src/PlurnkErrorStrategy.js.map +1 -1
- package/dist/src/PlurnkParser.d.ts.map +1 -1
- package/dist/src/PlurnkParser.js +18 -2
- package/dist/src/PlurnkParser.js.map +1 -1
- package/dist/src/generated/plurnkLexer.d.ts +12 -0
- package/dist/src/generated/plurnkLexer.d.ts.map +1 -1
- package/dist/src/generated/plurnkLexer.js +429 -367
- package/dist/src/generated/plurnkLexer.js.map +1 -1
- package/dist/src/generated/plurnkParser.d.ts +19 -9
- package/dist/src/generated/plurnkParser.d.ts.map +1 -1
- package/dist/src/generated/plurnkParser.js +564 -659
- package/dist/src/generated/plurnkParser.js.map +1 -1
- package/dist/src/generated/plurnkParserVisitor.d.ts +7 -0
- package/dist/src/generated/plurnkParserVisitor.d.ts.map +1 -1
- package/dist/src/generated/plurnkParserVisitor.js +6 -0
- package/dist/src/generated/plurnkParserVisitor.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/types.generated.d.ts +1 -4
- package/dist/src/types.generated.d.ts.map +1 -1
- package/package.json +1 -1
- package/plurnk.md +77 -136
package/SPEC.md
CHANGED
|
@@ -224,7 +224,7 @@ framed-turn ::= turn | fence-open turn fence-close
|
|
|
224
224
|
turn ::= plan sep tail-0
|
|
225
225
|
```
|
|
226
226
|
|
|
227
|
-
§gbnf-turn-shape The `gemma` transport root samples one complete
|
|
227
|
+
§gbnf-turn-shape Neither rail admits an empty thought: the `gemma` channel body and the `qwen` think body each begin with at least one character, so a constrained call reasons before it acts. The `gemma` transport root samples one complete
|
|
228
228
|
`<|channel>thought\n … <channel|>` enclosure. A Qwen-style chat template has
|
|
229
229
|
already supplied `<think>\n` when the `qwen` transport root begins, so that root
|
|
230
230
|
samples the body and required `</think>` closer. Each generated artifact declares
|
|
@@ -330,6 +330,15 @@ more horizontal whitespace characters before each slot and any permutation of
|
|
|
330
330
|
the slots admitted by that operation, at most once each. Accepted spacing and
|
|
331
331
|
permutation are not second canonical spellings.
|
|
332
332
|
|
|
333
|
+
§heading-inline-body Text that follows the last slot on a heading line — after
|
|
334
|
+
horizontal whitespace, beginning with a character that cannot open a slot (not `[`,
|
|
335
|
+
`(`, or `<`) — is the first body line: `## EXEC0 [crm] (crm_query) {"soql": "…"}` and
|
|
336
|
+
`## FIND0 (src/**) /createCoder/i` parse as their canonical two-line forms. Nothing is
|
|
337
|
+
lost and the stored statement is canonical; the spelling is tolerated and announced:
|
|
338
|
+
one warning-severity advisory follows the statement, naming the heading and the rule
|
|
339
|
+
(body content goes immediately beneath the OP heading line), so the model learns
|
|
340
|
+
the form from the packet and never from silent acceptance.
|
|
341
|
+
|
|
333
342
|
§operation-annotation A heading may end with one single-line Markdown HTML
|
|
334
343
|
comment. AstBuilder strips the delimiters and surrounding horizontal whitespace
|
|
335
344
|
into the statement's fixed `annotation: string | null` field. The annotation is
|
|
@@ -394,12 +403,12 @@ but that interpretation does not define KILL generally.
|
|
|
394
403
|
§plan-value **PLAN carries one complete Plurnk Plan.** Its entries are the
|
|
395
404
|
model's current working-memory inventory: durable findings are `memory`, finished
|
|
396
405
|
actions are `completed`, open inquiries are `pending`, and active priorities are
|
|
397
|
-
`in_progress`. Admission parses the JSON body — one JSON array document in any whitespace layout, including the {§json-result-rendering} spread the log projects —
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
406
|
+
`in_progress`. Admission parses the JSON body — one JSON array document in any whitespace layout, including the {§json-result-rendering} spread the log projects — strips unknown
|
|
407
|
+
entry keys (the model-facing Plan carries no priority: struck 2026-08-24 so the
|
|
408
|
+
log echoes only the canonical shape, starving stale-field habits), and validates
|
|
409
|
+
the canonical bare array: every entry has string `content` and `status` in
|
|
401
410
|
`pending | in_progress | completed | memory`. A nonempty plain-text,
|
|
402
|
-
malformed-JSON, or otherwise invalid body becomes one `
|
|
411
|
+
malformed-JSON, or otherwise invalid body becomes one `in_progress`
|
|
403
412
|
entry whose content is the exact authored body; admission performs no partial
|
|
404
413
|
repair or list inference. An empty body becomes the planless `[]`
|
|
405
414
|
value. Each PLAN completely replaces the current Plan; it never expresses a
|
|
@@ -411,14 +420,22 @@ the canonical value and has no other runtime effect.
|
|
|
411
420
|
|
|
412
421
|
§plan-acp-projection **Only an ACP-facing boundary projects the model-native
|
|
413
422
|
Plan.** It constructs ACP's `{ "entries": [...] }` Plan object from the internal
|
|
414
|
-
array,
|
|
415
|
-
|
|
416
|
-
|
|
423
|
+
array, synthesizes the ACP-required neutral `medium` priority on every entry
|
|
424
|
+
(the model-native Plan carries none), maps each `memory` entry to ACP
|
|
425
|
+
`completed`, and prefixes its content with exact "Memory: " framing without
|
|
426
|
+
duplicating an existing prefix. Every other entry field remains unchanged, and
|
|
427
|
+
the internal value is not mutated.
|
|
417
428
|
The projected value validates against the separately owned ACP Plan schema pinned
|
|
418
429
|
to ACP v1
|
|
419
430
|
[`schema-v1.21.0`](https://github.com/agentclientprotocol/agent-client-protocol/tree/schema-v1.21.0)
|
|
420
431
|
commit `272bf799f35a258c6a4107a0410ed361e83683d3`.
|
|
421
432
|
|
|
433
|
+
§exec-tag-signal EXEC's bracket slot names its runtime. A bracket whose first character is
|
|
434
|
+
a sign is a tag signal instead — a runtime never starts with `+` or `-` — so
|
|
435
|
+
`## EXEC0 [+fetch] (.)` and `## EXEC0 [crm] [+schema] (crm_describe)` admit: the tags
|
|
436
|
+
classify the log row exactly as on FIND or READ, the runtime is the explicit one or the
|
|
437
|
+
default shell, and each slot appears at most once.
|
|
438
|
+
|
|
422
439
|
§log-tag-signal FIND, READ, EDIT, COPY, MOVE, and BARE canonically express additions
|
|
423
440
|
as `+tag`. Because those operations have no tag-selection semantics, ANTLR also
|
|
424
441
|
tolerates unsigned `tag` as an equivalent addition; `-tag` is invalid. Core
|
|
@@ -1140,7 +1157,9 @@ explicit `null` means roots. Singular and plural cardinalities are distinct
|
|
|
1140
1157
|
contracts. Observation is not a client binding or permission grant.
|
|
1141
1158
|
|
|
1142
1159
|
§application-loop-observation Loop observation exposes the durable scheduler
|
|
1143
|
-
state
|
|
1160
|
+
state, exact terminal `OperationResult`, and exact count of packet-bearing
|
|
1161
|
+
Turns for one owned Worker. Packetless producer Turns and physical provider
|
|
1162
|
+
retries do not contribute to `packetCount`. Exterior
|
|
1144
1163
|
adapters consume this projection instead of reconstructing lifecycle from
|
|
1145
1164
|
events or persistence; events remain the live notification edge.
|
|
1146
1165
|
|
|
@@ -1206,10 +1225,11 @@ turn-shape imperatives (begin with `# PLAN0`, end with a terminal
|
|
|
1206
1225
|
`## EXEC0 <-1,300>`” instead of a raw `unrecognized character`. The redirect is
|
|
1207
1226
|
EXEC-scoped because its signal mode is exclusive; SEND/KILL are untouched.
|
|
1208
1227
|
- §matcher-body-redirect **Matcher body in the slot region.** When the
|
|
1209
|
-
post-target header region begins with `$`, `~`, or
|
|
1210
|
-
the unambiguous matcher to
|
|
1211
|
-
|
|
1212
|
-
|
|
1228
|
+
post-target header region begins with `$`, `~`, or `@` with no whitespace
|
|
1229
|
+
before it, the lexer redirects the unambiguous matcher to body content below the
|
|
1230
|
+
OP heading instead of returning the generic slot list (after whitespace it is
|
|
1231
|
+
already the inline body, {§heading-inline-body}). Slash-led regex and XPath are
|
|
1232
|
+
excluded because `/` can be target data.
|
|
1213
1233
|
- §combined-anchor-line-redirect **Combined anchor and line number in a scope.**
|
|
1214
1234
|
A text-coordinate scope containing `@hash:L` or `@hash L` is one bounded hard
|
|
1215
1235
|
error: `a scope position accepts one line coordinate; use the \`@hash\` anchor
|
|
@@ -1223,6 +1243,15 @@ turn-shape imperatives (begin with `# PLAN0`, end with a terminal
|
|
|
1223
1243
|
\`[…]\` tag slot; a target goes in \`(…)\`. Try \`## EDIT0 (path)\``). It is
|
|
1224
1244
|
gated on a path-shaped signal so a genuine additive-tag signal is not mis-steered
|
|
1225
1245
|
toward a path it lacks.
|
|
1246
|
+
- §misplaced-annotation-advisory **Annotation in the body.** A READ or FIND whose
|
|
1247
|
+
body is solely an HTML comment (`<!-- … -->`) can never carry a matcher: it is
|
|
1248
|
+
the annotation the model put on the line below the heading. The builder takes
|
|
1249
|
+
the comment as the annotation when the heading has none, builds the operation
|
|
1250
|
+
with no body, and raises one warning-severity advisory naming what happened
|
|
1251
|
+
and the correct form (`## READ0 (…) <…> <!-- … -->`); the parser places the
|
|
1252
|
+
advisory right after its statement and the service delivers it as a
|
|
1253
|
+
`parse_advisory` notice with its position. A body with any other content is a
|
|
1254
|
+
matcher, as before.
|
|
1226
1255
|
|
|
1227
1256
|
§error-shape The diagnostic class determines how much guidance the parser may
|
|
1228
1257
|
provide:
|
|
@@ -61,6 +61,29 @@
|
|
|
61
61
|
"name": "ordinary-run",
|
|
62
62
|
"events": [
|
|
63
63
|
{ "type": "RUN_STARTED", "threadId": "fixture", "runId": "run" },
|
|
64
|
+
{
|
|
65
|
+
"type": "STATE_SNAPSHOT",
|
|
66
|
+
"snapshot": {
|
|
67
|
+
"plurnk": {
|
|
68
|
+
"status": {
|
|
69
|
+
"lifecycle": "idle",
|
|
70
|
+
"model": null,
|
|
71
|
+
"loopId": null,
|
|
72
|
+
"packetCount": 0,
|
|
73
|
+
"activity": null
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"budget": {}
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"type": "STATE_DELTA",
|
|
81
|
+
"delta": [
|
|
82
|
+
{ "op": "replace", "path": "/plurnk/status/lifecycle", "value": "running" },
|
|
83
|
+
{ "op": "replace", "path": "/plurnk/status/loopId", "value": 1 },
|
|
84
|
+
{ "op": "replace", "path": "/plurnk/status/packetCount", "value": 1 }
|
|
85
|
+
]
|
|
86
|
+
},
|
|
64
87
|
{
|
|
65
88
|
"type": "CUSTOM",
|
|
66
89
|
"name": "plurnk.row",
|
|
@@ -73,6 +96,14 @@
|
|
|
73
96
|
"tx": { "body": "Work." }
|
|
74
97
|
}
|
|
75
98
|
},
|
|
99
|
+
{
|
|
100
|
+
"type": "STATE_DELTA",
|
|
101
|
+
"delta": [
|
|
102
|
+
{ "op": "replace", "path": "/plurnk/status/lifecycle", "value": "completed" },
|
|
103
|
+
{ "op": "replace", "path": "/plurnk/status/loopId", "value": 1 },
|
|
104
|
+
{ "op": "replace", "path": "/plurnk/status/activity", "value": null }
|
|
105
|
+
]
|
|
106
|
+
},
|
|
76
107
|
{
|
|
77
108
|
"type": "CUSTOM",
|
|
78
109
|
"name": "plurnk.terminated",
|
|
@@ -103,7 +134,7 @@
|
|
|
103
134
|
],
|
|
104
135
|
"expect": {
|
|
105
136
|
"completion": "success",
|
|
106
|
-
"families": ["log/entry", "loop/terminated"],
|
|
137
|
+
"families": ["log/entry", "loop/packet", "loop/terminated"],
|
|
107
138
|
"status": 200
|
|
108
139
|
}
|
|
109
140
|
},
|
package/dist/plurnk.gemma.gbnf
CHANGED
|
@@ -114,7 +114,8 @@ rz-chan-b22 ::= ("<" rz-chan-b1 | [|chanl>toug\n] rz-chan-b0 | "e" rz-chan-b23 |
|
|
|
114
114
|
rz-chan-b23 ::= ("<" rz-chan-b1 | [|chane>toug\n] rz-chan-b0 | "l" rz-chan-b24 | [^\x00-\x08\x0B-\x0C\x0E-\x1F\x7F<|chanel>toug\n] rz-chan-b0)?
|
|
115
115
|
rz-chan-b24 ::= ("<" rz-chan-b1 | "|" rz-chan-b25 | [chanel>toug\n] rz-chan-b0 | [^\x00-\x08\x0B-\x0C\x0E-\x1F\x7F<|chanel>toug\n] rz-chan-b0)?
|
|
116
116
|
rz-chan-b25 ::= ("<" rz-chan-b1 | [|chaneltoug\n] rz-chan-b0 | [^\x00-\x08\x0B-\x0C\x0E-\x1F\x7F<|chanel>toug\n] rz-chan-b0)?
|
|
117
|
-
|
|
117
|
+
rz-chan-first ::= [0-9A-Za-z]
|
|
118
|
+
channel ::= "<|channel>thought\n" rz-chan-first rz-chan-b0 "<channel|>"
|
|
118
119
|
turn ::= plan tail-0
|
|
119
120
|
framed-turn ::= turn | "```plurnk\n" turn "\n```"
|
|
120
121
|
root-gemma ::= channel sep framed-turn
|
package/dist/plurnk.qwen.gbnf
CHANGED
|
@@ -102,7 +102,8 @@ rz-think-b10 ::= ("<" rz-think-b1 | [thnk>\n/] rz-think-b0 | "i" rz-think-b11 |
|
|
|
102
102
|
rz-think-b11 ::= ("<" rz-think-b1 | [thik>\n/] rz-think-b0 | "n" rz-think-b12 | [^\x00-\x08\x0B-\x0C\x0E-\x1F\x7F<think>\n/] rz-think-b0)?
|
|
103
103
|
rz-think-b12 ::= ("<" rz-think-b1 | [thin>\n/] rz-think-b0 | "k" rz-think-b13 | [^\x00-\x08\x0B-\x0C\x0E-\x1F\x7F<think>\n/] rz-think-b0)?
|
|
104
104
|
rz-think-b13 ::= ("<" rz-think-b1 | [think\n/] rz-think-b0 | [^\x00-\x08\x0B-\x0C\x0E-\x1F\x7F<think>\n/] rz-think-b0)?
|
|
105
|
-
|
|
105
|
+
rz-think-first ::= [0-9A-Za-z]
|
|
106
|
+
qwen-tail ::= rz-think-first rz-think-b0 "</think>"
|
|
106
107
|
turn ::= plan tail-0
|
|
107
108
|
framed-turn ::= turn | "```plurnk\n" turn "\n```"
|
|
108
109
|
root-qwen ::= qwen-tail sep framed-turn
|
package/dist/schema/Plan.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://schemas.plurnk.xyz/v0/Plan.json",
|
|
4
|
-
"$comment": "Plurnk's model-native Plan is a bare array of
|
|
4
|
+
"$comment": "Plurnk's model-native Plan is a bare array of {content, status} working-memory entries \u2014 no priority; ACP projection (separately owned by AcpPlan.json) synthesizes the ACP-required priority at the edge.",
|
|
5
5
|
"title": "Plan",
|
|
6
6
|
"description": "Plurnk's complete model-native working-memory Plan entries.",
|
|
7
7
|
"type": "array",
|
|
8
|
-
"items": {
|
|
8
|
+
"items": {
|
|
9
|
+
"$ref": "#/$defs/PlanEntry"
|
|
10
|
+
},
|
|
9
11
|
"$defs": {
|
|
10
12
|
"PlanEntry": {
|
|
11
13
|
"description": "One finding, task, or goal in the model's working-memory plan.",
|
|
@@ -15,37 +17,44 @@
|
|
|
15
17
|
"description": "Human-readable description of what this task aims to accomplish.",
|
|
16
18
|
"type": "string"
|
|
17
19
|
},
|
|
18
|
-
"priority": {
|
|
19
|
-
"description": "The relative importance of this task.",
|
|
20
|
-
"$ref": "#/$defs/PlanEntryPriority"
|
|
21
|
-
},
|
|
22
20
|
"status": {
|
|
23
21
|
"description": "The current execution status of this task.",
|
|
24
22
|
"$ref": "#/$defs/PlanEntryStatus"
|
|
25
23
|
},
|
|
26
24
|
"_meta": {
|
|
27
25
|
"description": "Opaque entry metadata preserved through standards projection.",
|
|
28
|
-
"type": [
|
|
26
|
+
"type": [
|
|
27
|
+
"object",
|
|
28
|
+
"null"
|
|
29
|
+
],
|
|
29
30
|
"additionalProperties": true
|
|
30
31
|
}
|
|
31
32
|
},
|
|
32
|
-
"required": [
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
{ "type": "string", "const": "high" },
|
|
38
|
-
{ "type": "string", "const": "medium" },
|
|
39
|
-
{ "type": "string", "const": "low" }
|
|
40
|
-
]
|
|
33
|
+
"required": [
|
|
34
|
+
"content",
|
|
35
|
+
"status"
|
|
36
|
+
],
|
|
37
|
+
"additionalProperties": false
|
|
41
38
|
},
|
|
42
39
|
"PlanEntryStatus": {
|
|
43
40
|
"description": "ACP v1 plan-entry lifecycle states.",
|
|
44
41
|
"oneOf": [
|
|
45
|
-
{
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
42
|
+
{
|
|
43
|
+
"type": "string",
|
|
44
|
+
"const": "pending"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"type": "string",
|
|
48
|
+
"const": "in_progress"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"type": "string",
|
|
52
|
+
"const": "completed"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"type": "string",
|
|
56
|
+
"const": "memory"
|
|
57
|
+
}
|
|
49
58
|
]
|
|
50
59
|
}
|
|
51
60
|
}
|