@rhize/skill-forge 0.5.0 → 0.6.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 +36 -5
- package/dist/cli.js +413 -256
- package/dist/cli.js.map +1 -1
- package/dist/ingest-prompt.md +103 -10
- package/package.json +1 -1
package/dist/ingest-prompt.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# Skill Ingestion Pass
|
|
2
2
|
|
|
3
|
-
You are running the deep decide/absorb pass on a
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
You are running the deep decide/absorb pass on a candidate — a skill, or (since
|
|
4
|
+
skill-forge v0.6) an MCP server — that has just cleared the `skill-forge` quarantine →
|
|
5
|
+
profile → safety scan → overlap-analysis gate. The gate already answered "is this safe to
|
|
6
|
+
install?" — your job is the harder question: "given everything already configured, what
|
|
7
|
+
should actually be *done* with it?" §1 below tells you which branch to follow depending on
|
|
8
|
+
the candidate's type.
|
|
7
9
|
|
|
8
10
|
You may be any coding agent (Claude Code, Codex CLI, Cursor, Windsurf, OpenCode, Gemini
|
|
9
11
|
CLI, or another). Nothing below assumes a specific one. Use whatever file-reading,
|
|
@@ -29,7 +31,7 @@ is a JSON object shaped like:
|
|
|
29
31
|
"entries": [
|
|
30
32
|
{
|
|
31
33
|
"id": "a1b2c3d4",
|
|
32
|
-
"source": "the original slug / git URL / local path the skill was installed from",
|
|
34
|
+
"source": "the original slug / git URL / local path the skill or server was installed from",
|
|
33
35
|
"sourceType": "skills.sh | git | local",
|
|
34
36
|
"installedPath": "final path after promote, or null if only held in quarantine",
|
|
35
37
|
"quarantinePath": "path to the quarantine sandbox this entry was gated from",
|
|
@@ -37,11 +39,19 @@ is a JSON object shaped like:
|
|
|
37
39
|
"license": "detected license string, or null",
|
|
38
40
|
"safetyVerdict": "pass | warn | block",
|
|
39
41
|
"safetyFindings": ["human-readable safety findings, one per string"],
|
|
40
|
-
"overlapTop": [{ "skill": "nearest-existing-skill-name", "score": 0.0 }],
|
|
42
|
+
"overlapTop": [{ "skill": "nearest-existing-skill-or-server-name", "score": 0.0 }],
|
|
41
43
|
"suggestedVerb": "DEFER | ABSORB | FORK | REJECT | WATCH | null"
|
|
42
44
|
},
|
|
43
45
|
"status": "pending | ingested | dismissed",
|
|
44
|
-
"createdAt": "ISO-8601 timestamp"
|
|
46
|
+
"createdAt": "ISO-8601 timestamp",
|
|
47
|
+
"artifactType": "skill | mcp (optional — absent means 'skill')",
|
|
48
|
+
"capabilities": {
|
|
49
|
+
"tools": ["statically-extracted tool names — mcp entries only, optional field"],
|
|
50
|
+
"resources": ["statically-extracted resource templates/URIs"],
|
|
51
|
+
"prompts": ["statically-extracted prompt names"],
|
|
52
|
+
"transport": "stdio | http (optional, best-effort)",
|
|
53
|
+
"declaredConfidence": "high | partial | none"
|
|
54
|
+
}
|
|
45
55
|
}
|
|
46
56
|
]
|
|
47
57
|
}
|
|
@@ -52,9 +62,92 @@ Pick the entry with `"status": "pending"` whose `installedPath` (or `quarantineP
|
|
|
52
62
|
user and ask which to process, or work through them one at a time — don't silently drain
|
|
53
63
|
the whole queue.
|
|
54
64
|
|
|
55
|
-
If there is no matching queue entry at all (you were pointed straight at a skill
|
|
56
|
-
with no CLI queue involved), that's fine — do the same evaluation, just skip the
|
|
57
|
-
entry" step at the end since there's nothing to close.
|
|
65
|
+
If there is no matching queue entry at all (you were pointed straight at a skill or server
|
|
66
|
+
directory with no CLI queue involved), that's fine — do the same evaluation, just skip the
|
|
67
|
+
"close the entry" step at the end since there's nothing to close.
|
|
68
|
+
|
|
69
|
+
Check the entry's `artifactType` before continuing:
|
|
70
|
+
|
|
71
|
+
- **`"skill"` or absent** — this is a skill candidate; continue with §2–7 below.
|
|
72
|
+
- **`"mcp"`** — this is an MCP server candidate; skip §2–7 and follow **"If artifactType is
|
|
73
|
+
`mcp`"** immediately below instead. (If you have no queue entry to check, infer it: a
|
|
74
|
+
directory with a `SKILL.md` is a skill; a directory/package with an `.mcp.json`/
|
|
75
|
+
`mcp.json`, an MCP-server-shaped `package.json`, or an extracted npm tarball with no
|
|
76
|
+
`SKILL.md` is an MCP server.)
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## If artifactType is `"mcp"`
|
|
81
|
+
|
|
82
|
+
The target is an MCP **server**, not a skill — the decide/act/record steps below replace
|
|
83
|
+
§2–7 for this entry. The five-verb matrix, license triage, and record/close mechanics are
|
|
84
|
+
the same ones §2–7 use for skills; only what you're evaluating and where you act changes.
|
|
85
|
+
|
|
86
|
+
### Gather context — statically only, always
|
|
87
|
+
|
|
88
|
+
- **Read the entry's `capabilities` field** (introduced in skill-forge v0.6):
|
|
89
|
+
`{ tools, resources, prompts, transport?, declaredConfidence }`, a **statically-extracted**
|
|
90
|
+
profile — tool/resource/prompt names parsed from the candidate's `package.json`, any
|
|
91
|
+
shipped `.mcp.json`/manifest, and MCP SDK source-text patterns (e.g.
|
|
92
|
+
`server.tool("name", ...)`, `setRequestHandler(ListToolsRequestSchema, ...)`,
|
|
93
|
+
`server.resource(...)`, `server.prompt(...)`). It is never derived by running the server.
|
|
94
|
+
- **Do not run or install the server to inspect it.** No `npm install`, no executing its
|
|
95
|
+
binary or entry point, no invoking its tools to see what they do. If `capabilities` is
|
|
96
|
+
absent, empty, or `declaredConfidence` is `"partial"`/`"none"`, read more source
|
|
97
|
+
statically yourself (package.json, README, exported tool/resource/prompt registrations)
|
|
98
|
+
— never execute anything to fill the gap. This is a hard security invariant, not a style
|
|
99
|
+
preference: it mirrors the CLI's own static-only extraction.
|
|
100
|
+
- **Reuse `gate.safetyVerdict` / `gate.safetyFindings`** — the MCP safety scan (unpinned
|
|
101
|
+
`npx`, inline credentials, dangerous launch flags, broad filesystem args) already ran;
|
|
102
|
+
don't re-scan.
|
|
103
|
+
- **Judge redundancy against already-configured servers** using `gate.overlapTop` (nearest
|
|
104
|
+
server-name/package matches) plus your own read of the target mcp config file for
|
|
105
|
+
capability overlap: do any already-configured servers expose the same or near-identical
|
|
106
|
+
tools/resources as this candidate's `capabilities`?
|
|
107
|
+
|
|
108
|
+
### Decide — same five verbs, applied to a server
|
|
109
|
+
|
|
110
|
+
Weigh the same dimensions as skills (overlap, quality, license, maintenance, fit), reading
|
|
111
|
+
"quality" as `declaredConfidence` plus the safety verdict, and "overlap" as
|
|
112
|
+
tool/resource/prompt redundancy with an already-configured server:
|
|
113
|
+
|
|
114
|
+
- **DEFER** — genuinely new capability, cleanly scoped; keep the promoted config entry
|
|
115
|
+
exactly as installed.
|
|
116
|
+
- **ABSORB** — overlaps partially with something already configured but adds real
|
|
117
|
+
capability; keep it, but **tighten its config first** — trim `env` to only the variables
|
|
118
|
+
its declared tools actually need, narrow broad `args` (e.g. a filesystem root), and
|
|
119
|
+
record which values you removed or narrowed.
|
|
120
|
+
- **FORK** — worth keeping but its default config doesn't fit house convention (wrong
|
|
121
|
+
scope, wrong invocation style, name collision); adjust the config to fit rather than
|
|
122
|
+
installing it verbatim.
|
|
123
|
+
- **REJECT** — duplicates an already-configured server's capability, fails the license
|
|
124
|
+
triage, or `gate.safetyVerdict` is `"block"`; **remove the server entry** from the
|
|
125
|
+
target mcp config with a documented edit (state which entry you removed and why).
|
|
126
|
+
- **WATCH** — promising but not ready to trust (e.g. `declaredConfidence: "none"` and you
|
|
127
|
+
can't determine enough statically), or upstream looks immature; leave the config as-is
|
|
128
|
+
(or don't promote it) and leave a WATCH note — don't silently drop it.
|
|
129
|
+
|
|
130
|
+
License triage (§4 below) applies unchanged: classify `gate.license` before committing to
|
|
131
|
+
ABSORB or FORK, and never ABSORB/FORK on a copyleft, none-stated, or restrictive license
|
|
132
|
+
without the user's explicit sign-off.
|
|
133
|
+
|
|
134
|
+
### Act
|
|
135
|
+
|
|
136
|
+
Apply the config change (or deliberate non-change) implied by your verb directly to the
|
|
137
|
+
promoted mcp config file — the file the CLI's promote step wrote to (see `installedPath`
|
|
138
|
+
on the entry, or its `--mcp-target` resolution). Edit only the `mcpServers`/`servers` entry
|
|
139
|
+
for this candidate; never touch other servers' entries in the same file. Verify the file
|
|
140
|
+
still parses as valid JSON and the kept/tightened entry's `command`/`args`/`env` shape is
|
|
141
|
+
still well-formed — you're validating the *config*, not spawning the server.
|
|
142
|
+
|
|
143
|
+
### Record and close the queue entry
|
|
144
|
+
|
|
145
|
+
Record the same fields §6 asks for (candidate name/source, license class, verb chosen,
|
|
146
|
+
what actually changed in the config, reasoning, "n/a" where nothing applies), then close
|
|
147
|
+
the queue entry exactly as in §6's "Close the queue entry": set `status` to `"ingested"`
|
|
148
|
+
once recorded, or `"dismissed"` if the user declined. Report back per §7.
|
|
149
|
+
|
|
150
|
+
---
|
|
58
151
|
|
|
59
152
|
## 2. Gather context
|
|
60
153
|
|