@plurnk/plurnk-contracts 1.24.0 → 1.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/SPEC.md CHANGED
@@ -17,10 +17,10 @@ runtime-neutral wire envelopes; `@plurnk/plurnk-parser` implements the language
17
17
  | Client-owned interaction contract | `ClientInteractionRequest`, `ClientInteractionProjection`, `ClientInteractionResolution` |
18
18
  | Client capability presentation | `ClientDisplayCapabilities` |
19
19
  | Exterior adapter application calls | `ApplicationPort` |
20
- | Workspace MCP configuration | `McpServerDefinition`, `McpServerOptions`, `McpConfigurationOverlay` |
20
+ | Workspace MCP configuration | `McpServerDefinition`, `McpOAuth` |
21
21
  | Worker Agent Skills definition | `SkillDefinition` |
22
22
  | Worker outbound A2A agent definition | `A2aAgentDefinition` |
23
- | Worker Functionality lifecycle projections (family-neutral) | `FunctionalityCandidate`, `FunctionalityDiscoverQuery`, `FunctionalityDiscoverResult`, `FunctionalityDefinitionState`, `FunctionalityListResult`, `FunctionalityMutationResult` |
23
+ | Worker Functionality lifecycle projections (family-neutral) | `FunctionalityProvenance`, `FunctionalityCandidate`, `FunctionalityDiscoverQuery`, `FunctionalityDiscoverResult`, `FunctionalityDefinitionState`, `FunctionalityListResult`, `FunctionalityMutationResult` |
24
24
  | AG-UI discovery, client accounting, and shared conformance specimens | `AguiDiscovery`, `AguiClientConformance`, `AguiConformanceKit` |
25
25
  | JSON Schemas | `@plurnk/plurnk-contracts/schema/*.json` |
26
26
  | Generated JSON result rendering | `renderJsonResult` |
@@ -178,7 +178,7 @@ vocabulary of `proposals`. Capability admission precedes effect
178
178
  classification and proposal settlement.
179
179
 
