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.
Files changed (60) hide show
  1. {agent_skillforge-0.4.1/src/agent_skillforge.egg-info → agent_skillforge-0.4.2}/PKG-INFO +81 -10
  2. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/README.md +80 -9
  3. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/pyproject.toml +1 -1
  4. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2/src/agent_skillforge.egg-info}/PKG-INFO +81 -10
  5. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/agent_skillforge.egg-info/SOURCES.txt +7 -0
  6. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/__init__.py +1 -1
  7. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/cli.py +115 -0
  8. agent_skillforge-0.4.2/src/skillforge/evals.py +230 -0
  9. agent_skillforge-0.4.2/src/skillforge/openapi.py +202 -0
  10. agent_skillforge-0.4.2/src/skillforge/optimizer.py +273 -0
  11. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/security.py +69 -0
  12. agent_skillforge-0.4.2/tests/test_evals.py +95 -0
  13. agent_skillforge-0.4.2/tests/test_openapi.py +82 -0
  14. agent_skillforge-0.4.2/tests/test_optimizer.py +96 -0
  15. agent_skillforge-0.4.2/tests/test_sarif.py +64 -0
  16. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/LICENSE +0 -0
  17. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/setup.cfg +0 -0
  18. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/agent_skillforge.egg-info/dependency_links.txt +0 -0
  19. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/agent_skillforge.egg-info/entry_points.txt +0 -0
  20. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/agent_skillforge.egg-info/requires.txt +0 -0
  21. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/agent_skillforge.egg-info/top_level.txt +0 -0
  22. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/__main__.py +0 -0
  23. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/adapters.py +0 -0
  24. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/agent-observability/SKILL.md +0 -0
  25. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/antislop-code/SKILL.md +0 -0
  26. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/blast-radius-containment/SKILL.md +0 -0
  27. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/caveman/SKILL.md +0 -0
  28. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/cognitive-loop-breaker/SKILL.md +0 -0
  29. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/context-compactor/SKILL.md +0 -0
  30. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/contract-test-generator/SKILL.md +0 -0
  31. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/flaky-test-isolation/SKILL.md +0 -0
  32. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/human-in-the-loop/SKILL.md +0 -0
  33. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/mcp-tool-designer/SKILL.md +0 -0
  34. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/performance-profiler/SKILL.md +0 -0
  35. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/runtime-api-verification/SKILL.md +0 -0
  36. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/secret-sanitizer/SKILL.md +0 -0
  37. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/security-threat-modeler/SKILL.md +0 -0
  38. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/self-improving-agent/SKILL.md +0 -0
  39. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/skill-architect/SKILL.md +0 -0
  40. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/skill-architect/references/mechanics.md +0 -0
  41. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/spec-driven-development/SKILL.md +0 -0
  42. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/summarize/SKILL.md +0 -0
  43. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/supply-chain-sentinel/SKILL.md +0 -0
  44. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/systematic-debugging/SKILL.md +0 -0
  45. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/tavily-search/SKILL.md +0 -0
  46. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/builtin_skills/zero-downtime-migration/SKILL.md +0 -0
  47. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/errors.py +0 -0
  48. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/mcp_server.py +0 -0
  49. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/registry.py +0 -0
  50. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/src/skillforge/skill.py +0 -0
  51. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/tests/test_adapters.py +0 -0
  52. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/tests/test_badge.py +0 -0
  53. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/tests/test_builtins.py +0 -0
  54. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/tests/test_cli.py +0 -0
  55. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/tests/test_hardening.py +0 -0
  56. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/tests/test_mcp_server.py +0 -0
  57. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/tests/test_registry.py +0 -0
  58. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/tests/test_security.py +0 -0
  59. {agent_skillforge-0.4.1 → agent_skillforge-0.4.2}/tests/test_skill.py +0 -0
  60. {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.1
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 `--json` for automation:
151
+ For CI pipelines, pass `--strict` to fail on any warning, `--json` for automation, or `--sarif` for GitHub Code Scanning:
152
152
  ```bash
153
- skillforge audit ./skills/my-new-skill --strict --json
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. Generate an official verified badge (`badge`)
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
  [![Audited by SkillForge](https://img.shields.io/badge/SkillForge-Security%20Passed%20100%2F100-2ea44f?logo=shield&style=flat-square)](https://github.com/gintingism/skillforge)
181
242
  ```
182
243
 
183
- ### 5. Grab a skill directly from GitHub (`add`)
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
- ### 6. Verify skill integrity and detect drift (`verify`)
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
- ### 7. Compare changes before updating (`diff`)
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
- ### 8. Manage installed skills (`list` & `remove`)
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
- ### 9. Create and package your own skills (`create` & `pack`)
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 every Pull Request:
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 `--json` for automation:
113
+ For CI pipelines, pass `--strict` to fail on any warning, `--json` for automation, or `--sarif` for GitHub Code Scanning:
114
114
  ```bash
115
- skillforge audit ./skills/my-new-skill --strict --json
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. Generate an official verified badge (`badge`)
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
  [![Audited by SkillForge](https://img.shields.io/badge/SkillForge-Security%20Passed%20100%2F100-2ea44f?logo=shield&style=flat-square)](https://github.com/gintingism/skillforge)
143
204
  ```
144
205
 
145
- ### 5. Grab a skill directly from GitHub (`add`)
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
- ### 6. Verify skill integrity and detect drift (`verify`)
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
- ### 7. Compare changes before updating (`diff`)
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
- ### 8. Manage installed skills (`list` & `remove`)
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
- ### 9. Create and package your own skills (`create` & `pack`)
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 every Pull Request:
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.1"
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.1
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 `--json` for automation:
151
+ For CI pipelines, pass `--strict` to fail on any warning, `--json` for automation, or `--sarif` for GitHub Code Scanning:
152
152
  ```bash
153
- skillforge audit ./skills/my-new-skill --strict --json
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. Generate an official verified badge (`badge`)
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
  [![Audited by SkillForge](https://img.shields.io/badge/SkillForge-Security%20Passed%20100%2F100-2ea44f?logo=shield&style=flat-square)](https://github.com/gintingism/skillforge)
181
242
  ```
182
243
 
183
- ### 5. Grab a skill directly from GitHub (`add`)
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
- ### 6. Verify skill integrity and detect drift (`verify`)
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
- ### 7. Compare changes before updating (`diff`)
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
- ### 8. Manage installed skills (`list` & `remove`)
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
- ### 9. Create and package your own skills (`create` & `pack`)
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 every Pull Request:
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
@@ -1,3 +1,3 @@
1
1
  """SkillForge: portable skills for AI coding assistants."""
2
2
 
3
- __version__ = "0.4.1"
3
+ __version__ = "0.4.2"
@@ -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."""