@plurnk/plurnk-execs 0.4.32 → 0.4.34

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
@@ -113,6 +113,8 @@ The executor's only scheme-facing contribution is a **derived manifest** — `Ou
113
113
 
114
114
  MCP is the proof, not the exception: `plurnk-execs-mcp` is a plain producer — `run()` calls the tool and writes its JSON result to a `results` channel, exactly as `search` writes `results` — with no `read`, no `find`, no summary. Bring a need and it maps onto the log; the log paradigm already orients, and the executor never curates.
115
115
 
116
+ **Entry materialization is a sink, not a substrate breach (execs#18 / service#340).** `ExecArgs.entry?(path, content, { tags, mimetype }) → Promise<void>` lets an executor *request* that the consumer materialize a substrate entry — the same shape as `write`/`emit` (consumer-implemented callbacks; the executor never touches storage, tagging, or announcement machinery). The consumer creates the entry, applies the tags, and announces it through its ambience as a **folded** row (the meta line carries path + tokens; page-scale bodies never ride a wake packet). Consumer collision semantics: upsert content, union tags, bump freshness. A rejected `entry()` means *not materialized* — the requesting executor must treat that item as failed (search prunes its digest row). The sink is optional: absent, producers degrade gracefully (search emits its digest without materializing). This closed the gap that §2.6's earlier absolutism forced on the search flow (a double-fetch dance routed around the missing sink); the principle — executors own zero substrate machinery — is unchanged.
117
+
116
118
  ## §3 Discovery
117
119
 
118
120
  `discover(options?) → { registry }`. Scans **every installed package** under `<cwd>/node_modules` — scope-agnostic (scoped and unscoped) — for those declaring `plurnk.kind === "exec"`, and registers each runtime tag from `plurnk.runtimes[]`. The scan is deliberately not limited to `@plurnk/*`: a **third party** can publish an executor under their own scope (`@acme/acme-execs-foo`) and have it discovered with no involvement from this project. (For the batteries-included set, an aggregator package — `@plurnk/plurnk-execs-all` — depends on the framework's daughters flat so one install surfaces them all; the framework itself stays contract-only.)
@@ -203,7 +205,7 @@ A **registration** bound — a sibling of the §3 trust gate, **not** the §3.2
203
205
  | `PLURNK_EXECS_<TAG>=0` (or `false`) | surgical kill-switch for one tag |
204
206
  | `PLURNK_EXECS_ONLY=a,b,c` | allowlist — a tag not listed is disabled |
205
207
 
206
- The two compose within a layer (an allowlisted tag can still be individually killed). `ONLY` is reserved: a runtime tag may not be named `only`. Purely **subtractive** — there is no force-enable verb, by design.
208
+ The two compose within a layer (an allowlisted tag can still be individually killed). `ONLY` is reserved: a runtime tag may not be named `only`. **Keys are matched case-insensitively** — `PLURNK_EXECS_sh=0` ≡ `PLURNK_EXECS_SH=0`, the way the mcp config folds server names, so the natural lowercase-tag spelling doesn't silently no-op. Purely **subtractive** — there is no force-enable verb, by design.
207
209
 
208
210
  **The cascade is an intersection.** A tag is live iff enabled in *every* layer: `enabled(tag) = service ∧ client ∧ …`. Because each layer only subtracts, order is irrelevant and no downstream layer can undo an upstream disable — **the client can never re-enable what the service disabled**, structurally, not by a policed rule.
209
211
 
package/dist/policy.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export default class Policy {
2
+ #private;
2
3
  static isEnabled(tag: string, env?: Record<string, string | undefined>): boolean;
3
4
  static enabledAcross(tag: string, layers: Array<Record<string, string | undefined>>): boolean;
4
5
  }
@@ -1 +1 @@
1
- {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAqBA,MAAM,CAAC,OAAO,OAAO,MAAM;IACvB,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GAAG,OAAO;IAc7F,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GAAG,OAAO;CAGhG"}
1
+ {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAqBA,MAAM,CAAC,OAAO,OAAO,MAAM;;IAcvB,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GAAG,OAAO;IAc7F,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GAAG,OAAO;CAGhG"}
package/dist/policy.js CHANGED
@@ -20,11 +20,24 @@
20
20
  // `PLURNK_EXECS_*` format for the per-session client layer. One parser, both
21
21
  // tiers — the consumer feeds the client's map straight to these methods.
22
22
  export default class Policy {
23
+ // Read a PLURNK_EXECS_<suffix> key case-INSENSITIVELY. The env-var
24
+ // convention is uppercase, but an operator/agent naturally writes the tag as
25
+ // it appears (PLURNK_EXECS_sh=0) — matching the tag they see, not shouting
26
+ // it — and a case-sensitive miss would silently no-op (service#328). Fold
27
+ // the key the way the mcp config already folds server names. Direct hit
28
+ // first (the common uppercase form), then a folded scan.
29
+ static #read(env, suffix) {
30
+ const key = `PLURNK_EXECS_${suffix.toUpperCase()}`;
31
+ if (key in env)
32
+ return env[key];
33
+ const hit = Object.keys(env).find((k) => k.toUpperCase() === key);
34
+ return hit === undefined ? undefined : env[hit];
35
+ }
23
36
  static isEnabled(tag, env = process.env) {
24
- const off = env[`PLURNK_EXECS_${tag.toUpperCase()}`];
37
+ const off = Policy.#read(env, tag);
25
38
  if (off === "0" || off?.toLowerCase() === "false")
26
39
  return false;
27
- const only = env.PLURNK_EXECS_ONLY;
40
+ const only = Policy.#read(env, "ONLY");
28
41
  if (only) {
29
42
  const allow = new Set(only.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean));
30
43
  if (!allow.has(tag.toLowerCase()))
@@ -1 +1 @@
1
- {"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,+EAA+E;AAC/E,gFAAgF;AAChF,sEAAsE;AACtE,2EAA2E;AAC3E,EAAE;AACF,iEAAiE;AACjE,oEAAoE;AACpE,4EAA4E;AAC5E,yEAAyE;AACzE,4EAA4E;AAC5E,EAAE;AACF,4EAA4E;AAC5E,4EAA4E;AAC5E,+EAA+E;AAC/E,uCAAuC;AACvC,EAAE;AACF,uEAAuE;AACvE,mEAAmE;AACnE,6EAA6E;AAC7E,yEAAyE;AACzE,MAAM,CAAC,OAAO,OAAO,MAAM;IACvB,MAAM,CAAC,SAAS,CAAC,GAAW,EAAE,MAA0C,OAAO,CAAC,GAAG;QAC/E,MAAM,GAAG,GAAG,GAAG,CAAC,gBAAgB,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACrD,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,EAAE,WAAW,EAAE,KAAK,OAAO;YAAE,OAAO,KAAK,CAAC;QAChE,MAAM,IAAI,GAAG,GAAG,CAAC,iBAAiB,CAAC;QACnC,IAAI,IAAI,EAAE,CAAC;YACP,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;YAC1F,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;gBAAE,OAAO,KAAK,CAAC;QACpD,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,mEAAmE;IACnE,yEAAyE;IACzE,iDAAiD;IACjD,MAAM,CAAC,aAAa,CAAC,GAAW,EAAE,MAAiD;QAC/E,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IACjE,CAAC;CACJ"}
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,+EAA+E;AAC/E,gFAAgF;AAChF,sEAAsE;AACtE,2EAA2E;AAC3E,EAAE;AACF,iEAAiE;AACjE,oEAAoE;AACpE,4EAA4E;AAC5E,yEAAyE;AACzE,4EAA4E;AAC5E,EAAE;AACF,4EAA4E;AAC5E,4EAA4E;AAC5E,+EAA+E;AAC/E,uCAAuC;AACvC,EAAE;AACF,uEAAuE;AACvE,mEAAmE;AACnE,6EAA6E;AAC7E,yEAAyE;AACzE,MAAM,CAAC,OAAO,OAAO,MAAM;IACvB,mEAAmE;IACnE,6EAA6E;IAC7E,2EAA2E;IAC3E,0EAA0E;IAC1E,wEAAwE;IACxE,yDAAyD;IACzD,MAAM,CAAC,KAAK,CAAC,GAAuC,EAAE,MAAc;QAChE,MAAM,GAAG,GAAG,gBAAgB,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;QACnD,IAAI,GAAG,IAAI,GAAG;YAAE,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;QAChC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,CAAC;QAClE,OAAO,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,CAAC,SAAS,CAAC,GAAW,EAAE,MAA0C,OAAO,CAAC,GAAG;QAC/E,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACnC,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,EAAE,WAAW,EAAE,KAAK,OAAO;YAAE,OAAO,KAAK,CAAC;QAChE,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACvC,IAAI,IAAI,EAAE,CAAC;YACP,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;YAC1F,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;gBAAE,OAAO,KAAK,CAAC;QACpD,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,mEAAmE;IACnE,yEAAyE;IACzE,iDAAiD;IACjD,MAAM,CAAC,aAAa,CAAC,GAAW,EAAE,MAAiD;QAC/E,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IACjE,CAAC;CACJ"}
package/dist/types.d.ts CHANGED
@@ -18,6 +18,10 @@ export interface ExecArgs {
18
18
  write: (channel: string, chunk: string, mimetype?: string) => void;
19
19
  setState: (channel: string, state: ChannelState) => void;
20
20
  emit: (event: TelemetryEvent) => void;
21
+ entry?: (path: string, content: string, opts: {
22
+ tags: string[];
23
+ mimetype: string;
24
+ }) => Promise<void>;
21
25
  }
22
26
  export interface ExecResult {
23
27
  status: number;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAI1D,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAM3D,MAAM,WAAW,WAAW;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,YAAY,CAAC;CAC/B;AAKD,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACjB;AAOD,MAAM,WAAW,QAAQ;IAGrB,OAAO,EAAE,MAAM,CAAC;IAEhB,OAAO,EAAE,MAAM,CAAC;IAKhB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAWnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAMtB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAExB,MAAM,EAAE,WAAW,CAAC;IASpB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAEnE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAGzD,IAAI,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;CACzC;AAKD,MAAM,WAAW,UAAU;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAQD,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAO9C,MAAM,WAAW,mBAAmB;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAGD,MAAM,WAAW,QAAQ;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IAOd,OAAO,EAAE,MAAM,CAAC;IAMhB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IAOpB,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CACnC;AAOD,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAaD,MAAM,MAAM,YAAY,GAAG,MAAM,WAAW,EAAE,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;AAIxE,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAEzD,MAAM,WAAW,SAAS;IACtB,QAAQ,EAAE,YAAY,CAAC;IAKvB,OAAO,EAAE,MAAM,EAAE,CAAC;IAKlB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAG5B,GAAG,CAAC,EAAE,MAAM,CAAC;IAGb,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAID,MAAM,WAAW,SAAS;IACtB,wFAAwF;IACxF,GAAG,EAAE,MAAM,CAAC;IACZ,kCAAkC;IAClC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,mGAAmG;IACnG,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,KAAK,SAAS,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAI1D,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAM3D,MAAM,WAAW,WAAW;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,YAAY,CAAC;CAC/B;AAKD,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACjB;AAOD,MAAM,WAAW,QAAQ;IAGrB,OAAO,EAAE,MAAM,CAAC;IAEhB,OAAO,EAAE,MAAM,CAAC;IAKhB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAWnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAMtB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAExB,MAAM,EAAE,WAAW,CAAC;IASpB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAEnE,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IAGzD,IAAI,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAUtC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxG;AAKD,MAAM,WAAW,UAAU;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAQD,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAO9C,MAAM,WAAW,mBAAmB;IAChC,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAGD,MAAM,WAAW,QAAQ;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IAOd,OAAO,EAAE,MAAM,CAAC;IAMhB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IAOpB,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CACnC;AAOD,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAaD,MAAM,MAAM,YAAY,GAAG,MAAM,WAAW,EAAE,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;AAIxE,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAEzD,MAAM,WAAW,SAAS;IACtB,QAAQ,EAAE,YAAY,CAAC;IAKvB,OAAO,EAAE,MAAM,EAAE,CAAC;IAKlB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAG5B,GAAG,CAAC,EAAE,MAAM,CAAC;IAGb,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAID,MAAM,WAAW,SAAS;IACtB,wFAAwF;IACxF,GAAG,EAAE,MAAM,CAAC;IACZ,kCAAkC;IAClC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,mGAAmG;IACnG,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,KAAK,SAAS,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plurnk/plurnk-execs",
3
- "version": "0.4.32",
3
+ "version": "0.4.34",
4
4
  "description": "Framework + contract for the @plurnk/plurnk-execs-* runtime executor family.",
5
5
  "keywords": [
6
6
  "plurnk",