180
180
  §effort-wire `Effort` is exactly `off | adaptive | low |
181
- medium | high`. The schema owns this shared wire vocabulary. Providers own the
181
+ medium | high | xhigh | max`. The schema owns this shared wire vocabulary. Providers own the
182
182
  supported subset and native projection for a selected route; core owns the
183
183
  durable worker value.
184
184
 
@@ -300,10 +300,11 @@ fence only as the nesting form. Every producer of a statement — the parser, a
300
300
  `/look`, a client's tab-completion — writes `PLURNK_FENCE` rather than its own literal
301
301
  (plurnk/plurnk#92).
302
302
 
303
- §naked-operation **A native operation's name alone on a line opens it without a fence.** A
304
- column-zero line outside any block that is exactly an operation's name, with nothing but
305
- horizontal whitespace after it, opens that operation as if it were fenced with the taught three
306
- backticks: no target, no modifiers, and a body that runs to a line that is exactly the name
303
+ §naked-operation **A native name with only an optional aside opens without a fence.** A
304
+ column-zero line outside any block containing a native operation's name and at most one complete
305
+ `<!-- aside -->`, with only horizontal whitespace otherwise, opens that operation as if it were
306
+ fenced with the taught three backticks. The aside retains its ordinary meaning: no target or
307
+ modifiers are inferred. Its body runs to a line that is exactly the name
307
308
  again, to the next heading ({§fence-heading-in-body}), or to the end of the turn. A fence inside
308
309
  naming nothing known is body; the block expects no closer, so its body is never cut
309
310
  back ({§closer-fallback}). A naked `KILL` alone holds every fence inside it as text ({§naked-kill}). It runs, and one warning-severity receipt follows its statement —
@@ -312,10 +313,10 @@ operation: a naked `WAIT` parks, a naked `NOTE` takes its text, a naked `READ` m
312
313
  missing-target refusal. A closer the author wrote anyway is still not body: when the body's last line is
313
314
  a bare backtick fence that no other fence line in the body pairs with (an odd count of fence lines), that
314
315
  line is the block's closer and leaves the body, so `KILL`, then the answer, then a closing fence delivers
315
- the answer alone. Only the bare name qualifies; a name with anything else on its line is
316
- the unfenced form and still refuses ({§unfenced-operation}), executors are runtimes rather than
317
- operations, and reasoning is never read this way. In 9,196 recorded emissions, all 48 naked
318
- `KILL` lines were followed by the deliverable.
316
+ the answer alone. An aside-bearing name inside a body is not a closer. An incomplete or repeated
317
+ aside, an operand, or other heading text does not qualify and remains the unfenced form
318
+ ({§unfenced-operation}). Executors are runtimes rather than operations, and reasoning is never
319
+ read this way.
319
320
 
320
321
  §fence-heading-in-body Outside a complete nested block ({§balanced-fences}), a fence
321
322
  line of three or more backticks and a name that is a native operation or a known executor
@@ -458,15 +459,11 @@ operations the author wrote than the best repaired reading, the repaired reading
458
459
  inner fence keep what followed it (the qflash run192, run90 and run210 deliverables regain their last
459
460
  sections), one echoed transcript (glm run155) runs one more operation, and none loses one.
460
461
 
461
- §naked-kill **A naked KILL is the whole rest of the turn.** A parameterless `KILL` opened by its
462
- name alone ({§naked-operation}) is a completion, and nothing can follow a completion: every fenced
462
+ §naked-kill **A naked KILL is the whole rest of the turn.** A parameterless `KILL` opened without
463
+ a fence ({§naked-operation}), with or without an aside, is a completion: every fenced
463
464
  block inside it, a native operation heading included, is text the deliverable shows, exactly as
464
465
  inside a fenced KILL ({§terminal-kill}), and the block ends only at its name alone on a line or at
465
- the end of the input. No operation the deliverable shows runs. In the rtx5070 demo
466
- `demo-show-dont-run-sJU8zO` the model, asked to show a deletion without doing it, answered with a
467
- naked `KILL` whose deliverable quoted ```` ```KILL (notes.md) ````; read as a heading that ended
468
- the deliverable, the quoted KILL ran and deleted the file. The fenced form of the same answer had
469
- already read as quotation; this rule makes the two forms one.
466
+ the end of the input. No operation the deliverable shows runs.
470
467
 
471
468
  §pairing-witness **Witnesses.**
472
469
 
@@ -616,10 +613,7 @@ its slots, and `parameter` tags around the content are debris, as are a copied f
616
613
  (`{"lines":6}`) under the heading, a `comment` attribute (the aside), and `<||DSML||tool_calls>`
617
614
  spelled without spaces. An executor's unknown parameter is one of its options, `[{"maxTokens":
