skillscript-runtime 0.20.2 → 0.21.1
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 +37 -10
- package/dist/connectors/skill-store-mcp.js +1 -1
- package/dist/connectors/skill-store-mcp.js.map +1 -1
- package/dist/connectors/skill-store.js +1 -1
- package/dist/connectors/skill-store.js.map +1 -1
- package/dist/connectors/types.d.ts +32 -1
- package/dist/connectors/types.d.ts.map +1 -1
- package/dist/connectors/types.js.map +1 -1
- package/dist/dashboard/server.d.ts +9 -0
- package/dist/dashboard/server.d.ts.map +1 -1
- package/dist/dashboard/server.js +34 -2
- package/dist/dashboard/server.js.map +1 -1
- package/dist/dashboard/spa/app.js +66 -6
- package/dist/help-content.d.ts +9 -0
- package/dist/help-content.d.ts.map +1 -1
- package/dist/help-content.js +21 -0
- package/dist/help-content.js.map +1 -1
- package/dist/mcp-server.d.ts +17 -16
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +60 -16
- package/dist/mcp-server.js.map +1 -1
- package/dist/skill-catalog.d.ts +2 -10
- package/dist/skill-catalog.d.ts.map +1 -1
- package/dist/skill-catalog.js +15 -0
- package/dist/skill-catalog.js.map +1 -1
- package/dist/skill-surface.d.ts +19 -0
- package/dist/skill-surface.d.ts.map +1 -0
- package/dist/skill-surface.js +86 -0
- package/dist/skill-surface.js.map +1 -0
- package/docs/adopter-playbook.md +17 -8
- package/docs/configuration.md +9 -3
- package/docs/connector-contract-reference.md +4 -6
- package/docs/sqlite-skill-store.md +5 -7
- package/examples/skillscripts/hello-world.skill.provenance.json +1 -1
- package/package.json +1 -1
|
@@ -76,7 +76,10 @@ async function refresh() {
|
|
|
76
76
|
state.blockedShellAttempts = blocked;
|
|
77
77
|
state.lastUpdate = ts;
|
|
78
78
|
renderSecuredBanner();
|
|
79
|
-
|
|
79
|
+
// v0.21.0 — surface the running runtime version next to the poll timestamp.
|
|
80
|
+
const ver = state.capabilities?.runtimeVersion;
|
|
81
|
+
document.getElementById("poll-status").textContent =
|
|
82
|
+
`last updated ${ts.toLocaleTimeString()}${ver ? ` · skillscript v${ver}` : ""}`;
|
|
80
83
|
renderCurrentView();
|
|
81
84
|
} catch (err) {
|
|
82
85
|
document.getElementById("poll-status").textContent = `poll failed: ${err.message}`;
|
|
@@ -350,7 +353,7 @@ function renderSkills() {
|
|
|
350
353
|
${state.skills.map((s) => `
|
|
351
354
|
<tr onclick="window.location.hash='#skill/${encodeURIComponent(s.name)}'">
|
|
352
355
|
<td><strong>${esc(s.name)}</strong></td>
|
|
353
|
-
<td
|
|
356
|
+
<td>${skillStatusBadge(s)}</td>
|
|
354
357
|
<td>${esc(s.description ?? "—")}</td>
|
|
355
358
|
<td><code>${esc(s.version?.slice(0, 8) ?? "—")}</code></td>
|
|
356
359
|
</tr>
|
|
@@ -361,16 +364,28 @@ function renderSkills() {
|
|
|
361
364
|
`;
|
|
362
365
|
}
|
|
363
366
|
|
|
367
|
+
// v0.21.0 — gate-aware status badge (adopter finding 576632ca). A legacy skill
|
|
368
|
+
// stored `Approved` but failing the secured gate (e.g. a v1 stamp) WON'T run —
|
|
369
|
+
// badging it a plain green "Approved" while the Approvals tab lists it as
|
|
370
|
+
// "needs approval" reads as a contradiction. Show "re-approval needed" here too
|
|
371
|
+
// so both views agree on the truth (what the gate will actually do).
|
|
372
|
+
function skillStatusBadge(s) {
|
|
373
|
+
if (s.status === "Approved" && s.gate_ok === false) {
|
|
374
|
+
return `<span class="badge error" title="Approved status, but the body lacks a valid signature — won't run until re-approved">re-approval needed</span>`;
|
|
375
|
+
}
|
|
376
|
+
return `<span class="badge ${esc(s.status)}">${esc(s.status)}</span>`;
|
|
377
|
+
}
|
|
378
|
+
|
|
364
379
|
async function renderSkillDetail(name) {
|
|
365
380
|
try {
|
|
366
|
-
// v0.13.3 — source moved out of
|
|
381
|
+
// v0.13.3 — source moved out of skill_preflight into dedicated skill_read.
|
|
367
382
|
// Call both in parallel; skill_read may fail if the skill name doesn't
|
|
368
383
|
// resolve (load() throws), so guard it to keep the detail view rendering.
|
|
369
384
|
const [meta, readResult] = await Promise.all([
|
|
370
|
-
callTool("
|
|
385
|
+
callTool("skill_preflight", { name }),
|
|
371
386
|
callTool("skill_read", { name }).catch(() => null),
|
|
372
387
|
]);
|
|
373
|
-
const { metadata, versions, recent_fires, approval } = meta;
|
|
388
|
+
const { metadata, versions, recent_fires, approval, contract } = meta;
|
|
374
389
|
const source = readResult?.source ?? null;
|
|
375
390
|
const metrics = state.metrics?.perSkill?.[name];
|
|
376
391
|
const triggersForSkill = state.triggers.filter((t) => t.skillName === name);
|
|
@@ -397,6 +412,8 @@ async function renderSkillDetail(name) {
|
|
|
397
412
|
${renderStatusActions(name, metadata, approval)}
|
|
398
413
|
</section>
|
|
399
414
|
|
|
415
|
+
${renderEffectfulFootprintPanel(contract?.effectful_footprint)}
|
|
416
|
+
|
|
400
417
|
${source ? renderSecuritySignalsPanel(source) : ""}
|
|
401
418
|
|
|
402
419
|
<section>
|
|
@@ -626,6 +643,49 @@ function renderHighlightedSkillBody(source) {
|
|
|
626
643
|
// showing aggregated counts so a reviewer knows WHAT to look for before
|
|
627
644
|
// scanning the body. Pairs with renderHighlightedSkillBody() (the
|
|
628
645
|
// WHERE).
|
|
646
|
+
// v0.21.0 — the authoritative "what does it touch" least-privilege checklist
|
|
647
|
+
// for the human approver. Unlike renderSecuritySignalsPanel (regex over the
|
|
648
|
+
// source), this is the AST-derived effectful_footprint from skill_preflight —
|
|
649
|
+
// the SAME op enumeration the capability gate authorizes — so it's the truth of
|
|
650
|
+
// what the skill can do when signed, not a textual approximation. Surfaced right
|
|
651
|
+
// at the approve action so the operator sees the surface they're signing off.
|
|
652
|
+
function renderEffectfulFootprintPanel(fp) {
|
|
653
|
+
if (!fp) return ""; // source not loadable / parse failed → no contract to show
|
|
654
|
+
const items = [];
|
|
655
|
+
if (fp.connectors.length > 0) {
|
|
656
|
+
items.push(`<li class="sig-medium-text">Dispatches to ${fp.connectors.length} MCP connector${fp.connectors.length === 1 ? "" : "s"}: ${fp.connectors.map((c) => `<code>${esc(c)}</code>`).join(", ")}</li>`);
|
|
657
|
+
}
|
|
658
|
+
if (fp.builtins.length > 0) {
|
|
659
|
+
items.push(`<li class="sig-info-text">Uses ${fp.builtins.length} built-in op${fp.builtins.length === 1 ? "" : "s"}: ${fp.builtins.map((b) => `<code>${esc(b)}</code>`).join(", ")}</li>`);
|
|
660
|
+
}
|
|
661
|
+
if (fp.file_writes > 0) {
|
|
662
|
+
items.push(`<li class="sig-high-text">${fp.file_writes} <code>file_write</code> op${fp.file_writes === 1 ? "" : "s"} <small>(writes to the filesystem allowlist)</small></li>`);
|
|
663
|
+
}
|
|
664
|
+
if (fp.file_reads > 0) {
|
|
665
|
+
items.push(`<li class="sig-medium-text">${fp.file_reads} <code>file_read</code> op${fp.file_reads === 1 ? "" : "s"}</li>`);
|
|
666
|
+
}
|
|
667
|
+
if (fp.unsafe_shell > 0) {
|
|
668
|
+
items.push(`<li class="sig-high-text">${fp.unsafe_shell} unsafe (full-bash) shell op${fp.unsafe_shell === 1 ? "" : "s"}</li>`);
|
|
669
|
+
}
|
|
670
|
+
const safeShellBins = fp.shell_binaries.filter((b) => b !== "bash" || fp.unsafe_shell === 0);
|
|
671
|
+
if (safeShellBins.length > 0) {
|
|
672
|
+
items.push(`<li class="sig-medium-text">Runs shell ${safeShellBins.length === 1 ? "binary" : "binaries"}: ${safeShellBins.map((b) => `<code>${esc(b)}</code>`).join(", ")} <small>(allowlist-gated)</small></li>`);
|
|
673
|
+
}
|
|
674
|
+
if (fp.notifies > 0) {
|
|
675
|
+
items.push(`<li class="sig-medium-text">${fp.notifies} <code>notify</code> agent-wake op${fp.notifies === 1 ? "" : "s"}</li>`);
|
|
676
|
+
}
|
|
677
|
+
const body = items.length === 0
|
|
678
|
+
? `<p class="empty">Pure — no connector, shell, file, or notify ops. Nothing effectful to authorize.</p>`
|
|
679
|
+
: `<ul class="security-signals">${items.join("")}</ul>
|
|
680
|
+
<p><small>This is the AST-derived footprint the capability gate authorizes — the surface this skill can touch once approved. Confirm every line is least-privilege before signing.</small></p>`;
|
|
681
|
+
return `
|
|
682
|
+
<section>
|
|
683
|
+
<h2>What this skill touches</h2>
|
|
684
|
+
${body}
|
|
685
|
+
</section>
|
|
686
|
+
`;
|
|
687
|
+
}
|
|
688
|
+
|
|
629
689
|
function renderSecuritySignalsPanel(source) {
|
|
630
690
|
const sig = collectSecuritySignals(source);
|
|
631
691
|
const items = [];
|
|
@@ -957,7 +1017,7 @@ async function loadComposeContract(detailsEl) {
|
|
|
957
1017
|
panel.dataset.loaded = "true";
|
|
958
1018
|
const [kind, name] = detailsEl.dataset.composeRef.split(":");
|
|
959
1019
|
try {
|
|
960
|
-
const meta = await callTool("
|
|
1020
|
+
const meta = await callTool("skill_preflight", { name });
|
|
961
1021
|
const m = meta.metadata;
|
|
962
1022
|
// For inline (data-only), also fetch the body since it bakes at
|
|
963
1023
|
// compile time — reviewer sees what literally lands in the
|
package/dist/help-content.d.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
1
|
import type { Registry } from "./connectors/registry.js";
|
|
2
|
+
/**
|
|
3
|
+
* The canonical agent-usage block, delivered as the MCP server's `instructions`
|
|
4
|
+
* field at `initialize` so every connecting agent learns the workflow with no
|
|
5
|
+
* CLAUDE.md copy-paste. This static string is the shipped source of truth —
|
|
6
|
+
* backend-agnostic (no AMP / substrate references) so it serves dogfood +
|
|
7
|
+
* external adopters from one place. Keep the dev-agent CLAUDE.md and
|
|
8
|
+
* docs/adopter-agent-guide.md REFERENCING this, not forking divergent copies.
|
|
9
|
+
*/
|
|
10
|
+
export declare const SKILLSCRIPT_USAGE_INSTRUCTIONS = "A Skillscript runtime is wired over MCP. Skills are compiled, approved, reusable procedures \u2014 run them, don't re-derive.\n\n**Session start:** `skill_list()` \u2192 your skills, grouped: `skills` (invoke directly) \u00B7 `receives` (push context to you) \u00B7 `headless` (cron/event-fired; maintain, don't invoke). Know them before routine work.\n\n**Routine task \u2014 if a skill fits, use it, don't re-reason:**\n- `skill_preflight({name})` \u2192 vars, returns, requires, effectful footprint, cleared-to-run. (skill_list entries already carry this contract.)\n- `execute_skill({name})` \u2192 run end-to-end.\n- `compile_skill({name})` \u2192 preview the plan, no side effects.\n\n**Repeating a routine? Capture it as a skill.** What you can script = the wired connectors, models, and allowed shell binaries from `runtime_capabilities()` \u2014 that list is your menu. When you catch yourself re-running work over any of them, author it. If something you'd need isn't wired yet, ask the operator to add it, then capture it.\n- `help({topic})` \u2192 the language (ops, frontmatter, connectors, lint-codes).\n- Draft \u2192 `lint_skill({source})` \u2192 `compile_skill({source})` \u2192 `skill_write({name, source})`.\n- It lands **Draft** \u2014 you can't self-approve; a human does. Treat anything you authored as not-yet-runnable until approved.";
|
|
2
11
|
export declare function helpResponse(topic: string | null, runtimeVersion: string, registry?: Registry): Record<string, unknown>;
|
|
3
12
|
//# sourceMappingURL=help-content.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help-content.d.ts","sourceRoot":"","sources":["../src/help-content.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"help-content.d.ts","sourceRoot":"","sources":["../src/help-content.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEzD;;;;;;;GAOG;AACH,eAAO,MAAM,8BAA8B,k1CAYkF,CAAC;AA24B9H,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,cAAc,EAAE,MAAM,EACtB,QAAQ,CAAC,EAAE,QAAQ,GAClB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAqBzB"}
|
package/dist/help-content.js
CHANGED
|
@@ -13,6 +13,27 @@
|
|
|
13
13
|
//
|
|
14
14
|
// Token estimates per topic are approximate; help() output is intended
|
|
15
15
|
// for an agent's working context, not for human reading.
|
|
16
|
+
/**
|
|
17
|
+
* The canonical agent-usage block, delivered as the MCP server's `instructions`
|
|
18
|
+
* field at `initialize` so every connecting agent learns the workflow with no
|
|
19
|
+
* CLAUDE.md copy-paste. This static string is the shipped source of truth —
|
|
20
|
+
* backend-agnostic (no AMP / substrate references) so it serves dogfood +
|
|
21
|
+
* external adopters from one place. Keep the dev-agent CLAUDE.md and
|
|
22
|
+
* docs/adopter-agent-guide.md REFERENCING this, not forking divergent copies.
|
|
23
|
+
*/
|
|
24
|
+
export const SKILLSCRIPT_USAGE_INSTRUCTIONS = `A Skillscript runtime is wired over MCP. Skills are compiled, approved, reusable procedures — run them, don't re-derive.
|
|
25
|
+
|
|
26
|
+
**Session start:** \`skill_list()\` → your skills, grouped: \`skills\` (invoke directly) · \`receives\` (push context to you) · \`headless\` (cron/event-fired; maintain, don't invoke). Know them before routine work.
|
|
27
|
+
|
|
28
|
+
**Routine task — if a skill fits, use it, don't re-reason:**
|
|
29
|
+
- \`skill_preflight({name})\` → vars, returns, requires, effectful footprint, cleared-to-run. (skill_list entries already carry this contract.)
|
|
30
|
+
- \`execute_skill({name})\` → run end-to-end.
|
|
31
|
+
- \`compile_skill({name})\` → preview the plan, no side effects.
|
|
32
|
+
|
|
33
|
+
**Repeating a routine? Capture it as a skill.** What you can script = the wired connectors, models, and allowed shell binaries from \`runtime_capabilities()\` — that list is your menu. When you catch yourself re-running work over any of them, author it. If something you'd need isn't wired yet, ask the operator to add it, then capture it.
|
|
34
|
+
- \`help({topic})\` → the language (ops, frontmatter, connectors, lint-codes).
|
|
35
|
+
- Draft → \`lint_skill({source})\` → \`compile_skill({source})\` → \`skill_write({name, source})\`.
|
|
36
|
+
- It lands **Draft** — you can't self-approve; a human does. Treat anything you authored as not-yet-runnable until approved.`;
|
|
16
37
|
const QUICKSTART = `# Skillscript — quickstart
|
|
17
38
|
|
|
18
39
|
Skillscript is a declarative language for authoring agent workflows. A
|
package/dist/help-content.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help-content.js","sourceRoot":"","sources":["../src/help-content.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"help-content.js","sourceRoot":"","sources":["../src/help-content.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp-server.d.ts
CHANGED
|
@@ -14,23 +14,24 @@ import type { Registry } from "./connectors/registry.js";
|
|
|
14
14
|
* protocol conforms to MCP — real MCP clients (Claude Desktop, Cursor,
|
|
15
15
|
* future tools) can consume the server unchanged.
|
|
16
16
|
*
|
|
17
|
-
* Surface: tools wrapping existing T6 primitives
|
|
17
|
+
* Surface: tools wrapping existing T6 primitives, ordered by the cold-author
|
|
18
|
+
* workflow loop the descriptions teach (learn → discover → draft → commit →
|
|
19
|
+
* approve → run → automate → observe).
|
|
18
20
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* help({topic?}) → cold-agent language discovery (read, v0.2.8)
|
|
21
|
+
* LEARN help({topic?}) → language quickstart + deep topics
|
|
22
|
+
* runtime_capabilities({include?})→ wired connectors + shell-exec mode
|
|
23
|
+
* DISCOVER skill_list({filter?}) → SkillCatalog (grouped by audience; entries carry the full contract)
|
|
24
|
+
* skill_preflight({name}) → one skill's contract: takes/returns/requires/touches + approval + lifecycle
|
|
25
|
+
* skill_read({name, version?}) → {name, version, status, source} (the body itself)
|
|
26
|
+
* data_read({id, store?}) → PortableData | null (direct lookup; no data_write MCP by design)
|
|
27
|
+
* DRAFT lint_skill({source?|name}) → tiered diagnostics (inner loop)
|
|
28
|
+
* compile_skill({source?|name, inputs?})→ rendered artifact + errors + exec order (pre-commit)
|
|
29
|
+
* COMMIT skill_write({name, source, overwrite?})→ store the body (write; secured mode forces unsigned→Draft)
|
|
30
|
+
* APPROVE skill_status({name, new_state}) → Draft/Approved/Disabled (write; secured promote needs a signature)
|
|
31
|
+
* RUN execute_skill({name|source, inputs?, mechanical?})→ run + return result (write)
|
|
32
|
+
* AUTOMATE register_trigger / list_triggers / set_trigger_enabled / unregister_trigger → autonomous dispatch
|
|
33
|
+
* OBSERVE health_metrics({filter?}) → per-skill/connector aggregates
|
|
34
|
+
* blocked_shell_attempts() → allowlist-refused shell ops (observe→promote loop)
|
|
34
35
|
*/
|
|
35
36
|
export interface JsonRpcRequest {
|
|
36
37
|
jsonrpc: "2.0";
|
package/dist/mcp-server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAkE,MAAM,uBAAuB,CAAC;AAGxH,OAAO,KAAK,EAAE,SAAS,EAAgD,MAAM,gBAAgB,CAAC;AAC9F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp-server.js
CHANGED
|
@@ -4,10 +4,11 @@ import { healthMetrics } from "./metrics.js";
|
|
|
4
4
|
import { lint } from "./lint.js";
|
|
5
5
|
import { compile } from "./compile.js";
|
|
6
6
|
import { parse as parseSkill } from "./parser.js";
|
|
7
|
+
import { extractEffectfulFootprint } from "./skill-surface.js";
|
|
7
8
|
import { listKnownConnectorClasses } from "./connectors/config.js";
|
|
8
9
|
import { LintFailureError, MissingSkillReferenceError, OpError } from "./errors.js";
|
|
9
10
|
import { executeSkillByName, executeSkillFromSource, RecursionDepthExceededError, SkillNotFoundForCompositionError, } from "./composition.js";
|
|
10
|
-
import { helpResponse } from "./help-content.js";
|
|
11
|
+
import { helpResponse, SKILLSCRIPT_USAGE_INSTRUCTIONS } from "./help-content.js";
|
|
11
12
|
import { RUNTIME_VERSION } from "./version.js";
|
|
12
13
|
import { evaluateApprovalGate, isSecuredMode, hasApprovalPublicKey } from "./approval.js";
|
|
13
14
|
import { forceDraftStatus } from "./connectors/skill-store-mcp.js";
|
|
@@ -44,6 +45,9 @@ export class McpServer {
|
|
|
44
45
|
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
45
46
|
capabilities: { tools: {} },
|
|
46
47
|
serverInfo: { name: SERVER_NAME, version: this.version },
|
|
48
|
+
// Canonical agent-usage block — every connecting agent learns the
|
|
49
|
+
// workflow at session start, no CLAUDE.md copy-paste required.
|
|
50
|
+
instructions: SKILLSCRIPT_USAGE_INSTRUCTIONS,
|
|
47
51
|
},
|
|
48
52
|
};
|
|
49
53
|
case "tools/list":
|
|
@@ -118,7 +122,7 @@ export class McpServer {
|
|
|
118
122
|
registerBuiltinTools() {
|
|
119
123
|
this.registerTool({
|
|
120
124
|
name: "skill_list",
|
|
121
|
-
description: "Discover skills in the configured SkillStore
|
|
125
|
+
description: "Discover skills in the configured SkillStore. Returns a `SkillCatalog` pre-grouped by audience-derived category: `receives` (skills that push to the calling agent via `# Output: agent:`), `skills` (skills the agent can invoke), `headless` (admin-view only). Category derived from each skill's `# Output:` declarations. Filter by audience / status / trigger_kind / domain_tags / name_prefix / author (AND-composed). Default: audience=\"agent\", status=\"Approved\". Every entry carries the full preflight contract — `vars` (inputs), `returns` (exported vars), `requires` (capability needs), `effectful_footprint` (which connectors / shell binaries / file + notify ops it touches), plus `gate_ok` (cleared-to-run under the current mode) and `author` (when the substrate tracks it). So you can read a skill's whole I/O + effect contract here without a per-skill `skill_preflight` call; reach for `skill_preflight` when you want one skill's contract + version/lifecycle detail, or `skill_read` for the body.",
|
|
122
126
|
inputSchema: {
|
|
123
127
|
type: "object",
|
|
124
128
|
properties: {
|
|
@@ -143,7 +147,7 @@ export class McpServer {
|
|
|
143
147
|
});
|
|
144
148
|
this.registerTool({
|
|
145
149
|
name: "blocked_shell_attempts",
|
|
146
|
-
description: "
|
|
150
|
+
description: "List shell op dispatches refused by the binary allowlist gate. Queries the trace store cross-skill, filtering to op records carrying `blocked_reason: \"binary-not-allowed\"`. Returns a flat list for the dashboard's observe→promote loop: the operator sees what binaries skills tried to invoke, then decides whether to add any to `SKILLSCRIPT_SHELL_ALLOWLIST`. Read-only.",
|
|
147
151
|
inputSchema: {
|
|
148
152
|
type: "object",
|
|
149
153
|
properties: {
|
|
@@ -196,8 +200,8 @@ export class McpServer {
|
|
|
196
200
|
},
|
|
197
201
|
});
|
|
198
202
|
this.registerTool({
|
|
199
|
-
name: "
|
|
200
|
-
description: "
|
|
203
|
+
name: "skill_preflight",
|
|
204
|
+
description: "PRE-EXECUTION CONTRACT CHECK — call this BEFORE executing or composing a skill to see what it takes, returns, requires, and touches: its inputs (vars), exported variables (returns), capability requirements, and effectful footprint (which connectors / shell binaries / write + notify ops it dispatches). Also reports whether it's cleared to run (approval-gate state) + version/lifecycle. The least-privilege checklist for a human approver, and the contract surface for a cold author composing against it. Discover skills with skill_list (its entries already carry this same contract); call skill_preflight for one skill's contract plus version/lifecycle detail, or skill_read for the source body.",
|
|
201
205
|
inputSchema: {
|
|
202
206
|
type: "object",
|
|
203
207
|
properties: {
|
|
@@ -219,15 +223,28 @@ export class McpServer {
|
|
|
219
223
|
// stale-Approved skills (body edited since approval, token no
|
|
220
224
|
// longer verifies). `null` when the source isn't loadable.
|
|
221
225
|
let approval = null;
|
|
226
|
+
// v0.21.0 — the contract surface: what the skill TAKES (vars, via the
|
|
227
|
+
// parser's frontmatter), RETURNS (exported vars), REQUIRES (capability
|
|
228
|
+
// clauses), and TOUCHES (effectful footprint). Derived statically from
|
|
229
|
+
// the body. Null when the source isn't loadable.
|
|
230
|
+
let contract = null;
|
|
222
231
|
if (loaded?.source !== undefined) {
|
|
223
232
|
const g = evaluateApprovalGate(loaded.source);
|
|
224
233
|
approval = g.ok ? { gate_ok: true } : { gate_ok: false, reason: g.reason };
|
|
234
|
+
const parsed = parseSkill(loaded.source);
|
|
235
|
+
contract = {
|
|
236
|
+
vars: parsed.vars.map((v) => v.name),
|
|
237
|
+
returns: parsed.returns,
|
|
238
|
+
requires: parsed.requires,
|
|
239
|
+
effectful_footprint: extractEffectfulFootprint(parsed),
|
|
240
|
+
};
|
|
225
241
|
}
|
|
226
242
|
return {
|
|
227
243
|
metadata,
|
|
244
|
+
contract,
|
|
245
|
+
approval,
|
|
228
246
|
versions,
|
|
229
247
|
recent_fires,
|
|
230
|
-
approval,
|
|
231
248
|
};
|
|
232
249
|
},
|
|
233
250
|
});
|
|
@@ -277,7 +294,7 @@ export class McpServer {
|
|
|
277
294
|
});
|
|
278
295
|
this.registerTool({
|
|
279
296
|
name: "skill_status",
|
|
280
|
-
description: "Transition a skill's status
|
|
297
|
+
description: "Transition a skill's lifecycle status: Draft, Approved, Disabled. Approved is the only status that executes and lets triggers fire; Draft is the editing state; Disabled retires a skill without deleting it (re-enable by transitioning back to Approved/Draft). In secured mode you CANNOT promote to Approved here without a valid signature — approve via the dashboard or `skillfile approve` (which signs the body); a bare status flip can't grant approval. Write operation.",
|
|
281
298
|
inputSchema: {
|
|
282
299
|
type: "object",
|
|
283
300
|
properties: {
|
|
@@ -296,6 +313,19 @@ export class McpServer {
|
|
|
296
313
|
if (!isSkillStatus(newState)) {
|
|
297
314
|
throw new OpError(`\`skill_status\` requires \`new_state\` to be one of ${VALID_SKILL_STATUSES.map((s) => `"${s}"`).join(", ")}; got ${JSON.stringify(newState)}.`, "skill_status", `Pass \`new_state\` as one of: ${VALID_SKILL_STATUSES.join(" | ")}.`, name);
|
|
298
315
|
}
|
|
316
|
+
// v0.21.0 — store-agnostic secured-mode closure (red-team 33bf53d3).
|
|
317
|
+
// skill_status cannot GRANT approval in secured mode: promotion to
|
|
318
|
+
// Approved is refused unless the stored body already carries a valid v3
|
|
319
|
+
// signature. The per-store guard (FilesystemSkillStore/SqliteSkillStore)
|
|
320
|
+
// didn't cover custom adopter stores (e.g. AMP-backed), so an agent could
|
|
321
|
+
// flip Draft→Approved with no signature — a forgeable trust-state lie.
|
|
322
|
+
// Enforce HERE, at the ingress, regardless of substrate.
|
|
323
|
+
if (newState === "Approved" && isSecuredMode()) {
|
|
324
|
+
const loaded = await this.deps.skillStore.load(name).catch(() => null);
|
|
325
|
+
if (loaded === null || !evaluateApprovalGate(loaded.source).ok) {
|
|
326
|
+
throw new OpError(`cannot promote '${name}' to Approved in secured mode — the skill carries no valid signature. Approve it via the dashboard or \`skillfile approve\` (which signs the body); a status change alone cannot grant approval.`, "skill_status", `Sign the skill with the operator's key, then it can be Approved.`, name);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
299
329
|
const result = await this.deps.skillStore.update_status(name, newState);
|
|
300
330
|
// v0.19.1 — sync declarative triggers on status transition.
|
|
301
331
|
// Approved → register the skill's declared triggers; Draft or
|
|
@@ -307,7 +337,7 @@ export class McpServer {
|
|
|
307
337
|
});
|
|
308
338
|
this.registerTool({
|
|
309
339
|
name: "list_triggers",
|
|
310
|
-
description: "List registered triggers. Optionally filter by skill name or trigger source.",
|
|
340
|
+
description: "List registered triggers — the autonomous-dispatch registry. Optionally filter by skill name or trigger source (cron / event). Read-only. Pairs with register_trigger / set_trigger_enabled / unregister_trigger to manage how Approved skills fire on their own.",
|
|
311
341
|
inputSchema: {
|
|
312
342
|
type: "object",
|
|
313
343
|
properties: {
|
|
@@ -326,7 +356,7 @@ export class McpServer {
|
|
|
326
356
|
});
|
|
327
357
|
this.registerTool({
|
|
328
358
|
name: "register_trigger",
|
|
329
|
-
description: "Register
|
|
359
|
+
description: "Register an autonomous-dispatch trigger for a skill — cron (time-based) or event (HTTP POST /event ingress, named). Only Approved skills fire; the scheduler re-verifies the approval gate at fire time, so registering a trigger never bypasses approval. Skills can also declare triggers inline via `# Triggers:` frontmatter (synced automatically on approval) — use this tool for imperative / dynamic registration. Returns the registration. Write operation.",
|
|
330
360
|
inputSchema: {
|
|
331
361
|
type: "object",
|
|
332
362
|
properties: {
|
|
@@ -374,7 +404,7 @@ export class McpServer {
|
|
|
374
404
|
});
|
|
375
405
|
this.registerTool({
|
|
376
406
|
name: "unregister_trigger",
|
|
377
|
-
description: "
|
|
407
|
+
description: "Remove a registered trigger by id (see list_triggers for ids). Returns true if removed, false if the id wasn't found. Write operation.",
|
|
378
408
|
inputSchema: {
|
|
379
409
|
type: "object",
|
|
380
410
|
properties: { trigger_id: { type: "string" } },
|
|
@@ -387,7 +417,7 @@ export class McpServer {
|
|
|
387
417
|
});
|
|
388
418
|
this.registerTool({
|
|
389
419
|
name: "set_trigger_enabled",
|
|
390
|
-
description: "
|
|
420
|
+
description: "Toggle a trigger's enabled state without unregistering it — disabled triggers stay in the registry but the scheduler skips firing them (vacation / maintenance windows). State persists via the onTriggersChanged hook for imperative triggers. Returns the updated registration, or null if no trigger has that id. Write operation.",
|
|
391
421
|
inputSchema: {
|
|
392
422
|
type: "object",
|
|
393
423
|
properties: {
|
|
@@ -449,7 +479,7 @@ export class McpServer {
|
|
|
449
479
|
// ─── v0.2.3 — over-the-wire authoring lifecycle ────────────────────────
|
|
450
480
|
this.registerTool({
|
|
451
481
|
name: "lint_skill",
|
|
452
|
-
description: "Run static lint against a skill source body or stored skill name. Returns diagnostics across tier-1 (errors that block compile), tier-2 (warnings), tier-3 (advisories). Read-only.
|
|
482
|
+
description: "Run static lint against a skill source body or stored skill name. Returns diagnostics across tier-1 (errors that block compile), tier-2 (warnings), tier-3 (advisories). Read-only. The inner-loop affordance while drafting — lint as you iterate, then compile_skill for the full pre-commit check before skill_write.",
|
|
453
483
|
inputSchema: {
|
|
454
484
|
type: "object",
|
|
455
485
|
properties: {
|
|
@@ -461,7 +491,7 @@ export class McpServer {
|
|
|
461
491
|
});
|
|
462
492
|
this.registerTool({
|
|
463
493
|
name: "compile_skill",
|
|
464
|
-
description: "Compile a skill source body or stored skill name. Returns the rendered artifact + parse/compile errors + resolved variables + topological execution order. Read-only.
|
|
494
|
+
description: "Compile a skill source body or stored skill name. Returns the rendered artifact + parse/compile errors + resolved variables + topological execution order. Read-only. The pre-commit check after lint_skill passes and before skill_write — confirms the body compiles and shows the execution order without running effects (use execute_skill `mechanical: true` for a no-fire dispatch preview).",
|
|
465
495
|
inputSchema: {
|
|
466
496
|
type: "object",
|
|
467
497
|
properties: {
|
|
@@ -478,7 +508,7 @@ export class McpServer {
|
|
|
478
508
|
});
|
|
479
509
|
this.registerTool({
|
|
480
510
|
name: "skill_write",
|
|
481
|
-
description: "Write a skill body into the configured SkillStore. Tier-1 lint runs at write time (SkillStore contract)
|
|
511
|
+
description: "Write a skill body into the configured SkillStore. Tier-1 lint runs at write time (SkillStore contract) and throws on rejection — run lint_skill / compile_skill first to iterate cleanly. The `# Status:` header is honored: `# Status: Approved` lands Approved in unsecured mode, but in secured mode an unsigned body is forced to Draft (a write can't grant approval). Promote later via skill_status, or the dashboard / `skillfile approve` in secured mode. Returns version + content_hash. Write operation.",
|
|
482
512
|
inputSchema: {
|
|
483
513
|
type: "object",
|
|
484
514
|
properties: {
|
|
@@ -533,7 +563,7 @@ export class McpServer {
|
|
|
533
563
|
async executeSkill(args, callerCtx = {}) {
|
|
534
564
|
// v0.15.2 — `name` is the canonical kwarg; `skill_name` is a silent
|
|
535
565
|
// back-compat alias. Aligns the surface with the other skill_* tools
|
|
536
|
-
// (skill_read /
|
|
566
|
+
// (skill_read / skill_preflight / skill_status / skill_write all take
|
|
537
567
|
// `name`). Per Perry signoff (thread 75abc8c0): silent alias — no
|
|
538
568
|
// tier-3 advisory, no deprecation warn. If both are supplied with
|
|
539
569
|
// different values, that's ambiguous; reject so the caller picks one.
|
|
@@ -817,7 +847,21 @@ export class McpServer {
|
|
|
817
847
|
// posture (every write requires explicit human promotion regardless
|
|
818
848
|
// of body claim) opt in via the flag at runtime startup. Per Perry's
|
|
819
849
|
// `787b6b95` Option A.
|
|
820
|
-
|
|
850
|
+
// v0.21.0 — store-agnostic secured-mode closure (red-team 33bf53d3).
|
|
851
|
+
// skill_write cannot GRANT approval: if the body claims Approved without a
|
|
852
|
+
// valid v3 signature, force Draft — regardless of the SkillStore impl. The
|
|
853
|
+
// per-store guard didn't cover custom adopter stores (AMP-backed), letting an
|
|
854
|
+
// agent write status=Approved with no signature (a forgeable trust-state lie
|
|
855
|
+
// that misleads skill_list / skill_preflight / the dashboard). evaluateApproval
|
|
856
|
+
// -Gate is not-ok for any Draft OR unsigned-Approved body, so a genuine
|
|
857
|
+
// approve-flow write (signed body) is honored; everything else lands Draft.
|
|
858
|
+
let bodyToStore = source;
|
|
859
|
+
if (this.deps.forceAlwaysDraft === true) {
|
|
860
|
+
bodyToStore = forceDraftStatus(source);
|
|
861
|
+
}
|
|
862
|
+
else if (isSecuredMode() && !evaluateApprovalGate(source).ok) {
|
|
863
|
+
bodyToStore = forceDraftStatus(source);
|
|
864
|
+
}
|
|
821
865
|
// v0.17.0 — thread host-attested caller identity into `store({author})`
|
|
822
866
|
// so MCP-authored skills stamp `SkillMeta.author = <calling agent>`,
|
|
823
867
|
// not the runtime's wiring identity. When ctx.callerIdentity is
|