@plurnk/plurnk-schemes 1.3.12 → 1.4.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 +25 -14
- package/SPEC.md +311 -75
- package/dist/DefaultRead.d.ts +8 -4
- package/dist/DefaultRead.d.ts.map +1 -1
- package/dist/DefaultRead.js +37 -13
- package/dist/DefaultRead.js.map +1 -1
- package/dist/Manifest.d.ts +6 -0
- package/dist/Manifest.d.ts.map +1 -0
- package/dist/Manifest.js +115 -0
- package/dist/Manifest.js.map +1 -0
- package/dist/Matcher.d.ts +5 -6
- package/dist/Matcher.d.ts.map +1 -1
- package/dist/Matcher.js +51 -59
- package/dist/Matcher.js.map +1 -1
- package/dist/MimetypeClassifier.d.ts +1 -1
- package/dist/MimetypeClassifier.d.ts.map +1 -1
- package/dist/MimetypeClassifier.js +11 -15
- package/dist/MimetypeClassifier.js.map +1 -1
- package/dist/NetworkAddress.d.ts +13 -0
- package/dist/NetworkAddress.d.ts.map +1 -0
- package/dist/NetworkAddress.js +43 -0
- package/dist/NetworkAddress.js.map +1 -0
- package/dist/OutputScheme.d.ts.map +1 -1
- package/dist/OutputScheme.js +5 -6
- package/dist/OutputScheme.js.map +1 -1
- package/dist/PacketSections.d.ts +6 -0
- package/dist/PacketSections.d.ts.map +1 -0
- package/dist/PacketSections.js +42 -0
- package/dist/PacketSections.js.map +1 -0
- package/dist/PathMimetype.js +9 -9
- package/dist/PathMimetype.js.map +1 -1
- package/dist/Results.d.ts +29 -8
- package/dist/Results.d.ts.map +1 -1
- package/dist/Results.js +102 -44
- package/dist/Results.js.map +1 -1
- package/dist/SchemeDiscovery.d.ts +2 -0
- package/dist/SchemeDiscovery.d.ts.map +1 -1
- package/dist/SchemeDiscovery.js +40 -42
- package/dist/SchemeDiscovery.js.map +1 -1
- package/dist/SchemeResolver.d.ts.map +1 -1
- package/dist/SchemeResolver.js +4 -5
- package/dist/SchemeResolver.js.map +1 -1
- package/dist/Slicer.d.ts +36 -14
- package/dist/Slicer.d.ts.map +1 -1
- package/dist/Slicer.js +330 -362
- package/dist/Slicer.js.map +1 -1
- package/dist/Summarize.js +3 -3
- package/dist/Summarize.js.map +1 -1
- package/dist/ctx.d.ts +60 -60
- package/dist/ctx.d.ts.map +1 -1
- package/dist/edit-receipt.d.ts +39 -0
- package/dist/edit-receipt.d.ts.map +1 -0
- package/dist/edit-receipt.js +2 -0
- package/dist/edit-receipt.js.map +1 -0
- package/dist/handler.d.ts +7 -8
- package/dist/handler.d.ts.map +1 -1
- package/dist/handler.js +4 -2
- package/dist/handler.js.map +1 -1
- package/dist/index.d.ts +13 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/packet.d.ts +2 -3
- package/dist/packet.d.ts.map +1 -1
- package/dist/packet.js +2 -20
- package/dist/packet.js.map +1 -1
- package/dist/types.d.ts +3 -11
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -7
- package/dist/types.js.map +1 -1
- package/package.json +10 -8
package/SPEC.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Contract for `@plurnk/plurnk-schemes-*` sibling packages. Audience: implementer of a URI scheme handler. Consumer: [plurnk-service](https://github.com/plurnk/plurnk-service) (SPEC.md §3).
|
|
4
4
|
|
|
5
|
-
## §1 Manifest
|
|
5
|
+
## §manifest §1 Manifest
|
|
6
6
|
|
|
7
7
|
```json
|
|
8
8
|
{
|
|
@@ -16,13 +16,12 @@ Class-level manifest (static field on the default export):
|
|
|
16
16
|
```ts
|
|
17
17
|
import type { SchemeManifest } from "@plurnk/plurnk-schemes";
|
|
18
18
|
|
|
19
|
-
class
|
|
19
|
+
class Notes {
|
|
20
20
|
static manifest: SchemeManifest = {
|
|
21
|
-
name: "
|
|
21
|
+
name: "notes",
|
|
22
22
|
channels: { body: "text/markdown", preview: "text/markdown" },
|
|
23
23
|
defaultChannel: "body",
|
|
24
24
|
category: "data",
|
|
25
|
-
scope: "workspace",
|
|
26
25
|
writableBy: ["model", "client"],
|
|
27
26
|
volatile: false,
|
|
28
27
|
modelVisible: true,
|
|
@@ -35,21 +34,39 @@ class Known {
|
|
|
35
34
|
|---|---|
|
|
36
35
|
| `name` | Matches `package.json#plurnk.name`. Addressing/routing identity (the URI prefix). |
|
|
37
36
|
| `channels` | `Record<channelName, mimetype>`. Channel names lowercase. Empty = dynamic per-call. |
|
|
38
|
-
| `defaultChannel` | Channel
|
|
39
|
-
| `category` | `"data"` (entry-bearing) \| `"logging"` (`log://` rows) \| `"control"` (addresses sister
|
|
40
|
-
| `
|
|
41
|
-
| `writableBy` | Subset of `["model", "client", "system", "plugin"]`. Consumer returns 403 for outside-set writes. |
|
|
37
|
+
| `defaultChannel` | Channel targeted when path has no `#fragment`. Dynamic-channel schemes may name it without fixing a mimetype; empty means no default. |
|
|
38
|
+
| `category` | `"data"` (entry-bearing) \| `"logging"` (`log://` rows) \| `"control"` (addresses sister workers, owns no entries — e.g. `worker://`). |
|
|
39
|
+
| `writableBy` | Subset of `["model", "client", "plurnk", "plugin"]`; empty declares an immutable scheme. Consumer returns 403 for outside-set writes. |
|
|
42
40
|
| `volatile` | Boolean. |
|
|
43
41
|
| `modelVisible` | Boolean. |
|
|
44
|
-
| `folderScopes?` | `true` declares that a trailing slash on READ is a collection scope. Absent/false means `/` is ordinary resource syntax. Matcher bodies and explicit globs remain queries independently. |
|
|
45
|
-
| `flags?` | Optional `SchemeFlagAffinity
|
|
42
|
+
| `folderScopes?` | `true` declares that a trailing slash on FIND or READ is a collection scope. Absent/false means `/` is ordinary resource syntax. Matcher bodies and explicit globs remain queries independently. |
|
|
43
|
+
| `flags?` | Optional exact `SchemeFlagAffinity`; see {§manifest-flag-affinity}. |
|
|
46
44
|
| `example?` | The scheme's terse **hot-path** one-liner (e.g. `"READ(foo://thing/42)"`) — renders in the live catalogue every turn, so keep it to one canonical usage line. Omit → not advertised. Depth goes in `documentation`. |
|
|
47
|
-
| `documentation?` | The **deep doc** (semantics / channels / edge cases). Consumer materializes it as a pull-able `worker://plurnk/docs/<name>.md` entry READ on demand; never hits the hot path. Mirrors `ExecInfo.documentation
|
|
48
|
-
| `glyph?` |
|
|
49
|
-
| `foldedByDefault?` | Entries land FOLDED, off the ranked manifest surface (READable via address, not poured into the ranked view). For executor-output streams (`<tag>://`) — containment one level up
|
|
50
|
-
| `storedScheme?` | Value persisted to `entries.scheme`, which may differ from the addressing `name`.
|
|
45
|
+
| `documentation?` | The **deep doc** (semantics / channels / edge cases). Consumer materializes it as a pull-able `worker://plurnk/docs/<name>.md` entry READ on demand; never hits the hot path. Mirrors `ExecInfo.documentation`. |
|
|
46
|
+
| §manifest-client-display `glyph?` | Non-empty opaque client presentation glyph. It is projected through {§client-display-capabilities}; omission delegates identity fallback to the client. It never enters model teaching. |
|
|
47
|
+
| `foldedByDefault?` | Entries land FOLDED, off the ranked manifest surface (READable via address, not poured into the ranked view). For executor-output streams (`<tag>://`) — containment one level up. Absent/false → ranked/first-class. |
|
|
48
|
+
| `storedScheme?` | Value persisted to `entries.scheme`, which may differ from the addressing `name`. Absent defaults to `name`. It must be a non-null string because every persisted identity component is non-null. |
|
|
51
49
|
|
|
52
|
-
|
|
50
|
+
The manifest is closed: unknown top-level fields fail admission. Entry
|
|
51
|
+
visibility is not manifest metadata; the consumer resolves it through the
|
|
52
|
+
entry owner's identity.
|
|
53
|
+
|
|
54
|
+
§manifest-flag-affinity `flags` is a closed environmental-authority declaration.
|
|
55
|
+
Unknown flag fields fail manifest admission; absent fields are false. Only registered
|
|
56
|
+
schemes enter affinity evaluation; an unknown name remains the consumer's
|
|
57
|
+
registration failure.
|
|
58
|
+
|
|
59
|
+
| Field | Scheme is inactive when | Declared requirement |
|
|
60
|
+
| ---------------------- | -------------------------------- | --------------------------------------- |
|
|
61
|
+
| `excludedInAsk` | `mode === "ask"` | Act-mode operation authority |
|
|
62
|
+
| `requiresWeb` | `noWeb === true` | Web access |
|
|
63
|
+
| `requiresInteraction` | `noInteraction === true` | Interactive access |
|
|
64
|
+
|
|
65
|
+
Proposal behavior is not scheme affinity. A handler proposes by returning 202;
|
|
66
|
+
the consumer's proposal lifecycle decides whether a client, loop auto,
|
|
67
|
+
`noProposals`, or a timeout resolves it.
|
|
68
|
+
|
|
69
|
+
§manifest-self-doc **Self-doc split (terse pushes, depth pulls).** `example` is the hot-path listing rendered every turn — keep it terse. `documentation` is the deep prose (every op, channel, status code, gotcha); the consumer materializes it as a pull-able **`worker://plurnk/docs/<name>.md`** entry the model READs on demand, off the hot path. Both live on the manifest; the consumer decides what's pushed vs pulled. `glyph` is client display metadata under {§manifest-client-display}, not self-documentation.
|
|
53
70
|
|
|
54
71
|
**Authoring convention — `docs/<name>.md`.** The contract field stays a plain `string`, but a sibling SHOULD keep the deep doc in a **`docs/<name>.md`** file at the package root rather than inline, and load it into the manifest at module init — e.g. `documentation: await readFile(new URL("../docs/<name>.md", import.meta.url), "utf-8")` (top-level await; `../` resolves identically from `src/` in test and `dist/` once built). Ship it by adding `docs/**/*` to `files`. This keeps prose out of the handler source and gives editors real Markdown; the contract and the consumer's `worker://plurnk/docs/<name>.md` materialization are unchanged. A missing file fails-hard at import (no silent empty doc).
|
|
55
72
|
|
|
@@ -61,21 +78,19 @@ dispatch. An absent method returns **501**, except FIND on an entry-bearing
|
|
|
61
78
|
FIND automatically. The op-dispatch surface is the exported
|
|
62
79
|
**`SchemeHandler`** interface — every method optional, each
|
|
63
80
|
`(statement, ctx) => Promise<SchemeResult>`, the per-op statement type from
|
|
64
|
-
grammar:
|
|
81
|
+
grammar. `editBatch` returns the typed `EditBatchResult` specialization:
|
|
65
82
|
|
|
66
83
|
```ts
|
|
67
|
-
import type { SchemeHandler } from "@plurnk/plurnk-schemes";
|
|
84
|
+
import type { EditBatchResult, SchemeHandler } from "@plurnk/plurnk-schemes";
|
|
68
85
|
|
|
69
86
|
export interface SchemeHandler {
|
|
87
|
+
ready?(): Promise<void>;
|
|
70
88
|
close?(): Promise<void>;
|
|
89
|
+
resolveEntryAddress?(target: ParsedPath, ctx: SchemeCtx): Promise<EntryAddress | null>;
|
|
71
90
|
prepareFind?(statement: FindStatement, ctx: SchemeCtx): Promise<SchemeResult>;
|
|
72
91
|
read?(statement: ReadStatement, ctx: SchemeCtx): Promise<SchemeResult>;
|
|
73
92
|
find?(statement: FindStatement, ctx: SchemeCtx): Promise<SchemeResult>;
|
|
74
|
-
|
|
75
|
-
fold?(statement: FoldStatement, ctx: SchemeCtx): Promise<SchemeResult>;
|
|
76
|
-
editBatch?(statements: readonly EditStatement[], ctx: SchemeCtx): Promise<SchemeResult>;
|
|
77
|
-
copy?(statement: CopyStatement, ctx: SchemeCtx): Promise<SchemeResult>;
|
|
78
|
-
move?(statement: MoveStatement, ctx: SchemeCtx): Promise<SchemeResult>;
|
|
93
|
+
editBatch?(statements: readonly EditStatement[], ctx: SchemeCtx): Promise<EditBatchResult>;
|
|
79
94
|
send?(statement: SendStatement, ctx: SchemeCtx): Promise<SchemeResult>;
|
|
80
95
|
exec?(statement: ExecStatement, ctx: SchemeCtx): Promise<SchemeResult>;
|
|
81
96
|
work?(statement: WorkStatement, ctx: SchemeCtx): Promise<SchemeResult>;
|
|
@@ -87,55 +102,232 @@ export interface SchemeHandler {
|
|
|
87
102
|
```
|
|
88
103
|
|
|
89
104
|
`prepareFind?` is not a second query implementation. It is the optional
|
|
90
|
-
discovery/materialization seam invoked before the consumer's standard
|
|
91
|
-
when a data scheme has no custom `find()`. Stored schemes omit it.
|
|
105
|
+
discovery/materialization seam invoked before the consumer's standard resource
|
|
106
|
+
selection when a data scheme has no custom `find()`. Stored schemes omit it.
|
|
107
|
+
FIND and matcher READ both invoke it before selecting entries. Acquisition
|
|
92
108
|
schemes use it to make an exact requested resource into an ordinary entry,
|
|
93
|
-
then receive the same catalog, matcher
|
|
94
|
-
semantics as every other entry-bearing scheme.
|
|
95
|
-
|
|
96
|
-
|
|
109
|
+
then receive the same catalog, matcher evidence, weight, pagination, and status
|
|
110
|
+
semantics as every other entry-bearing scheme. The consumer resolves the
|
|
111
|
+
standard query through the same canonical entry identity used by
|
|
112
|
+
`ctx.entries`: a URL authority remains part of that identity and cannot be
|
|
113
|
+
dropped between preparation and lookup. A custom `find()` replaces the whole
|
|
114
|
+
operation only where the scheme owns genuinely different candidate semantics.
|
|
115
|
+
|
|
116
|
+
§entry-address-resolution `resolveEntryAddress?` gives a client observation the
|
|
117
|
+
same address law as model-facing operations without creating a second CRUD
|
|
118
|
+
protocol. It returns the canonical stored `pathname` and a semantic owner:
|
|
119
|
+
|
|
120
|
+
| Return | Meaning |
|
|
121
|
+
|-----------------------------------------|---------------------------------------------------|
|
|
122
|
+
| `{ pathname, owner: "commons" }` | Resolve in the shared workspace namespace |
|
|
123
|
+
| `{ pathname, owner: "worker" }` | Resolve in the calling worker's namespace |
|
|
124
|
+
| `null` | The selector names no client-visible entry |
|
|
125
|
+
| Hook absent | Use the standard pathname and `commons` ownership |
|
|
126
|
+
|
|
127
|
+
The consumer supplies the observing worker through `SchemeCtx`, lowers the
|
|
128
|
+
semantic owner to its private storage identity, and performs the read. A plugin
|
|
129
|
+
never receives or returns database owner IDs. Schemes implement the hook only
|
|
130
|
+
when their standard operation path has scheme-specific canonicalization or
|
|
131
|
+
caller ownership; the hook must apply that same rule rather than inventing a
|
|
132
|
+
client-only address vocabulary.
|
|
133
|
+
|
|
134
|
+
A sibling does `export default class X implements SchemeHandler` (with `static manifest: SchemeManifest`) and gets compile-time signature checking. Every registered handler exposes either that static manifest or an instance `manifest` for dynamically derived identities; `Manifest.of` validates the complete resolved declaration and its registration name before the handler becomes dispatchable. The interface is the handler-delegable subset of grammar's operation union. `LOOK`/`BUFF` are client-facing operations, while OPEN/FOLD are core-owned log curation; none is dispatchable to a plugin scheme. **The statement + path types (`ReadStatement`, `SendStatement`, `UrlPath`, …) are re-exported from this barrel**, so a sibling depends on and peers (`^1`) ONLY `@plurnk/plurnk-schemes` — grammar rides underneath as the framework's transitive dep (§3).
|
|
135
|
+
|
|
136
|
+
§handler-lifecycle A registered handler object is a process-lived shared
|
|
137
|
+
instance and may receive overlapping operation calls. Retained handler state is
|
|
138
|
+
ordinary; handlers must make concurrent access and semantic isolation explicit.
|
|
139
|
+
|
|
140
|
+
| Concern | Contract |
|
|
141
|
+
| ------------------ | -------- |
|
|
142
|
+
| Readiness | `ready?()` runs after registration and before capability advertisement. It establishes that advertised resources are usable. |
|
|
143
|
+
| Hook cardinality | The consumer invokes each hook once per unique handler object identity, even when multiple registered names share that object. |
|
|
144
|
+
| Operation context | `SchemeCtx` and capabilities extracted from it remain operation-owned under {§scheme-ctx-lifetime}; only the `StreamSubscription` returned by `subscriptions.open` is retainable. |
|
|
145
|
+
| Retained state | Tenant- or address-selectable state keys every semantic isolation coordinate. A global pool is valid only when it carries no cross-tenant session state. |
|
|
146
|
+
| Live ownership | An address-selectable live resource has one unambiguous owner. Conflicting acquisition fails explicitly; it never overwrites the existing owner. |
|
|
147
|
+
| Shutdown | After in-flight scheme work drains and before backing stores close, `close?()` releases partially or fully initialized handler resources. The consumer attempts and awaits every unique handler close, then aggregates every failure. |
|
|
148
|
+
|
|
149
|
+
Handlers without initialization or retained resources omit the corresponding
|
|
150
|
+
hook.
|
|
97
151
|
|
|
98
|
-
|
|
152
|
+
The entry CRUD primitives (`readEntry`/`writeEntry`/`deleteEntry`) are not handler operations; schemes use `ctx.entries`. Proposal application is the optional `applyResolution` handler hook described in §3.bis.
|
|
99
153
|
|
|
100
|
-
|
|
154
|
+
OPEN and FOLD are not handler methods. They curate visibility and tags on the
|
|
155
|
+
core-owned log; an entry scheme has no visibility state and receives 501.
|
|
101
156
|
|
|
102
|
-
|
|
157
|
+
§scheme-edit-batch-receipt **Regional mutation receipts.** COPY and MOVE are not
|
|
158
|
+
handler methods. The engine composes their source and
|
|
159
|
+
destination resource selections over `ctx.entries` and uses `editBatch` for a
|
|
160
|
+
scoped destination or source mutation. This keeps channel selection, snapshot
|
|
161
|
+
ordering, cross-scheme failures, and proposal sequencing uniform for every data
|
|
162
|
+
scheme. Scheme hooks return their ordinary mutation result and, for a regional
|
|
163
|
+
`editBatch`, an `EditBatchResult` carrying its aggregate `EditBatchReceipt`:
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
type EditReceiptUnit = "lines" | "codePoints";
|
|
167
|
+
|
|
168
|
+
interface EditEffectReceipt {
|
|
169
|
+
readonly requested: string;
|
|
170
|
+
readonly source: string;
|
|
171
|
+
readonly result: string;
|
|
172
|
+
readonly removed: number;
|
|
173
|
+
readonly inserted: number;
|
|
174
|
+
readonly context: string;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
interface AppliedEditBatchReceipt {
|
|
178
|
+
readonly revision: string;
|
|
179
|
+
readonly unit: EditReceiptUnit;
|
|
180
|
+
readonly before: number;
|
|
181
|
+
readonly after: number;
|
|
182
|
+
readonly effects: readonly EditEffectReceipt[];
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
interface ReviewerReplacementEditBatchReceipt {
|
|
186
|
+
readonly revision: string;
|
|
187
|
+
readonly unit: EditReceiptUnit;
|
|
188
|
+
readonly before: number;
|
|
189
|
+
readonly after: number;
|
|
190
|
+
readonly disposition: "reviewer-replaced";
|
|
191
|
+
readonly superseded: readonly string[];
|
|
192
|
+
readonly replacement: EditEffectReceipt;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
type EditBatchReceipt =
|
|
196
|
+
| AppliedEditBatchReceipt
|
|
197
|
+
| ReviewerReplacementEditBatchReceipt;
|
|
198
|
+
|
|
199
|
+
interface EditBatchResult extends SchemeResult {
|
|
200
|
+
readonly editReceipt?: EditBatchReceipt | null;
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
| Batch outcome | Authored correlation | Landed effects |
|
|
205
|
+
| ------------------------------------ | ------------------------------------------------- | --------------------------------------------------------------------- |
|
|
206
|
+
| Applied as proposed | `effects[N]` describes authored EDIT `N` | One truthful effect per authored EDIT |
|
|
207
|
+
| Resolver replaced the proposed body | `superseded[N]` retains authored marker `N` | One `replacement` effect describes the bytes that actually landed |
|
|
208
|
+
|
|
209
|
+
The replacement form is not a heuristic attribution. An arbitrary resolver
|
|
210
|
+
body supersedes every authored EDIT because its correspondence to those edits
|
|
211
|
+
cannot be known. The consumer projects the replacement once on the durable
|
|
212
|
+
proposal-owning row and projects each authored marker's superseded disposition
|
|
213
|
+
on its own row.
|
|
214
|
+
|
|
215
|
+
The engine validates that receipt and owns the ordered COPY/MOVE resource
|
|
216
|
+
effects shown to consumers; plugins do not invent a second effect envelope.
|
|
103
217
|
|
|
104
218
|
## §3 Helpers exported by this repo
|
|
105
219
|
|
|
106
220
|
### Types
|
|
107
221
|
|
|
108
|
-
- Manifest/flags: `SchemeManifest`, `SchemeFlagAffinity`, `WriterTier
|
|
109
|
-
-
|
|
110
|
-
-
|
|
222
|
+
- Manifest/flags: `SchemeManifest`, `SchemeFlagAffinity`, and `WriterTier`; contracts-owned `LoopFlags` and `DEFAULT_LOOP_FLAGS` are re-exported for compatibility.
|
|
223
|
+
- Mutation receipts: `EditBatchResult`, `EditBatchReceipt`, `EditReceipt`, `EditEffectReceipt`, and `EditReceiptUnit`.
|
|
224
|
+
- §scheme-packet-transform **Packet-section transformation.** A scheme may implement `transformSections(sections: PacketSectionDraft[]) → PacketSectionDraft[] | Promise<…>` to add, remove, or reorder sections before core measures the packet. The exact draft shape is `{ name; slot: "system"|"user"; header: string|null; content }`; no token measurement exists at this boundary. Core invokes implementations in registration order and applies `PacketSections.assertDrafts` to the initial list and every returned list. Names are non-empty and unique within the packet.
|
|
225
|
+
- Behavior contract: `SchemeHandler` (§2). Scheme-facing grammar types re-exported here so siblings pin only this package: `PlurnkStatement` + the per-op statement types (`ReadStatement`, `FindStatement`, `OpenStatement`, `FoldStatement`, `EditStatement`, `CopyStatement`, `MoveStatement`, `SendStatement`, `ExecStatement`, `WorkStatement`, `ForkStatement`, `KillStatement`, `PlanStatement`) and path types (`ParsedPath` = `LocalPath` | `UrlPath`).
|
|
226
|
+
- Target syntax: contracts-owned `PathSyntax` is re-exported for the shared exact-versus-path-glob classifier {§path-glob}.
|
|
111
227
|
- Discovery: `SchemeDiscovery` (behavior class) with `SchemeInfo` / `SchemeDiscoveryResult` / `DiscoverOptions` (§6).
|
|
112
|
-
- Executor-scheme (
|
|
113
|
-
- Results: `SchemeResult` is the universal `
|
|
114
|
-
-
|
|
228
|
+
- §executor-scheme-output Executor-scheme ("an executor is a scheme"): `OutputScheme.manifestFromRuntime(decl)` derives a read-only-output `SchemeManifest` from an executor's `RuntimeDecl` (zero scheme-authoring); `DefaultRead.read(content, mimetype, statement, mimetypes)` -> `ReadResolution` is the free text-scope/matcher read over produced output (reuses `Slicer`/`Matcher`). A matcher selects the complete output resource before `<scope>` projects text; without a scope, READ returns the complete resource. Match evidence remains metadata for a model-chosen follow-up READ. `Summarize.summarize(content, mimetype)` -> `OrientIndex` is the structural-only EXEC-receipt index (no content - universal-receipt containment). A per-tag executor-scheme supplies its manifest via instance `get manifest()` (§2 `SchemeHandler.manifest?`).
|
|
229
|
+
- Results: `SchemeResult` is the universal operation-result contract. Statuses below 400 carry no `problem`; statuses 400–599 require RFC 9457 `ProblemDetails`, and the legacy `error` member is forbidden. `EntryResult`, `ProposalResult`, and `PassthroughResult` are optional conventional shapes, not engine routing discriminators. Guards inspect those optional shapes; proposal routing itself is engine-owned and follows status plus operation semantics.
|
|
230
|
+
- Standard FIND results may carry `omittedItems` and `maximumItems` when a selected catalog is too large to enumerate. `omittedItems` is the exact selected-resource count and `maximumItems` is the active materialization limit. These names cannot collide with the model-facing string `overflow` metadata used for truncated packet bodies.
|
|
231
|
+
- Capability ctx (see §3.bis): `SchemeCtx`, `StreamSubscription`, and the domain capabilities. Entry authors additionally receive `EntryOperationCaps`, semantic `EntryOwner`/`EntryAddress`, and typed standard-operation results. `editBatch` receives every same-turn EDIT for one canonical resource and channel; it validates against one snapshot and commits one revision or none. There is no sequential single-EDIT fallback.
|
|
115
232
|
|
|
116
233
|
Behavior ships as `export default class` (one class per file, static methods) — the ecosystem class paradigm. Type-only modules, the barrel, and the frozen `DEFAULT_LOOP_FLAGS` constant are the only non-class files.
|
|
117
234
|
|
|
235
|
+
### §network-address Network address identity
|
|
236
|
+
|
|
237
|
+
`NetworkAddress.from(target)` is the single non-secret normalization path for
|
|
238
|
+
HTTP and WebSocket targets. It returns the exact addressed `scheme`, the
|
|
239
|
+
canonical entry `pathname`, a fragmentless and credential-free transport
|
|
240
|
+
`url`, and whether userinfo was present so the handler can reject it.
|
|
241
|
+
|
|
242
|
+
| Component | Entry identity | Transport URL | Plurnk channel |
|
|
243
|
+
|------------------|-----------------------------------------------------|---------------|----------------|
|
|
244
|
+
| Scheme | Exact `http`, `https`, `ws`, or `wss` | Yes | No |
|
|
245
|
+
| Host | Canonical WHATWG hostname | Yes | No |
|
|
246
|
+
| Port | Non-default port | Yes | No |
|
|
247
|
+
| Path | Canonical pathname | Yes | No |
|
|
248
|
+
| Query | Serialized order, duplicates, and explicit empty `?` | Yes | No |
|
|
249
|
+
| Fragment | No | No | Yes |
|
|
250
|
+
| Userinfo/headers | No | No | No |
|
|
251
|
+
|
|
252
|
+
The canonical storage form is
|
|
253
|
+
`/<host>[:<port>]<path>[?<query>]`, keyed together with workspace, owner, and
|
|
254
|
+
the exact addressed scheme. `NetworkAddress.render(scheme, pathname)` is its
|
|
255
|
+
model-facing inverse: it applies the Plurnk lexical target spelling
|
|
256
|
+
{§path-parentheses} after reconstructing the exact address. Transport URLs and
|
|
257
|
+
storage identity never carry that syntax layer. Routing aliases select a
|
|
258
|
+
handler; they do not collapse resource identity.
|
|
259
|
+
|
|
118
260
|
### Active-scheme resolution — `SchemeResolver`
|
|
119
261
|
|
|
120
262
|
- `SchemeResolver.forLoop(handlers: ReadonlyMap<string, object>, flags: LoopFlags): Set<string>` — applies `manifest.flags` affinity to each handler and returns names of schemes active under the loop's flags.
|
|
121
263
|
|
|
122
|
-
### Mimetype classification — `MimetypeClassifier`
|
|
264
|
+
### §mimetype-classifier Mimetype classification — `MimetypeClassifier`
|
|
123
265
|
|
|
124
|
-
- `MimetypeClassifier.isBinary(mimetype)` —
|
|
125
|
-
- `MimetypeClassifier.
|
|
126
|
-
- `MimetypeClassifier.
|
|
266
|
+
- `MimetypeClassifier.isBinary(mimetype)` — pure taxonomy for a registry-free boundary. Delegates to `classifyMimetype` from `@plurnk/plurnk-mimetypes`; a consumer with a configured `Mimetypes` service uses `Mimetypes.classify()` so installed handler declarations remain authoritative ({§mimetype-classification}).
|
|
267
|
+
- `MimetypeClassifier.isHtml(mimetype)` — recognizes the normalized web-projection family: `text/html` and `application/xhtml+xml`.
|
|
268
|
+
- `MimetypeClassifier.isJson(mimetype)` - `application/json` plus `+json` variants, used only by result summarization.
|
|
127
269
|
- `MimetypeClassifier.normalizeAutoText(mimetype)` — `text/plain` / null / undefined → `TEXT_PRIMITIVE_MIMETYPE` (`text/markdown`).
|
|
128
270
|
- `TEXT_PRIMITIVE_MIMETYPE` — `"text/markdown"` (named export from the same module).
|
|
129
271
|
|
|
130
|
-
###
|
|
272
|
+
### §scheme-projection Projection capability
|
|
273
|
+
|
|
274
|
+
Acquisition schemes delegate model-facing projection to the consumer's one
|
|
275
|
+
configured mimetype family. They neither instantiate readers nor widen durable
|
|
276
|
+
entry channels beyond Unicode text.
|
|
277
|
+
|
|
278
|
+
| Surface | Contract |
|
|
279
|
+
| --------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
280
|
+
| `readable(content, mimetype)` | Project an acquired Unicode representation. |
|
|
281
|
+
| `readableBytes(chunks, mimetype)` | Project one async byte source under the mimetype family's bounded-input policy. |
|
|
282
|
+
| `identity(mimetype)` | Return the opaque identity of configured projection behavior for cache and materialization freshness. |
|
|
283
|
+
| `isBinary(mimetype)` | Classify through the configured registry; installed handler declarations remain authoritative. |
|
|
284
|
+
| `ProjectedText` | Derived Unicode plus its output mimetype, source mimetype, and opaque projection identity. |
|
|
285
|
+
|
|
286
|
+
A returned object is present even when its `content` is `""`; only `null`
|
|
287
|
+
denotes absence. Consumers must not infer projection presence from content
|
|
288
|
+
length. A thrown projection call is an execution failure whose cause
|
|
289
|
+
propagates; it must never be converted to `null`.
|
|
290
|
+
`ProjectionInputLimitError` is the projection boundary's exported name for the
|
|
291
|
+
configured mimetype family's typed bounded-input failure.
|
|
292
|
+
|
|
293
|
+
### §slicer-text-algebra Text-region slicing and replacement - `Slicer`
|
|
131
294
|
|
|
132
|
-
|
|
133
|
-
- `Slicer.linesRaw(content, marker)` — same shape; no `N:\t` prefix.
|
|
134
|
-
- `Slicer.jsonItems(content, marker)` — JSON-source item slice. Returns `{ status, body?, error? }`.
|
|
135
|
-
- `Slicer.lineMarkerEdit(content, marker, body)` — line-navigable EDIT.
|
|
136
|
-
- `Slicer.jsonItemEdit(content, marker, body)` — structural JSON EDIT.
|
|
295
|
+
`Slicer` owns one text algebra for every textual mimetype:
|
|
137
296
|
|
|
138
|
-
|
|
297
|
+
| Scope | Meaning |
|
|
298
|
+
|---|---|
|
|
299
|
+
| `<N>` | whole physical line `N` |
|
|
300
|
+
| `<N,M>` | inclusive whole physical lines `N..M` |
|
|
301
|
+
| `<SL,SC,EL,EC>` | exact exclusive-end region using 1-based Unicode code-point columns |
|
|
302
|
+
| `<0>` / `<-1>` | mutation anchors before the first / after the final line |
|
|
303
|
+
|
|
304
|
+
As an unadvertised ingestion tolerance, `Slicer` accepts
|
|
305
|
+
`<startLine,startColumn,endLine>` and immediately lowers it to the complete
|
|
306
|
+
four-coordinate region ending after the final code point of `endLine`.
|
|
307
|
+
Successful results carry schemes-owned, boundary-validated normalization
|
|
308
|
+
evidence containing both the authored and canonical coordinates. Producers do
|
|
309
|
+
not emit or proactively teach the tolerated form.
|
|
310
|
+
|
|
311
|
+
- `Slicer.lines(content, marker)` returns the selected text, source
|
|
312
|
+
`startLine`, and complete resolved `region`; `Slicer.linesRaw` preserves
|
|
313
|
+
original newline separators for COPY/MOVE source transfer.
|
|
314
|
+
- `Slicer.textReplacement(content, marker, body)` lowers a line shorthand or
|
|
315
|
+
exact region to one `{start,end,body}` replacement against the source
|
|
316
|
+
snapshot.
|
|
317
|
+
- `Slicer.lineMarkerEdit` applies one replacement.
|
|
318
|
+
- `Slicer.lineMarkerEditBatch` validates all replacements against one snapshot,
|
|
319
|
+
rejects overlaps, and applies all or none.
|
|
320
|
+
- `Slicer.page(items, marker)` is the separate ordered-result pagination
|
|
321
|
+
helper; it accepts only one or two integer positions.
|
|
322
|
+
|
|
323
|
+
A line/pagination 416 carries `range: { unit, requested: { first, last },
|
|
324
|
+
available: { first, last, total } }`. An exact-region failure, including a
|
|
325
|
+
failed tolerated three-coordinate scope, carries `requestedCoordinates`
|
|
326
|
+
exactly as authored; an invalid-arity text scope does likewise. Both carry
|
|
327
|
+
`columnKind: "unicodeCodePoints"`. Empty sources use `null` line-range
|
|
328
|
+
endpoints and `total: 0`.
|
|
329
|
+
|
|
330
|
+
### §path-extension-mimetype Path-extension mimetype — `PathMimetype`
|
|
139
331
|
|
|
140
332
|
- `PathMimetype.resolve(pathname, defaultMimetype, mimetypes)` — pathname extension → `Mimetypes.detect({ ext })`; falls back to `defaultMimetype` when no extension. text/plain auto-normalizes to text/markdown.
|
|
141
333
|
|
|
@@ -143,19 +335,34 @@ Behavior ships as `export default class` (one class per file, static methods)
|
|
|
143
335
|
|
|
144
336
|
- `Results.isEntry` / `Results.isProposal` / `Results.isPassthrough` — guards for the optional conventional result shapes.
|
|
145
337
|
- `Results.isErrorStatus(status)` — `status >= 400`.
|
|
146
|
-
- `Results.
|
|
147
|
-
- `Results.
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
- `
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
338
|
+
- `Results.problem(owner, code, status, detail, extensions?)` — build and validate RFC 9457 Problem Details with a stable `https://problems.plurnk.dev/<owner>/<code>` type.
|
|
339
|
+
- `Results.failure(owner, code, status, detail, fields?, extensions?)` — build and validate a failed operation result.
|
|
340
|
+
- `Results.assert(result)` — validate the complete success/failure discrimination and reject malformed plugin output.
|
|
341
|
+
- `Results.assertMatchEvidence(evidence)` / `assertMatchEvidenceList(evidence)` - enforce the exact `{ path?, region? }` shape and shared `TextRegion` contract.
|
|
342
|
+
- `Results.assertReadResult(result)` - validate the universal operation result plus any `region` and `matches` it exposes.
|
|
343
|
+
- `Results.attachInstance(result, uri)` — attach the durable occurrence URI to a failed result.
|
|
344
|
+
|
|
345
|
+
A handler owns its failure classification and explanation. The daemon owns the
|
|
346
|
+
durable `instance`, because only it knows the committed log coordinate. A
|
|
347
|
+
malformed handler result is a plugin contract violation and fails hard; the
|
|
348
|
+
consumer does not invent a fallback error or reinterpret arbitrary fields.
|
|
349
|
+
The same discrimination applies to every `SchemeCtx` capability result:
|
|
350
|
+
entries, channels, and tags never return a bare failure status.
|
|
351
|
+
|
|
352
|
+
### Matcher dispatch - `Matcher` {§matcher-dispatch}
|
|
353
|
+
|
|
354
|
+
- `Matcher.matchAgainstContent(body, content, mimetype, mimetypes)` is the body-matcher adapter over `Mimetypes.query` (glob/regex/jsonpath/xpath).
|
|
355
|
+
- A match returns status 200 and `matches: MatchEvidence[]`.
|
|
356
|
+
`MatchEvidence` is `{path?, region?}`. `path` preserves a structural locator;
|
|
357
|
+
`region` is a complete four-coordinate `TextRegion` only when the finding has
|
|
358
|
+
an honest exact or nearest-enclosing mapping into the text the model can READ.
|
|
359
|
+
Each item must contain at least one of `path` or `region`; other fields violate
|
|
360
|
+
the shared evidence contract.
|
|
361
|
+
- The matcher is a boolean resource selector. It does not replace content with matched values or choose a retrieval window. `DefaultRead` returns the complete selected resource unless the authored READ supplies `<L>`.
|
|
362
|
+
- Empty results return 204 with `matches: []`; `UnsupportedDialectError` maps to 415; `InvalidExpressionError` maps to 400; `QueryParseFailureError` maps to 203 with raw content, text/markdown, and `reason`.
|
|
363
|
+
- A multi-resource matcher omits candidates that return 415 when at least one candidate supports the dialect. If no candidate supports it, the matcher returns the first exact 415 Problem. An unreadable binary marker therefore cannot poison a repository-wide text search or masquerade as a match.
|
|
364
|
+
|
|
365
|
+
### §capability-ctx §3.bis Capability ctx — the stable trusted-extension surface
|
|
159
366
|
|
|
160
367
|
Scheme plugins are trusted in-process Node.js code. `SchemeCtx` is not a
|
|
161
368
|
sandbox or a security boundary; an installed plugin already has the process's
|
|
@@ -169,6 +376,8 @@ its implementation.
|
|
|
169
376
|
- `entries` — direct storage over the scheme's own namespace
|
|
170
377
|
(`read`/`write`/`delete`) plus `operations`, the standard PLURNK
|
|
171
378
|
`READ`/`EDIT`/`FIND`/`SEND` implementation for entry-bearing schemes.
|
|
379
|
+
A write may omit channel state to select the `static` default; a successful
|
|
380
|
+
storage read always returns each channel's persisted lifecycle state.
|
|
172
381
|
Standard operations are bound to the handler's manifest. Their optional
|
|
173
382
|
owner is semantic: `"commons"` (default) or the current `"worker"`; database
|
|
174
383
|
owner IDs are not part of the plugin contract. A handler may implement its
|
|
@@ -176,11 +385,23 @@ its implementation.
|
|
|
176
385
|
fan-out; one without it receives the standard stored-entry behavior.
|
|
177
386
|
- `channels` — content writes + state (`append`/`replace`/`setState`).
|
|
178
387
|
- `tags` — entry tags (`add`/`remove`/`list`).
|
|
179
|
-
- `notify` — between-turn client signal (`streamEvent`, metadata-only); not model-facing. (No `wakeWorker`: the
|
|
180
|
-
- `projection` —
|
|
181
|
-
- `subscriptions` — streaming lifecycle:
|
|
388
|
+
- `notify` — between-turn client signal (`streamEvent`, metadata-only); not model-facing. (No `wakeWorker`: the worker wake carries subscription-close context that only exists at stream completion, so it lives on `subscriptions.close`. Only streaming schemes wake a worker, always via close.)
|
|
389
|
+
- `projection` — the text and bounded-byte projection capability in {§scheme-projection}. Acquisition schemes own bytes/DOM; they do not instantiate or second-guess the reader family. `null` means no readable projection.
|
|
390
|
+
- §scheme-subscriptions `subscriptions` — one streaming lifecycle:
|
|
182
391
|
|
|
183
|
-
|
|
392
|
+
| Surface | Lifetime | Contract |
|
|
393
|
+
| --------------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------- |
|
|
394
|
+
| `open(pathname, handle)` | Operation | Bind durable and live identity, return the exact object, and route cancellation through its signal/handle. |
|
|
395
|
+
| Returned `StreamSubscription` | Retainable | `AbortSignal` plus fused chunk publication and terminal settlement; the only retainable capability. |
|
|
396
|
+
| `subscriptions.notifyChunk/close` | Operation | Forward to the exact returned object; own no second state or persistence path. |
|
|
397
|
+
|
|
398
|
+
`notifyChunk` appends and emits one stream event. Its optional stateless
|
|
399
|
+
`mimetype` retypes the channel only when the stored type differs.
|
|
400
|
+
`close` validates and persists the exact universal `SchemeResult`, settles
|
|
401
|
+
channel state, unregisters the live handle, and wakes the worker. `summary` is
|
|
402
|
+
presentation only; it never replaces or reconstructs the result.
|
|
403
|
+
|
|
404
|
+
There is **no `visibility` capability**: entry-level SHOW/HIDE was removed in the index/visibility teardown — SHOW/HIDE now collapse/expand `log://` rows, a log-side concern with no entry-visibility for a scheme to set.
|
|
184
405
|
|
|
185
406
|
The consumer passes exactly this public context to every handler. Bundled
|
|
186
407
|
adapters that also implement daemon-owned lifecycle behavior receive those
|
|
@@ -188,7 +409,22 @@ collaborators separately at construction or binding time; consumers must not
|
|
|
188
409
|
decorate `SchemeCtx` with database handles, registries, tokenizers, notifier
|
|
189
410
|
callbacks, or other private service state.
|
|
190
411
|
|
|
191
|
-
|
|
412
|
+
§scheme-ctx-lifetime `SchemeCtx` belongs to one operation call. A handler may
|
|
413
|
+
use it for the duration of that call, including asynchronous work awaited by
|
|
414
|
+
the call, but must not retain the context or any other extracted capability
|
|
415
|
+
after the handler returns. A streaming handler may retain only the exact
|
|
416
|
+
`StreamSubscription` returned by `subscriptions.open`; its bound methods carry
|
|
417
|
+
that subscription's identity without retaining the general context. Other
|
|
418
|
+
retained handler-owned resources follow {§handler-lifecycle}.
|
|
419
|
+
|
|
420
|
+
**Proposals are not a capability.** A side-effecting scheme proposes by *returning* a `ProposalResult` (status 202); the engine owns the resolution lifecycle. On acceptance it calls the handler's optional `applyResolution({ attrs, body }, ctx)` hook. `attrs` is the payload returned by the proposing operation and `body` is the resolver-approved body, when present. The hook returns a `ProposalApplyResult`: a status below 400 completes the accept; a failure preserves the applying scheme's Problem Details as the proposal's final result.
|
|
421
|
+
|
|
422
|
+
§scheme-edit-proposal-receipt An accepted EDIT proposal may return its final
|
|
423
|
+
aggregate `editReceipt` alongside its per-row model-facing `result`. A resolver
|
|
424
|
+
replacement must use the reviewer-replaced form from
|
|
425
|
+
{§scheme-edit-batch-receipt}. Core consumes that aggregate as transient batch
|
|
426
|
+
coordination and COPY/MOVE composition input; it persists only per-row receipts
|
|
427
|
+
or ordered resource effects.
|
|
192
428
|
|
|
193
429
|
## §4 What's NOT in this repo
|
|
194
430
|
|
|
@@ -199,12 +435,12 @@ Raw CRUD methods are not a parallel handler protocol. For `data` schemes whose
|
|
|
199
435
|
handlers omit resource-specific storage hooks, engine-owned COPY/MOVE/KILL
|
|
200
436
|
orchestration uses the manifest-bound `ctx.entries` implementation.
|
|
201
437
|
|
|
202
|
-
## §5 Trusted extension contract
|
|
438
|
+
## §trusted-extension §5 Trusted extension contract
|
|
203
439
|
|
|
204
440
|
Installed schemes may legitimately own network connections, subprocesses,
|
|
205
|
-
caches, pools, or other host resources
|
|
206
|
-
|
|
207
|
-
|
|
441
|
+
caches, pools, or other host resources under {§handler-lifecycle}. These powers
|
|
442
|
+
are why installation is a trust decision and why contained interoperability
|
|
443
|
+
belongs in MCP rather than an in-process plugin.
|
|
208
444
|
|
|
209
445
|
The supported compatibility boundary is `@plurnk/plurnk-schemes`. Plugins
|
|
210
446
|
should not import private service modules, depend on database layout, or call
|
|
@@ -212,13 +448,13 @@ prepared statements directly: those are unstable implementation details, not
|
|
|
212
448
|
additional plugin capabilities. Use `SchemeCtx` or propose a new semantic
|
|
213
449
|
capability when the public surface cannot express a coherent extension.
|
|
214
450
|
|
|
215
|
-
## §6 Discovery & registration (third-party)
|
|
451
|
+
## §scheme-discovery §6 Discovery & registration (third-party)
|
|
216
452
|
|
|
217
453
|
A scheme handler is discovered and registered with **zero first-party involvement** — install it, it lights up. The contract:
|
|
218
454
|
|
|
219
|
-
- **Declare** `plurnk.kind: "scheme"` in `package.json`
|
|
220
|
-
- **`SchemeDiscovery` owns the scan (this package).** `SchemeDiscovery.discover({ cwd? })` walks *all* of `node_modules` — scoped (`@acme/foo`) and unscoped — and returns `{ schemes: {name, packageName, exportName?, attribution?}[], skipped }` for every package declaring `plurnk.kind === "scheme"`. Scope-agnostic, so a third party under their own scope is found with no first-party allow-list
|
|
221
|
-
-
|
|
455
|
+
- **Declare** the exact string `plurnk.kind: "scheme"` in `package.json` ({§plugin-family-kind}). Then name the scheme(s) it owns in one of two forms: `plurnk.schemes: [{ name, export }, …]` (canonical — one entry per scheme, `export` naming the handler-class export) or `plurnk.name: "<scheme>"` (one-scheme shorthand for the `default` export). One package may own several names inside this family; each name has exactly one owner.
|
|
456
|
+
- **`SchemeDiscovery` owns the scan (this package).** `SchemeDiscovery.discover({ cwd? })` walks *all* of `node_modules` — scoped (`@acme/foo`) and unscoped — and returns `{ schemes: {name, packageName, exportName?, attribution?}[], packageAttributions, skipped }` for every package declaring `plurnk.kind === "scheme"`. Scope-agnostic, so a third party under their own scope is found with no first-party allow-list; two names claiming one prefix fail-hard (across packages or within one), as does a malformed `plurnk.schemes` (locality of error, not a silent skip). It returns **descriptors, not handlers** — contract-only, it never imports a scheme package; the consumer imports each `packageName` and registers `new mod[exportName ?? "default"]()`, applying in-tree precedence. The scan primitives — package enumeration, the `PLURNK_PLUGINS_TRUSTED_ONLY` trust gate, the deployment-root `node_modules` walk — are one implementation in `@plurnk/plurnk-meta`, shared by all four family-head scanners; `SchemeDiscovery` adds only the scheme-descriptor shape on top.
|
|
457
|
+
- **Attribution is package-authored.** `packageAttributions` carries one canonical validated static tag list per admitted package. `SchemeInfo.attribution` remains the published per-scheme projection when a declaration exists; a loaded handler may additionally implement the shared runtime hook ({§plugin-attribution}). Neither the descriptor nor the consumer owns another policy.
|
|
222
458
|
- **The framework stays contract-only.** `@plurnk/plurnk-schemes` does not depend on scheme plugins. The daemon declares its bundled plugins as direct dependencies, and additional plugins are installed at the application root. Plugins declare the framework as a peer dependency using the repository's normal same-minor compatibility range; the framework itself is ignored by discovery because it has no `plurnk.kind`.
|
|
223
459
|
- **The default bundle is the daemon's own `dependencies`**, not an aggregator package (the `-all` metapackages are retired). Installing `plurnk-core` surfaces the first-party schemes; any other leaf — first-party or third-party — is added by installing it, and scope-agnostic discovery lights it up identically. No bundle is ever a gate.
|
|
224
|
-
- **Trust.**
|
|
460
|
+
- **Trust.** The scanner enforces the shared predicate before attribution or scheme-field validation and returns withheld package names in `skipped`; the host owns presentation ({§plugin-trust-boundary}).
|
package/dist/DefaultRead.d.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import type { ReadStatement } from "@plurnk/plurnk-
|
|
1
|
+
import type { ReadStatement } from "@plurnk/plurnk-contracts";
|
|
2
|
+
import type { TextRegion } from "@plurnk/plurnk-contracts";
|
|
2
3
|
import type { Mimetypes } from "@plurnk/plurnk-mimetypes";
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
import type { RangeExtent } from "./Slicer.ts";
|
|
5
|
+
import type { SchemeResult } from "./Results.ts";
|
|
6
|
+
export interface ReadResolution extends SchemeResult {
|
|
5
7
|
readonly body?: string;
|
|
6
|
-
readonly
|
|
8
|
+
readonly startLine?: number;
|
|
9
|
+
readonly region?: TextRegion;
|
|
10
|
+
readonly range?: RangeExtent;
|
|
7
11
|
}
|
|
8
12
|
export default class DefaultRead {
|
|
9
13
|
static read(content: string, mimetype: string, statement: ReadStatement, mimetypes: Mimetypes): Promise<ReadResolution>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultRead.d.ts","sourceRoot":"","sources":["../src/DefaultRead.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"DefaultRead.d.ts","sourceRoot":"","sources":["../src/DefaultRead.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAI1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,WAAW,cAAe,SAAQ,YAAY;IAChD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;CAChC;AAED,MAAM,CAAC,OAAO,OAAO,WAAW;IAK5B,OAAa,IAAI,CACb,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,aAAa,EACxB,SAAS,EAAE,SAAS,GACrB,OAAO,CAAC,cAAc,CAAC,CA6BzB;CACJ"}
|