@dot-skill/protocol 0.4.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -0
- package/dist/authoring.d.ts +14 -0
- package/dist/authoring.js +260 -0
- package/dist/contract.d.ts +190 -0
- package/dist/contract.js +1 -0
- package/dist/extract.d.ts +89 -0
- package/dist/extract.js +299 -0
- package/dist/index.d.ts +7 -3
- package/dist/index.js +4 -2
- package/dist/recipe.d.ts +3 -0
- package/dist/recipe.js +1 -0
- package/dist/source.d.ts +23 -1
- package/dist/source.js +50 -1
- package/dist/types.d.ts +126 -5
- package/dist/types.js +3 -3
- package/package.json +21 -4
- package/skill-contract.schema.json +105 -0
package/dist/extract.js
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-skill identification → scaffold extraction for agents.
|
|
3
|
+
*
|
|
4
|
+
* Segmentation is an agent/adapter responsibility. This module does not invent
|
|
5
|
+
* skills from free prose: the caller must supply candidate topics. It emits
|
|
6
|
+
* incomplete SkillContract / SkillSource scaffolds plus completeness reports
|
|
7
|
+
* so create flows stay coherent with SkillContract 0.5 and refuse incomplete
|
|
8
|
+
* release compiles.
|
|
9
|
+
*/
|
|
10
|
+
import { createHash } from "node:crypto";
|
|
11
|
+
import { assessSkillContract, scaffoldSkillContract } from "./authoring.js";
|
|
12
|
+
import { PROTOCOL_VERSION } from "./types.js";
|
|
13
|
+
function slugify(title) {
|
|
14
|
+
const slug = title
|
|
15
|
+
.toLowerCase()
|
|
16
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
17
|
+
.replace(/^-+|-+$/g, "")
|
|
18
|
+
.slice(0, 64);
|
|
19
|
+
return slug || "skill-candidate";
|
|
20
|
+
}
|
|
21
|
+
function candidateId(title, index) {
|
|
22
|
+
const digest = createHash("sha256")
|
|
23
|
+
.update(`${index}:${title}`)
|
|
24
|
+
.digest("hex")
|
|
25
|
+
.slice(0, 12);
|
|
26
|
+
return `cand_${digest}`;
|
|
27
|
+
}
|
|
28
|
+
function normalizeCandidates(input) {
|
|
29
|
+
const fromCandidates = input.candidates ?? [];
|
|
30
|
+
const fromTopics = (input.topics ?? []).map((topic) => typeof topic === "string" ? { title: topic } : topic);
|
|
31
|
+
const merged = [...fromCandidates, ...fromTopics];
|
|
32
|
+
const seen = new Set();
|
|
33
|
+
const out = [];
|
|
34
|
+
for (const item of merged) {
|
|
35
|
+
const title = typeof item.title === "string" ? item.title.trim() : "";
|
|
36
|
+
if (!title)
|
|
37
|
+
continue;
|
|
38
|
+
const key = title.toLowerCase();
|
|
39
|
+
if (seen.has(key))
|
|
40
|
+
continue;
|
|
41
|
+
seen.add(key);
|
|
42
|
+
out.push({ ...item, title });
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
function parseJourney(raw) {
|
|
47
|
+
if (!raw || typeof raw !== "object") {
|
|
48
|
+
throw new Error('extract expects JSON object { summary, candidates|topics: [...] }. Run: skill agent-guide');
|
|
49
|
+
}
|
|
50
|
+
const obj = raw;
|
|
51
|
+
const summary = typeof obj.summary === "string"
|
|
52
|
+
? obj.summary
|
|
53
|
+
: typeof obj.journey_summary === "string"
|
|
54
|
+
? obj.journey_summary
|
|
55
|
+
: "";
|
|
56
|
+
if (!summary.trim()) {
|
|
57
|
+
throw new Error("extract requires a redacted journey summary string (summary or journey_summary).");
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
kind: "redacted_journey",
|
|
61
|
+
summary: summary.trim(),
|
|
62
|
+
redacted: obj.redacted !== false,
|
|
63
|
+
sensitivity: obj.sensitivity === "private" ||
|
|
64
|
+
obj.sensitivity === "shareable_redacted" ||
|
|
65
|
+
obj.sensitivity === "public"
|
|
66
|
+
? obj.sensitivity
|
|
67
|
+
: "shareable_redacted",
|
|
68
|
+
candidates: Array.isArray(obj.candidates)
|
|
69
|
+
? obj.candidates
|
|
70
|
+
: undefined,
|
|
71
|
+
topics: Array.isArray(obj.topics)
|
|
72
|
+
? obj.topics
|
|
73
|
+
: undefined,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function seedContract(title, intent, skillKind, sensitivity) {
|
|
77
|
+
const scaffold = scaffoldSkillContract();
|
|
78
|
+
scaffold.title = title;
|
|
79
|
+
scaffold.intent =
|
|
80
|
+
intent?.trim() ||
|
|
81
|
+
`__required__: state the transferable intent for “${title}” (what an agent must do).`;
|
|
82
|
+
if (skillKind)
|
|
83
|
+
scaffold.skill_kind = skillKind;
|
|
84
|
+
scaffold.sensitivity = sensitivity;
|
|
85
|
+
return scaffold;
|
|
86
|
+
}
|
|
87
|
+
function sourceScaffold(args) {
|
|
88
|
+
return {
|
|
89
|
+
kind: "skill_source",
|
|
90
|
+
id: args.id,
|
|
91
|
+
hash: `sha256:${"0".repeat(64)}`,
|
|
92
|
+
title: args.title,
|
|
93
|
+
summary: args.summary,
|
|
94
|
+
intent: args.contract.intent,
|
|
95
|
+
contract: args.contract,
|
|
96
|
+
candidates: undefined,
|
|
97
|
+
sections: [],
|
|
98
|
+
steering: [],
|
|
99
|
+
prompts: [],
|
|
100
|
+
code_refs: [],
|
|
101
|
+
parents: [],
|
|
102
|
+
agent: {
|
|
103
|
+
host: args.host,
|
|
104
|
+
deployment: "unknown",
|
|
105
|
+
},
|
|
106
|
+
journey: {
|
|
107
|
+
summary: args.summary,
|
|
108
|
+
redacted: true,
|
|
109
|
+
sensitivity: args.sensitivity,
|
|
110
|
+
},
|
|
111
|
+
inputs_declared: "inferred",
|
|
112
|
+
sensitivity: args.sensitivity,
|
|
113
|
+
created_at: new Date(0).toISOString(),
|
|
114
|
+
actor: { id: "agent" },
|
|
115
|
+
source_protocol_version: PROTOCOL_VERSION,
|
|
116
|
+
source_refs: args.evidenceRefs.map((ref, i) => ({
|
|
117
|
+
product: "extract",
|
|
118
|
+
kind: "evidence",
|
|
119
|
+
id: `ev_${i + 1}`,
|
|
120
|
+
hash: ref,
|
|
121
|
+
})),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const PROTOCOL_RULES = [
|
|
125
|
+
"Identify distinct transferable skills from the redacted journey; do not collapse unrelated topics into one skill.",
|
|
126
|
+
"One skill workspace per candidate (skill init in its own directory).",
|
|
127
|
+
"Fill a SkillContract 0.5 for each skill; section prose alone cannot satisfy release completeness.",
|
|
128
|
+
"Run skill status / skill contract-check; refuse release compile when incomplete.",
|
|
129
|
+
"Never invent filler declarations to force a mint; use continuity checkpoint for partial handoff.",
|
|
130
|
+
"Secrets stay as {{refs}} / env refs; journey text must stay redacted.",
|
|
131
|
+
];
|
|
132
|
+
const CREATE_PATH = [
|
|
133
|
+
"skill agent-guide",
|
|
134
|
+
"Identify N candidate skills → write redacted_journey.json with summary + candidates|topics",
|
|
135
|
+
"skill extract redacted_journey.json -o ./extraction",
|
|
136
|
+
"For each selected candidate: mkdir workspace && cd workspace && skill init --title \"…\"",
|
|
137
|
+
"Copy/adapt contract scaffold → complete every declaration (or explicit none/not_applicable)",
|
|
138
|
+
"skill journey --summary \"…\" && skill propose … (evidence sections)",
|
|
139
|
+
"skill contract-check .skill/… or contract.json --profile release",
|
|
140
|
+
"skill status → skill compile -m \"…\" --approve --mint (or checkpoint if incomplete)",
|
|
141
|
+
];
|
|
142
|
+
/**
|
|
143
|
+
* Emit incomplete SkillContract/SkillSource scaffolds for agent-identified candidates.
|
|
144
|
+
* Does not invent topics from free prose when candidates/topics are absent.
|
|
145
|
+
*/
|
|
146
|
+
export function extractSkillCandidates(raw, options = {}) {
|
|
147
|
+
const journey = parseJourney(raw);
|
|
148
|
+
const profile = options.profile ?? "release";
|
|
149
|
+
const host = options.host ?? "__set_SKILL_HOST__";
|
|
150
|
+
const candidates = normalizeCandidates(journey);
|
|
151
|
+
if (candidates.length === 0) {
|
|
152
|
+
throw new Error("No skill candidates supplied. Identify distinct skills from the journey, then pass candidates:[{title,evidence_refs?}] or topics:[\"…\"]. See: skill agent-guide");
|
|
153
|
+
}
|
|
154
|
+
const scaffolds = candidates.map((item, index) => {
|
|
155
|
+
const id = item.id?.trim() || candidateId(item.title, index);
|
|
156
|
+
const evidence = item.evidence_refs?.filter((r) => typeof r === "string" && r.trim()) ??
|
|
157
|
+
[];
|
|
158
|
+
if (evidence.length === 0) {
|
|
159
|
+
evidence.push(`journey:${slugify(item.title)}`);
|
|
160
|
+
}
|
|
161
|
+
const contract = seedContract(item.title, item.intent, item.skill_kind, journey.sensitivity ?? "shareable_redacted");
|
|
162
|
+
const assessment = assessSkillContract(contract, profile);
|
|
163
|
+
const candidate = {
|
|
164
|
+
id,
|
|
165
|
+
title: item.title,
|
|
166
|
+
evidence_refs: evidence,
|
|
167
|
+
assessment,
|
|
168
|
+
// Incomplete scaffold is intentional; do not claim a complete contract.
|
|
169
|
+
contract: undefined,
|
|
170
|
+
};
|
|
171
|
+
const workspace_slug = slugify(item.title);
|
|
172
|
+
const missing = assessment.issues.map(({ field, message, fix }) => ({
|
|
173
|
+
field,
|
|
174
|
+
message,
|
|
175
|
+
fix,
|
|
176
|
+
}));
|
|
177
|
+
const source = sourceScaffold({
|
|
178
|
+
id: `src_${id.replace(/^cand_/, "")}`,
|
|
179
|
+
title: item.title,
|
|
180
|
+
summary: journey.summary,
|
|
181
|
+
contract,
|
|
182
|
+
evidenceRefs: evidence,
|
|
183
|
+
sensitivity: journey.sensitivity ?? "shareable_redacted",
|
|
184
|
+
host,
|
|
185
|
+
});
|
|
186
|
+
return {
|
|
187
|
+
candidate,
|
|
188
|
+
contract_scaffold: contract,
|
|
189
|
+
source_scaffold: source,
|
|
190
|
+
workspace_slug,
|
|
191
|
+
missing,
|
|
192
|
+
next_steps: [
|
|
193
|
+
`mkdir -p ${workspace_slug} && cd ${workspace_slug} && export SKILL_HOST=${host === "__set_SKILL_HOST__" ? "cursor" : host} && skill init --title ${JSON.stringify(item.title)}`,
|
|
194
|
+
"Complete contract_scaffold into a real SkillContract 0.5 (every declaration explicit).",
|
|
195
|
+
`skill contract-check contract.json --profile ${profile}`,
|
|
196
|
+
'skill journey --summary "…" && skill propose --json \'[…]\'',
|
|
197
|
+
"skill status — refuse release compile until complete; use skill checkpoint for handoff.",
|
|
198
|
+
],
|
|
199
|
+
};
|
|
200
|
+
});
|
|
201
|
+
return {
|
|
202
|
+
kind: "skill_extraction",
|
|
203
|
+
protocol_version: PROTOCOL_VERSION,
|
|
204
|
+
profile,
|
|
205
|
+
journey_summary: journey.summary,
|
|
206
|
+
redacted: journey.redacted !== false,
|
|
207
|
+
candidate_count: scaffolds.length,
|
|
208
|
+
scaffolds,
|
|
209
|
+
protocol: {
|
|
210
|
+
one_workspace_per_skill: true,
|
|
211
|
+
refuse_release_if_incomplete: true,
|
|
212
|
+
rules: PROTOCOL_RULES,
|
|
213
|
+
create_path: CREATE_PATH,
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
/** Alias for adapters that prefer "segment" vocabulary. */
|
|
218
|
+
export const segmentJourney = extractSkillCandidates;
|
|
219
|
+
/** Structured agent-facing create / multi-skill protocol (also printed by CLI). */
|
|
220
|
+
export function agentCreateGuide() {
|
|
221
|
+
return {
|
|
222
|
+
kind: "skill_agent_guide",
|
|
223
|
+
protocol_version: PROTOCOL_VERSION,
|
|
224
|
+
purpose: "Create portable .skill packages with SkillContract 0.5. Identify multiple skills from a conversation when warranted; enforce completeness; never fake a release.",
|
|
225
|
+
rules: PROTOCOL_RULES,
|
|
226
|
+
identify_multiple_skills: [
|
|
227
|
+
"Read the redacted journey / work summary. List distinct transferable skills (separate intents, triggers, or runtimes).",
|
|
228
|
+
"Do not invent a multi-skill auto-pipeline beyond this protocol. You identify; the CLI scaffolds.",
|
|
229
|
+
"Write JSON: { \"kind\":\"redacted_journey\", \"summary\":\"…\", \"redacted\":true, \"candidates\":[{ \"title\":\"…\", \"evidence_refs\":[\"…\"], \"intent\":\"…\", \"skill_kind\":\"procedure|knowledge|integration\" }] }",
|
|
230
|
+
"Run: skill extract journey.json -o ./extraction",
|
|
231
|
+
"Present candidates + missing[] reports to the human. Only proceed on selected skills.",
|
|
232
|
+
"One directory / one skill init per selected candidate. Never merge unrelated candidates into one workspace.",
|
|
233
|
+
],
|
|
234
|
+
create_one_skill: [
|
|
235
|
+
"export SKILL_HOST=<your-host-id>",
|
|
236
|
+
"skill init --title \"…\"",
|
|
237
|
+
"skill journey --summary \"Redacted human+AI journey…\"",
|
|
238
|
+
"Complete SkillContract 0.5 (skill contract-template → edit → skill contract-check).",
|
|
239
|
+
"skill propose --json '[{\"title\":\"…\",\"body\":\"…\",\"type\":\"decision|integration|…\"}]' for evidence sections",
|
|
240
|
+
"skill status — inspect completeness / missing",
|
|
241
|
+
"Partial handoff: skill checkpoint -m \"WIP\"",
|
|
242
|
+
"Release only when complete: skill compile -m \"…\" --approve --mint",
|
|
243
|
+
"On compile_refused: list missing fields/fixes; do not pack a fake release.",
|
|
244
|
+
],
|
|
245
|
+
ingest: [
|
|
246
|
+
"skill inspect ./file.skill",
|
|
247
|
+
"skill validate ./file.skill",
|
|
248
|
+
"skill verify-trust ./file.skill",
|
|
249
|
+
"skill load ./file.skill # continuity resume",
|
|
250
|
+
"skill run ./file.skill # dry-run by default",
|
|
251
|
+
],
|
|
252
|
+
cli: [
|
|
253
|
+
"skill agent-guide [--json]",
|
|
254
|
+
"skill extract <journey.json> [-o dir] [--profile release|continuity]",
|
|
255
|
+
"skill segment … # alias of extract",
|
|
256
|
+
"skill contract-template",
|
|
257
|
+
"skill contract-check <contract-or-source.json> [--profile release|continuity]",
|
|
258
|
+
"skill status",
|
|
259
|
+
],
|
|
260
|
+
refuse: [
|
|
261
|
+
"Refuse release compile/mint when contract assessment is incomplete.",
|
|
262
|
+
"Refuse to invent filler skills or filler contract fields to satisfy gates.",
|
|
263
|
+
"Refuse to create multiple skills in one workspace.",
|
|
264
|
+
"Refuse to proceed without SKILL_HOST on create/mint paths.",
|
|
265
|
+
],
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
/** Human-readable text form of agentCreateGuide (for terminals / AGENT.md parity). */
|
|
269
|
+
export function formatAgentGuide(guide = agentCreateGuide()) {
|
|
270
|
+
const lines = [
|
|
271
|
+
`skill agent-guide — Open .skill Protocol v${guide.protocol_version}`,
|
|
272
|
+
"",
|
|
273
|
+
guide.purpose,
|
|
274
|
+
"",
|
|
275
|
+
"Rules:",
|
|
276
|
+
...guide.rules.map((r) => ` - ${r}`),
|
|
277
|
+
"",
|
|
278
|
+
"Identify → propose multiple skills:",
|
|
279
|
+
...guide.identify_multiple_skills.map((r, i) => ` ${i + 1}. ${r}`),
|
|
280
|
+
"",
|
|
281
|
+
"Create one skill (complete or refuse):",
|
|
282
|
+
...guide.create_one_skill.map((r) => ` $ ${r}`),
|
|
283
|
+
"",
|
|
284
|
+
"Ingest / load / run:",
|
|
285
|
+
...guide.ingest.map((r) => ` $ ${r}`),
|
|
286
|
+
"",
|
|
287
|
+
"CLI:",
|
|
288
|
+
...guide.cli.map((r) => ` $ ${r}`),
|
|
289
|
+
"",
|
|
290
|
+
"Refuse when:",
|
|
291
|
+
...guide.refuse.map((r) => ` - ${r}`),
|
|
292
|
+
"",
|
|
293
|
+
];
|
|
294
|
+
return lines.join("\n");
|
|
295
|
+
}
|
|
296
|
+
/** Type guard helper for partial SkillContract assessments on scaffolds. */
|
|
297
|
+
export function assessExtractionScaffold(scaffold, profile = "release") {
|
|
298
|
+
return assessSkillContract(scaffold.contract_scaffold, profile);
|
|
299
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
/** Open .skill Protocol v0.
|
|
1
|
+
/** Open .skill Protocol v0.5 — types, constants, authoring APIs, and schemas. */
|
|
2
2
|
export { PROTOCOL_VERSION, CONTAINER_VERSION, WORKFLOW_DIALECT_VERSION, MEDIA_TYPE, MANIFEST_MEDIA_TYPE, DEFAULT_SKILL_POLICY, } from "./types.js";
|
|
3
|
-
export type { SkillCompileProfile, PackageSensitivity, ProvenanceMode, MintStatus, PermanenceAnchorKind, TrustProfile, InputSource, SensitivityLevel, AskWhen, SideEffectClass, CapabilityFallback, KnowledgeItemType, SteeringEffect, WorkflowStepKind, SkillRunStatus, RuntimeMode, CompletenessPart, GenerationUsage, JourneyProvenance, CompletenessReport, JsonSchema, ContentDigest, ProvenanceRef, InputSlot, OutputContract, CapabilityAdapterHint, CapabilityRequirement, SkillPermission, SkillPolicy, SkillDependency, MintRecord, CreationAttestation, PermanenceAnchor, SkillManifest, KnowledgeItem, SteeringConstraint, WorkflowStepBase, InstructStep, PromptStep, ToolStep, TransformStep, BranchStep, IterateStep, DelegateStep, CheckpointStep, HumanDecisionStep, VerifyStep, EmitStep, SubskillStep, WorkflowStep, Workflow, CompilationIssue, CompilationMapping, CompilationReport, SkillPackageFiles, SkillStepRecord, SkillRun, } from "./types.js";
|
|
4
|
-
export { FORBIDDEN_AGENT_HOSTS, isValidAgentHost, } from "./source.js";
|
|
3
|
+
export type { SkillCompileProfile, PackageSensitivity, ProvenanceMode, MintStatus, PermanenceAnchorKind, TrustProfile, TrustState, HostClaimBinding, IssuerClass, InputSource, SensitivityLevel, AskWhen, SideEffectClass, CapabilityFallback, KnowledgeItemType, SteeringEffect, WorkflowStepKind, SkillRunStatus, RuntimeMode, CompletenessPart, GenerationUsage, JourneyProvenance, CompletenessReport, JsonSchema, ContentDigest, ProvenanceRef, InputSlot, OutputContract, CapabilityAdapterHint, CapabilityRequirement, SkillPermission, SkillPolicy, SkillDependency, MintRecord, SealedManifestClaims, CreationAttestation, TrustView, PermanenceAnchor, SkillManifest, KnowledgeItem, SteeringConstraint, WorkflowStepBase, InstructStep, PromptStep, ToolStep, TransformStep, BranchStep, IterateStep, DelegateStep, CheckpointStep, HumanDecisionStep, VerifyStep, EmitStep, SubskillStep, WorkflowStep, Workflow, CompilationIssue, CompilationMapping, CompilationReport, SkillPackageFiles, SkillStepRecord, SkillRun, } from "./types.js";
|
|
4
|
+
export { FORBIDDEN_AGENT_HOSTS, AGENT_RUNTIME_MARKER_ENVS, isValidAgentHost, detectAgentRuntimeMarkers, hasAgentRuntimeEvidence, } from "./source.js";
|
|
5
|
+
export { assessSkillContract, scaffoldSkillContract, explainContractAssessment, } from "./authoring.js";
|
|
6
|
+
export { extractSkillCandidates, segmentJourney, agentCreateGuide, formatAgentGuide, assessExtractionScaffold, } from "./extract.js";
|
|
7
|
+
export type { JourneyCandidateInput, RedactedJourneyInput, ExtractionScaffold, ExtractionReport, AgentGuide, } from "./extract.js";
|
|
8
|
+
export type { SkillKind, DeclarationStatus, ExplicitDeclaration, ContractTrigger, InputApproval, ContractInput, ContractPrecondition, ContractStepKind, ContractStep, ContractBranch, ContractHumanDecision, ContractCapability, ContractPermission, ForbiddenAction, ContractOutput, RecoveryEdge, VerificationAssertion, ContractCorrection, ContractEvidence, ContractProvenance, SkillContract, ContractField, ContractIssue, ContractAssessment, SkillCandidate, } from "./contract.js";
|
|
5
9
|
export type { SectionType, SectionAuthor, CodeRef, Attachment, PersonRef, SkillSection, SteeringEvent, PromptVersion, AgentContext, SkillSource, SteeringVerb, CaptureFidelity, } from "./source.js";
|
|
6
10
|
export { recipeToSkillSource } from "./recipe.js";
|
|
7
11
|
export type { IngredientType, VisibilityIntent, RecipeIngredient, Recipe, Skill, } from "./recipe.js";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
/** Open .skill Protocol v0.
|
|
1
|
+
/** Open .skill Protocol v0.5 — types, constants, authoring APIs, and schemas. */
|
|
2
2
|
export { PROTOCOL_VERSION, CONTAINER_VERSION, WORKFLOW_DIALECT_VERSION, MEDIA_TYPE, MANIFEST_MEDIA_TYPE, DEFAULT_SKILL_POLICY, } from "./types.js";
|
|
3
|
-
export { FORBIDDEN_AGENT_HOSTS, isValidAgentHost, } from "./source.js";
|
|
3
|
+
export { FORBIDDEN_AGENT_HOSTS, AGENT_RUNTIME_MARKER_ENVS, isValidAgentHost, detectAgentRuntimeMarkers, hasAgentRuntimeEvidence, } from "./source.js";
|
|
4
|
+
export { assessSkillContract, scaffoldSkillContract, explainContractAssessment, } from "./authoring.js";
|
|
5
|
+
export { extractSkillCandidates, segmentJourney, agentCreateGuide, formatAgentGuide, assessExtractionScaffold, } from "./extract.js";
|
|
4
6
|
export { recipeToSkillSource } from "./recipe.js";
|
package/dist/recipe.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* Skillerr (and similar products) map recipe/ingredient/bake → SkillSource/compile.
|
|
6
6
|
*/
|
|
7
7
|
import type { GenerationUsage, JourneyProvenance } from "./types.js";
|
|
8
|
+
import type { SkillContract } from "./contract.js";
|
|
8
9
|
import type { AgentContext, Attachment, CodeRef, PersonRef, PromptVersion, SectionType, SkillSource, SteeringEvent } from "./source.js";
|
|
9
10
|
/** @deprecated Prefer SectionType from source.ts — kept for Skillerr adapters. */
|
|
10
11
|
export type IngredientType = SectionType;
|
|
@@ -48,6 +49,8 @@ export interface Recipe {
|
|
|
48
49
|
source_protocol_version: string;
|
|
49
50
|
generation_usage?: GenerationUsage;
|
|
50
51
|
journey_summary?: string;
|
|
52
|
+
/** Optional 0.5 protocol-native semantics carried through this lossy product adapter. */
|
|
53
|
+
contract?: SkillContract;
|
|
51
54
|
}
|
|
52
55
|
/** @deprecated Legacy flat markdown skill export. Prefer SkillManifest / `.skill`. */
|
|
53
56
|
export interface Skill {
|
package/dist/recipe.js
CHANGED
|
@@ -45,6 +45,7 @@ export function recipeToSkillSource(recipe, overrides = {}) {
|
|
|
45
45
|
title: recipe.title,
|
|
46
46
|
summary: recipe.summary,
|
|
47
47
|
intent: recipe.summary ?? recipe.title,
|
|
48
|
+
contract: recipe.contract ? structuredClone(recipe.contract) : undefined,
|
|
48
49
|
sections,
|
|
49
50
|
steering: recipe.steering,
|
|
50
51
|
prompts: recipe.prompts,
|
package/dist/source.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Products (Skillerr, etc.) may use their own words (ingredient, recipe, bake).
|
|
5
5
|
* Adapters map those into SkillSource / SkillSection before compile.
|
|
6
6
|
*/
|
|
7
|
+
import type { SkillContract, SkillCandidate } from "./contract.js";
|
|
7
8
|
import type { GenerationUsage, JourneyProvenance, PackageSensitivity } from "./types.js";
|
|
8
9
|
export type SectionType = "prompt" | "decision" | "architecture" | "diagram" | "integration" | "resource" | "reference" | "lesson" | "requirement" | "tradeoff" | "risk" | "question" | "implementation_note" | "config" | "correction_note" | "doc" | "message" | "handoff" | "code" | "intent" | "workflow_note";
|
|
9
10
|
export type SectionAuthor = "agent" | "human_via_agent";
|
|
@@ -89,6 +90,13 @@ export interface SkillSource {
|
|
|
89
90
|
title: string;
|
|
90
91
|
summary?: string;
|
|
91
92
|
intent?: string;
|
|
93
|
+
/**
|
|
94
|
+
* 0.5 source of truth for transferable semantics. A missing contract marks
|
|
95
|
+
* a 0.4-compatible text source and is release-lossy.
|
|
96
|
+
*/
|
|
97
|
+
contract?: SkillContract;
|
|
98
|
+
/** Optional extraction candidates. Segmentation belongs to an adapter/AI, not the compiler. */
|
|
99
|
+
candidates?: SkillCandidate[];
|
|
92
100
|
sections: SkillSection[];
|
|
93
101
|
steering: SteeringEvent[];
|
|
94
102
|
prompts: PromptVersion[];
|
|
@@ -111,6 +119,20 @@ export interface SkillSource {
|
|
|
111
119
|
hash?: string;
|
|
112
120
|
}>;
|
|
113
121
|
}
|
|
114
|
-
/**
|
|
122
|
+
/**
|
|
123
|
+
* Hosts that are not valid AI agent runtimes for skill creation / mint.
|
|
124
|
+
* Humans exporting SKILL_HOST=cli|shell|manual must never mint as an agent.
|
|
125
|
+
*/
|
|
115
126
|
export declare const FORBIDDEN_AGENT_HOSTS: Set<string>;
|
|
116
127
|
export declare function isValidAgentHost(host: string | undefined | null): boolean;
|
|
128
|
+
/**
|
|
129
|
+
* Process / mint markers that indicate an agent runtime path (not a bare human shell).
|
|
130
|
+
* These are still spoofable by a determined local process — residual risk remains —
|
|
131
|
+
* but a human who only exports SKILL_HOST=cursor without any agent context fails this check.
|
|
132
|
+
*/
|
|
133
|
+
export declare const AGENT_RUNTIME_MARKER_ENVS: readonly ["CURSOR_AGENT", "CURSOR_TRACE_ID", "COMPOSER_SESSION_ID", "SKILL_AGENT_INVOCATION", "SKILL_SESSION_ID", "CLAUDE_CODE_ENTRYPOINT", "AIDER_ACTIVE"];
|
|
134
|
+
export declare function detectAgentRuntimeMarkers(env?: Record<string, string | undefined>): string[];
|
|
135
|
+
export declare function hasAgentRuntimeEvidence(evidence?: {
|
|
136
|
+
markers?: string[];
|
|
137
|
+
session_id?: string;
|
|
138
|
+
} | null, env?: Record<string, string | undefined>): boolean;
|
package/dist/source.js
CHANGED
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
* Products (Skillerr, etc.) may use their own words (ingredient, recipe, bake).
|
|
5
5
|
* Adapters map those into SkillSource / SkillSection before compile.
|
|
6
6
|
*/
|
|
7
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* Hosts that are not valid AI agent runtimes for skill creation / mint.
|
|
9
|
+
* Humans exporting SKILL_HOST=cli|shell|manual must never mint as an agent.
|
|
10
|
+
*/
|
|
8
11
|
export const FORBIDDEN_AGENT_HOSTS = new Set([
|
|
9
12
|
"",
|
|
10
13
|
"human",
|
|
@@ -12,9 +15,55 @@ export const FORBIDDEN_AGENT_HOSTS = new Set([
|
|
|
12
15
|
"none",
|
|
13
16
|
"cli",
|
|
14
17
|
"user",
|
|
18
|
+
"shell",
|
|
19
|
+
"bash",
|
|
20
|
+
"zsh",
|
|
21
|
+
"sh",
|
|
22
|
+
"fish",
|
|
23
|
+
"powershell",
|
|
24
|
+
"pwsh",
|
|
25
|
+
"cmd",
|
|
26
|
+
"terminal",
|
|
27
|
+
"console",
|
|
28
|
+
"tty",
|
|
29
|
+
"stdin",
|
|
30
|
+
"keyboard",
|
|
31
|
+
"local-shell",
|
|
32
|
+
"human-cli",
|
|
33
|
+
"operator",
|
|
15
34
|
]);
|
|
16
35
|
export function isValidAgentHost(host) {
|
|
17
36
|
if (!host)
|
|
18
37
|
return false;
|
|
19
38
|
return !FORBIDDEN_AGENT_HOSTS.has(host.trim().toLowerCase());
|
|
20
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Process / mint markers that indicate an agent runtime path (not a bare human shell).
|
|
42
|
+
* These are still spoofable by a determined local process — residual risk remains —
|
|
43
|
+
* but a human who only exports SKILL_HOST=cursor without any agent context fails this check.
|
|
44
|
+
*/
|
|
45
|
+
export const AGENT_RUNTIME_MARKER_ENVS = [
|
|
46
|
+
"CURSOR_AGENT",
|
|
47
|
+
"CURSOR_TRACE_ID",
|
|
48
|
+
"COMPOSER_SESSION_ID",
|
|
49
|
+
"SKILL_AGENT_INVOCATION",
|
|
50
|
+
"SKILL_SESSION_ID",
|
|
51
|
+
"CLAUDE_CODE_ENTRYPOINT",
|
|
52
|
+
"AIDER_ACTIVE",
|
|
53
|
+
];
|
|
54
|
+
export function detectAgentRuntimeMarkers(env = process.env) {
|
|
55
|
+
const found = [];
|
|
56
|
+
for (const key of AGENT_RUNTIME_MARKER_ENVS) {
|
|
57
|
+
const v = env[key];
|
|
58
|
+
if (v !== undefined && String(v).trim() !== "")
|
|
59
|
+
found.push(key);
|
|
60
|
+
}
|
|
61
|
+
return found;
|
|
62
|
+
}
|
|
63
|
+
export function hasAgentRuntimeEvidence(evidence, env = process.env) {
|
|
64
|
+
if (evidence?.session_id && evidence.session_id.trim())
|
|
65
|
+
return true;
|
|
66
|
+
if (evidence?.markers?.some((m) => m.trim()))
|
|
67
|
+
return true;
|
|
68
|
+
return detectAgentRuntimeMarkers(env).length > 0;
|
|
69
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
/** Open .skill Protocol v0.
|
|
2
|
-
|
|
1
|
+
/** Open .skill Protocol v0.5 — semantic types for portable `.skill` packages. */
|
|
2
|
+
import type { ContractBranch, ContractHumanDecision, InputApproval, ContractPrecondition, ContractTrigger, ExplicitDeclaration, RecoveryEdge, SkillContract, VerificationAssertion } from "./contract.js";
|
|
3
|
+
export declare const PROTOCOL_VERSION = "0.5.0";
|
|
3
4
|
export declare const CONTAINER_VERSION = "1.0";
|
|
4
|
-
export declare const WORKFLOW_DIALECT_VERSION = "1.
|
|
5
|
+
export declare const WORKFLOW_DIALECT_VERSION = "1.1";
|
|
5
6
|
/** Media type for a packaged `.skill` archive (zip). */
|
|
6
7
|
export declare const MEDIA_TYPE = "application/vnd.dot-skill+zip";
|
|
7
8
|
/** Media type for the manifest JSON document inside a `.skill` archive. */
|
|
@@ -18,6 +19,21 @@ export type ProvenanceMode = "full" | "redacted" | "proof_only";
|
|
|
18
19
|
export type MintStatus = "draft" | "minted";
|
|
19
20
|
export type PermanenceAnchorKind = "registry" | "transparency_log" | "ledger" | "content_addressed_store" | "other";
|
|
20
21
|
export type TrustProfile = "open" | "minted" | "anchored" | `issuer:${string}`;
|
|
22
|
+
/**
|
|
23
|
+
* Human-readable trust decision for TrustView / inspect --trust.
|
|
24
|
+
* - untrusted: unsigned, open, or failed verification
|
|
25
|
+
* - development: public-dev HMAC verified structurally — never production trust
|
|
26
|
+
* - self_reported: signed, but host/model claims are env/self-asserted (not issuer-verified)
|
|
27
|
+
* - verified_issuer: configured non-public issuer key bound the sealed claims
|
|
28
|
+
*/
|
|
29
|
+
export type TrustState = "untrusted" | "development" | "self_reported" | "verified_issuer";
|
|
30
|
+
/** How the host/model claim was bound into the seal. */
|
|
31
|
+
export type HostClaimBinding = "self_reported" | "verified_issuer";
|
|
32
|
+
/**
|
|
33
|
+
* Class of mint issuer key material.
|
|
34
|
+
* public_dev_hmac MUST NOT be treated as production trust.
|
|
35
|
+
*/
|
|
36
|
+
export type IssuerClass = "public_dev_hmac" | "configured_hmac" | "verified_issuer";
|
|
21
37
|
export type InputSource = "human" | "environment" | "secret" | "artifact" | "derived";
|
|
22
38
|
export type SensitivityLevel = "public" | "private" | "secret";
|
|
23
39
|
export type AskWhen = "always" | "if_missing" | "never";
|
|
@@ -29,7 +45,7 @@ export type WorkflowStepKind = "instruct" | "prompt" | "tool" | "transform" | "b
|
|
|
29
45
|
export type SkillRunStatus = "pending" | "running" | "paused" | "succeeded" | "failed" | "cancelled";
|
|
30
46
|
export type RuntimeMode = "inspect" | "explain" | "dry_run" | "execute" | "resume";
|
|
31
47
|
/** Parts the compiler checks before producing a package. */
|
|
32
|
-
export type CompletenessPart = "agent_context" | "intent" | "sections" | "workflow" | "knowledge_or_prompts" | "inputs_declared" | "journey" | "generation_usage" | "human_approvals";
|
|
48
|
+
export type CompletenessPart = "agent_context" | "intent" | "sections" | "workflow" | "knowledge_or_prompts" | "inputs_declared" | "journey" | "generation_usage" | "human_approvals" | "semantic_contract" | "triggers" | "inputs" | "preconditions" | "steps" | "branches" | "human_decisions" | "capabilities" | "permissions" | "forbidden_actions" | "outputs" | "recovery" | "verification" | "corrections" | "provenance";
|
|
33
49
|
export interface GenerationUsage {
|
|
34
50
|
input_tokens?: number;
|
|
35
51
|
output_tokens?: number;
|
|
@@ -79,6 +95,7 @@ export interface InputSlot {
|
|
|
79
95
|
default?: unknown;
|
|
80
96
|
sensitivity: SensitivityLevel;
|
|
81
97
|
ask_when: AskWhen;
|
|
98
|
+
approval?: InputApproval;
|
|
82
99
|
examples?: unknown[];
|
|
83
100
|
provenance?: ProvenanceRef[];
|
|
84
101
|
generalization_reason?: string;
|
|
@@ -139,9 +156,60 @@ export interface MintRecord {
|
|
|
139
156
|
mint_issuer?: string;
|
|
140
157
|
content_id?: string;
|
|
141
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* Claims bound by the creation seal (identity + safety + content digests).
|
|
161
|
+
* Digest of this object is `sealed_manifest_digest`.
|
|
162
|
+
*/
|
|
163
|
+
export interface SealedManifestClaims {
|
|
164
|
+
id: string;
|
|
165
|
+
version: string;
|
|
166
|
+
title: string;
|
|
167
|
+
intent?: string;
|
|
168
|
+
description: string;
|
|
169
|
+
package_digest: string;
|
|
170
|
+
permissions: Array<{
|
|
171
|
+
side_effect_class: SideEffectClass;
|
|
172
|
+
description: string;
|
|
173
|
+
paths?: string[];
|
|
174
|
+
hosts?: string[];
|
|
175
|
+
requires_consent: boolean;
|
|
176
|
+
}>;
|
|
177
|
+
policy: {
|
|
178
|
+
require_signatures: boolean;
|
|
179
|
+
require_minted?: boolean;
|
|
180
|
+
require_anchor?: boolean;
|
|
181
|
+
allow_network: boolean;
|
|
182
|
+
filesystem_roots?: string[];
|
|
183
|
+
consent_for: SideEffectClass[];
|
|
184
|
+
trust_profile?: TrustProfile;
|
|
185
|
+
max_tool_calls: number;
|
|
186
|
+
max_runtime_ms: number;
|
|
187
|
+
fail_on_unsupported_step: boolean;
|
|
188
|
+
};
|
|
189
|
+
capabilities: Array<{
|
|
190
|
+
name: string;
|
|
191
|
+
side_effect_class: SideEffectClass;
|
|
192
|
+
required: boolean;
|
|
193
|
+
}>;
|
|
194
|
+
inputs: Array<{
|
|
195
|
+
name: string;
|
|
196
|
+
sensitivity: SensitivityLevel;
|
|
197
|
+
required: boolean;
|
|
198
|
+
source: InputSource;
|
|
199
|
+
}>;
|
|
200
|
+
content: ContentDigest[];
|
|
201
|
+
contract?: {
|
|
202
|
+
title: string;
|
|
203
|
+
intent: string;
|
|
204
|
+
skill_kind: string;
|
|
205
|
+
sensitivity: string;
|
|
206
|
+
};
|
|
207
|
+
}
|
|
142
208
|
export interface CreationAttestation {
|
|
143
209
|
kind: "creation_attestation";
|
|
144
210
|
package_digest: string;
|
|
211
|
+
/** Digest over identity + permissions/policy/capabilities + content index. */
|
|
212
|
+
sealed_manifest_digest: string;
|
|
145
213
|
skill_id: string;
|
|
146
214
|
skill_version: string;
|
|
147
215
|
minted_at: string;
|
|
@@ -155,6 +223,12 @@ export interface CreationAttestation {
|
|
|
155
223
|
model?: string;
|
|
156
224
|
deployment?: "local" | "hosted" | "hybrid" | "unknown";
|
|
157
225
|
endpoint?: string;
|
|
226
|
+
/** Whether host/model claims are self-asserted or issuer-verified. */
|
|
227
|
+
host_claim_binding: HostClaimBinding;
|
|
228
|
+
/** Issuer key class — public_dev_hmac is never production trust. */
|
|
229
|
+
issuer_class: IssuerClass;
|
|
230
|
+
/** Agent-runtime markers observed at mint (inspectable; still spoofable locally). */
|
|
231
|
+
agent_runtime_markers?: string[];
|
|
158
232
|
journey: {
|
|
159
233
|
/** @deprecated Prefer source_id — Skillerr recipe id when adapted. */
|
|
160
234
|
recipe_id?: string;
|
|
@@ -172,6 +246,35 @@ export interface CreationAttestation {
|
|
|
172
246
|
};
|
|
173
247
|
policy_profile?: TrustProfile;
|
|
174
248
|
}
|
|
249
|
+
/** Seal / trust summary readable without compile or model body ingest. */
|
|
250
|
+
export interface TrustView {
|
|
251
|
+
trust_state: TrustState;
|
|
252
|
+
mint_status: MintStatus;
|
|
253
|
+
signed: boolean;
|
|
254
|
+
issuer?: string;
|
|
255
|
+
issuer_class?: IssuerClass;
|
|
256
|
+
host_claim_binding?: HostClaimBinding;
|
|
257
|
+
agent?: {
|
|
258
|
+
host?: string;
|
|
259
|
+
provider?: string;
|
|
260
|
+
model?: string;
|
|
261
|
+
runtime?: string;
|
|
262
|
+
version?: string;
|
|
263
|
+
key_id?: string;
|
|
264
|
+
deployment?: string;
|
|
265
|
+
markers?: string[];
|
|
266
|
+
};
|
|
267
|
+
package_digest: string;
|
|
268
|
+
sealed_manifest_digest?: string;
|
|
269
|
+
attestation_digest?: string;
|
|
270
|
+
label: string;
|
|
271
|
+
warnings: string[];
|
|
272
|
+
issues: Array<{
|
|
273
|
+
severity: "error" | "warning";
|
|
274
|
+
code: string;
|
|
275
|
+
message: string;
|
|
276
|
+
}>;
|
|
277
|
+
}
|
|
175
278
|
export interface PermanenceAnchor {
|
|
176
279
|
kind: PermanenceAnchorKind;
|
|
177
280
|
package_digest: string;
|
|
@@ -192,7 +295,16 @@ export interface SkillManifest {
|
|
|
192
295
|
title: string;
|
|
193
296
|
description: string;
|
|
194
297
|
intent?: string;
|
|
195
|
-
|
|
298
|
+
/** Authoritative 0.5 semantic contract. Absent only on legacy/draft adapters. */
|
|
299
|
+
contract?: SkillContract;
|
|
300
|
+
triggers?: ContractTrigger[];
|
|
301
|
+
preconditions?: ExplicitDeclaration<ContractPrecondition>;
|
|
302
|
+
branches?: ExplicitDeclaration<ContractBranch>;
|
|
303
|
+
human_decisions?: ExplicitDeclaration<ContractHumanDecision>;
|
|
304
|
+
forbidden_actions?: SkillContract["forbidden_actions"];
|
|
305
|
+
recovery?: ExplicitDeclaration<RecoveryEdge>;
|
|
306
|
+
verification?: ExplicitDeclaration<VerificationAssertion>;
|
|
307
|
+
corrections?: SkillContract["corrections"];
|
|
196
308
|
authors?: Array<{
|
|
197
309
|
id: string;
|
|
198
310
|
display_name?: string;
|
|
@@ -217,6 +329,8 @@ export interface SkillManifest {
|
|
|
217
329
|
package_sensitivity?: PackageSensitivity;
|
|
218
330
|
mint?: MintRecord;
|
|
219
331
|
attestation_digest?: string;
|
|
332
|
+
/** Present on minted packages — binds identity/policy/content claims in the seal. */
|
|
333
|
+
sealed_manifest_digest?: string;
|
|
220
334
|
anchors?: PermanenceAnchor[];
|
|
221
335
|
legacy?: boolean;
|
|
222
336
|
needs_human_review?: boolean;
|
|
@@ -331,6 +445,11 @@ export interface Workflow {
|
|
|
331
445
|
entrypoint: string;
|
|
332
446
|
steps: WorkflowStep[];
|
|
333
447
|
constraints?: SteeringConstraint[];
|
|
448
|
+
preconditions?: ExplicitDeclaration<ContractPrecondition>;
|
|
449
|
+
branches?: ExplicitDeclaration<ContractBranch>;
|
|
450
|
+
human_decisions?: ExplicitDeclaration<ContractHumanDecision>;
|
|
451
|
+
recovery?: ExplicitDeclaration<RecoveryEdge>;
|
|
452
|
+
verification?: ExplicitDeclaration<VerificationAssertion>;
|
|
334
453
|
}
|
|
335
454
|
export interface CompilationIssue {
|
|
336
455
|
severity: "error" | "warning" | "info";
|
|
@@ -360,6 +479,8 @@ export interface CompilationReport {
|
|
|
360
479
|
pending_approvals: string[];
|
|
361
480
|
approved: boolean;
|
|
362
481
|
completeness: CompletenessReport;
|
|
482
|
+
semantic_contract: "native_0.5" | "legacy_lossy";
|
|
483
|
+
losses?: string[];
|
|
363
484
|
}
|
|
364
485
|
export interface SkillPackageFiles {
|
|
365
486
|
manifest: SkillManifest;
|