opsward.lint#
Schema lint (opsward#17, gap 2): spec and config violations, pass or fail, no score.
diagnose --min-score is the cheap scored gate; lint is the strict one. It runs
every validator over every project skill, and checks the hooks config, and reports each
violation with a repo-relative path. A validator is SkillInfo -> list[str]:
opsward– opsward’s own agentskills.io spec check (validate_skill_spec()), always available;skill– theskillpackage’sskill.validate()(pip install 'opsward[lint]'), which composes its own registered validators;agnixandskillcheck– external linters, run as subprocesses (npm install -g agnix,pip install skillcheck); their JSON diagnostics of levelerrorandwarningbecome findings. opsward does not depend on either, and they are opt-in by name: their rule sets are wider and noisier than the spec check, so a gate on"auto"must not turn red because a machine happens to have one installed.
"auto" (the default) is AUTO_VALIDATORS, each when it is available. A host
can pass any mapping of name to validator instead.
>>> from pathlib import Path
>>> from opsward.base import ScanResult, SkillInfo
>>> sr = ScanResult(Path("repo"), skills=[SkillInfo("Bad_Name", Path("repo/.claude/skills/Bad_Name"),
... has_skill_md=True, frontmatter={"name": "Bad_Name"})])
>>> findings = list(lint(sr, validators={"opsward": opsward_validator}))
>>> findings[0].path, findings[0].source
('.claude/skills/Bad_Name', 'opsward')
Module Attributes
these names, each when it is available. |
|
Diagnostic levels of an external linter that count as findings ( |
|
Seconds an external linter may take on one skill. |
|
name -> (validator, is-it-available). |
|
the same set on every machine. |
|
How to install each optional validator (named in the "not installed" error). |
|
Where Claude Code reads hooks from; a settings file holds hooks only under |
Functions
|
agnix over the skill's directory. |
|
Every spec/config violation in the scanned project, skills first, then hooks. |
|
opsward's own spec check; a skill directory without a SKILL.md is one violation. |
|
Turn |
|
The |
|
skillcheck over the skill's SKILL.md. |
Classes
|
One violation: where (repo-relative), which validator said so, and what. |
- opsward.lint.AUTO_VALIDATORS = ('opsward', 'skill')#
the same set on every machine.
- Type:
What
"auto"runs (each when available)
- opsward.lint.DFLT_EXTERNAL_TIMEOUT = 120#
Seconds an external linter may take on one skill.
- opsward.lint.DFLT_VALIDATORS = 'auto'#
these names, each when it is available.
- Type:
What
validators="auto"means
- opsward.lint.EXTERNAL_FINDING_LEVELS = ('error', 'warning')#
Diagnostic levels of an external linter that count as findings (
infodoes not).
- opsward.lint.HOOKS_FILES = ('hooks.json', 'settings.json', 'settings.local.json')#
Where Claude Code reads hooks from; a settings file holds hooks only under
hooks.
- opsward.lint.INSTALL_HINTS = {'agnix': 'npm install -g agnix', 'skill': "pip install 'opsward[lint]'", 'skillcheck': 'pip install skillcheck'}#
How to install each optional validator (named in the “not installed” error).
- class opsward.lint.LintFinding(path, source, message)[source]#
Bases:
objectOne violation: where (repo-relative), which validator said so, and what.
- opsward.lint.VALIDATORS: dict[str, tuple[Callable[[SkillInfo], list], Callable[[], bool]]] = {'agnix': (<function agnix_validator>, <function _on_path.<locals>.<lambda>>), 'opsward': (<function opsward_validator>, <function <lambda>>), 'skill': (<function skill_package_validator>, <function _skill_package_available>), 'skillcheck': (<function skillcheck_validator>, <function _on_path.<locals>.<lambda>>)}#
name -> (validator, is-it-available).
- Type:
Every known validator
- opsward.lint.lint(scan_result, *, validators='auto')[source]#
Every spec/config violation in the scanned project, skills first, then hooks.
Hooks are read from every file in
HOOKS_FILESthat exists, not only the onescanpicked, so an unparseable or shadowed hooks file is still reported.- Return type:
- opsward.lint.opsward_validator(skill)[source]#
opsward’s own spec check; a skill directory without a SKILL.md is one violation.
- opsward.lint.resolve_validators(spec='auto')[source]#
Turn
"auto","opsward,skill"or a mapping into a name -> validator dict.- Raises:
ValueError – an unknown name, or a named validator that is not installed.
- Return type:
>>> list(resolve_validators("opsward")) ['opsward'] >>> resolve_validators("nope") Traceback (most recent call last): ... ValueError: unknown validator 'nope' (known: opsward, skill, agnix, skillcheck)
- opsward.lint.skill_package_validator(skill)[source]#
The
skillpackage’svalidate()over the skill’s directory.A directory with no SKILL.md is left to
opsward_validator()(skillwould report it again, with an absolute path).
- opsward.lint.skillcheck_validator(skill)[source]#
skillcheck over the skill’s SKILL.md.