618
615
  "2500"}]`, for its owner to accept or refuse; `bash` names `sh` when `sh` is the registered shell.
619
- Of 69 distinct recorded emissions carrying DSML markup (the 11,500 distinct emissions recorded
620
- through run429), 60 read this way and 9 draw the {§native-tool-call-receipt}: a bare
621
- `<||DSML|| calls>` with nothing inside, and calls whose native operation carries a parameter
622
- plurnk has no slot for.
616
+ Calls that cannot be mapped draw {§native-tool-call-receipt}.
623
617
  Qwen's own shapes read the same way: a flat JSON call whose operation is the value
624
618
  of an `op`, `action` or `cmd` key in any case (`{"op": "READ", "path": …, "range": …}`),
625
619
  an XML element named by the operation (`<NOTE>…</NOTE>`, `<FIND (path) <1,3></FIND>`,
@@ -634,17 +628,17 @@ unknown name or parameter, or a FIND, READ, EDIT, COPY or MOVE naming no target,
634
628
  whole emission as it was. An emission that already yields an operation is never
635
629
  rewritten. No diagnostic, notice or teaching mentions a successful reading (#760).
636
630
 
637
- §native-tool-call-receipt **Markup that was not read is named.** When an emission yields no
638
- operation and carries native tool-call markup that could not be read, the parse reports one
639
- hard diagnostic at the markup, naming it and the fenced form that runs — `` `<tool_call>` is
640
- tool-call markup, which plurnk does not run, so nothing ran. An operation is a fenced block:
641
- three backticks and `READ (django/forms/widgets.py)` on the opening line. `` The form names
642
- the operation and target the markup itself names where it names them (`sh` for a shell
643
- command, `NOTE` for a note or narration), and otherwise the generic "the operation with its target,
644
- such as `READ (path)`". The model believes it
645
- acted; silence would let it wait on a result that never comes. Of 107 distinct recorded
646
- no-operation qflash emissions carrying call-like markup, 63 read under {§native-tool-calls}, 42 draw
647
- this receipt, and 2, a bare JSON object of narration with no tool-call marker, draw neither.
631
+ Bare `invoke` elements use the same slots as wrapped calls. A complete JSON object
632
+ inside an invoke supplies arguments when no explicit parameter elements are
633
+ present; parameter bodies remain literal. Unknown native-operation arguments
634
+ are not guessed.
635
+
636
+ §native-tool-call-receipt **Unexecuted native markup draws a warning.** After exact
637
+ recovery, the first remaining native-call block in outside text receives one
638
+ warning naming its markup and the fenced form. It does not invalidate real OPs
639
+ beside it, become an operation, or independently earn a strike. A turn with no
640
+ operation follows {§empty-turn}. Quoted examples and operation bodies are not
641
+ attempted calls. Outside text remains unchanged evidence under {§outside-text}.
648
642
 
649
643
  §empty-section Both the compact bodyless form and an empty multiline block
650
644
  normalize optional bodies to null. Closing fences are conventional, never required
@@ -808,17 +802,22 @@ in ordinary log token accounting and model-driven curation; prior notes are not
808
802
  automatically hidden. A NOTE-only turn does not request completion; ordinary
809
803
  repetition and strike rules still apply.
810
804
 
811
- §reasoning-notes NOTE is the only operation admitted from exposed provider
812
- reasoning. The shared fence parser selects line-leading NOTE statements in a
813
- quotation-preserving reasoning context: other backtick or tilde code blocks are
814
- opaque, and operation-heading recovery cannot escape them. Blockquoted and inline
815
- examples are not headings. Program parsing is unchanged; other reasoned operations
816
- never execute.
817
- Selected notes precede the content program in the admitted turn and use the
818
- ordinary dispatcher, persistence and log projection. Reasoning bytes and content
819
- bytes remain separate, unchanged forensic sources. Rejected or superseded
820
- provider attempts cannot commit notes. Non-thinking models use NOTE in their
821
- ordinary program. No task inventory is inferred from notes or lifecycle prose.
805
+ §reasoning-operations The shared fence parser admits complete, line-leading NOTE,
806
+ FIND and READ statements from exposed provider reasoning. Admission is part of
807
+ the language, not an optional compatibility mode. Other backtick or tilde
808
+ code blocks are opaque; heading and missing-closer recovery cannot escape them or
809
+ complete an unfinished reasoning operation. Blockquoted and inline examples are
810
+ not headings. Other reasoned operations never execute.
811
+
812
+ Operations are admitted only after the provider response completes; their
813
+ presence never interrupts generation. Selected operations precede the content
814
+ program, in source order without deduplication, and use ordinary dispatch,
815
+ permissions, persistence and log
816
+ projection. FIND/READ count as operational work for admission and continuation;
817
+ NOTE alone does not rescue an empty or inadmissible content program. Reasoning
818
+ and content remain separate, unchanged forensic sources. Rejected or superseded
819
+ provider attempts execute none of their operations. All three operations remain
820
+ available in the ordinary program; no task inventory is inferred from reasoning.
822
821
 
823
822
  §exec-executor-slot The fence name selects the executor directly: for example,
824
823
  `python3 (tools/report.py)` or `gitea (issue_list)` on the opening fence line.
@@ -964,8 +963,9 @@ Mutation semantics:
964
963
  | KILL | Status of deletion or termination |
965
964
  | NOTE / WAIT | Literal memory or wait explanation |
966
965
 
967
- §find-result-unit For FIND, authored target shape fixes the paginated result
968
- unit. An exact target with a matcher pages flat match locations; a glob or
966
+ §find-result-unit For FIND, target selection fixes the paginated result
967
+ unit after scheme address resolution ({§entry-address-resolution}). An exact
968
+ resource target with a matcher pages flat match locations; a glob or
969
969
  folder target, and every matcher-less FIND, pages resources. Resolving a glob to
970
970
  one resource does not make it exact. The same `<N>`, inclusive `<N,M>`,
971
971
  configured markerless first page ({§markerless-first-page}), and explicit-all
@@ -1185,11 +1185,11 @@ operation receives empty-turn recovery, not successful completion ({§empty-turn
1185
1185
 
1186
1186
  | Intent | Nominal status | Meaning |
1187
1187
  |---|---|---|
1188
- | Unanswered messages or unobserved results | 102 | Continue silently |
1188
+ | Unobserved messages or results | 102 | Continue silently |
1189
1189
  | No authored response operations or fresh operation/parser failure, without WAIT | 102 | Recover before automatic parking |
1190
1190
  | WAIT | 202 | Park when a live obligation exists; otherwise continue at 102 |
1191
1191
  | Eligible parameterless KILL ({§kill-conclusion}), live work remains, no fresh failure | 202 | Join the held work without delivering its body |
1192
- | Eligible parameterless KILL, results observed, no held work, messages answered or answered by its body | 200 | Deliver the answer and conclude under {§kill-conclusion}; an empty KILL need not repeat a delivered response |
1192
+ | Eligible parameterless KILL, messages and results observed, no held work | 200 | Conclude under {§kill-conclusion}; deliver a nonempty body, or finish silently without inventing or repeating a reply |
1193
1193
  | Other admitted program | 102 | Continue regardless of earlier replies or live work |
1194
1194
  | KILL own worker | 499 | Cancel unfinished work in that worker and its descendants |
1195
1195
  | Runtime or infrastructure failure | 5xx | Not a model-authored task status |
@@ -1284,8 +1284,8 @@ intent.
1284
1284
  so.** An outside-text line that opens at column zero with an operation's name and anything else
1285
1285
  — `KILL The answer…`, `READ (a.md)`, `KILL (notes.md)` — draws one warning: `` `KILL` has no
1286
1286
  fence, so it did not run. `` The line is not response text ({§response-text}): it is neither stored
1287
- as outside text nor echoed into the next packet, and the exact emission remains at `ops://`; the bare name alone
1288
- opens the operation instead ({§naked-operation}). A registered executor's name followed by an
1287
+ as outside text nor echoed into the next packet, and the exact emission remains at `ops://`; a name
1288
+ with only an optional complete aside opens the operation instead ({§naked-operation}). A registered executor's name followed by an
1289
1289
  operand slot — `gitea (list_issues)`, `sh(build.sh)` — draws the same warning under the executor's
