skillscript-runtime 0.14.1 → 0.15.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.
Files changed (48) hide show
  1. package/dist/approval.d.ts +9 -0
  2. package/dist/approval.d.ts.map +1 -1
  3. package/dist/approval.js +35 -2
  4. package/dist/approval.js.map +1 -1
  5. package/dist/bootstrap.d.ts.map +1 -1
  6. package/dist/bootstrap.js +10 -0
  7. package/dist/bootstrap.js.map +1 -1
  8. package/dist/cli.js +10 -6
  9. package/dist/cli.js.map +1 -1
  10. package/dist/connectors/config.d.ts.map +1 -1
  11. package/dist/connectors/config.js +4 -0
  12. package/dist/connectors/config.js.map +1 -1
  13. package/dist/connectors/index.d.ts +1 -0
  14. package/dist/connectors/index.d.ts.map +1 -1
  15. package/dist/connectors/index.js +4 -0
  16. package/dist/connectors/index.js.map +1 -1
  17. package/dist/connectors/skill-store-mcp.d.ts +17 -0
  18. package/dist/connectors/skill-store-mcp.d.ts.map +1 -0
  19. package/dist/connectors/skill-store-mcp.js +180 -0
  20. package/dist/connectors/skill-store-mcp.js.map +1 -0
  21. package/dist/mutation-gate.d.ts +12 -6
  22. package/dist/mutation-gate.d.ts.map +1 -1
  23. package/dist/mutation-gate.js +19 -11
  24. package/dist/mutation-gate.js.map +1 -1
  25. package/dist/parser.d.ts +13 -0
  26. package/dist/parser.d.ts.map +1 -1
  27. package/dist/parser.js +32 -1
  28. package/dist/parser.js.map +1 -1
  29. package/dist/runtime.d.ts.map +1 -1
  30. package/dist/runtime.js +20 -3
  31. package/dist/runtime.js.map +1 -1
  32. package/examples/README.md +7 -5
  33. package/examples/connectors/McpConnectorTemplate/McpConnectorTemplate.ts +7 -0
  34. package/examples/connectors/McpConnectorTemplate/README.md +3 -2
  35. package/examples/connectors/README.md +1 -1
  36. package/examples/connectors/SkillStoreTemplate/SkillStoreTemplate.ts +26 -0
  37. package/examples/custom-bootstrap.example.ts +16 -5
  38. package/examples/onboarding-scaffold/bootstrap.ts +19 -8
  39. package/examples/skillscripts/data-store-roundtrip.skill.md +11 -0
  40. package/examples/skillscripts/doc-qa-with-citations.skill.md +1 -1
  41. package/examples/skillscripts/hello-world.skill.md +10 -0
  42. package/examples/skillscripts/{hello.skill.provenance.json → hello-world.skill.provenance.json} +2 -2
  43. package/examples/skillscripts/morning-brief.skill.md +1 -1
  44. package/examples/skillscripts/skill-store-roundtrip.skill.md +11 -0
  45. package/package.json +1 -1
  46. package/scaffold/examples/hello-world.skill.md +10 -0
  47. package/examples/skillscripts/hello.skill.md +0 -9
  48. package/scaffold/examples/hello.skill.md +0 -10
