@podo/skill-validator 0.0.0-stage → 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Giedrius Jaloveckas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,287 @@
1
- # Temporary Holding Version
1
+ # Skill Validator CLI
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Offline Node 22+ validator for directories containing `SKILL.md`. Uses the
4
+ website's deterministic rules, security heuristics, static package checks, and
5
+ token estimates. No network requests, AI calls, or execution of skill scripts.
6
+
7
+ **Public npm package:** `@podo/skill-validator`. Stable installations should pin
8
+ `0.1.0`; verify its registry publication before installing it.
9
+ The package does not require Cloudsmith or Nexus. Direct npm downloads from the
10
+ target Jenkins agent still need a network/policy check. The source repository
11
+ does not need to move to distribute this package.
12
+
13
+ ## Try locally
14
+
15
+ From the repository root:
16
+
17
+ ```sh
18
+ npm --prefix cli ci
19
+ npm --prefix cli run build
20
+ node cli/dist/cli.js validate cli/test/fixtures/skills/csv-summary
21
+ node cli/dist/cli.js --help
22
+ ```
23
+
24
+ Build an installable tarball with `npm pack` from `cli/`, then install that
25
+ tarball in another project with `npm install -D /absolute/path/to/the.tgz`.
26
+ Both `skill-validator` and `skillval` invoke the same command.
27
+
28
+ ## Install from public npm
29
+
30
+ **After the stable release is published and verified**, pin its exact version:
31
+
32
+ ```sh
33
+ npm install --save-dev --save-exact --ignore-scripts \
34
+ @podo/skill-validator@0.1.0 \
35
+ --registry=https://registry.npmjs.org/
36
+ ./node_modules/.bin/skill-validator validate skills
37
+ ```
38
+
39
+ Commit the manifest and lockfile for reproducible installs. Public consumers need
40
+ no npm credentials. An existing `@podo:registry` mapping takes precedence over the
41
+ default registry; remove an obsolete mapping or explicitly set
42
+ `--@podo:registry=https://registry.npmjs.org/` for this command.
43
+
44
+ The public package and its bundled first-party validator engine are MIT-licensed;
45
+ see [`LICENSE`](LICENSE). Bundled dependency licenses are preserved in
46
+ [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md). This does not change the license
47
+ of the rest of the website repository.
48
+
49
+ ## Commands
50
+
51
+ After installing the package locally:
52
+
53
+ ```sh
54
+ skill-validator validate skills
55
+ skill-validator skills/foo/SKILL.md # validate is the default command
56
+ skill-validator doctor # install/config/discovery diagnostics
57
+ skill-validator rules list # web-only rules are marked [web/live only]
58
+ skill-validator rules explain B4
59
+ skill-validator prompt skills/foo # offline repair prompt, to stdout
60
+ ```
61
+
62
+ With no paths, discovery starts at `skills/` in the current directory if it
63
+ exists, otherwise at the current directory. Paths must stay within the nearest
64
+ Git repository root (or the current directory when outside Git).
65
+
66
+ ### Reports and flags
67
+
68
+ ```sh
69
+ skill-validator validate skills --format json --out report.json
70
+ skill-validator validate skills --format junit,json,markdown --report-dir reports
71
+ skill-validator validate skills --fail-on critical --quiet
72
+ ```
73
+
74
+ - `--format`: comma-separated `text,json,junit,markdown`; default `text`.
75
+ - `--report-dir`: required for multiple formats. Fixed filenames are
76
+ `report.txt`, `report.json`, `junit.xml`, and `report.md`.
77
+ - `--out`: a single-format destination; `-` means stdout. Mutually exclusive
78
+ with `--report-dir`. Outputs must stay inside the repository and outside skill
79
+ directories, so reports cannot overwrite skill source.
80
+ - `--fail-on`: `critical`, `high`, `suggestion`, `info`, or `none`; default `high`.
81
+ - `--quiet`: counts and gate line only in text output; machine formats stay intact.
82
+ - `--config`: explicit config path, otherwise `.skill-validator.json` at repo root.
83
+
84
+ File output creates parent directories and writes atomically. Its short summary
85
+ goes to stderr; stdout JSON/XML is not mixed with logs. Text is uncolored. Text
86
+ and Markdown cap output at 20 findings per skill; JSON and JUnit are complete.
87
+ Destinations inside any skill are refused, including unselected or ignored skills
88
+ and filesystem case aliases. Failed writes remove their owned temporary file and
89
+ leave any existing destination intact.
90
+
91
+ Exit codes:
92
+
93
+ - `0`: no findings meet the configured threshold.
94
+ - `1`: findings fail the gate.
95
+ - `2`: invalid invocation, config, missing skills, incomplete discovery,
96
+ unreadable or refused input, or output I/O failure. A closed stdout/stderr pipe
97
+ exits 2 without an unhandled stack trace and without forcing pending output to
98
+ be truncated.
99
+ - `3`: internal CLI error; prints the version, Node version, and the npm package
100
+ page (the source repository is private, so there is no issue tracker link). Set
101
+ `SKILL_VALIDATOR_DEBUG=1` for a stack trace, which may contain sensitive data.
102
+
103
+ Zero skills is never a successful validation. `doctor` can report zero skills
104
+ without failing because it is diagnostic, not a gate.
105
+
106
+ ## Configuration
107
+
108
+ The default gate is `high`. A team can initially choose `critical` with reviewed
109
+ severity overrides, then tighten the gate after checking real skills:
110
+
111
+ ```json
112
+ {
113
+ "failOn": "critical",
114
+ "ruleSeverities": {
115
+ "TT-003": "high",
116
+ "DE-002": "suggestion"
117
+ },
118
+ "ignore": ["drafts/**"]
119
+ }
120
+ ```
121
+
122
+ Flags override config. Unknown keys, rule IDs, and severity values are errors,
123
+ as are overrides for web/live-only rules (AI-assisted review, URL/registry
124
+ liveness, HP-001): the CLI never reports them, so an override cannot take effect.
125
+ Overrides change visible findings and preserve `originalSeverity` in JSON;
126
+ they do not hide rules. First-party API integrations can legitimately read tokens
127
+ and make requests, which is why the example recalibrates those security rules.
128
+
129
+ `ignore` accepts repo-relative glob patterns and affects **skill discovery only**.
130
+ Each pattern is limited to 1,024 characters and 128 glob operators; invalid or
131
+ unevaluable patterns are configuration errors, not internal crashes.
132
+ It cannot hide files inside a discovered skill. `.git` and `node_modules` are
133
+ excluded at the root of a skill only; nested copies (for example
134
+ `scripts/node_modules`) are scanned and count toward the per-skill limits below.
135
+ Discovery itself never descends into `.git` or `node_modules`. Protect CI configuration with CODEOWNERS/review requirements:
136
+ a PR-controlled threshold can otherwise weaken its own gate.
137
+
138
+ ## Scope and safety
139
+
140
+ - Discovery descends at most four directories below each input root. If any
141
+ eligible directory (not ignored, not `.git`/`node_modules`) lies below that
142
+ limit, the run exits 2 and names it, even when other skills were found, so a
143
+ gate never passes on a partly searched tree. Pass a narrower root, or add
144
+ directories without skills to `ignore`. `doctor` reports them without failing.
145
+ Overlapping inputs are deduplicated, including explicit nested inputs. Nested
146
+ skills stay in their parent bundle so rule A0 can report them. A skill's contents
147
+ are loaded as a complete bundle rather than subject to the discovery depth limit.
148
+ - Symlinks and nonregular skill files are refused. Per-skill limits are 2,000 files,
149
+ 100 MiB total file size, and 5 MiB per text file. Discovery and bundle traversal
150
+ each cap directories at 10,000; discovery counts unique directories, not repeated
151
+ overlapping visits. Bundle nesting is capped at 64.
152
+ - Archives are not CLI inputs. Binary files contribute metadata and size, not
153
+ decoded content. Skills and inputs are never executed.
154
+ - JavaScript `.js`, `.mjs`, and `.cjs` files are decoded and security-scanned with
155
+ the same executable-risk weighting. Malformed frontmatter mappings and eval
156
+ document/case shapes produce findings instead of passing silently or crashing.
157
+ - These checks bound ordinary validation; they are not a sandbox against a
158
+ separate process maliciously changing directories during a scan.
159
+ - Security patterns currently report the first matching occurrence per rule/file.
160
+ A passing result is not proof a skill is safe or effective.
161
+
162
+ The website additionally performs liveness and optional AI review, so its complete
163
+ report can differ. CLI reports explicitly list `ai-review` and `liveness` as not
164
+ run. Static known-hallucinated-package rule HP-002 still runs offline.
165
+
166
+ ### Report contract and privacy
167
+
168
+ JSON has `schemaVersion: 1`, relative paths, stable finding fingerprints, and an
169
+ explicit `gate`. The published package includes
170
+ [`schema/report.schema.json`](schema/report.schema.json). Fingerprints normalize
171
+ line endings and include diagnostic text so separate eval cases stay distinct.
172
+ They exclude line numbers and severity; wording changes can change an identifier.
173
+ They are identifiers, not a baseline feature.
174
+ Legal POSIX names such as colons and newlines retain their identity. A relative
175
+ path that could be read as a Windows drive-absolute or rooted path (a drive letter
176
+ and colon followed by a separator or nothing, or a leading backslash) is prefixed
177
+ with `./`; the prefixed path resolves to the same file. Absolute and `..` paths
178
+ never appear in reports.
179
+
180
+ JUnit includes one failing testcase per blocking finding and an `@summary` case
181
+ per skill. A testcase is named by rule ID; when a rule blocks more than once in
182
+ a skill, the name becomes `<ruleId>:<fingerprint>` so cases stay distinct.
183
+ Advisory findings are neither failures nor fake skipped tests. Counts match the
184
+ gate; timestamps and durations are omitted for stable output.
185
+ XML attribute encoding preserves tabs, newlines, and carriage returns in paths,
186
+ so distinct files do not merge into the same Jenkins testcase identity.
187
+
188
+ Security snippets are omitted from reports and from repair prompts, and common
189
+ credential patterns are redacted from both. This is best-effort, not complete
190
+ secret detection. Prompts still quote other source content (for example
191
+ descriptions and suggested replacements), and reports include skill paths and
192
+ finding text. Treat both as potentially sensitive; use appropriate artifact
193
+ access/retention. Text and Markdown output show control characters in paths as
194
+ visible `\uXXXX` escapes; JSON keeps the exact path.
195
+
196
+ ## Jenkins advisory example
197
+
198
+ **After publishing and verifying direct registry access:** add a separate stage
199
+ to the existing pipeline and preserve all existing checks. The example assumes
200
+ Node 22+ is already available and skills live under `plugins/`; adapt this path
201
+ to the consuming repository. It uses an exact package version without adding
202
+ application dependencies to that repository. A consumer with a package manifest
203
+ can instead commit a pinned devDependency/lockfile and use `npm ci --ignore-scripts`.
204
+
205
+ ```groovy
206
+ stage('Skill Validator (advisory)') {
207
+ steps {
208
+ // Remove stale artifacts before invocation, including crash paths.
209
+ dir('skill-validator-report') { deleteDir() }
210
+ script {
211
+ def status = sh(returnStatus: true, script: '''
212
+ npm exec --yes --ignore-scripts \
213
+ --registry=https://registry.npmjs.org/ \
214
+ --@podo:registry=https://registry.npmjs.org/ \
215
+ --package=@podo/skill-validator@0.1.0 -- \
216
+ skill-validator validate plugins --fail-on none \
217
+ --format junit,json,markdown \
218
+ --report-dir skill-validator-report --quiet
219
+ ''')
220
+ if (status != 0) {
221
+ error("skill-validator input/tool failure (${status}); see log")
222
+ }
223
+ }
224
+ }
225
+ post {
226
+ always {
227
+ archiveArtifacts artifacts: 'skill-validator-report/*', allowEmptyArchive: true
228
+ junit testResults: 'skill-validator-report/junit.xml', allowEmptyResults: false
229
+ }
230
+ }
231
+ }
232
+ ```
233
+
234
+ `--fail-on none` keeps findings advisory; invalid input, failed downloads, and tool
235
+ errors remain blocking. Missing JUnit is an error, not an empty successful run.
236
+ Protect policy files and preserve the marketplace's existing validation stages.
237
+ This example has not yet been executed on a Jenkins agent; it does not establish
238
+ permission to bypass any employer-required registry proxy.
239
+
240
+ ## Development
241
+
242
+ From `cli/`, run `npm ci`, `npm run typecheck`, and `npm test`. The tests build
243
+ the bundle, validate report schemas/JUnit, exercise the exit-code and filesystem
244
+ contracts, and install a packed tarball without runtime dependencies.
245
+ Release-orchestration tests simulate identity/registry/upload responses while
246
+ using real npm packing; they never upload a package or request credentials.
247
+ Also run root typecheck, tests, and build when changing shared engine code.
248
+ The test suite uses Python 3's standard library for XML round-trips and isolated
249
+ OS-level write/pipe fault injection; Python is not a package runtime dependency.
250
+ The repository CI workflow (`.github/workflows/ci.yml`) runs these checks for
251
+ the application, CLI, and server across its OS/Node matrix. It never publishes
252
+ packages or deploys the app.
253
+
254
+ ## Publishing
255
+
256
+ The release script targets **public npm**, not an internal registry, and verifies
257
+ the signed-in account is `podo`. Sign in from your own terminal:
258
+
259
+ ```sh
260
+ npm login --registry=https://registry.npmjs.org/
261
+ npm whoami --registry=https://registry.npmjs.org/
262
+ ```
263
+
264
+ Use npm's browser/2FA flow; never paste credentials into chat or tracked files.
265
+ The script uses existing npm authentication without copying or printing secrets.
266
+ Public publishing requires the account's applicable 2FA or npm-approved automation
267
+ authentication. A successful dry-run is not proof of publishing permission.
268
+
269
+ - `scripts/publish-cli.sh dry-run`: installs build dependencies without lifecycle
270
+ scripts, typechecks, tests, and packs an audited tarball. No authentication,
271
+ registry availability request, or upload; allowed before committing.
272
+ - `scripts/publish-cli.sh test`: requires a clean committed tree and a unique
273
+ prerelease version, then publishes the exact checked tarball with `canary`.
274
+ - `scripts/publish-cli.sh release`: additionally requires a stable version and an
275
+ exact matching `cli-vX.Y.Z` tag on HEAD, then publishes with `latest`.
276
+
277
+ Both publishing modes pin default **and scoped** registries, check identity and
278
+ version availability, and stop on registry errors. An existing exact version is
279
+ not overwritten; use a new version for changed bytes. The packed allowlist is
280
+ only the executable, schema, package metadata, README, license, and dependency
281
+ notices. Inspect the artifact for sensitive material before the first upload.
282
+
283
+ CLI tags are independent of web `vX.Y.Z` tags and do not require a Playground
284
+ deploy. After each release, verify its public access and integrity,
285
+ install it in a clean directory without credentials, and run it on a real Jenkins
286
+ agent before enabling consumer integration. Publication does not establish
287
+ Jenkins compatibility: that remains a separate acceptance check.
@@ -0,0 +1,58 @@
1
+ # Bundled dependency notices
2
+
3
+ The CLI bundles the following third-party software. These notices apply to that
4
+ software; the CLI and its bundled first-party validator engine use the MIT
5
+ license in `LICENSE`. No dependency code has been intentionally modified; the
6
+ build bundles and transforms it for Node.js.
7
+
8
+ ## js-yaml
9
+
10
+ Source: https://github.com/nodeca/js-yaml
11
+
12
+ (The MIT License)
13
+
14
+ Copyright (C) 2011-2015 by Vitaly Puzrin
15
+
16
+ Permission is hereby granted, free of charge, to any person obtaining a copy
17
+ of this software and associated documentation files (the "Software"), to deal
18
+ in the Software without restriction, including without limitation the rights
19
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20
+ copies of the Software, and to permit persons to whom the Software is
21
+ furnished to do so, subject to the following conditions:
22
+
23
+ The above copyright notice and this permission notice shall be included in
24
+ all copies or substantial portions of the Software.
25
+
26
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32
+ THE SOFTWARE.
33
+
34
+ ## picomatch
35
+
36
+ Source: https://github.com/micromatch/picomatch
37
+
38
+ The MIT License (MIT)
39
+
40
+ Copyright (c) 2017-present, Jon Schlinkert.
41
+
42
+ Permission is hereby granted, free of charge, to any person obtaining a copy
43
+ of this software and associated documentation files (the "Software"), to deal
44
+ in the Software without restriction, including without limitation the rights
45
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
46
+ copies of the Software, and to permit persons to whom the Software is
47
+ furnished to do so, subject to the following conditions:
48
+
49
+ The above copyright notice and this permission notice shall be included in
50
+ all copies or substantial portions of the Software.
51
+
52
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
53
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
54
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
55
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
56
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
57
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
58
+ THE SOFTWARE.