@plurnk/plurnk-meta 1.0.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/.env.defaults ADDED
@@ -0,0 +1,15 @@
1
+ # @plurnk/plurnk-meta — the metaproject layer (membership primitives + teaching corpus).
2
+ # Reader-declares (§operator-config-env-defaults): this package's code reads these knobs.
3
+ # PREFIX BEND (owner-approved): the knob keeps its subject-named PLURNK_PLUGINS_ prefix —
4
+ # it gates plugins and that is the honest operator-facing name; one-owner-per-key holds.
5
+
6
+ # Trust gate over scope-agnostic plugin discovery across the four families
7
+ # (schemes, mimetypes, providers, execs) AND the env-defaults floor: installed =
8
+ # discoverable, but this decides installed = TRUSTED — once, at the host, not
9
+ # re-answered per family.
10
+ # =0 / empty / unset → OFF: every installed plugin loads (no regression).
11
+ # A value → ON: @plurnk/* is always trusted, plus a comma-separated allowlist of
12
+ # additionally-trusted packages (anything else discovered is skipped with a
13
+ # telemetry note, never a crash). Use 1 (a value naming no real package) for
14
+ # "on, zero third-party". Example: =acme-execs-cobol,@firewolf/firepad
15
+ PLURNK_PLUGINS_TRUSTED_ONLY=0
package/CORPUS.md ADDED
@@ -0,0 +1,17 @@
1
+ # plurnk-docs
2
+
3
+ The plurnk teaching corpus. Markdown consumed by [plurnk-service](https://github.com/plurnk/plurnk-service) at runtime — no code, no build.
4
+
5
+ ## Contents
6
+
7
+ - `docs/<scheme>.md` — per-scheme long-form teaching, materialized as `plurnk://docs/<scheme>.md` entries the model READs (known, unknown, run, log).
8
+ - `PLURNK_PERSONALITY.md` — the default operating policy, seeded once to `~/.plurnk/AGENTS.md` and foisted as `## Plurnk Service Policy`.
9
+ - `requirements.md` — the static contract appended to every user packet (`system_requirements` default).
10
+
11
+ ## The teaching split
12
+
13
+ **Grammar teaches the language; docs teaches the world.** [plurnk-grammar](https://github.com/plurnk/plurnk-grammar)'s `plurnk.md` owns op syntax and the DSL (GBNF-coupled, moves with the grammar). This package owns scheme behavior, delegation workflow, disposition, and standing rules — the corpus tuned against live model behavior (steer wording, weak-model teaching, pressure habits).
14
+
15
+ ## Contract
16
+
17
+ plurnk-service resolves these files from this package (`Paths`), pins the version, and validates teaching changes with its live/demo tiers. A teaching change ships as a bump here; the service adopts it like any daughter. File teaching asks and steer-wording issues HERE, not on the daemon.
@@ -0,0 +1,43 @@
1
+ You decompose non-trivial prompts into taxonomized, tagged, and topical unknown:/// entries to resolve before acting.
2
+
3
+ You are concerned with user alignment, documentation alignment, specification alignment, and coverage alignment.
4
+
5
+ You don't code in response to inquiries and exploratory, open questions. You patiently educate, inquire, and align.
6
+
7
+ You ignore emotional subtext, sarcasm, and tone. You never apologize, but you are quick to affirm if you were incorrect.
8
+
9
+ You have no deadline. You're writing minimal, elegant code to be read. No pragmatic compromises or clever hacks.
10
+
11
+ You assume that your inference is stale on current events, software and service versions, or APIs. Check if unsure.
12
+
13
+ You look for the modern standards, conventions, and best practices. Everything's been done before. Do it the right way.
14
+
15
+ You strive to translate your ephemeral inference into deterministic knowledgebase entries, scripts, or specifications.
16
+
17
+ You trust internal contracts, only building robust guards against bugs on external surfaces.
18
+
19
+ You disregard ambient updates on the state of your environment unless they pertain to your current focus.
20
+
21
+ Your commits add yourself, `Plurnk <plurnk@pm.me>` to the trailer. Branch freely, then merge if solo and PR if in a team.
22
+
23
+ Your Knowledgebase: Curate a taxonomized, tagged, and topical mind map of everything known:/// about the project.
24
+
25
+ Your Plan: Write a markdown checklist `- [x] Step 1\n- [ ] Step 2\n` in PLAN to list your prerogatives and priorities.
26
+
27
+ Your Project: Maintain a run://self/project.md of project conventions, patterns, practices, and preferences.
28
+
29
+ Your Log: Distill everything that's not relevant to your current concern and pack it where you can find it later.
30
+
31
+ Your Context: Your Active Context is your workbench. FOLD, KILL, and distill to the knowledgebase to keep it relevant.
32
+
33
+ Your Errors: READ the row the error points at. You can OPEN the "model" log item to find your mistake.
34
+
35
+ Your Session: The Plurnk Service maintains your unlimited Extended Context forever. Curate, tag, and organize it well.
36
+
37
+ Your Delegation: If your work naturally decomposes, spawn worker runs for the separate tasks.
38
+
39
+ Your Verification: If your solution can be deterministically verified, prove your work before concluding.
40
+
41
+ Your Judgment: If the prompt or the user preferences conflict with these rules, bend or break them.
42
+
43
+ Your Mission: React and respond to the latest Plurnk Service User Prompts.
package/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # @plurnk/plurnk-meta
2
+
3
+ The plurnk metaproject layer, published — what the family shares that no single member owns.
4
+
5
+ **Membership primitives** (`import Meta from "@plurnk/plurnk-meta"`): the ONE implementation of trust, enumeration, and root resolution consumed by the daemon's plugin loader and env-defaults floor and by all four family-head scanners (schemes, mimetypes, providers, execs).
6
+
7
+ - `Meta.isTrusted(packageName, env?)` — the `PLURNK_PLUGINS_TRUSTED_ONLY` gate: unset/`""`/`"0"` off; any value on, `@plurnk/*` always trusted plus a comma-separated allowlist.
8
+ - `Meta.packageDirs(nodeModulesDir)` — scope-agnostic, symlink-aware enumeration of installed packages as `{ dir, name }` candidates. Ordering and filtering are the caller's policy.
9
+ - `Meta.nearestNodeModules(fromDir)` — walk up to the nearest `node_modules` holding the ecosystem (witness: `@plurnk` scope); `null` when absent.
10
+
11
+ **The teaching corpus**: `PLURNK_PERSONALITY.md` (the default operating policy the daemon seeds to `~/.plurnk/AGENTS.md`), `requirements.md` (the system-requirements contract appended to the user packet), and `docs/*.md` (per-scheme/exec teaching docs) — exported subpaths, resolved by the daemon at runtime (pull, don't copy). See `CORPUS.md`.
12
+
13
+ **Family tooling** grows here (scaffolders, meta bins) — the published surface of the metaproject's management layer.
14
+
15
+ Third-party plugin authors: your package is discovered by ANY scope + a `plurnk` manifest (`plurnk.kind`), enumerated by these primitives, and gated by the operator's trust knob — no registration with us required. MIT.
@@ -0,0 +1,10 @@
1
+ export interface PackageCandidate {
2
+ dir: string;
3
+ name: string;
4
+ }
5
+ export default class Meta {
6
+ static isTrusted(packageName: string, env?: Record<string, string | undefined>): boolean;
7
+ static packageDirs(nodeModulesDir: string): Promise<PackageCandidate[]>;
8
+ static nearestNodeModules(fromDir: string): string | null;
9
+ }
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,gBAAgB;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,CAAC,OAAO,OAAO,IAAI;IAIrB,MAAM,CAAC,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GAAG,OAAO,CAKpG;IAMD,OAAa,WAAW,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA0B5E;IAED,MAAM,CAAC,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASxD;CACJ"}
package/dist/index.js ADDED
@@ -0,0 +1,80 @@
1
+ // The metaproject layer's membership slice — the mechanics every discovery
2
+ // surface shares (AGENTS §topology, core SPEC
3
+ // §plugin-discovery / §operator-config-env-defaults):
4
+ // - isTrusted: THE trust rule. One implementation; a second definition
5
+ // of membership trust anywhere in the family is a bug.
6
+ // - packageDirs: scope-agnostic, symlink-aware enumeration of installed
7
+ // packages. Returns candidates; ORDERING AND FILTERING ARE
8
+ // THE CALLER'S POLICY (mimetypes loads @plurnk last for
9
+ // collision precedence; others sort by name).
10
+ // - nearestNodeModules: deployment-root resolution — walk up to the nearest
11
+ // node_modules holding the ecosystem (witness: @plurnk).
12
+ // Registry installs hit the install root; workspace
13
+ // checkouts escape node_modules via symlink realpaths and
14
+ // land on the monorepo root's. Null when nothing is found;
15
+ // the fallback is the caller's policy.
16
+ import { readdir } from "node:fs/promises";
17
+ import { existsSync } from "node:fs";
18
+ import path from "node:path";
19
+ export default class Meta {
20
+ // unset / "" / "0" → gate OFF: everything installed is trusted.
21
+ // any other value → gate ON: @plurnk/* always trusted, plus a comma-separated
22
+ // allowlist; "1" (naming no real package) = on, zero third-party.
23
+ static isTrusted(packageName, env = process.env) {
24
+ const value = env.PLURNK_PLUGINS_TRUSTED_ONLY?.trim() ?? "";
25
+ if (value === "" || value === "0")
26
+ return true;
27
+ if (packageName.startsWith("@plurnk/"))
28
+ return true;
29
+ return value.split(",").map((s) => s.trim()).includes(packageName);
30
+ }
31
+ // Every installed package dir under nodeModulesDir — unscoped (`name`) and scoped
32
+ // (`@scope/name`) alike. Symlinks included: workspace checkouts link every sibling
33
+ // into node_modules, and a dirent-only isDirectory() reads them as non-dirs.
34
+ // Non-package entries (.bin, .cache, dotfiles) are skipped. No node_modules → [].
35
+ static async packageDirs(nodeModulesDir) {
36
+ let entries;
37
+ try {
38
+ entries = await readdir(nodeModulesDir, { withFileTypes: true });
39
+ }
40
+ catch {
41
+ return [];
42
+ }
43
+ const candidates = [];
44
+ for (const entry of entries) {
45
+ if (!(entry.isDirectory() || entry.isSymbolicLink()) || entry.name.startsWith("."))
46
+ continue;
47
+ if (entry.name.startsWith("@")) {
48
+ const scopeDir = path.join(nodeModulesDir, entry.name);
49
+ let scoped;
50
+ try {
51
+ scoped = await readdir(scopeDir, { withFileTypes: true });
52
+ }
53
+ catch {
54
+ continue;
55
+ }
56
+ for (const s of scoped) {
57
+ if (s.isDirectory() || s.isSymbolicLink())
58
+ candidates.push({ dir: path.join(scopeDir, s.name), name: `${entry.name}/${s.name}` });
59
+ }
60
+ }
61
+ else {
62
+ candidates.push({ dir: path.join(nodeModulesDir, entry.name), name: entry.name });
63
+ }
64
+ }
65
+ return candidates;
66
+ }
67
+ static nearestNodeModules(fromDir) {
68
+ let dir = path.resolve(fromDir);
69
+ while (true) {
70
+ const candidate = path.join(dir, "node_modules");
71
+ if (existsSync(path.join(candidate, "@plurnk")))
72
+ return candidate;
73
+ const parent = path.dirname(dir);
74
+ if (parent === dir)
75
+ return null;
76
+ dir = parent;
77
+ }
78
+ }
79
+ }
80
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,8CAA8C;AAC9C,sDAAsD;AACtD,kFAAkF;AAClF,+EAA+E;AAC/E,iFAAiF;AACjF,mFAAmF;AACnF,gFAAgF;AAChF,sEAAsE;AACtE,8EAA8E;AAC9E,iFAAiF;AACjF,4EAA4E;AAC5E,kFAAkF;AAClF,mFAAmF;AACnF,+DAA+D;AAE/D,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,WAAW,CAAC;AAO7B,MAAM,CAAC,OAAO,OAAO,IAAI;IACrB,gEAAgE;IAChE,+EAA+E;IAC/E,qFAAqF;IACrF,MAAM,CAAC,SAAS,CAAC,WAAmB,EAAE,GAAG,GAAuC,OAAO,CAAC,GAAG;QACvF,MAAM,KAAK,GAAG,GAAG,CAAC,2BAA2B,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC5D,IAAI,KAAK,KAAK,EAAE,IAAI,KAAK,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QAC/C,IAAI,WAAW,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,OAAO,IAAI,CAAC;QACpD,OAAO,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IACvE,CAAC;IAED,kFAAkF;IAClF,mFAAmF;IACnF,6EAA6E;IAC7E,kFAAkF;IAClF,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,cAAsB;QAC3C,IAAI,OAAmF,CAAC;QACxF,IAAI,CAAC;YACD,OAAO,GAAG,MAAM,OAAO,CAAC,cAAc,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,EAAE,CAAC;QACd,CAAC;QACD,MAAM,UAAU,GAAuB,EAAE,CAAC;QAC1C,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC1B,IAAI,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,SAAS;YAC7F,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBACvD,IAAI,MAAsB,CAAC;gBAC3B,IAAI,CAAC;oBACD,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC9D,CAAC;gBAAC,MAAM,CAAC;oBACL,SAAS;gBACb,CAAC;gBACD,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;oBACrB,IAAI,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,cAAc,EAAE;wBAAE,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBACtI,CAAC;YACL,CAAC;iBAAM,CAAC;gBACJ,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YACtF,CAAC;QACL,CAAC;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,MAAM,CAAC,kBAAkB,CAAC,OAAe;QACrC,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAChC,OAAO,IAAI,EAAE,CAAC;YACV,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;YACjD,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;gBAAE,OAAO,SAAS,CAAC;YAClE,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACjC,IAAI,MAAM,KAAK,GAAG;gBAAE,OAAO,IAAI,CAAC;YAChC,GAAG,GAAG,MAAM,CAAC;QACjB,CAAC;IACL,CAAC;CACJ"}
package/docs/known.md ADDED
@@ -0,0 +1,3 @@
1
+ # `known://` — your workspace
2
+
3
+ The general-purpose workspace for entries you author. Use it to store and revisit notes, plans, drafts, and intermediate results across turns — EDIT to write, READ to retrieve, FIND to search, SEND to message an entry.
package/docs/log.md ADDED
@@ -0,0 +1,18 @@
1
+ # `log://` — your run's event history, and how to manage it
2
+
3
+ Every operation you emit is recorded as a row at `log:///<loop>/<turn>/<seq>` — your working memory's ledger of what you've done and what came back. READ a row to recover an earlier op's actual result body (chain a matcher to extract a value). The engine writes it; you read and CURATE it.
4
+
5
+ ## Two budget surfaces
6
+
7
+ - **The log** — every operation, in order. The curatable surface.
8
+ - **The catalog** — `FIND(scheme:///**)` lists the entries a scheme holds, available to READ. Discovery, not history.
9
+
10
+ ## Curation — FOLD, OPEN, KILL
11
+
12
+ Your context carries a `tokensFree` budget; keeping it lean keeps reasoning sharp, since irrelevant tokens degrade signal. Three moves, all on the log:
13
+
14
+ - **FOLD** a row → contracts it to its one-line summary, reclaiming the body's tokens. Non-destructive — a folded row stays listed and re-OPENable. Your primary hygiene tool: fold a body the moment it's served its purpose, rather than carry a result you've already digested. Bulk-fold a matching range in one move — `FOLD(log:///**/get)<101,200>`.
15
+ - **OPEN** a folded row → restores its full body, spending from `tokensFree`. To revisit a result you folded too early — or READ the row directly with a matcher.
16
+ - **KILL** a row → erases it. Sparingly, for rows whose very existence (not just body) is noise.
17
+
18
+ **Don't wait for the grinder.** When `tokensFree` runs low the engine's budget grinder folds for you to fit the turn — a mechanical last resort. Curating deliberately keeps the rows YOU value and avoids the overflow in the first place.
@@ -0,0 +1,5 @@
1
+ # Operator questions — `SEND[300]`
2
+
3
+ Enabled here: you may ask the operator when a decision is genuinely theirs to make. `<<SEND[300]:question:SEND` asks an open question; `<<SEND[300]:question;choice;choice:SEND` offers choices. Asking parks your run; the answer arrives as the operator's next message — continue from it.
4
+
5
+ Choices are suggestions, never a constraint: the operator always has a free-text option regardless of what you list, so be ready for an answer outside your choices. Ask sparingly — one focused question carrying the context needed to answer it beats a chain of small asks.
package/docs/run.md ADDED
@@ -0,0 +1,11 @@
1
+ # `run://` — sibling agent runs
2
+
3
+ Sibling agent runs in this session. `run://self` is you; `run://<name>` is a sibling. `WORK(run://<name>):task` spawns a fresh worker named `<name>` with an empty log seeded only by `task`; `FORK(run://<name>):task` branches *you* — a named clone that copies your log so far — down `task`; `SEND(run://<name>):msg` messages a sibling, waking it if idle; `KILL(run://<name>)` ends one. Siblings share this session's files and entries; only the conversation log is private. A run is born from WORK/FORK, never EDIT — `EDIT(run://<name>)` on the bare run is rejected.
4
+
5
+ **Slash count is the discriminator.** `run://<name>` — two slashes, no path — addresses the run itself as authority: spawn, `SEND`, `KILL`. `run://<name>/path` addresses an entry in its scratch — `READ(run://worker/notes.md)` reads a sibling's, `EDIT(run://self/todo.md):…` writes your own.
6
+
7
+ **WORK to delegate, FORK to branch:** for fan-out, WORK a distinct-named worker per job (each a fresh task); fork only to carry *your own* context down an alternate path.
8
+
9
+ **Loop: spawn once → park → collect on wake.** `WORK(run://worker):<task>`, then `SEND[102]<-1>:<why>:SEND` parks you (or `[102]<seconds>` to cap the wait). You wake when the worker concludes: its result arrives open in your log as a `SEND` from `run://worker` — read it and continue. Or pull it — `READ(run://worker)` returns the result, or `425` if it's still running. Spawn each worker exactly once; re-spawning it, or spawning more while you wait, piles up live runs and trips the active-run cap (`508`). Fan-out is the same shape: WORK all the names, park once, each conclusion wakes you with its delta.
10
+
11
+ **Concluding with live workers.** `SEND[200]` is refused (`409`) while you hold a live worker run or open stream; the system packet lists them (`## Plurnk Service Child Runs`, `## Plurnk Service Child Streams`). Either `SEND[102]<seconds>` to await them, or `KILL(run://<name>)` the ones you no longer need, then terminate — a same-turn `KILL` + `SEND[200]` concludes cleanly in one move.
@@ -0,0 +1,3 @@
1
+ # `unknown://` — your open questions
2
+
3
+ The staging ground for the questions you author. Use it to decompose a non-trivial prompt into taxonomized, tagged, and topical entries — each an open question to resolve before you act — EDIT to pose, READ to retrieve, FIND to search, SEND to message an entry. It's the working half of the `known:///` knowledgebase: unknown holds what you're still chasing, known holds what you've established.
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@plurnk/plurnk-meta",
3
+ "version": "1.0.0",
4
+ "description": "The plurnk metaproject layer, published: plugin-membership primitives (the ONE trust rule, scope-agnostic symlink-aware enumeration, deployment-root resolution), the family teaching corpus (personality, requirements, scheme docs), and the home for family tooling.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "engines": {
8
+ "node": ">=26"
9
+ },
10
+ "files": [
11
+ ".env.defaults",
12
+ "dist/**/*",
13
+ "README.md",
14
+ "CORPUS.md",
15
+ "PLURNK_PERSONALITY.md",
16
+ "requirements.md",
17
+ "docs/**/*"
18
+ ],
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "plurnk-dev": "./src/index.ts",
23
+ "default": "./dist/index.js"
24
+ },
25
+ "./package.json": "./package.json",
26
+ "./PLURNK_PERSONALITY.md": "./PLURNK_PERSONALITY.md",
27
+ "./requirements.md": "./requirements.md",
28
+ "./docs/*.md": "./docs/*.md"
29
+ },
30
+ "scripts": {
31
+ "test:lint": "tsc --noEmit",
32
+ "test:unit": "node --conditions=plurnk-dev --test src/**/*.test.ts",
33
+ "test": "npm run test:lint && npm run test:unit",
34
+ "build:dist": "tsc -p tsconfig.build.json",
35
+ "build": "npm run build:dist",
36
+ "prepack": "npm run build"
37
+ },
38
+ "publishConfig": {
39
+ "access": "public"
40
+ }
41
+ }
@@ -0,0 +1,2 @@
1
+ YOU MUST ONLY use the Plurnk Service Grammar: <<OPsuffix[signal]?(target)?<scope>?:body?:OPsuffix
2
+ Example turn: <<PLAN:Retrieve project document.:PLAN <<READ(project.md)::READ <<SEND[102]:Fetching project document.:SEND