1290
1290
  own spelling; quoted blocks, offset lines and names inside a sentence draw nothing, since `sh`,
1291
1291
  `env` and `members` are ordinary words. The model that wrote it believes it ran: stored as
@@ -1553,42 +1553,29 @@ model-language syntax or model packet teaching.
1553
1553
 
1554
1554
  ### §mcp-server-definition 13.8 MCP server definitions
1555
1555
 
1556
- `McpServerDefinition` is the transport-neutral normalized definition of one
1557
- workspace MCP server. It is a closed `stdio`/`http` union. The schema
1558
- owns transport-specific fields, enabled/read tool sets, supported HTTP
1559
- authorization choices, and symbolic credential references; it carries no
1560
- workspace identifier, connection state, discovered catalog, or secret value.
1561
- `Validator.assertMcpServerDefinition` is the MCP host's admission boundary
1562
- before persistence or connection work.
1563
-
1564
- §mcp-server-options `McpServerOptions` is the closed client/daemon-shared
1565
- supplement accepted when adding an MCP server by alias and target. It reuses
1566
- only `McpServerDefinition` option fields and cannot repeat identity, target, or
1567
- transport. The target determines the transport; normalization through
1568
- `McpServerDefinition` rejects options belonging to the other transport.
1569
-
1570
- Interactive OAuth always requires a callback URL. Its structurally exclusive
1571
- identity modes are an HTTPS Client ID Metadata Document URL, a pre-registered
1572
- client ID plus symbolic secret, or neither for server-advertised Dynamic Client
1573
- Registration fallback. A definition cannot combine those identity modes.
1574
-
1575
- §mcp-configuration-overlay `McpConfigurationOverlay` is the bounded raw
1576
- configuration projection a client may carry to MCP list and enable actions: its
1577
- string-valued `PLURNK_MCP_*` variables, whole. Which of those names are the
1578
- host's own controls is the host's fact alone — its parser skips every control
1579
- it owns, so a carried timeout or enabled list has no effect and no client or
1580
- contract restates that vocabulary.
1581
- The client does not interpret this map. The MCP host composes it over the
1582
- lower normalized definition through the same parser that admits service
1583
- environment declarations, then validates the resulting
1584
- `McpServerDefinition`. Carrying the overlay does not connect, persist, or
1585
- expand credentials by itself.
1556
+ `McpServerDefinition` is the one definition the workspace `mcp` Functionality family
1557
+ accepts and persists: one complete connection definition with its alias `name`.
1558
+ It is a closed union of the two supported transports, `stdio`
1559
+ (`command`, optional `args`, `env`, `cwd`) and `streamable-http` (`url`, optional
1560
+ `headers` and `authorization`). Source provenance, workspace scope, connection
1561
+ state, catalog and resolved credentials are not definition fields. Adding or
1562
+ removing a definition does not install or remove a plugin. Transport and
1563
+ authentication fields replace together ({§configuration-definition-resolution}).
1564
+
1565
+ §mcp-oauth `McpOAuth` is the client-managed OAuth plurnk holds for one Streamable
1566
+ HTTP server, included in that server's `authorization`. Interactive OAuth always requires a callback URL, and
1567
+ its structurally exclusive identity modes are an HTTPS Client ID Metadata Document URL,
1568
+ a pre-registered client ID with a symbolic secret, or neither for server-advertised
1569
+ Dynamic Client Registration. A client-credentials grant names its client ID and
1570
+ symbolic secret, optionally binding an issuer. Every secret is one complete `${NAME}`
1571
+ reference to the operator environment; `Validator.assertMcpOAuth` validates the shape.
1586
1572
 
