skillscript-runtime 0.2.4
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/ARCHITECTURE.md +70 -0
- package/LICENSE +21 -0
- package/README.md +346 -0
- package/dist/audit.d.ts +33 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +76 -0
- package/dist/audit.js.map +1 -0
- package/dist/bootstrap.d.ts +69 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +117 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +805 -0
- package/dist/cli.js.map +1 -0
- package/dist/compile.d.ts +88 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +544 -0
- package/dist/compile.js.map +1 -0
- package/dist/connectors/agent-noop.d.ts +23 -0
- package/dist/connectors/agent-noop.d.ts.map +1 -0
- package/dist/connectors/agent-noop.js +43 -0
- package/dist/connectors/agent-noop.js.map +1 -0
- package/dist/connectors/agent.d.ts +54 -0
- package/dist/connectors/agent.d.ts.map +1 -0
- package/dist/connectors/agent.js +21 -0
- package/dist/connectors/agent.js.map +1 -0
- package/dist/connectors/index.d.ts +13 -0
- package/dist/connectors/index.d.ts.map +1 -0
- package/dist/connectors/index.js +17 -0
- package/dist/connectors/index.js.map +1 -0
- package/dist/connectors/local-model.d.ts +41 -0
- package/dist/connectors/local-model.d.ts.map +1 -0
- package/dist/connectors/local-model.js +106 -0
- package/dist/connectors/local-model.js.map +1 -0
- package/dist/connectors/mcp.d.ts +22 -0
- package/dist/connectors/mcp.d.ts.map +1 -0
- package/dist/connectors/mcp.js +31 -0
- package/dist/connectors/mcp.js.map +1 -0
- package/dist/connectors/memory-store.d.ts +53 -0
- package/dist/connectors/memory-store.d.ts.map +1 -0
- package/dist/connectors/memory-store.js +169 -0
- package/dist/connectors/memory-store.js.map +1 -0
- package/dist/connectors/registry.d.ts +74 -0
- package/dist/connectors/registry.d.ts.map +1 -0
- package/dist/connectors/registry.js +127 -0
- package/dist/connectors/registry.js.map +1 -0
- package/dist/connectors/skill-store.d.ts +38 -0
- package/dist/connectors/skill-store.d.ts.map +1 -0
- package/dist/connectors/skill-store.js +314 -0
- package/dist/connectors/skill-store.js.map +1 -0
- package/dist/connectors/types.d.ts +188 -0
- package/dist/connectors/types.d.ts.map +1 -0
- package/dist/connectors/types.js +35 -0
- package/dist/connectors/types.js.map +1 -0
- package/dist/dashboard/server.d.ts +40 -0
- package/dist/dashboard/server.d.ts.map +1 -0
- package/dist/dashboard/server.js +122 -0
- package/dist/dashboard/server.js.map +1 -0
- package/dist/dashboard/spa/app.js +375 -0
- package/dist/dashboard/spa/index.html +26 -0
- package/dist/dashboard/spa/styles.css +99 -0
- package/dist/errors.d.ts +111 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +187 -0
- package/dist/errors.js.map +1 -0
- package/dist/filters.d.ts +17 -0
- package/dist/filters.d.ts.map +1 -0
- package/dist/filters.js +40 -0
- package/dist/filters.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/lint.d.ts +97 -0
- package/dist/lint.d.ts.map +1 -0
- package/dist/lint.js +990 -0
- package/dist/lint.js.map +1 -0
- package/dist/mcp-server.d.ts +93 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +505 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/metrics.d.ts +51 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +107 -0
- package/dist/metrics.js.map +1 -0
- package/dist/parser.d.ts +160 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +991 -0
- package/dist/parser.js.map +1 -0
- package/dist/provenance.d.ts +43 -0
- package/dist/provenance.d.ts.map +1 -0
- package/dist/provenance.js +58 -0
- package/dist/provenance.js.map +1 -0
- package/dist/runtime.d.ts +145 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +1071 -0
- package/dist/runtime.js.map +1 -0
- package/dist/scheduler.d.ts +121 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +271 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/skill-manager.d.ts +121 -0
- package/dist/skill-manager.d.ts.map +1 -0
- package/dist/skill-manager.js +251 -0
- package/dist/skill-manager.js.map +1 -0
- package/dist/testing/conformance.d.ts +57 -0
- package/dist/testing/conformance.d.ts.map +1 -0
- package/dist/testing/conformance.js +365 -0
- package/dist/testing/conformance.js.map +1 -0
- package/dist/testing/index.d.ts +3 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +5 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/trace.d.ts +141 -0
- package/dist/trace.d.ts.map +1 -0
- package/dist/trace.js +226 -0
- package/dist/trace.js.map +1 -0
- package/examples/README.md +56 -0
- package/examples/classify-support-ticket.skill.md +30 -0
- package/examples/cut-release-tag.skill.md +40 -0
- package/examples/doc-qa-with-citations.skill.md +12 -0
- package/examples/feedback-sentiment-scan.skill.md +29 -0
- package/examples/hello.skill.md +9 -0
- package/examples/hello.skill.provenance.json +10 -0
- package/examples/morning-brief.skill.md +24 -0
- package/examples/programmatic-trace-demo.mjs +89 -0
- package/examples/service-health-watch.skill.md +18 -0
- package/package.json +100 -0
- package/scaffold/config.toml +35 -0
- package/scaffold/connectors.json +19 -0
- package/scaffold/examples/hello.skill.md +9 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
// ContractConformance test suites. Verifies that any connector implementation
|
|
2
|
+
// actually honors its contract. Framework-agnostic: each suite returns an
|
|
3
|
+
// array of `ConformanceTest { name, run() }` objects that callers wire into
|
|
4
|
+
// their test framework. Example in vitest:
|
|
5
|
+
//
|
|
6
|
+
// import { describe, it } from "vitest";
|
|
7
|
+
// import { SkillStoreConformance } from "skillscript-runtime/testing";
|
|
8
|
+
//
|
|
9
|
+
// describe("FilesystemSkillStore conformance", () => {
|
|
10
|
+
// const tests = SkillStoreConformance.buildTests({
|
|
11
|
+
// build: () => new FilesystemSkillStore(mkdtempSync(...)),
|
|
12
|
+
// ctor: FilesystemSkillStore,
|
|
13
|
+
// });
|
|
14
|
+
// for (const t of tests) it(`[${t.category}] ${t.name}`, t.run);
|
|
15
|
+
// });
|
|
16
|
+
//
|
|
17
|
+
// Test categories per the v1 spec:
|
|
18
|
+
// 1. method-existence — every declared method present + callable
|
|
19
|
+
// 2. return-type — methods return values matching the contract shape
|
|
20
|
+
// 3. error-contract — methods throw the documented error class on the
|
|
21
|
+
// documented trigger condition
|
|
22
|
+
// 4. static-capabilities — `staticCapabilities()` returns a well-formed
|
|
23
|
+
// `StaticCapabilities` object
|
|
24
|
+
// 5. feature-behavior — for every feature flag the impl declares true,
|
|
25
|
+
// the corresponding behavior actually works
|
|
26
|
+
//
|
|
27
|
+
// What conformance does NOT cover: performance (separate `benchmarks` suite),
|
|
28
|
+
// cross-impl interop (v2 work).
|
|
29
|
+
import { SkillNotFoundError, ConnectorError } from "../errors.js";
|
|
30
|
+
export const SkillStoreConformance = {
|
|
31
|
+
buildTests(fixture) {
|
|
32
|
+
return [
|
|
33
|
+
...staticCapabilitiesTests(fixture.ctor, "skill_store"),
|
|
34
|
+
methodExistence("SkillStore.load present", fixture, "load"),
|
|
35
|
+
methodExistence("SkillStore.query present", fixture, "query"),
|
|
36
|
+
methodExistence("SkillStore.metadata present", fixture, "metadata"),
|
|
37
|
+
methodExistence("SkillStore.versions present", fixture, "versions"),
|
|
38
|
+
methodExistence("SkillStore.store present", fixture, "store"),
|
|
39
|
+
methodExistence("SkillStore.delete present", fixture, "delete"),
|
|
40
|
+
methodExistence("SkillStore.update_status present", fixture, "update_status"),
|
|
41
|
+
methodExistence("SkillStore.manifest present", fixture, "manifest"),
|
|
42
|
+
{
|
|
43
|
+
category: "return-type",
|
|
44
|
+
name: "query returns empty array on empty store",
|
|
45
|
+
run: withInstance(fixture, async (store) => {
|
|
46
|
+
const r = await store.query();
|
|
47
|
+
assert(Array.isArray(r), `query must return an array (got ${typeof r})`);
|
|
48
|
+
assert(r.length === 0, `empty store must return [], got ${r.length} entries`);
|
|
49
|
+
}),
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
category: "return-type",
|
|
53
|
+
name: "store returns VersionInfo with required fields",
|
|
54
|
+
run: withInstance(fixture, async (store) => {
|
|
55
|
+
const info = await store.store("conformance-test", SAMPLE_SKILL);
|
|
56
|
+
assert(typeof info.name === "string", "VersionInfo.name must be string");
|
|
57
|
+
assert(typeof info.version === "string", "VersionInfo.version must be string");
|
|
58
|
+
assert(/^[a-f0-9]+$/.test(info.content_hash), "VersionInfo.content_hash must be hex");
|
|
59
|
+
assert(typeof info.changed_at === "number", "VersionInfo.changed_at must be number");
|
|
60
|
+
}),
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
category: "return-type",
|
|
64
|
+
name: "load returns SkillSource with non-empty content_hash and source",
|
|
65
|
+
run: withInstance(fixture, async (store) => {
|
|
66
|
+
await store.store("conformance-test", SAMPLE_SKILL);
|
|
67
|
+
const src = await store.load("conformance-test");
|
|
68
|
+
assert(src.source === SAMPLE_SKILL, "load.source must round-trip the stored bytes");
|
|
69
|
+
assert(src.content_hash.length > 0, "load.content_hash must be populated");
|
|
70
|
+
assert(typeof src.metadata.status === "string", "load.metadata.status must be populated");
|
|
71
|
+
}),
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
category: "error-contract",
|
|
75
|
+
name: "load throws SkillNotFoundError on missing skill",
|
|
76
|
+
run: withInstance(fixture, async (store) => {
|
|
77
|
+
await expectThrows(() => store.load("definitely-missing-skill-xyz"), (err) => err instanceof SkillNotFoundError, "expected SkillNotFoundError");
|
|
78
|
+
}),
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
category: "error-contract",
|
|
82
|
+
name: "delete throws SkillNotFoundError on missing skill",
|
|
83
|
+
run: withInstance(fixture, async (store) => {
|
|
84
|
+
await expectThrows(() => store.delete("definitely-missing-skill-xyz"), (err) => err instanceof SkillNotFoundError, "expected SkillNotFoundError");
|
|
85
|
+
}),
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
category: "error-contract",
|
|
89
|
+
name: "errors carry connector_type='skill_store'",
|
|
90
|
+
run: withInstance(fixture, async (store) => {
|
|
91
|
+
try {
|
|
92
|
+
await store.load("missing");
|
|
93
|
+
assertUnreachable("expected throw");
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
assert(err instanceof ConnectorError, "error must extend ConnectorError");
|
|
97
|
+
assert(err.connector_type === "skill_store", "connector_type must be 'skill_store'");
|
|
98
|
+
}
|
|
99
|
+
}),
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
category: "feature-behavior",
|
|
103
|
+
name: "update_status: previous_status populated when supports_audit_trail=true",
|
|
104
|
+
run: withInstance(fixture, async (store) => {
|
|
105
|
+
const caps = fixture.ctor.staticCapabilities();
|
|
106
|
+
if (caps.features["supports_audit_trail"] !== true)
|
|
107
|
+
return; // skip; feature opt-out
|
|
108
|
+
await store.store("conformance-test", SAMPLE_SKILL);
|
|
109
|
+
const v = await store.update_status("conformance-test", "Approved");
|
|
110
|
+
assert(v.previous_status !== undefined, "audit-trail impl must populate previous_status");
|
|
111
|
+
assert(v.status === "Approved", "update_status must persist new status");
|
|
112
|
+
}),
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
category: "feature-behavior",
|
|
116
|
+
name: "filter narrows by status when supports_writes=true",
|
|
117
|
+
run: withInstance(fixture, async (store) => {
|
|
118
|
+
const caps = fixture.ctor.staticCapabilities();
|
|
119
|
+
if (caps.features["supports_writes"] !== true)
|
|
120
|
+
return;
|
|
121
|
+
await store.store("draft-a", SAMPLE_SKILL);
|
|
122
|
+
await store.store("approved-b", SAMPLE_SKILL);
|
|
123
|
+
await store.update_status("approved-b", "Approved");
|
|
124
|
+
const approved = await store.query({ status: "Approved" });
|
|
125
|
+
assert(approved.length === 1, `expected 1 approved skill, got ${approved.length}`);
|
|
126
|
+
assert(approved[0].name === "approved-b", `expected 'approved-b', got '${approved[0].name}'`);
|
|
127
|
+
}),
|
|
128
|
+
},
|
|
129
|
+
];
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
export const MemoryStoreConformance = {
|
|
133
|
+
buildTests(fixture) {
|
|
134
|
+
return [
|
|
135
|
+
...staticCapabilitiesTests(fixture.ctor, "memory_store"),
|
|
136
|
+
methodExistence("MemoryStore.query present", fixture, "query"),
|
|
137
|
+
methodExistence("MemoryStore.manifest present", fixture, "manifest"),
|
|
138
|
+
{
|
|
139
|
+
category: "return-type",
|
|
140
|
+
name: "query returns array of PortableMemory shape",
|
|
141
|
+
run: withInstance(fixture, async (store) => {
|
|
142
|
+
const r = await store.query({ query: "anything", limit: 10, mode: "fts" });
|
|
143
|
+
assert(Array.isArray(r), `query must return an array (got ${typeof r})`);
|
|
144
|
+
for (const m of r) {
|
|
145
|
+
assert(typeof m.id === "string", "PortableMemory.id must be string");
|
|
146
|
+
assert(typeof m.summary === "string", "PortableMemory.summary must be string");
|
|
147
|
+
}
|
|
148
|
+
}),
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
category: "feature-behavior",
|
|
152
|
+
name: "supportedModes that declare true actually work",
|
|
153
|
+
run: withInstance(fixture, async (store) => {
|
|
154
|
+
const caps = fixture.ctor.staticCapabilities();
|
|
155
|
+
const modes = ["fts", "semantic", "rerank"];
|
|
156
|
+
for (const mode of modes) {
|
|
157
|
+
const flag = `supports_${mode === "fts" ? "fts" : mode}`;
|
|
158
|
+
if (caps.features[flag] === true) {
|
|
159
|
+
// Should not throw; empty result acceptable.
|
|
160
|
+
const r = await store.query({ query: "test", limit: 1, mode });
|
|
161
|
+
assert(Array.isArray(r), `mode='${mode}' must return an array`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}),
|
|
165
|
+
},
|
|
166
|
+
];
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
export const LocalModelConformance = {
|
|
170
|
+
buildTests(fixture) {
|
|
171
|
+
return [
|
|
172
|
+
...staticCapabilitiesTests(fixture.ctor, "local_model"),
|
|
173
|
+
methodExistence("LocalModel.run present", fixture, "run"),
|
|
174
|
+
methodExistence("LocalModel.manifest present", fixture, "manifest"),
|
|
175
|
+
{
|
|
176
|
+
category: "return-type",
|
|
177
|
+
name: "manifest returns capabilities_version + manifest fields",
|
|
178
|
+
run: withInstance(fixture, async (model) => {
|
|
179
|
+
const m = await model.manifest();
|
|
180
|
+
assert(typeof m.capabilities_version === "string", "manifest.capabilities_version must be string");
|
|
181
|
+
assert(typeof m.manifest === "object" && m.manifest !== null, "manifest.manifest must be object");
|
|
182
|
+
}),
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
category: "feature-behavior",
|
|
186
|
+
name: "run returns string on success when liveDispatch=true",
|
|
187
|
+
run: withInstance(fixture, async (model) => {
|
|
188
|
+
if (fixture.liveDispatch !== true)
|
|
189
|
+
return; // skip when not reachable
|
|
190
|
+
const r = await model.run("hi", { maxTokens: 5 });
|
|
191
|
+
assert(typeof r === "string", `run must return string (got ${typeof r})`);
|
|
192
|
+
}),
|
|
193
|
+
},
|
|
194
|
+
];
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
export const McpConnectorConformance = {
|
|
198
|
+
buildTests(fixture) {
|
|
199
|
+
return [
|
|
200
|
+
...staticCapabilitiesTests(fixture.ctor, "mcp_connector"),
|
|
201
|
+
methodExistence("McpConnector.call present", fixture, "call"),
|
|
202
|
+
methodExistence("McpConnector.manifest present", fixture, "manifest"),
|
|
203
|
+
{
|
|
204
|
+
category: "return-type",
|
|
205
|
+
name: "manifest returns capabilities_version + manifest fields",
|
|
206
|
+
run: withInstance(fixture, async (connector) => {
|
|
207
|
+
const m = await connector.manifest();
|
|
208
|
+
assert(typeof m.capabilities_version === "string", "manifest.capabilities_version must be string");
|
|
209
|
+
}),
|
|
210
|
+
},
|
|
211
|
+
];
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
export const AgentConnectorConformance = {
|
|
215
|
+
buildTests(fixture) {
|
|
216
|
+
const tests = [
|
|
217
|
+
...staticCapabilitiesTests(fixture.ctor, "agent_connector"),
|
|
218
|
+
methodExistence("AgentConnector.list_agents present", fixture, "list_agents"),
|
|
219
|
+
methodExistence("AgentConnector.deliver present", fixture, "deliver"),
|
|
220
|
+
methodExistence("AgentConnector.wake present", fixture, "wake"),
|
|
221
|
+
methodExistence("AgentConnector.manifest present", fixture, "manifest"),
|
|
222
|
+
{
|
|
223
|
+
category: "return-type",
|
|
224
|
+
name: "list_agents returns an array",
|
|
225
|
+
run: withInstance(fixture, async (connector) => {
|
|
226
|
+
const r = await connector.list_agents();
|
|
227
|
+
assert(Array.isArray(r), `list_agents must return an array (got ${typeof r})`);
|
|
228
|
+
}),
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
category: "return-type",
|
|
232
|
+
name: "manifest returns capabilities_version + manifest fields",
|
|
233
|
+
run: withInstance(fixture, async (connector) => {
|
|
234
|
+
const m = await connector.manifest();
|
|
235
|
+
assert(typeof m.capabilities_version === "string", "manifest.capabilities_version must be string");
|
|
236
|
+
}),
|
|
237
|
+
},
|
|
238
|
+
];
|
|
239
|
+
const testAgentId = fixture.testAgentId;
|
|
240
|
+
if (testAgentId !== undefined) {
|
|
241
|
+
tests.push({
|
|
242
|
+
category: "feature-behavior",
|
|
243
|
+
name: "deliver(kind=augment) returns DeliveryReceipt with delivered_at",
|
|
244
|
+
run: withInstance(fixture, async (connector) => {
|
|
245
|
+
const receipt = await connector.deliver(testAgentId, { kind: "augment", content: "conformance" });
|
|
246
|
+
assert(typeof receipt.delivered_at === "number", "DeliveryReceipt.delivered_at must be number");
|
|
247
|
+
}),
|
|
248
|
+
});
|
|
249
|
+
tests.push({
|
|
250
|
+
category: "feature-behavior",
|
|
251
|
+
name: "deliver(kind=template) returns DeliveryReceipt with delivered_at",
|
|
252
|
+
run: withInstance(fixture, async (connector) => {
|
|
253
|
+
const receipt = await connector.deliver(testAgentId, { kind: "template", prompt: "conformance" });
|
|
254
|
+
assert(typeof receipt.delivered_at === "number", "DeliveryReceipt.delivered_at must be number");
|
|
255
|
+
}),
|
|
256
|
+
});
|
|
257
|
+
tests.push({
|
|
258
|
+
category: "feature-behavior",
|
|
259
|
+
name: "wake returns WakeReceipt with woken_at",
|
|
260
|
+
run: withInstance(fixture, async (connector) => {
|
|
261
|
+
const receipt = await connector.wake(testAgentId);
|
|
262
|
+
assert(typeof receipt.woken_at === "number", "WakeReceipt.woken_at must be number");
|
|
263
|
+
}),
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
return tests;
|
|
267
|
+
},
|
|
268
|
+
};
|
|
269
|
+
// ─── Shared assertion helpers ─────────────────────────────────────────────
|
|
270
|
+
function assert(condition, message) {
|
|
271
|
+
if (!condition)
|
|
272
|
+
throw new Error(`Conformance assertion failed: ${message}`);
|
|
273
|
+
}
|
|
274
|
+
function assertUnreachable(message) {
|
|
275
|
+
throw new Error(`Conformance assertion failed: ${message}`);
|
|
276
|
+
}
|
|
277
|
+
async function expectThrows(fn, predicate, message) {
|
|
278
|
+
try {
|
|
279
|
+
await fn();
|
|
280
|
+
throw new Error(`Conformance assertion failed: ${message}, but no error was thrown`);
|
|
281
|
+
}
|
|
282
|
+
catch (err) {
|
|
283
|
+
if (err instanceof Error && err.message.startsWith("Conformance assertion failed"))
|
|
284
|
+
throw err;
|
|
285
|
+
if (!predicate(err)) {
|
|
286
|
+
throw new Error(`Conformance assertion failed: ${message}, got ${err?.constructor?.name ?? typeof err}: ${err?.message ?? err}`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
function methodExistence(name, fixture, method) {
|
|
291
|
+
return {
|
|
292
|
+
category: "method-existence",
|
|
293
|
+
name,
|
|
294
|
+
run: withInstance(fixture, async (instance) => {
|
|
295
|
+
const obj = instance;
|
|
296
|
+
assert(typeof obj[method] === "function", `instance.${method} must be a function`);
|
|
297
|
+
}),
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
function staticCapabilitiesTests(ctor, expectedKind) {
|
|
301
|
+
return [
|
|
302
|
+
{
|
|
303
|
+
category: "static-capabilities",
|
|
304
|
+
name: `staticCapabilities() returns connector_type='${expectedKind}'`,
|
|
305
|
+
run: async () => {
|
|
306
|
+
const caps = ctor.staticCapabilities();
|
|
307
|
+
assert(caps.connector_type === expectedKind, `connector_type must be '${expectedKind}' (got '${caps.connector_type}')`);
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
category: "static-capabilities",
|
|
312
|
+
name: "staticCapabilities() returns non-empty implementation + contract_version",
|
|
313
|
+
run: async () => {
|
|
314
|
+
const caps = ctor.staticCapabilities();
|
|
315
|
+
assert(typeof caps.implementation === "string" && caps.implementation.length > 0, "implementation must be non-empty string");
|
|
316
|
+
assert(typeof caps.contract_version === "string" && /^\d+\.\d+\.\d+$/.test(caps.contract_version), "contract_version must be semver-ish");
|
|
317
|
+
},
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
category: "static-capabilities",
|
|
321
|
+
name: "staticCapabilities() features map is well-formed",
|
|
322
|
+
run: async () => {
|
|
323
|
+
const caps = ctor.staticCapabilities();
|
|
324
|
+
assert(typeof caps.features === "object" && caps.features !== null, "features must be object");
|
|
325
|
+
for (const [k, v] of Object.entries(caps.features)) {
|
|
326
|
+
assert(typeof v === "boolean", `feature '${k}' must be boolean (got ${typeof v})`);
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
category: "static-capabilities",
|
|
332
|
+
name: "staticCapabilities() callable without instance construction",
|
|
333
|
+
run: async () => {
|
|
334
|
+
// The whole point of static-capabilities: the linter must be able to
|
|
335
|
+
// discover features without paying construction cost. This test
|
|
336
|
+
// asserts the method is on the class (constructor), not on the
|
|
337
|
+
// prototype/instance.
|
|
338
|
+
const caps = ctor.staticCapabilities();
|
|
339
|
+
assert(caps !== null, "static call returned null");
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
];
|
|
343
|
+
}
|
|
344
|
+
function withInstance(fixture, body) {
|
|
345
|
+
return async () => {
|
|
346
|
+
const instance = fixture.build();
|
|
347
|
+
try {
|
|
348
|
+
await body(instance);
|
|
349
|
+
}
|
|
350
|
+
finally {
|
|
351
|
+
if (typeof fixture.teardown === "function")
|
|
352
|
+
await fixture.teardown(instance);
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
// Sample skill used by SkillStore conformance tests that need a payload.
|
|
357
|
+
const SAMPLE_SKILL = `# Skill: conformance-test
|
|
358
|
+
# Status: draft
|
|
359
|
+
|
|
360
|
+
t:
|
|
361
|
+
! hi
|
|
362
|
+
|
|
363
|
+
default: t
|
|
364
|
+
`;
|
|
365
|
+
//# sourceMappingURL=conformance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conformance.js","sourceRoot":"","sources":["../../src/testing/conformance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { SkillStoreConformance, MemoryStoreConformance, LocalModelConformance, McpConnectorConformance, AgentConnectorConformance, } from "./conformance.js";
|
|
2
|
+
export type { ConformanceTest, ConformanceCategory, SkillStoreFixture, MemoryStoreFixture, LocalModelFixture, McpConnectorFixture, AgentConnectorFixture, } from "./conformance.js";
|
|
3
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// `skillscript-runtime/testing` entry point. ContractConformance suites for
|
|
2
|
+
// the four connector contracts. Imported by impl authors writing conformance
|
|
3
|
+
// tests against their substrate; not part of the runtime hot path.
|
|
4
|
+
export { SkillStoreConformance, MemoryStoreConformance, LocalModelConformance, McpConnectorConformance, AgentConnectorConformance, } from "./conformance.js";
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,6EAA6E;AAC7E,mEAAmE;AAEnE,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,kBAAkB,CAAC"}
|
package/dist/trace.d.ts
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import type { ExecutionError } from "./runtime.js";
|
|
2
|
+
/**
|
|
3
|
+
* Per-fire dispatch trace recording. Lets operators query "what did this
|
|
4
|
+
* skill do at 09:05?" + "which fires failed?" + replay traces against
|
|
5
|
+
* current connectors for "does this still work?" debugging.
|
|
6
|
+
*
|
|
7
|
+
* Three trace modes per-deployment + per-fire (per Open Q #6 disposition):
|
|
8
|
+
* - off — no per-fire record. Error-only trace records still written
|
|
9
|
+
* (NFR-11 floor: failures always visible).
|
|
10
|
+
* - on — every op + every output recorded.
|
|
11
|
+
* - sample — N% of fires recorded; sampling is deterministic via SHA-256
|
|
12
|
+
* of (trigger_id + skill_name).
|
|
13
|
+
*
|
|
14
|
+
* Trace store contract: pluggable backend. v1 ships `FilesystemTraceStore`
|
|
15
|
+
* (file-backed default, zero external dependency). `MemoryStoreTraceStore`
|
|
16
|
+
* (substrate-backed via the configured MemoryStore connector) becomes
|
|
17
|
+
* possible when MemoryStore contract grows a write surface — currently
|
|
18
|
+
* read-only per §3.
|
|
19
|
+
*/
|
|
20
|
+
export type TraceMode = "off" | "on" | "sample";
|
|
21
|
+
export interface TraceConfig {
|
|
22
|
+
mode: TraceMode;
|
|
23
|
+
/** Used when mode === "sample"; integer 0-100. Default 10. */
|
|
24
|
+
samplePct?: number;
|
|
25
|
+
/** Retention in ms before prune archives the record. Default 30d. */
|
|
26
|
+
retentionMs?: number;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Versioned trace record. Bumping `version` is a breaking change for
|
|
30
|
+
* trace store consumers; T6 ships at version 1.
|
|
31
|
+
*/
|
|
32
|
+
export interface TraceRecord {
|
|
33
|
+
version: 1;
|
|
34
|
+
trace_id: string;
|
|
35
|
+
skill_name: string;
|
|
36
|
+
skill_version: string;
|
|
37
|
+
trigger: {
|
|
38
|
+
source: string;
|
|
39
|
+
name: string;
|
|
40
|
+
fired_at_ms: number;
|
|
41
|
+
};
|
|
42
|
+
identity: {
|
|
43
|
+
agent_id?: string;
|
|
44
|
+
};
|
|
45
|
+
ops: TraceOpRecord[];
|
|
46
|
+
emissions: string[];
|
|
47
|
+
outputs: Record<string, unknown>;
|
|
48
|
+
errors: ExecutionError[];
|
|
49
|
+
fired_at_ms: number;
|
|
50
|
+
completed_at_ms: number;
|
|
51
|
+
duration_ms: number;
|
|
52
|
+
}
|
|
53
|
+
export interface TraceOpRecord {
|
|
54
|
+
op_kind: string;
|
|
55
|
+
target: string;
|
|
56
|
+
body: string;
|
|
57
|
+
started_at_ms: number;
|
|
58
|
+
duration_ms: number;
|
|
59
|
+
/** True when the op produced an error (captured in TraceRecord.errors). */
|
|
60
|
+
errored: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Connector instance this op dispatched through. Present for `$`/`~`/`>`
|
|
63
|
+
* ops; absent for `@`/`!`/`??`/`$set`/`foreach`/`if` (no connector
|
|
64
|
+
* involvement). Used by `healthMetrics()` for per-connector aggregation.
|
|
65
|
+
*/
|
|
66
|
+
connector?: string;
|
|
67
|
+
}
|
|
68
|
+
export interface TraceQueryFilter {
|
|
69
|
+
skill_name?: string;
|
|
70
|
+
since_ms?: number;
|
|
71
|
+
until_ms?: number;
|
|
72
|
+
limit?: number;
|
|
73
|
+
}
|
|
74
|
+
export interface TraceStore {
|
|
75
|
+
write(record: TraceRecord): Promise<void>;
|
|
76
|
+
query(filter: TraceQueryFilter): Promise<TraceRecord[]>;
|
|
77
|
+
get(traceId: string): Promise<TraceRecord | null>;
|
|
78
|
+
/**
|
|
79
|
+
* Prune records older than now-retentionMs. Non-destructive by default:
|
|
80
|
+
* v1 hard-deletes (audit trail simplification); v1.x can add an archive
|
|
81
|
+
* path. Returns the count of records pruned.
|
|
82
|
+
*/
|
|
83
|
+
prune(retentionMs: number): Promise<number>;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Writes JSON records under `<rootDir>/<skill_name>/<trace_id>.json`.
|
|
87
|
+
* Zero external dependency; suitable for the standalone runtime out of
|
|
88
|
+
* the box. Operators with a substrate wired can swap for a
|
|
89
|
+
* substrate-backed store via config.
|
|
90
|
+
*/
|
|
91
|
+
export declare class FilesystemTraceStore implements TraceStore {
|
|
92
|
+
private readonly rootDir;
|
|
93
|
+
constructor(rootDir: string);
|
|
94
|
+
write(record: TraceRecord): Promise<void>;
|
|
95
|
+
query(filter: TraceQueryFilter): Promise<TraceRecord[]>;
|
|
96
|
+
get(traceId: string): Promise<TraceRecord | null>;
|
|
97
|
+
prune(retentionMs: number): Promise<number>;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Deterministic sample decision per Open Q #2: SHA-256 of `trigger_id +
|
|
101
|
+
* ":" + skill_name`, take the first byte mod 100, fire trace if under
|
|
102
|
+
* `pct`. Same inputs always produce the same sampling decision — useful
|
|
103
|
+
* for reproducible testing + dashboard drill-down.
|
|
104
|
+
*/
|
|
105
|
+
export declare function shouldSample(triggerId: string, skillName: string, pct: number): boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Accumulator used by the runtime during a single fire. Records per-op
|
|
108
|
+
* timing + body; finalize() builds the immutable TraceRecord.
|
|
109
|
+
*/
|
|
110
|
+
export declare class TraceBuilder {
|
|
111
|
+
private readonly skill_name;
|
|
112
|
+
private readonly skill_version;
|
|
113
|
+
private readonly trigger;
|
|
114
|
+
private readonly identity;
|
|
115
|
+
private readonly ops;
|
|
116
|
+
private readonly firedAtMs;
|
|
117
|
+
readonly trace_id: string;
|
|
118
|
+
constructor(skill_name: string, skill_version: string, trigger: {
|
|
119
|
+
source: string;
|
|
120
|
+
name: string;
|
|
121
|
+
fired_at_ms: number;
|
|
122
|
+
}, identity: {
|
|
123
|
+
agent_id?: string;
|
|
124
|
+
});
|
|
125
|
+
recordOp(record: TraceOpRecord): void;
|
|
126
|
+
finalize(emissions: string[], outputs: Record<string, unknown>, errors: ExecutionError[]): TraceRecord;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Decide whether a fire should be traced given config + trigger context.
|
|
130
|
+
* Used by the runtime / scheduler at fire start. `mode === "off"` always
|
|
131
|
+
* returns false (errors are still surfaced via `result.errors[]` — the
|
|
132
|
+
* NFR-11 floor); the trace store is bypassed entirely.
|
|
133
|
+
*/
|
|
134
|
+
export declare function shouldTraceFire(config: TraceConfig | undefined, triggerId: string, skillName: string): boolean;
|
|
135
|
+
export declare const TRACE_DEFAULTS: {
|
|
136
|
+
readonly SAMPLE_PCT: 10;
|
|
137
|
+
readonly RETENTION_MS: number;
|
|
138
|
+
};
|
|
139
|
+
/** Convenience for tests: derive the on-disk path FilesystemTraceStore writes to. */
|
|
140
|
+
export declare function _traceFilePathFor(rootDir: string, record: TraceRecord): string;
|
|
141
|
+
//# sourceMappingURL=trace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../src/trace.ts"],"names":[],"mappings":"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"}
|