agent-skillforge 0.4.1__tar.gz → 0.4.2__tar.gz
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.
- {agent_skillforge-0.4.1/src/agent_skillforge.egg-info → agent_skillforge-0.4.2}/PKG-INFO +81 -10
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/README.md +80 -9
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/pyproject.toml +1 -1
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2/src/agent_skillforge.egg-info}/PKG-INFO +81 -10
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/agent_skillforge.egg-info/SOURCES.txt +7 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/__init__.py +1 -1
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/cli.py +115 -0
- agent_skillforge-0.4.2/src/skillforge/evals.py +230 -0
- agent_skillforge-0.4.2/src/skillforge/openapi.py +202 -0
- agent_skillforge-0.4.2/src/skillforge/optimizer.py +273 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/security.py +69 -0
- agent_skillforge-0.4.2/tests/test_evals.py +95 -0
- agent_skillforge-0.4.2/tests/test_openapi.py +82 -0
- agent_skillforge-0.4.2/tests/test_optimizer.py +96 -0
- agent_skillforge-0.4.2/tests/test_sarif.py +64 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/LICENSE +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/setup.cfg +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/agent_skillforge.egg-info/dependency_links.txt +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/agent_skillforge.egg-info/entry_points.txt +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/agent_skillforge.egg-info/requires.txt +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/agent_skillforge.egg-info/top_level.txt +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/__main__.py +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/adapters.py +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/agent-observability/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/antislop-code/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/blast-radius-containment/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/caveman/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/cognitive-loop-breaker/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/context-compactor/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/contract-test-generator/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/flaky-test-isolation/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/human-in-the-loop/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/mcp-tool-designer/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/performance-profiler/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/runtime-api-verification/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/secret-sanitizer/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/security-threat-modeler/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/self-improving-agent/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/skill-architect/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/skill-architect/references/mechanics.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/spec-driven-development/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/summarize/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/supply-chain-sentinel/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/systematic-debugging/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/tavily-search/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/zero-downtime-migration/SKILL.md +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/errors.py +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/mcp_server.py +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/registry.py +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/skill.py +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/tests/test_adapters.py +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/tests/test_badge.py +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/tests/test_builtins.py +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/tests/test_cli.py +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/tests/test_hardening.py +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/tests/test_mcp_server.py +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/tests/test_registry.py +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/tests/test_security.py +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/tests/test_skill.py +0 -0
- {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/tests/test_verify_and_pinning.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-skillforge
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: Universal package manager, security auditor, and MCP server for portable agent skills (SKILL.md).
|
|
5
5
|
Author-email: gintingism <gintingism@users.noreply.github.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -148,9 +148,10 @@ What the auditor scans for:
|
|
|
148
148
|
- **Progressive Disclosure Budget (QUAL-003):** Flags `SKILL.md` bodies exceeding 500 lines or ~5,000 tokens so heavy references are moved to `references/`.
|
|
149
149
|
- **Broken Disclosure Pointers (QUAL-004):** Verifies cited `references/...` or `scripts/...` exist.
|
|
150
150
|
|
|
151
|
-
For CI pipelines, pass `--strict` to fail on any warning, or `--
|
|
151
|
+
For CI pipelines, pass `--strict` to fail on any warning, `--json` for automation, or `--sarif` for GitHub Code Scanning:
|
|
152
152
|
```bash
|
|
153
|
-
|
|
153
|
+
# Export standard OASIS SARIF v2.1.0 report
|
|
154
|
+
skillforge audit ./skills/my-new-skill --sarif results.sarif
|
|
154
155
|
```
|
|
155
156
|
|
|
156
157
|
### 3. Profile your project's context token budget (`budget`)
|
|
@@ -169,7 +170,67 @@ Context Budget Profile (22 skills)
|
|
|
169
170
|
Disclosed Resources Cost: ~349 tokens
|
|
170
171
|
```
|
|
171
172
|
|
|
172
|
-
### 4.
|
|
173
|
+
### 4. Test skill trigger accuracy and assertions (`test`)
|
|
174
|
+
|
|
175
|
+
Verify that your skill description triggers on relevant user prompts, ignores unrelated requests, and respects keyword constraints using a deterministic test suite:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
# Initialize a starter evals/evals.json test suite
|
|
179
|
+
skillforge test ./skills/my-skill --init
|
|
180
|
+
|
|
181
|
+
# Run test cases
|
|
182
|
+
skillforge test ./skills/my-skill
|
|
183
|
+
```
|
|
184
|
+
```text
|
|
185
|
+
Running evals for 'my-skill' (4 test cases)...
|
|
186
|
+
[PASS] trigger_positive_core_my_skill: "Please help me with my-skill following our workflow."
|
|
187
|
+
[PASS] trigger_positive_task: "I need to execute a task: my skill workflow description"
|
|
188
|
+
[PASS] suppress_negative_unrelated_math: "Calculate the Fibonacci sequence for n=30 in Python."
|
|
189
|
+
[PASS] suppress_negative_greeting: "Hello there, what is the weather like in Tokyo today?"
|
|
190
|
+
|
|
191
|
+
Result: PASSED (4/4 passed)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Use `--json` in CI to verify that changes to `description` do not break activation accuracy.
|
|
195
|
+
|
|
196
|
+
### 5. Optimize bloated skills with progressive disclosure (`optimize`)
|
|
197
|
+
|
|
198
|
+
When a skill exceeds the 500-line or 5,000-token progressive disclosure budget (`QUAL-003`), extract heavy reference sections into `references/` while keeping concise pointers in `SKILL.md`:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
# Refactor an oversized skill directory in-place
|
|
202
|
+
skillforge optimize ./skills/bloated-api-skill --max-lines 400
|
|
203
|
+
|
|
204
|
+
# Or output to a fresh destination folder
|
|
205
|
+
skillforge optimize ./skills/bloated-api-skill -o ./skills/clean-api-skill
|
|
206
|
+
```
|
|
207
|
+
```text
|
|
208
|
+
Optimized 'bloated-api-skill':
|
|
209
|
+
Lines: 680 -> 240 (440 lines saved)
|
|
210
|
+
Tokens: ~6200 -> ~2100 (4100 tokens saved)
|
|
211
|
+
Extracted References:
|
|
212
|
+
- references/database-guidelines.md
|
|
213
|
+
- references/api-endpoints-manual.md
|
|
214
|
+
Destination: ./skills/clean-api-skill
|
|
215
|
+
Audit Verification: PASSED
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### 6. Convert OpenAPI / Swagger to a portable skill (`import-openapi`)
|
|
219
|
+
|
|
220
|
+
Convert an existing REST API specification (OpenAPI 3.0, 3.1, or Swagger 2.0 in JSON or YAML) into a progressive disclosure skill package without running external scripts:
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
skillforge import-openapi ./openapi.yaml --output ./skills
|
|
224
|
+
```
|
|
225
|
+
```text
|
|
226
|
+
Successfully imported 'petstore-api' into skills/petstore-api
|
|
227
|
+
SKILL.md: 28 lines (~320 body tokens)
|
|
228
|
+
endpoints.md reference: ~1850 tokens
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
The resulting package contains an executive overview in `SKILL.md` and detailed endpoint schemas in `references/endpoints.md`, keeping turn-by-turn context overhead low.
|
|
232
|
+
|
|
233
|
+
### 7. Generate an official verified badge (`badge`)
|
|
173
234
|
|
|
174
235
|
Show users that your skill is clean, secure, and audited. Generate an official badge for your skill repository:
|
|
175
236
|
|
|
@@ -180,7 +241,7 @@ skillforge badge ./my-skill
|
|
|
180
241
|
[](https://github.com/gintingism/skillforge)
|
|
181
242
|
```
|
|
182
243
|
|
|
183
|
-
###
|
|
244
|
+
### 8. Grab a skill directly from GitHub (`add`)
|
|
184
245
|
|
|
185
246
|
Pull skills directly from remote Git repositories with security auditing and reproducible commit pinning:
|
|
186
247
|
|
|
@@ -197,7 +258,7 @@ skillforge add gintingism/skillforge:systematic-debugging
|
|
|
197
258
|
|
|
198
259
|
SkillForge fetches the skill, audits its security, routes it to all detected assistant targets, and pins its SHA-256 digest + Git commit SHA into `skillforge.lock`.
|
|
199
260
|
|
|
200
|
-
###
|
|
261
|
+
### 9. Verify skill integrity and detect drift (`verify`)
|
|
201
262
|
|
|
202
263
|
Check installed skills against `skillforge.lock` in CI/CD or local environments without modifying files or making network requests. Detects file tampering, missing dependencies, or unmanaged skills:
|
|
203
264
|
|
|
@@ -215,7 +276,7 @@ skillforge verify --json
|
|
|
215
276
|
Verification PASSED: 2 skill(s) match skillforge.lock.
|
|
216
277
|
```
|
|
217
278
|
|
|
218
|
-
###
|
|
279
|
+
### 10. Compare changes before updating (`diff`)
|
|
219
280
|
|
|
220
281
|
Inspect diffs between local skills and upstream repositories, or compare two skill versions:
|
|
221
282
|
|
|
@@ -224,7 +285,7 @@ skillforge diff ./skills/my-skill
|
|
|
224
285
|
skillforge diff my-skill gintingism/skillforge:my-skill
|
|
225
286
|
```
|
|
226
287
|
|
|
227
|
-
###
|
|
288
|
+
### 11. Manage installed skills (`list` & `remove`)
|
|
228
289
|
|
|
229
290
|
See which skills are active across your editor targets:
|
|
230
291
|
|
|
@@ -246,7 +307,7 @@ To remove a skill from all detected assistants and update your lockfile:
|
|
|
246
307
|
skillforge remove antislop-code
|
|
247
308
|
```
|
|
248
309
|
|
|
249
|
-
###
|
|
310
|
+
### 12. Create and package your own skills (`create` & `pack`)
|
|
250
311
|
|
|
251
312
|
Scaffold a single skill file or a full directory package with scripts and reference docs:
|
|
252
313
|
|
|
@@ -268,7 +329,7 @@ skillforge unpack ./db-migrator.zip --output ./skills
|
|
|
268
329
|
|
|
269
330
|
## 🤖 Automate in CI/CD (GitHub Action)
|
|
270
331
|
|
|
271
|
-
Add SkillForge to your GitHub Actions workflow to audit
|
|
332
|
+
Add SkillForge to your GitHub Actions workflow to audit pull requests, enforce progressive disclosure budgets, and upload SARIF reports to GitHub Code Scanning:
|
|
272
333
|
|
|
273
334
|
```yaml
|
|
274
335
|
name: Audit Agent Skills
|
|
@@ -277,6 +338,9 @@ on: [pull_request, push]
|
|
|
277
338
|
jobs:
|
|
278
339
|
audit:
|
|
279
340
|
runs-on: ubuntu-latest
|
|
341
|
+
permissions:
|
|
342
|
+
security-events: write
|
|
343
|
+
contents: read
|
|
280
344
|
steps:
|
|
281
345
|
- uses: actions/checkout@v4
|
|
282
346
|
- name: Run SkillForge Security & Token Linter
|
|
@@ -285,6 +349,13 @@ jobs:
|
|
|
285
349
|
path: './skills'
|
|
286
350
|
strict: 'true'
|
|
287
351
|
budget: 'true'
|
|
352
|
+
sarif: 'skillforge-findings.sarif'
|
|
353
|
+
|
|
354
|
+
- name: Upload SARIF to GitHub Code Scanning
|
|
355
|
+
uses: github/codeql-action/upload-sarif@v3
|
|
356
|
+
if: always()
|
|
357
|
+
with:
|
|
358
|
+
sarif_file: 'skillforge-findings.sarif'
|
|
288
359
|
```
|
|
289
360
|
|
|
290
361
|
---
|
|
@@ -110,9 +110,10 @@ What the auditor scans for:
|
|
|
110
110
|
- **Progressive Disclosure Budget (QUAL-003):** Flags `SKILL.md` bodies exceeding 500 lines or ~5,000 tokens so heavy references are moved to `references/`.
|
|
111
111
|
- **Broken Disclosure Pointers (QUAL-004):** Verifies cited `references/...` or `scripts/...` exist.
|
|
112
112
|
|
|
113
|
-
For CI pipelines, pass `--strict` to fail on any warning, or `--
|
|
113
|
+
For CI pipelines, pass `--strict` to fail on any warning, `--json` for automation, or `--sarif` for GitHub Code Scanning:
|
|
114
114
|
```bash
|
|
115
|
-
|
|
115
|
+
# Export standard OASIS SARIF v2.1.0 report
|
|
116
|
+
skillforge audit ./skills/my-new-skill --sarif results.sarif
|
|
116
117
|
```
|
|
117
118
|
|
|
118
119
|
### 3. Profile your project's context token budget (`budget`)
|
|
@@ -131,7 +132,67 @@ Context Budget Profile (22 skills)
|
|
|
131
132
|
Disclosed Resources Cost: ~349 tokens
|
|
132
133
|
```
|
|
133
134
|
|
|
134
|
-
### 4.
|
|
135
|
+
### 4. Test skill trigger accuracy and assertions (`test`)
|
|
136
|
+
|
|
137
|
+
Verify that your skill description triggers on relevant user prompts, ignores unrelated requests, and respects keyword constraints using a deterministic test suite:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
# Initialize a starter evals/evals.json test suite
|
|
141
|
+
skillforge test ./skills/my-skill --init
|
|
142
|
+
|
|
143
|
+
# Run test cases
|
|
144
|
+
skillforge test ./skills/my-skill
|
|
145
|
+
```
|
|
146
|
+
```text
|
|
147
|
+
Running evals for 'my-skill' (4 test cases)...
|
|
148
|
+
[PASS] trigger_positive_core_my_skill: "Please help me with my-skill following our workflow."
|
|
149
|
+
[PASS] trigger_positive_task: "I need to execute a task: my skill workflow description"
|
|
150
|
+
[PASS] suppress_negative_unrelated_math: "Calculate the Fibonacci sequence for n=30 in Python."
|
|
151
|
+
[PASS] suppress_negative_greeting: "Hello there, what is the weather like in Tokyo today?"
|
|
152
|
+
|
|
153
|
+
Result: PASSED (4/4 passed)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Use `--json` in CI to verify that changes to `description` do not break activation accuracy.
|
|
157
|
+
|
|
158
|
+
### 5. Optimize bloated skills with progressive disclosure (`optimize`)
|
|
159
|
+
|
|
160
|
+
When a skill exceeds the 500-line or 5,000-token progressive disclosure budget (`QUAL-003`), extract heavy reference sections into `references/` while keeping concise pointers in `SKILL.md`:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# Refactor an oversized skill directory in-place
|
|
164
|
+
skillforge optimize ./skills/bloated-api-skill --max-lines 400
|
|
165
|
+
|
|
166
|
+
# Or output to a fresh destination folder
|
|
167
|
+
skillforge optimize ./skills/bloated-api-skill -o ./skills/clean-api-skill
|
|
168
|
+
```
|
|
169
|
+
```text
|
|
170
|
+
Optimized 'bloated-api-skill':
|
|
171
|
+
Lines: 680 -> 240 (440 lines saved)
|
|
172
|
+
Tokens: ~6200 -> ~2100 (4100 tokens saved)
|
|
173
|
+
Extracted References:
|
|
174
|
+
- references/database-guidelines.md
|
|
175
|
+
- references/api-endpoints-manual.md
|
|
176
|
+
Destination: ./skills/clean-api-skill
|
|
177
|
+
Audit Verification: PASSED
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### 6. Convert OpenAPI / Swagger to a portable skill (`import-openapi`)
|
|
181
|
+
|
|
182
|
+
Convert an existing REST API specification (OpenAPI 3.0, 3.1, or Swagger 2.0 in JSON or YAML) into a progressive disclosure skill package without running external scripts:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
skillforge import-openapi ./openapi.yaml --output ./skills
|
|
186
|
+
```
|
|
187
|
+
```text
|
|
188
|
+
Successfully imported 'petstore-api' into skills/petstore-api
|
|
189
|
+
SKILL.md: 28 lines (~320 body tokens)
|
|
190
|
+
endpoints.md reference: ~1850 tokens
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
The resulting package contains an executive overview in `SKILL.md` and detailed endpoint schemas in `references/endpoints.md`, keeping turn-by-turn context overhead low.
|
|
194
|
+
|
|
195
|
+
### 7. Generate an official verified badge (`badge`)
|
|
135
196
|
|
|
136
197
|
Show users that your skill is clean, secure, and audited. Generate an official badge for your skill repository:
|
|
137
198
|
|
|
@@ -142,7 +203,7 @@ skillforge badge ./my-skill
|
|
|
142
203
|
[](https://github.com/gintingism/skillforge)
|
|
143
204
|
```
|
|
144
205
|
|
|
145
|
-
###
|
|
206
|
+
### 8. Grab a skill directly from GitHub (`add`)
|
|
146
207
|
|
|
147
208
|
Pull skills directly from remote Git repositories with security auditing and reproducible commit pinning:
|
|
148
209
|
|
|
@@ -159,7 +220,7 @@ skillforge add gintingism/skillforge:systematic-debugging
|
|
|
159
220
|
|
|
160
221
|
SkillForge fetches the skill, audits its security, routes it to all detected assistant targets, and pins its SHA-256 digest + Git commit SHA into `skillforge.lock`.
|
|
161
222
|
|
|
162
|
-
###
|
|
223
|
+
### 9. Verify skill integrity and detect drift (`verify`)
|
|
163
224
|
|
|
164
225
|
Check installed skills against `skillforge.lock` in CI/CD or local environments without modifying files or making network requests. Detects file tampering, missing dependencies, or unmanaged skills:
|
|
165
226
|
|
|
@@ -177,7 +238,7 @@ skillforge verify --json
|
|
|
177
238
|
Verification PASSED: 2 skill(s) match skillforge.lock.
|
|
178
239
|
```
|
|
179
240
|
|
|
180
|
-
###
|
|
241
|
+
### 10. Compare changes before updating (`diff`)
|
|
181
242
|
|
|
182
243
|
Inspect diffs between local skills and upstream repositories, or compare two skill versions:
|
|
183
244
|
|
|
@@ -186,7 +247,7 @@ skillforge diff ./skills/my-skill
|
|
|
186
247
|
skillforge diff my-skill gintingism/skillforge:my-skill
|
|
187
248
|
```
|
|
188
249
|
|
|
189
|
-
###
|
|
250
|
+
### 11. Manage installed skills (`list` & `remove`)
|
|
190
251
|
|
|
191
252
|
See which skills are active across your editor targets:
|
|
192
253
|
|
|
@@ -208,7 +269,7 @@ To remove a skill from all detected assistants and update your lockfile:
|
|
|
208
269
|
skillforge remove antislop-code
|
|
209
270
|
```
|
|
210
271
|
|
|
211
|
-
###
|
|
272
|
+
### 12. Create and package your own skills (`create` & `pack`)
|
|
212
273
|
|
|
213
274
|
Scaffold a single skill file or a full directory package with scripts and reference docs:
|
|
214
275
|
|
|
@@ -230,7 +291,7 @@ skillforge unpack ./db-migrator.zip --output ./skills
|
|
|
230
291
|
|
|
231
292
|
## 🤖 Automate in CI/CD (GitHub Action)
|
|
232
293
|
|
|
233
|
-
Add SkillForge to your GitHub Actions workflow to audit
|
|
294
|
+
Add SkillForge to your GitHub Actions workflow to audit pull requests, enforce progressive disclosure budgets, and upload SARIF reports to GitHub Code Scanning:
|
|
234
295
|
|
|
235
296
|
```yaml
|
|
236
297
|
name: Audit Agent Skills
|
|
@@ -239,6 +300,9 @@ on: [pull_request, push]
|
|
|
239
300
|
jobs:
|
|
240
301
|
audit:
|
|
241
302
|
runs-on: ubuntu-latest
|
|
303
|
+
permissions:
|
|
304
|
+
security-events: write
|
|
305
|
+
contents: read
|
|
242
306
|
steps:
|
|
243
307
|
- uses: actions/checkout@v4
|
|
244
308
|
- name: Run SkillForge Security & Token Linter
|
|
@@ -247,6 +311,13 @@ jobs:
|
|
|
247
311
|
path: './skills'
|
|
248
312
|
strict: 'true'
|
|
249
313
|
budget: 'true'
|
|
314
|
+
sarif: 'skillforge-findings.sarif'
|
|
315
|
+
|
|
316
|
+
- name: Upload SARIF to GitHub Code Scanning
|
|
317
|
+
uses: github/codeql-action/upload-sarif@v3
|
|
318
|
+
if: always()
|
|
319
|
+
with:
|
|
320
|
+
sarif_file: 'skillforge-findings.sarif'
|
|
250
321
|
```
|
|
251
322
|
|
|
252
323
|
---
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "agent-skillforge"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.2"
|
|
8
8
|
description = "Universal package manager, security auditor, and MCP server for portable agent skills (SKILL.md)."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-skillforge
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: Universal package manager, security auditor, and MCP server for portable agent skills (SKILL.md).
|
|
5
5
|
Author-email: gintingism <gintingism@users.noreply.github.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -148,9 +148,10 @@ What the auditor scans for:
|
|
|
148
148
|
- **Progressive Disclosure Budget (QUAL-003):** Flags `SKILL.md` bodies exceeding 500 lines or ~5,000 tokens so heavy references are moved to `references/`.
|
|
149
149
|
- **Broken Disclosure Pointers (QUAL-004):** Verifies cited `references/...` or `scripts/...` exist.
|
|
150
150
|
|
|
151
|
-
For CI pipelines, pass `--strict` to fail on any warning, or `--
|
|
151
|
+
For CI pipelines, pass `--strict` to fail on any warning, `--json` for automation, or `--sarif` for GitHub Code Scanning:
|
|
152
152
|
```bash
|
|
153
|
-
|
|
153
|
+
# Export standard OASIS SARIF v2.1.0 report
|
|
154
|
+
skillforge audit ./skills/my-new-skill --sarif results.sarif
|
|
154
155
|
```
|
|
155
156
|
|
|
156
157
|
### 3. Profile your project's context token budget (`budget`)
|
|
@@ -169,7 +170,67 @@ Context Budget Profile (22 skills)
|
|
|
169
170
|
Disclosed Resources Cost: ~349 tokens
|
|
170
171
|
```
|
|
171
172
|
|
|
172
|
-
### 4.
|
|
173
|
+
### 4. Test skill trigger accuracy and assertions (`test`)
|
|
174
|
+
|
|
175
|
+
Verify that your skill description triggers on relevant user prompts, ignores unrelated requests, and respects keyword constraints using a deterministic test suite:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
# Initialize a starter evals/evals.json test suite
|
|
179
|
+
skillforge test ./skills/my-skill --init
|
|
180
|
+
|
|
181
|
+
# Run test cases
|
|
182
|
+
skillforge test ./skills/my-skill
|
|
183
|
+
```
|
|
184
|
+
```text
|
|
185
|
+
Running evals for 'my-skill' (4 test cases)...
|
|
186
|
+
[PASS] trigger_positive_core_my_skill: "Please help me with my-skill following our workflow."
|
|
187
|
+
[PASS] trigger_positive_task: "I need to execute a task: my skill workflow description"
|
|
188
|
+
[PASS] suppress_negative_unrelated_math: "Calculate the Fibonacci sequence for n=30 in Python."
|
|
189
|
+
[PASS] suppress_negative_greeting: "Hello there, what is the weather like in Tokyo today?"
|
|
190
|
+
|
|
191
|
+
Result: PASSED (4/4 passed)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Use `--json` in CI to verify that changes to `description` do not break activation accuracy.
|
|
195
|
+
|
|
196
|
+
### 5. Optimize bloated skills with progressive disclosure (`optimize`)
|
|
197
|
+
|
|
198
|
+
When a skill exceeds the 500-line or 5,000-token progressive disclosure budget (`QUAL-003`), extract heavy reference sections into `references/` while keeping concise pointers in `SKILL.md`:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
# Refactor an oversized skill directory in-place
|
|
202
|
+
skillforge optimize ./skills/bloated-api-skill --max-lines 400
|
|
203
|
+
|
|
204
|
+
# Or output to a fresh destination folder
|
|
205
|
+
skillforge optimize ./skills/bloated-api-skill -o ./skills/clean-api-skill
|
|
206
|
+
```
|
|
207
|
+
```text
|
|
208
|
+
Optimized 'bloated-api-skill':
|
|
209
|
+
Lines: 680 -> 240 (440 lines saved)
|
|
210
|
+
Tokens: ~6200 -> ~2100 (4100 tokens saved)
|
|
211
|
+
Extracted References:
|
|
212
|
+
- references/database-guidelines.md
|
|
213
|
+
- references/api-endpoints-manual.md
|
|
214
|
+
Destination: ./skills/clean-api-skill
|
|
215
|
+
Audit Verification: PASSED
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### 6. Convert OpenAPI / Swagger to a portable skill (`import-openapi`)
|
|
219
|
+
|
|
220
|
+
Convert an existing REST API specification (OpenAPI 3.0, 3.1, or Swagger 2.0 in JSON or YAML) into a progressive disclosure skill package without running external scripts:
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
skillforge import-openapi ./openapi.yaml --output ./skills
|
|
224
|
+
```
|
|
225
|
+
```text
|
|
226
|
+
Successfully imported 'petstore-api' into skills/petstore-api
|
|
227
|
+
SKILL.md: 28 lines (~320 body tokens)
|
|
228
|
+
endpoints.md reference: ~1850 tokens
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
The resulting package contains an executive overview in `SKILL.md` and detailed endpoint schemas in `references/endpoints.md`, keeping turn-by-turn context overhead low.
|
|
232
|
+
|
|
233
|
+
### 7. Generate an official verified badge (`badge`)
|
|
173
234
|
|
|
174
235
|
Show users that your skill is clean, secure, and audited. Generate an official badge for your skill repository:
|
|
175
236
|
|
|
@@ -180,7 +241,7 @@ skillforge badge ./my-skill
|
|
|
180
241
|
[](https://github.com/gintingism/skillforge)
|
|
181
242
|
```
|
|
182
243
|
|
|
183
|
-
###
|
|
244
|
+
### 8. Grab a skill directly from GitHub (`add`)
|
|
184
245
|
|
|
185
246
|
Pull skills directly from remote Git repositories with security auditing and reproducible commit pinning:
|
|
186
247
|
|
|
@@ -197,7 +258,7 @@ skillforge add gintingism/skillforge:systematic-debugging
|
|
|
197
258
|
|
|
198
259
|
SkillForge fetches the skill, audits its security, routes it to all detected assistant targets, and pins its SHA-256 digest + Git commit SHA into `skillforge.lock`.
|
|
199
260
|
|
|
200
|
-
###
|
|
261
|
+
### 9. Verify skill integrity and detect drift (`verify`)
|
|
201
262
|
|
|
202
263
|
Check installed skills against `skillforge.lock` in CI/CD or local environments without modifying files or making network requests. Detects file tampering, missing dependencies, or unmanaged skills:
|
|
203
264
|
|
|
@@ -215,7 +276,7 @@ skillforge verify --json
|
|
|
215
276
|
Verification PASSED: 2 skill(s) match skillforge.lock.
|
|
216
277
|
```
|
|
217
278
|
|
|
218
|
-
###
|
|
279
|
+
### 10. Compare changes before updating (`diff`)
|
|
219
280
|
|
|
220
281
|
Inspect diffs between local skills and upstream repositories, or compare two skill versions:
|
|
221
282
|
|
|
@@ -224,7 +285,7 @@ skillforge diff ./skills/my-skill
|
|
|
224
285
|
skillforge diff my-skill gintingism/skillforge:my-skill
|
|
225
286
|
```
|
|
226
287
|
|
|
227
|
-
###
|
|
288
|
+
### 11. Manage installed skills (`list` & `remove`)
|
|
228
289
|
|
|
229
290
|
See which skills are active across your editor targets:
|
|
230
291
|
|
|
@@ -246,7 +307,7 @@ To remove a skill from all detected assistants and update your lockfile:
|
|
|
246
307
|
skillforge remove antislop-code
|
|
247
308
|
```
|
|
248
309
|
|
|
249
|
-
###
|
|
310
|
+
### 12. Create and package your own skills (`create` & `pack`)
|
|
250
311
|
|
|
251
312
|
Scaffold a single skill file or a full directory package with scripts and reference docs:
|
|
252
313
|
|
|
@@ -268,7 +329,7 @@ skillforge unpack ./db-migrator.zip --output ./skills
|
|
|
268
329
|
|
|
269
330
|
## 🤖 Automate in CI/CD (GitHub Action)
|
|
270
331
|
|
|
271
|
-
Add SkillForge to your GitHub Actions workflow to audit
|
|
332
|
+
Add SkillForge to your GitHub Actions workflow to audit pull requests, enforce progressive disclosure budgets, and upload SARIF reports to GitHub Code Scanning:
|
|
272
333
|
|
|
273
334
|
```yaml
|
|
274
335
|
name: Audit Agent Skills
|
|
@@ -277,6 +338,9 @@ on: [pull_request, push]
|
|
|
277
338
|
jobs:
|
|
278
339
|
audit:
|
|
279
340
|
runs-on: ubuntu-latest
|
|
341
|
+
permissions:
|
|
342
|
+
security-events: write
|
|
343
|
+
contents: read
|
|
280
344
|
steps:
|
|
281
345
|
- uses: actions/checkout@v4
|
|
282
346
|
- name: Run SkillForge Security & Token Linter
|
|
@@ -285,6 +349,13 @@ jobs:
|
|
|
285
349
|
path: './skills'
|
|
286
350
|
strict: 'true'
|
|
287
351
|
budget: 'true'
|
|
352
|
+
sarif: 'skillforge-findings.sarif'
|
|
353
|
+
|
|
354
|
+
- name: Upload SARIF to GitHub Code Scanning
|
|
355
|
+
uses: github/codeql-action/upload-sarif@v3
|
|
356
|
+
if: always()
|
|
357
|
+
with:
|
|
358
|
+
sarif_file: 'skillforge-findings.sarif'
|
|
288
359
|
```
|
|
289
360
|
|
|
290
361
|
---
|
|
@@ -12,7 +12,10 @@ src/skillforge/__main__.py
|
|
|
12
12
|
src/skillforge/adapters.py
|
|
13
13
|
src/skillforge/cli.py
|
|
14
14
|
src/skillforge/errors.py
|
|
15
|
+
src/skillforge/evals.py
|
|
15
16
|
src/skillforge/mcp_server.py
|
|
17
|
+
src/skillforge/openapi.py
|
|
18
|
+
src/skillforge/optimizer.py
|
|
16
19
|
src/skillforge/registry.py
|
|
17
20
|
src/skillforge/security.py
|
|
18
21
|
src/skillforge/skill.py
|
|
@@ -43,9 +46,13 @@ tests/test_adapters.py
|
|
|
43
46
|
tests/test_badge.py
|
|
44
47
|
tests/test_builtins.py
|
|
45
48
|
tests/test_cli.py
|
|
49
|
+
tests/test_evals.py
|
|
46
50
|
tests/test_hardening.py
|
|
47
51
|
tests/test_mcp_server.py
|
|
52
|
+
tests/test_openapi.py
|
|
53
|
+
tests/test_optimizer.py
|
|
48
54
|
tests/test_registry.py
|
|
55
|
+
tests/test_sarif.py
|
|
49
56
|
tests/test_security.py
|
|
50
57
|
tests/test_skill.py
|
|
51
58
|
tests/test_verify_and_pinning.py
|
|
@@ -13,7 +13,10 @@ import typer
|
|
|
13
13
|
|
|
14
14
|
from .adapters import detect_adapters
|
|
15
15
|
from .errors import SecurityAuditError, SkillForgeError
|
|
16
|
+
from .evals import init_evals, run_evals
|
|
16
17
|
from .mcp_server import run_mcp_server
|
|
18
|
+
from .openapi import import_openapi
|
|
19
|
+
from .optimizer import optimize_skill
|
|
17
20
|
from .registry import BuiltinRegistry, CompositeRegistry, GitRemoteRegistry, LocalRegistry, Registry
|
|
18
21
|
from .security import Severity, SkillAuditor, audit_path
|
|
19
22
|
from .skill import Skill, SkillPackage
|
|
@@ -61,6 +64,7 @@ def audit(
|
|
|
61
64
|
path: Path,
|
|
62
65
|
strict: bool = typer.Option(False, "--strict", help="Fail on any warning or low-severity finding."),
|
|
63
66
|
json_output: bool = typer.Option(False, "--json", help="Emit machine-readable JSON."),
|
|
67
|
+
sarif_output: Path | None = typer.Option(None, "--sarif", help="Emit OASIS SARIF v2.1.0 report for GitHub Code Scanning."),
|
|
64
68
|
) -> None:
|
|
65
69
|
"""Audit a skill for prompt injection, zero-width unicode, and security issues."""
|
|
66
70
|
try:
|
|
@@ -72,6 +76,12 @@ def audit(
|
|
|
72
76
|
typer.echo(f"Audit error: {exc}", err=True)
|
|
73
77
|
raise typer.Exit(code=1) from exc
|
|
74
78
|
|
|
79
|
+
if sarif_output:
|
|
80
|
+
sarif_output.parent.mkdir(parents=True, exist_ok=True)
|
|
81
|
+
sarif_output.write_text(json.dumps(report.to_sarif(), indent=2), encoding="utf-8")
|
|
82
|
+
if not json_output:
|
|
83
|
+
typer.echo(f"Wrote SARIF report to {sarif_output}")
|
|
84
|
+
|
|
75
85
|
if json_output:
|
|
76
86
|
typer.echo(json.dumps(report.to_dict()))
|
|
77
87
|
else:
|
|
@@ -207,6 +217,111 @@ def unpack(archive: Path, output: Path = typer.Option(Path("."), "--output", "-o
|
|
|
207
217
|
typer.echo(f"Unpacked skill '{package.skill.name}' into {output}")
|
|
208
218
|
|
|
209
219
|
|
|
220
|
+
@app.command("import-openapi")
|
|
221
|
+
def import_openapi_cmd(
|
|
222
|
+
spec_path: Path = typer.Argument(..., help="Path to OpenAPI/Swagger JSON or YAML specification file."),
|
|
223
|
+
output_dir: Path = typer.Option(Path("./skills"), "--output", "-o", help="Destination skills directory."),
|
|
224
|
+
name: str | None = typer.Option(None, "--name", "-n", help="Optional override for skill name."),
|
|
225
|
+
) -> None:
|
|
226
|
+
"""Convert an OpenAPI / Swagger specification into a progressive disclosure skill package."""
|
|
227
|
+
try:
|
|
228
|
+
pkg = import_openapi(spec_path, output_dir, skill_name=name)
|
|
229
|
+
dest = output_dir / pkg.skill.name
|
|
230
|
+
typer.echo(f"Successfully imported '{pkg.skill.name}' into {dest}")
|
|
231
|
+
typer.echo(f" SKILL.md: {pkg.skill.body_lines} lines (~{pkg.skill.body_tokens} body tokens)")
|
|
232
|
+
typer.echo(f" endpoints.md reference: ~{pkg.resource_tokens} tokens")
|
|
233
|
+
except (SkillForgeError, OSError) as exc:
|
|
234
|
+
typer.echo(f"Import error: {exc}", err=True)
|
|
235
|
+
raise typer.Exit(code=1) from exc
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
@app.command("test")
|
|
239
|
+
def test_skill(
|
|
240
|
+
path: Path = typer.Argument(Path("."), help="Path to skill directory or SKILL.md file."),
|
|
241
|
+
init: bool = typer.Option(False, "--init", help="Generate starter evals/evals.json test suite."),
|
|
242
|
+
evals_path: Path | None = typer.Option(None, "--evals", help="Path to custom evals.json test suite file."),
|
|
243
|
+
json_output: bool = typer.Option(False, "--json", help="Emit machine-readable JSON."),
|
|
244
|
+
) -> None:
|
|
245
|
+
"""Run trigger accuracy and output assertions against an evals.json test suite."""
|
|
246
|
+
try:
|
|
247
|
+
if init:
|
|
248
|
+
target_file = init_evals(path)
|
|
249
|
+
typer.echo(f"Initialized eval suite in {target_file}")
|
|
250
|
+
return
|
|
251
|
+
|
|
252
|
+
report = run_evals(path, evals_path=evals_path)
|
|
253
|
+
except (SkillForgeError, OSError) as exc:
|
|
254
|
+
if json_output:
|
|
255
|
+
typer.echo(json.dumps({"passed": False, "error": str(exc)}))
|
|
256
|
+
else:
|
|
257
|
+
typer.echo(f"Eval error: {exc}", err=True)
|
|
258
|
+
raise typer.Exit(code=1) from exc
|
|
259
|
+
|
|
260
|
+
if json_output:
|
|
261
|
+
typer.echo(json.dumps(report.to_dict(), indent=2))
|
|
262
|
+
else:
|
|
263
|
+
typer.echo(f"Running evals for '{report.skill_name}' ({report.total_cases} test cases)...")
|
|
264
|
+
for r in report.results:
|
|
265
|
+
status = "PASS" if r.passed else "FAIL"
|
|
266
|
+
typer.echo(f" [{status}] {r.case_id}: \"{r.prompt[:50]}\"")
|
|
267
|
+
if not r.passed:
|
|
268
|
+
typer.echo(f" Reason: {r.reason}", err=True)
|
|
269
|
+
|
|
270
|
+
status_str = "PASSED" if report.passed else "FAILED"
|
|
271
|
+
typer.echo(f"\nResult: {status_str} ({report.passed_cases}/{report.total_cases} passed)")
|
|
272
|
+
|
|
273
|
+
if not report.passed:
|
|
274
|
+
raise typer.Exit(code=1)
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
@app.command("optimize")
|
|
278
|
+
def optimize_skill_cmd(
|
|
279
|
+
path: Path = typer.Argument(Path("."), help="Path to skill directory or SKILL.md file."),
|
|
280
|
+
output: Path | None = typer.Option(None, "--output", "-o", help="Optional output destination directory."),
|
|
281
|
+
max_lines: int = typer.Option(400, "--max-lines", help="Maximum lines for SKILL.md body."),
|
|
282
|
+
max_tokens: int = typer.Option(4000, "--max-tokens", help="Maximum token count for SKILL.md body."),
|
|
283
|
+
json_output: bool = typer.Option(False, "--json", help="Emit machine-readable JSON."),
|
|
284
|
+
) -> None:
|
|
285
|
+
"""Refactor a bloated SKILL.md into progressive disclosure references."""
|
|
286
|
+
try:
|
|
287
|
+
result = optimize_skill(
|
|
288
|
+
package_dir=path,
|
|
289
|
+
output_dir=output,
|
|
290
|
+
max_lines=max_lines,
|
|
291
|
+
max_tokens=max_tokens,
|
|
292
|
+
)
|
|
293
|
+
except (SkillForgeError, OSError) as exc:
|
|
294
|
+
if json_output:
|
|
295
|
+
typer.echo(json.dumps({"success": False, "error": str(exc)}))
|
|
296
|
+
else:
|
|
297
|
+
typer.echo(f"Optimization error: {exc}", err=True)
|
|
298
|
+
raise typer.Exit(code=1) from exc
|
|
299
|
+
|
|
300
|
+
if json_output:
|
|
301
|
+
typer.echo(json.dumps(result.to_dict(), indent=2))
|
|
302
|
+
return
|
|
303
|
+
|
|
304
|
+
typer.echo(f"Optimized '{result.skill_name}':")
|
|
305
|
+
typer.echo(f" Lines: {result.original_lines} -> {result.optimized_lines} ({result.lines_saved} lines saved)")
|
|
306
|
+
typer.echo(f" Tokens: ~{result.original_tokens} -> ~{result.optimized_tokens} ({result.tokens_saved} tokens saved)")
|
|
307
|
+
|
|
308
|
+
if result.extracted_references:
|
|
309
|
+
typer.echo(" Extracted References:")
|
|
310
|
+
for ref in result.extracted_references:
|
|
311
|
+
typer.echo(f" - {ref}")
|
|
312
|
+
else:
|
|
313
|
+
typer.echo(" No sections required extraction (already within budget).")
|
|
314
|
+
|
|
315
|
+
if result.saved_path:
|
|
316
|
+
typer.echo(f" Destination: {result.saved_path}")
|
|
317
|
+
|
|
318
|
+
status_str = "PASSED" if result.passed_audit else "FAILED"
|
|
319
|
+
typer.echo(f" Audit Verification: {status_str}")
|
|
320
|
+
if result.audit_findings:
|
|
321
|
+
for finding in result.audit_findings:
|
|
322
|
+
typer.echo(f" [Finding] {finding}")
|
|
323
|
+
|
|
324
|
+
|
|
210
325
|
@app.command()
|
|
211
326
|
def search(query: str, registry: Path = typer.Option(Path(".skillforge"), "--registry")) -> None:
|
|
212
327
|
"""Search available skills across local and built-in registries."""
|