1587
1573
  `SkillDefinition` is the one definition the workspace `skills` Functionality
1588
- family accepts and persists: the standard `name`, source `scope`, and optional
1589
- installer `source`. `Validator.assertSkillDefinition` validates the wire shape;
1574
+ family accepts and persists: the standard `name`, its `source`, an optional git
1575
+ `ref`, and the `commit` the service recorded. Only host-provided trees omit
1576
+ `source`; installation scopes are not part of this shape. `Validator.assertSkillDefinition` validates the wire shape;
1590
1577
  the schema's name grammar is exposed as `SKILL_NAME` for loaders and discovery
1591
- ({§agent-skills-name}). Core owns installation truth and lifecycle
1578
+ ({§agent-skills-name}). Core owns source resolution and lifecycle
1592
1579
  ({§skills-functionality}).
1593
1580
 
1594
1581
  `A2aAgentDefinition` is the one definition the Worker `a2a` Functionality
@@ -1609,6 +1596,14 @@ An exterior adapter owns its own protocol validation, identity binding, and
1609
1596
  projection while reusing the same workspace, worker, loop, operation, proposal,
1610
1597
  interaction, and event owners through this port.
1611
1598
 
1599
+ `ApplicationOperationEvent` is the schema-owned dispatch observation consumed
1600
+ through that subscription; its production boundary is {§notifications-operation-event}.
1601
+
1602
+ `configurationNotices` exposes current launcher-owned configuration diagnostics
1603
+ without acquiring a workspace or provider. Adapters use the existing Notice
1604
+ projection; model turns combine these with workspace diagnostics according to
1605
+ {§configuration-repair-path}.
1606
+
1612
1607
  `runLoop.source` is trusted causal provenance supplied by an adapter, distinct