@@ -0,0 +1,180 @@
1
+ // v0.15.0 — `SkillStoreMcpConnector`. Bridge class that exposes a registered
2
+ // `SkillStore` instance as an `McpConnector`, so `$ skill_write`, `$ skill_read`,
3
+ // and `$ skill_delete` work as in-skill dispatch from within an executing
4
+ // skill. Parallel structure to `DataStoreMcpConnector` — same bridge-instance-
5
+ // registered-under-multiple-names pattern; the runtime's name-match dispatch
6
+ // (v0.7.2) resolves bare `$ skill_<verb>` calls here.
7
+ //
8
+ // Motivation: closes the substrate-symmetry asymmetry where DataStore writes
9
+ // were in-skill dispatchable (via `DataStoreMcpConnector` wiring at bootstrap
10
+ // time) but SkillStore writes weren't — SkillStore mutators existed only on
11
+ // the outside MCP wire surface. With this bridge, the Lisp-shape claim —
12
+ // skills can program skills — becomes a usable in-skill capability:
13
+ // foreach TPL in ${TEMPLATES.items}:
14
+ // $ skill_write name=${TPL.name} source=${TPL.body}
15
+ //
16
+ // Trust model (v0.15.0): in-skill `$ skill_write` requires `# Autonomous: true`
17
+ // (or `??` / `approved=...`) per the broadened mutation gate. The wrapped
18
+ // `SkillStore.store()` auto-stamps `# Status: Approved` bodies, so an
19
+ // Autonomous parent that writes an Approved child produces a runnable child.
20
+ // Same trust as `$ data_write`: the Autonomous header is the contract; humans
21
+ // review the parent skill, the parent commits to whatever substrate it writes.
22
+ //
23
+ // Bundled surface (intentionally narrow — see Perry's threat-model push-back
24
+ // in thread f2a85892):
25
+ //
26
+ // $ skill_write name="..." source="..." [overwrite=true] -> R
27
+ // $ skill_read name="..." [version="..."] -> R
28
+ //
29
+ // Explicitly NOT in this bridge (v0.15.0 scope):
30
+ // - `skill_delete` — destructive, no use case articulated yet.
31
+ // - `skill_update_status` — the gate-bypassing op (promotes Draft →
32
+ // Approved). Allowing it in-skill would let an Autonomous parent both
33
+ // write Draft AND promote Approved in the same fire, defeating the
34
+ // Draft-default trust boundary below.
35
+ // - `skill_list` / `skill_metadata` — reads are doable but cold-author UX
36
+ // is better via `skill_read` + introspection of the returned body.
37
+ //
38
+ // **Trust boundary — Draft-default for in-skill writes (v0.15.0).** Different
39
+ // threat model from `$ data_write`: a bad data_write produces one bad row
40
+ // (bounded blast radius); a bad skill_write produces an executable artifact
41
+ // that fires arbitrarily many times in arbitrary contexts (unbounded blast
42
+ // radius). The bridge forces `# Status: Draft` regardless of what the body
43
+ // declares. To make the written skill runnable, an authorized agent
44
+ // (human via dashboard, or MCP-direct) reviews + promotes via the
45
+ // outside-MCP `skill_status` tool. The Lisp-shape primitive (skill-writes-
46
+ // skill) is preserved; only immediate-loop execution is gated.
47
+ //
48
+ // MCP-wire `skill_write` (outside agents authoring directly) keeps the
49
+ // existing behavior — body's `# Status:` declaration is honored, auto-stamped
50
+ // by FilesystemSkillStore.store(). The new trust boundary is specifically
51
+ // "dispatched from inside an executing skill," because that's the surface
52
+ // where parent-author review doesn't transitively cover child content.
53
+ //
54
+ // Wiring: auto-registered at bootstrap as connector instance "skill_read" +
55
+ // "skill_write" pointing at the substrate's SkillStore. Adopters override by
56
+ // re-registering the names with their own bridge or a different McpConnector.
57
+ const CONTRACT_VERSION = "1.0.0";
58
+ export class SkillStoreMcpConnector {
59
+ skillStore;
60
+ static staticCapabilities() {
61
+ return {
62
+ connector_type: "mcp_connector",
63
+ implementation: "SkillStoreMcpConnector",
64
+ contract_version: CONTRACT_VERSION,
65
+ features: {
66
+ supports_identity_propagation: false,
67
+ supports_streaming_responses: false,
68
+ supports_batch: false,
69
+ },
70
+ };
71
+ }
72
+ /**
73
+ * Two canonical tools (v0.15.0). Bare-form `$ skill_<verb>` name-matches
74
+ * against the registered connector instance; the toolName argument here
75
+ * distinguishes which substrate method to invoke.
76
+ */
77
+ static staticTools() {
78
+ return ["skill_read", "skill_write"];
79
+ }
80
+ constructor(skillStore) {
81
+ this.skillStore = skillStore;
82
+ }
83
+ async call(toolName, args, _ctxOverrides) {
84
+ if (toolName === "skill_write")
85
+ return this.dispatchWrite(args);
86
+ return this.dispatchRead(args);
87
+ }
88
+ async dispatchRead(args) {
89
+ const name = typeof args["name"] === "string" ? args["name"] : "";
90
+ if (name === "") {
91
+ throw new Error("SkillStoreMcpConnector: `name` kwarg is required and must be a non-empty string.");
92
+ }
93
+ const version = typeof args["version"] === "string" && args["version"] !== "" ? args["version"] : undefined;
94
+ const skill = await this.skillStore.load(name, version);
95
+ return {
96
+ name: skill.name,
97
+ version: skill.version,
98
+ content_hash: skill.content_hash,
99
+ source: skill.source,
100
+ status: skill.metadata.status,
101
+ };
102
+ }
103
+ async dispatchWrite(args) {
104
+ const name = typeof args["name"] === "string" ? args["name"] : "";
105
+ const source = typeof args["source"] === "string" ? args["source"] : "";
106
+ if (name === "") {
107
+ throw new Error("SkillStoreMcpConnector: `name` kwarg is required for skill_write and must be a non-empty string.");
108
+ }
109
+ if (source === "") {
110
+ throw new Error("SkillStoreMcpConnector: `source` kwarg is required for skill_write and must be a non-empty string.");
111
+ }
112
+ // overwrite parity with MCP wire `skill_write({overwrite})`: when false
113
+ // and a skill with this name already exists, the substrate's `store()`
114
+ // throws StorageConflictError. The bridge surfaces that through.
115
+ const overwrite = args["overwrite"] === true;
116
+ if (!overwrite) {
117
+ try {
118
+ await this.skillStore.metadata(name);
119
+ throw new Error(`SkillStoreMcpConnector: skill '${name}' already exists. Pass overwrite=true to replace.`);
120
+ }
121
+ catch (err) {
122
+ const e = err;
123
+ // SkillNotFoundError is the green path (no clash); any other error rethrows.
124
+ if (e.name !== "SkillNotFoundError" && !(e.message ?? "").startsWith("Skill not found:")) {
125
+ throw err;
126
+ }
127
+ }
128
+ }
129
+ // v0.15.0 trust boundary — in-skill writes force `# Status: Draft`
130
+ // regardless of body declaration. Threat-model rationale documented in
131
+ // the file header. Stamp by replacing any existing `# Status:` line
132
+ // (or inserting after `# Skill:` / at body top if absent). Outside-MCP
133
+ // skill_write bypasses this bridge and keeps the dashboard auto-stamp
134
+ // path; only in-skill dispatch sees the override.
135
+ const draftedBody = forceDraftStatus(source);
136
+ const info = await this.skillStore.store(name, draftedBody);
137
+ return {
138
+ name: info.name,
139
+ version: info.version,
140
+ content_hash: info.content_hash,
141
+ status: info.status,
142
+ };
143
+ }
144
+ async manifest() {
145
+ const ssManifest = await this.skillStore.manifest();
146
+ return {
147
+ capabilities_version: "1",
148
+ manifest: {
149
+ kind: "skill-store-bridge",
150
+ wraps: ssManifest.manifest ?? {},
151
+ },
152
+ };
153
+ }
154
+ }
155
+ /**
156
+ * v0.15.0 — replace any `# Status:` line in the body with `# Status: Draft`.
157
+ * If no `# Status:` line is present, insert one after `# Skill:` (or at
158
+ * body top as fallback). Mirrors the `rewriteStatusHeader` shape used by
159
+ * FilesystemSkillStore.update_status but lives here so the bridge can apply
160
+ * the Draft-only policy without coupling to substrate internals.
161
+ *
162
+ * Why this is here (not in FilesystemSkillStore.store): the Draft-only
163
+ * gate is a property of the in-skill dispatch surface, not of the
164
+ * substrate. Outside-MCP writes (dashboard, MCP-direct agents) should
165
+ * keep the existing "body declares status" behavior. The override lives
166
+ * at the bridge — the boundary between in-skill dispatch and substrate.
167
+ */
168
+ function forceDraftStatus(body) {
169
+ const draftLine = "# Status: Draft";
170
+ const statusRe = /^#\s*Status\s*:.*$/m;
171
+ if (statusRe.test(body)) {
172
+ return body.replace(statusRe, draftLine);
173
+ }
174
+ const skillRe = /^(#\s*Skill\s*:.*?)$/m;
175
+ if (skillRe.test(body)) {
176
+ return body.replace(skillRe, `$1\n${draftLine}`);
177
+ }
178
+ return `${draftLine}\n${body}`;
179
+ }
180
+ //# sourceMappingURL=skill-store-mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-store-mcp.js","sourceRoot":"","sources":["../../src/connectors/skill-store-mcp.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,19 @@
1
1
  import type { SkillOp } from "./parser.js";
2
2
  /**
3
3
  * Mutating-tool name shapes that trigger mutation classification when used
4
- * with a bare `$ tool` dispatch. The pattern is a curated allowlist of
5
- * conventional mutation-verb prefixes — `write_`, `update_`, `delete_`,
6
- * etc. extended over time as the wild-and-crazy harness surfaces new
7
- * mutation clusters (`archive_`, `prune_`, `deploy_`, `expire_`, ...).
4
+ * with a bare `$ tool` dispatch. v0.15.0 broadens the pattern from prefix-
5
+ * anchored (`/^(?:write_|update_|...)/ `) to underscore-boundary-anchored,
6
+ * so resource_action names (skill_write, skill_delete, memory_write,
7
+ * skill_update_status) classify uniformly with action_resource names
8
+ * (write_file, update_status). Verbs are matched as underscore-delimited
9
+ * tokens — `data_writer` is NOT a mutation (no boundary after "write"),
10
+ * but `data_write`, `write_file`, and `pre_write_audit` all are.
8
11
  *
9
- * Substrate-specific mutating tools whose names don't match the prefix
10
- * list aren't auto-classified; authors can still declare intent via
12
+ * Closes the discipline-only-contract gap where the prefix pattern silently
13
+ * passed `skill_write` while explicit special-casing caught `data_write`.
14
+ *
15
+ * Substrate-specific mutating tools whose names don't fit any verb token
16
+ * still aren't auto-classified; authors can declare intent via
11
17
  * `approved="reason"` per-op kwarg or `# Autonomous: true` skill header.
12
18
  */
13
19
  export declare const MUTATING_TOOL_PATTERN: RegExp;
@@ -1 +1 @@
1
- {"version":3,"file":"mutation-gate.d.ts","sourceRoot":"","sources":["../src/mutation-gate.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,QAA+N,CAAC;AAElQ,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,eAAe,GAAG,YAAY,CAAC;AAEzE,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,YAAY,CAAC;IACnB,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,OAAO,GAAG,sBAAsB,GAAG,IAAI,CAgB3E;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,OAAO,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,iBAAiB,GAAG,OAAO,CAKvF;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,cAAc,EAAE,sBAAsB,GAAG,MAAM,CAW3F"}
1
+ {"version":3,"file":"mutation-gate.d.ts","sourceRoot":"","sources":["../src/mutation-gate.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,qBAAqB,QAA+M,CAAC;AAElP,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,eAAe,GAAG,YAAY,CAAC;AAEzE,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,YAAY,CAAC;IACnB,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,OAAO,GAAG,sBAAsB,GAAG,IAAI,CAkB3E;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,OAAO,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,iBAAiB,GAAG,OAAO,CAKvF;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,cAAc,EAAE,sBAAsB,GAAG,MAAM,CAW3F"}
@@ -16,16 +16,22 @@
16
16
  // bypass throws instead of silently passing.
17
17
  /**
18
18
  * Mutating-tool name shapes that trigger mutation classification when used
19
- * with a bare `$ tool` dispatch. The pattern is a curated allowlist of
20
- * conventional mutation-verb prefixes — `write_`, `update_`, `delete_`,
21
- * etc. extended over time as the wild-and-crazy harness surfaces new
22
- * mutation clusters (`archive_`, `prune_`, `deploy_`, `expire_`, ...).
19
+ * with a bare `$ tool` dispatch. v0.15.0 broadens the pattern from prefix-
20
+ * anchored (`/^(?:write_|update_|...)/ `) to underscore-boundary-anchored,
21
+ * so resource_action names (skill_write, skill_delete, memory_write,
22
+ * skill_update_status) classify uniformly with action_resource names
23
+ * (write_file, update_status). Verbs are matched as underscore-delimited
24
+ * tokens — `data_writer` is NOT a mutation (no boundary after "write"),
25
+ * but `data_write`, `write_file`, and `pre_write_audit` all are.
23
26
  *
24
- * Substrate-specific mutating tools whose names don't match the prefix
25
- * list aren't auto-classified; authors can still declare intent via
27
+ * Closes the discipline-only-contract gap where the prefix pattern silently
28
+ * passed `skill_write` while explicit special-casing caught `data_write`.
29
+ *
30
+ * Substrate-specific mutating tools whose names don't fit any verb token
31
+ * still aren't auto-classified; authors can declare intent via
26
32
  * `approved="reason"` per-op kwarg or `# Autonomous: true` skill header.
27
33
  */
28
- export const MUTATING_TOOL_PATTERN = /^(?:write_|update_|delete_|remove_|set_|create_|insert_|put_|patch_|destroy_|archive_|prune_|deploy_|expire_|consolidate_|purge_|reset_|rotate_|move_|rename_|drop_|truncate_|upsert_|overwrite_|clear_|wipe_|finalize_).*/;
34
+ export const MUTATING_TOOL_PATTERN = /(?:^|_)(?:write|update|delete|remove|set|create|insert|put|patch|destroy|archive|prune|deploy|expire|consolidate|purge|reset|rotate|move|rename|drop|truncate|upsert|overwrite|clear|wipe|finalize)(?:_|$)/;
29
35
  /**
30
36
  * Returns the mutation classification for an op, or `null` if the op isn't
31
37
  * a mutation. Called by both the lint warning rule and the runtime
@@ -34,10 +40,12 @@ export const MUTATING_TOOL_PATTERN = /^(?:write_|update_|delete_|remove_|set_|cr
34
40
  export function classifyMutation(op) {
35
41
  if (op.kind === "$") {
36
42
  const toolName = op.body.split(/\s+/)[0] ?? "";
37
- // `data_write` is explicitly a mutation tool name — flag it even though
38
- // it doesn't start with `write_` (the canonical prefix anchor). The
39
- // dotted-name match (`<connector>.data_write`) is also caught so
40
- // qualified dispatch through a named bridge instance is gated identically.
43
+ // v0.15.0 the broadened `MUTATING_TOOL_PATTERN` now subsumes the
44
+ // earlier explicit `data_write` special-case (verbs match at any
45
+ // underscore boundary). `data_write` keeps its own `kind` for
46
+ // back-compat in `buildAuthorizationSuggestion` error copy; everything
47
+ // else (skill_write, write_file, memory_delete, ...) flows through
48
+ // the pattern path as `kind: "mutating_tool"`.
41
49
  const isDataWrite = toolName === "data_write" || /(?:^|_)data_write(?:_|$)/.test(toolName);
42
50
  if (isDataWrite)
43
51
  return { kind: "data_write", detail: toolName };
@@ -1 +1 @@
1
- {"version":3,"file":"mutation-gate.js","sourceRoot":"","sources":["../src/mutation-gate.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,6EAA6E;AAC7E,2EAA2E;AAC3E,0EAA0E;AAC1E,8EAA8E;AAC9E,EAAE;AACF,wEAAwE;AACxE,aAAa;AACb,6EAA6E;AAC7E,0EAA0E;AAC1E,gDAAgD;AAChD,uEAAuE;AACvE,0EAA0E;AAC1E,2EAA2E;AAC3E,4EAA4E;AAC5E,+CAA+C;AAI/C;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,4NAA4N,CAAC;AAUlQ;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAW;IAC1C,IAAI,EAAE,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC;QACpB,MAAM,QAAQ,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/C,wEAAwE;QACxE,oEAAoE;QACpE,iEAAiE;QACjE,2EAA2E;QAC3E,MAAM,WAAW,GAAG,QAAQ,KAAK,YAAY,IAAI,0BAA0B,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3F,IAAI,WAAW;YAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QACjE,IAAI,qBAAqB,CAAC,IAAI,CAAC,QAAQ,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QAC7F,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,EAAE,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QAC7B,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,CAAC,UAAU,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;IACnE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAkBD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,oBAAoB,CAAC,EAAW,EAAE,SAA4B;IAC5E,IAAI,OAAO,EAAE,CAAC,QAAQ,KAAK,QAAQ,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3E,IAAI,SAAS,CAAC,eAAe;QAAE,OAAO,IAAI,CAAC;IAC3C,IAAI,SAAS,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IACtC,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,4BAA4B,CAAC,cAAsC;IACjF,MAAM,QAAQ,GACZ,cAAc,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,cAAc;QACrD,CAAC,CAAC,cAAc,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,KAAK,cAAc,CAAC,MAAM,EAAE;YACxE,CAAC,CAAC,oBAAoB,cAAc,CAAC,MAAM,IAAI,CAAC;IAClD,OAAO,CACL,oBAAoB,QAAQ,gCAAgC;QAC5D,wDAAwD;QACxD,mFAAmF;QACnF,qFAAqF,CACtF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"mutation-gate.js","sourceRoot":"","sources":["../src/mutation-gate.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,6EAA6E;AAC7E,2EAA2E;AAC3E,0EAA0E;AAC1E,8EAA8E;AAC9E,EAAE;AACF,wEAAwE;AACxE,aAAa;AACb,6EAA6E;AAC7E,0EAA0E;AAC1E,gDAAgD;AAChD,uEAAuE;AACvE,0EAA0E;AAC1E,2EAA2E;AAC3E,4EAA4E;AAC5E,+CAA+C;AAI/C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,4MAA4M,CAAC;AAUlP;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAW;IAC1C,IAAI,EAAE,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC;QACpB,MAAM,QAAQ,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/C,mEAAmE;QACnE,iEAAiE;QACjE,8DAA8D;QAC9D,uEAAuE;QACvE,mEAAmE;QACnE,+CAA+C;QAC/C,MAAM,WAAW,GAAG,QAAQ,KAAK,YAAY,IAAI,0BAA0B,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3F,IAAI,WAAW;YAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QACjE,IAAI,qBAAqB,CAAC,IAAI,CAAC,QAAQ,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QAC7F,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,EAAE,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QAC7B,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,CAAC,UAAU,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;IACnE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAkBD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,oBAAoB,CAAC,EAAW,EAAE,SAA4B;IAC5E,IAAI,OAAO,EAAE,CAAC,QAAQ,KAAK,QAAQ,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3E,IAAI,SAAS,CAAC,eAAe;QAAE,OAAO,IAAI,CAAC;IAC3C,IAAI,SAAS,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IACtC,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,4BAA4B,CAAC,cAAsC;IACjF,MAAM,QAAQ,GACZ,cAAc,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,cAAc;QACrD,CAAC,CAAC,cAAc,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,KAAK,cAAc,CAAC,MAAM,EAAE;YACxE,CAAC,CAAC,oBAAoB,cAAc,CAAC,MAAM,IAAI,CAAC;IAClD,OAAO,CACL,oBAAoB,QAAQ,gCAAgC;QAC5D,wDAAwD;QACxD,mFAAmF;QACnF,qFAAqF,CACtF,CAAC;AACJ,CAAC"}
package/dist/parser.d.ts CHANGED
@@ -255,6 +255,19 @@ export interface ParsedSkill {
255
255
  * surfaces.
256
256
  */
257
257
  export declare function processSetValue(raw: string): string;
258
+ /**
259
+ * v0.7.2 — interpret common escape sequences in double-quoted string
260
+ * literals: `\n` → newline, `\t` → tab, `\\` → literal backslash,
261
+ * `\"` → literal quote. Other `\X` sequences pass through verbatim
262
+ * (no over-eager interpretation; future v0.8+ may add `\r` / `\0` /
263
+ * etc. if cold-author demand surfaces).
264
+ *
265
+ * v0.15.0 — exported so runtime's `coerceKwargValue` can apply the same
266
+ * interpretation to `$` op kwarg values. Pre-v0.15.0 this only ran via
267
+ * `processSetValue` ($set + function-call kwargs), leaving `$ skill_write
268
+ * source="..."` with literal `\n` / `\"` bytes in the value.
269
+ */
270
+ export declare function interpretDoubleQuotedEscapes(s: string): string;
258
271
  /**
259
272
  * Tokenize whitespace-separated `key=value` pairs, respecting matching
260
273
  * single/double quotes and `[...]` brackets.
@@ -1 +1 @@
1
- {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,MAAM,GAAG,GAAG,GAAG,MAAM,GAAG,SAAS,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,WAAW,GAAG,YAAY,GAAG,QAAQ,CAAC;AAEpJ;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,mGAS7B,CAAC;AAEX,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,mGAAmG;QACnG,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QACvB,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9B;;;;WAIG;QACH,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,gBAAgB,CAAC,EAAE;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,mGAAmG;QACnG,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAC5B;;;;WAIG;QACH,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QACjC;;;;WAIG;QACH,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF;;;;;OAKG;IACH,SAAS,CAAC,EAAE;QACV,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAC9B,CAAC;IACF;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC;IACxB,UAAU,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC,CAAC;IACtD,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC;IACvB;;;;OAIG;IACH,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAChD;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE;QACb,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QACtB,0EAA0E;QAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,4EAA4E;QAC5E,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,CAAC;IACF;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;OAUG;IACH,UAAU,CAAC,EAAE,eAAe,CAAC;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,OAAO,EAAE,CAAC;IAEf,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,UAAU,GAAG,YAAY,CAAC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,aAAa,GAAG,YAAY,GAAG,QAAQ,CAAC;AAEnG,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAEzE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG,MAAM,CAAC;AAC9C,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,UAAU,GAAG,UAAU,CAAC;AAgBnE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B;;;;OAIG;IACH,IAAI,EAAE,SAAS,CAAC;IAChB,uFAAuF;IACvF,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAClC;;;;;OAKG;IACH,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B;;;;;OAKG;IACH,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAChC,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,oFAAoF;IACpF,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB;;;;;OAKG;IACH,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAClC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB;;;;;OAKG;IACH,mBAAmB,EAAE,OAAO,CAAC;IAC7B;;;;;;;;;OASG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB;;;;;OAKG;IACH,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB;;;;;;;;;;;;OAYG;IACH,UAAU,EAAE,OAAO,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAuXD;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAmBnD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,4BAA4B,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAU9D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA+D3D;AAuND;;;GAGG;AACH;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQtE;AAED,wBAAgB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CA08BjD"}
package/dist/parser.js CHANGED
@@ -480,8 +480,13 @@ export function processSetValue(raw) {
480
480
  * `\"` → literal quote. Other `\X` sequences pass through verbatim
481
481
  * (no over-eager interpretation; future v0.8+ may add `\r` / `\0` /
482
482
  * etc. if cold-author demand surfaces).
483
+ *
484
+ * v0.15.0 — exported so runtime's `coerceKwargValue` can apply the same
485
+ * interpretation to `$` op kwarg values. Pre-v0.15.0 this only ran via
486
+ * `processSetValue` ($set + function-call kwargs), leaving `$ skill_write
487
+ * source="..."` with literal `\n` / `\"` bytes in the value.
483
488
  */
484
- function interpretDoubleQuotedEscapes(s) {
489
+ export function interpretDoubleQuotedEscapes(s) {
485
490
  return s.replace(/\\(["\\nt])/g, (match, ch) => {
486
491
  switch (ch) {
487
492
  case '"': return '"';
@@ -518,6 +523,21 @@ export function tokenizeKeywordArgs(input) {
518
523
  }
519
524
  if (inQuote) {
520
525
  current += ch;
526
+ // v0.15.0 — recognize `\"`, `\'`, `\\` as escapes inside a quoted
527
+ // string. Without this, `text="he said \"hi\""` closes the value at
528
+ // the first `\"` and the trailing `hi\""` lands as separate tokens
529
+ // (or worse, silent truncation when feeding to a $ dispatch op).
530
+ // Mirrors processSetValue's interpretDoubleQuotedEscapes for the
531
+ // outer-tokenization layer; the value still gets fed to escape
532
+ // interpretation downstream (processSetValue / coerceKwargValue).
533
+ if (ch === "\\" && i + 1 < input.length) {
534
+ const next = input[i + 1];
535
+ if (next === inQuote || next === "\\") {
536
+ current += next;
537
+ i++;
538
+ continue;
539
+ }
540
+ }
521
541
  if (ch === inQuote)
522
542
  inQuote = null;
523
543
  continue;
@@ -578,6 +598,17 @@ function extractParenBody(text, openIdx) {
578
598
  continue;
579
599
  }
580
600
  if (inQuote !== null) {
601
+ // v0.15.0 — recognize `\"`, `\'`, `\\` as escapes inside a quoted
602
+ // string (parallel to tokenizeKeywordArgs). Without this,
603
+ // `emit(text="he said \"hi\"")` mis-closes the inner quote and the
604
+ // paren-balance walker treats `)` as content.
605
+ if (ch === "\\" && i + 1 < text.length) {
606
+ const next = text[i + 1];
607
+ if (next === inQuote || next === "\\") {
608
+ i++;
609
+ continue;
610
+ }
611
+ }
581
612
  if (ch === inQuote)
582
613
  inQuote = null;
583
614
  continue;