1613
1608
  from user-authored prompt content. An adapter may expose no public means to set
1614
1609
  it; Core validates and records it through the same prompt admission path.
@@ -1826,7 +1821,8 @@ diagnostics are:
1826
1821
  of a FIND, READ or targeted KILL is a body, and those operations take none: the builder
1827
1822
  keeps the statement without it and raises one warning-severity advisory (`READ
1828
1823
  takes no body; the body was ignored. A pattern belongs on the opening fence line
1829
- after the path.`), delivered like {§misplaced-aside-advisory} as a
1824
+ after the path.`). KILL's advisory names `KILL with a target`; it must not
1825
+ prohibit parameterless completion bodies. Delivered like {§misplaced-aside-advisory} as a
1830
1826
  `parse_advisory` notice (a warning, never an error). One sigil line beneath the heading is the bare form
1831
1827
  written a line low and still lifts; nothing else is promoted into a matcher from
1832
1828
  below the heading, and the advisory never echoes the body.
@@ -70,6 +70,7 @@
70
70
  "model": null,
71
71
  "loopId": null,
72
72
  "packetCount": 0,
73
+ "preparation": [],
73
74
  "activity": null
74
75
  }
75
76
  },
@@ -79,6 +80,15 @@
79
80
  {
80
81
  "type": "STATE_DELTA",
81
82
  "delta": [
83
+ { "op": "replace", "path": "/plurnk/status/preparation", "value": [
84
+ { "family": "mcp", "alias": "search", "phase": "preparing", "since": "2026-09-29T00:00:00.000Z" }
85
+ ] }
86
+ ]
87
+ },
88
+ {
89
+ "type": "STATE_DELTA",
90
+ "delta": [
91
+ { "op": "replace", "path": "/plurnk/status/preparation", "value": [] },
82
92
  { "op": "replace", "path": "/plurnk/status/lifecycle", "value": "running" },
83
93
  { "op": "replace", "path": "/plurnk/status/loopId", "value": 1 },
84
94
  { "op": "replace", "path": "/plurnk/status/packetCount", "value": 1 }
@@ -134,7 +144,7 @@
134
144
  ],
135
145
  "expect": {
136
146
  "completion": "success",
137
- "families": ["log/entry", "loop/packet", "loop/terminated"],
147
+ "families": ["log/entry", "loop/packet", "loop/terminated", "workspace/preparation"],
138
148
  "status": 200
139
149
  }
140
150
  },
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.plurnk.xyz/v0/ApplicationOperationEvent.json",
4
+ "title": "ApplicationOperationEvent",
5
+ "description": "A core-owned dispatch boundary. A settled dispatch has its exact result; it does not assert asynchronous process completion.",
6
+ "type": "object",
7
+ "required": ["workerId", "loopId", "turnId", "sequence", "origin", "projectRoot", "statement", "phase"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "workerId": { "type": "integer", "minimum": 1 },
11
+ "loopId": { "type": "integer", "minimum": 1 },
12
+ "turnId": { "type": "integer", "minimum": 1 },
13
+ "sequence": { "type": "integer", "minimum": 1 },
14
+ "origin": { "enum": ["model", "client", "_plurnk", "plugin"] },
15
+ "projectRoot": { "type": ["string", "null"] },
16
+ "statement": { "$ref": "https://schemas.plurnk.xyz/v0/PlurnkStatement.json" },
17
+ "phase": { "enum": ["started", "settled"] },
18
+ "result": { "$ref": "https://schemas.plurnk.xyz/v0/OperationResult.json" }
19
+ },
20
+ "allOf": [
21
+ {
22
+ "if": { "properties": { "phase": { "const": "settled" } } },
23
+ "then": { "required": ["result"] },
24
+ "else": { "not": { "required": ["result"] } }
25
+ }
26
+ ]
27
+ }
@@ -19,15 +19,6 @@
19
19
  "description": "The exact family definition, conforming to the family's definition schema.",
20
20
  "type": "object"
21
21
  },
22
- "provenance": {
23
- "type": "object",
24
- "additionalProperties": false,
25
- "required": ["kind", "source"],
26
- "properties": {
27
- "kind": { "type": "string", "minLength": 1 },
28
- "source": { "type": "string", "minLength": 1 },
29
- "reference": { "type": "string", "minLength": 1 }
30
- }
31
- }
22
+ "provenance": { "$ref": "https://schemas.plurnk.xyz/v0/FunctionalityProvenance.json" }
32
23
  }
33
24
  }
@@ -13,10 +13,14 @@
13
13
  "enum": ["service", "workspace", "worker"]
14
14
  },
15
15
  "state": {
16
- "description": "disabled: available, model-invisible. active: enabled and prepared. unavailable: enabled but preparation has an exact Problem. authorization-required: enabled and awaiting a protocol continuation.",
17
- "enum": ["disabled", "active", "unavailable", "authorization-required"]
16
+ "description": "disabled: available, model-invisible. dormant: enabled without a resident publication. active: enabled and prepared. unavailable: enabled but preparation has an exact Problem. authorization-required: enabled and awaiting a protocol continuation.",
17
+ "enum": ["disabled", "dormant", "active", "unavailable", "authorization-required"]
18
18
  },
19
19
  "definition": { "type": "object" },
20
+ "provenance": {
21
+ "description": "The winning configuration input, when supplied by a source reader. Independent of origin and readiness; absent for locally owned definitions or host-provided resources without a configuration input.",
22
+ "$ref": "https://schemas.plurnk.xyz/v0/FunctionalityProvenance.json"
23
+ },
20
24
  "inherited": {
21
25
  "description": "The Worker this entry was copied from when this Worker was created (WORK or FORK), preserved across generations until this Worker changes the entry. Absent for an entry this Worker set itself. Worker-scoped families only.",
22
26
  "type": "string",
@@ -9,7 +9,7 @@
9
9
  "query": { "type": "string", "minLength": 1 },
10
10
  "source": { "type": "string", "minLength": 1 },
11
11
  "configuration": {
12
- "description": "Caller-supplied configuration material the family interprets as candidates (a client's own PLURNK_MCP_* environment, a local directory list). It contributes candidates with client-configuration provenance; it never becomes durable authority.",
12
+ "description": "Caller-supplied configuration material the family interprets as candidates (a client's own PLURNK_A2A_* environment, a local directory list). It contributes candidates with client-configuration provenance; it never becomes durable authority.",
13
13
  "type": "object"
14
14
  }
15
15
  }
@@ -0,0 +1,15 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.plurnk.xyz/v0/FunctionalityPreparationActivity.json",
4
+ "title": "FunctionalityPreparationActivity",
5
+ "description": "Current workspace capability preparation, not a published outcome. No definitions or credentials.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["family", "alias", "phase", "since"],
9
+ "properties": {
10
+ "family": { "type": "string", "minLength": 1 },
11
+ "alias": { "type": ["string", "null"], "minLength": 1 },
12
+ "phase": { "enum": ["preparing", "publishing"] },
13
+ "since": { "type": "string", "format": "date-time" }
14
+ }
15
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.plurnk.xyz/v0/FunctionalityProvenance.json",
4
+ "title": "FunctionalityProvenance",
5
+ "description": "The input supplying a definition or discovery candidate, separate from ownership, preparation and authority.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": ["kind", "source"],
9
+ "properties": {
10
+ "kind": { "type": "string", "minLength": 1 },
11
+ "source": { "type": "string", "minLength": 1 },
12
+ "reference": { "type": "string", "minLength": 1 }
13
+ }
14
+ }
@@ -0,0 +1,64 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://schemas.plurnk.xyz/v0/McpOAuth.json",
4
+ "title": "McpOAuth",
5
+ "description": "OAuth configuration within one Streamable HTTP MCP server definition. Every secret is a ${NAME} reference to the operator environment.",
6
+ "oneOf": [
7
+ {
8
+ "type": "object",
9
+ "description": "Interactive OAuth identified by an HTTPS Client ID Metadata Document.",
10
+ "additionalProperties": false,
11
+ "required": ["type", "redirectUrl", "clientMetadataUrl"],
12
+ "properties": {
13
+ "type": { "const": "oauth" },
14
+ "redirectUrl": { "type": "string", "format": "uri" },
15
+ "clientMetadataUrl": { "type": "string", "format": "uri", "pattern": "^https://.+/.+" },
16
+ "scope": { "type": "string", "minLength": 1 }
17
+ }
18
+ },
19
+ {
20
+ "type": "object",
21
+ "description": "Interactive OAuth with a pre-registered client ID and secret.",
22
+ "additionalProperties": false,
23
+ "required": ["type", "redirectUrl", "clientId", "clientSecret"],
24
+ "properties": {
25
+ "type": { "const": "oauth" },
26
+ "redirectUrl": { "type": "string", "format": "uri" },
27
+ "clientId": { "type": "string", "minLength": 1 },
28
+ "clientSecret": { "$ref": "#/$defs/environmentReference" },
29
+ "scope": { "type": "string", "minLength": 1 }
30
+ }
31
+ },
32
+ {
33
+ "type": "object",
34
+ "description": "Interactive OAuth through server-advertised Dynamic Client Registration.",
35
+ "additionalProperties": false,
36
+ "required": ["type", "redirectUrl"],
37
+ "properties": {
38
+ "type": { "const": "oauth" },
39
+ "redirectUrl": { "type": "string", "format": "uri" },
40
+ "scope": { "type": "string", "minLength": 1 }
41
+ }
42
+ },
43
+ {
44
+ "type": "object",
45
+ "description": "A noninteractive client-credentials grant; issuer optionally binds the credentials to one authorization server.",
46
+ "additionalProperties": false,
47
+ "required": ["type", "clientId", "clientSecret"],
48
+ "properties": {
49
+ "type": { "const": "client-credentials" },
50
+ "clientId": { "type": "string", "minLength": 1 },
51
+ "clientSecret": { "$ref": "#/$defs/environmentReference" },
52
+ "scope": { "type": "string", "minLength": 1 },
53
+ "issuer": { "type": "string", "minLength": 1 }
54
+ }
55
+ }
56
+ ],
57
+ "$defs": {
58
+ "environmentReference": {
59
+ "description": "An operator environment variable reference such as ${GITEA_TOKEN}, never a literal secret.",
60
+ "type": "string",
61
+ "pattern": "^\\$\\{[A-Za-z_][A-Za-z0-9_]*\\}$"
62
+ }
63
+ }
64
+ }