Skip to content

feat(skills): inventory and audit effective skill roots - #64244

Open
mudrii wants to merge 1 commit into
NousResearch:mainfrom
mudrii:feat/skill-inventory-audit
Open

feat(skills): inventory and audit effective skill roots#64244
mudrii wants to merge 1 commit into
NousResearch:mainfrom
mudrii:feat/skill-inventory-audit

Conversation

@mudrii

@mudrii mudrii commented Jul 14, 2026

Copy link
Copy Markdown

Summary

  • add hermes skills inventory with table and machine-readable JSON output
  • classify active, disabled, archived, quarantined, external, symlinked, and shadowed skills
  • extend hermes skills audit --all-active across effective external roots while deduplicating symlink targets
  • propagate meaningful CLI exit codes and raise the default security-audit failure threshold to high

Why

Auditing only the stock profile directory misses effectively active skills supplied through external roots and symlinks. Operators need one deterministic inventory of the actual skill surface and an audit mode that scans each active target exactly once.

Verification

  • /Users/mudrii/.hermes/hermes-agent/venv/bin/python -m pytest -q tests/hermes_cli/test_security_audit.py tests/hermes_cli/test_skills_hub.py tests/hermes_cli/test_skills_subparser.py
  • 60 passed, 0 failed
  • ruff check passed
  • git diff --check passed

Copilot AI review requested due to automatic review settings July 14, 2026 06:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a deterministic “effective skills” inventory and extends hermes skills audit to optionally scan all effectively active skills across local roots, external roots, and symlinks. It also adjusts CLI exit-code behavior and raises the default hermes security audit --fail-on threshold to high so non-critical findings can still gate automation when desired.

Changes:

  • Add hermes skills inventory (table + --json) and new inventory implementation (hermes_cli/skills_inventory.py).
  • Extend hermes skills audit with --all-active to scan effectively active skills across external roots and symlinks.
  • Raise default OSV audit failure threshold to high and add parser/tests to confirm defaults.

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/hermes_cli/test_skills_subparser.py Adds parser coverage for skills inventory and skills audit --all-active.
tests/hermes_cli/test_skills_hub.py Adds behavioral tests for inventory classification and all-active audit output.
tests/hermes_cli/test_security_audit.py Adds coverage for the new default --fail-on high behavior and help text.
hermes_cli/subcommands/skills.py Adds skills inventory subcommand and skills audit --all-active flag.
hermes_cli/subcommands/security.py Updates security audit --fail-on default to high and help text.
hermes_cli/skills_inventory.py New module implementing inventory collection + rendering/JSON output.
hermes_cli/skills_hub.py Wires inventory, adds --all-active audit mode, and returns exit codes from skills_command.
hermes_cli/security_audit.py Updates runtime default fail_on fallback from critical to high.
hermes_cli/main.py Exits with the non-zero return code from skills_command.
.gitignore Ignores .hardening-task.txt.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +87 to +91
def _iter_status_skill_files(status_root: Path):
if not status_root.is_dir():
return
for skill_md in sorted(status_root.rglob("SKILL.md")):
yield skill_md
Comment thread hermes_cli/skills_hub.py
Comment on lines 1145 to +1148
targets = [e for e in installed if e["name"] == name]
if not targets:
c.print(f"[bold red]Error:[/] '{name}' is not a hub-installed skill.\n")
return
return 0
Comment thread hermes_cli/skills_hub.py
Comment on lines +1096 to +1105
report = collect_skill_inventory()
active_entries = [e for e in report["entries"] if e["active"]]
if name:
active_entries = [e for e in active_entries if e["name"] == name]
if not active_entries:
c.print(f"[bold red]Error:[/] '{name}' is not an active skill.\n")
return 1

skipped = report["counts"]["total"] - len(active_entries)
c.print(f"\n[bold]Auditing {len(active_entries)} active skill(s)...[/]\n")
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/cli CLI entry point, hermes_cli/, setup wizard tool/skills Skills system (list, view, manage) labels Jul 14, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing an actual gap: current main audits only HubLockFile entries (hermes_cli/skills_hub.py:1074-1103) even though the runtime indexes configured external roots (agent/prompt_builder.py:1580-1613).

Problems

  • hermes_cli/skills_hub.py:1147-1148 prints an error for a requested missing hub skill but returns 0. The new cmd_skills() propagation at hermes_cli/main.py:12779-12781 means scripts still see success. Return a nonzero status and cover it.
  • hermes_cli/skills_hub.py:1122 supplies local/external as the scanner source. tools/skills_guard.py:651-657,1102-1128 derives trust from this value, so these labels become community; the existing hub path preserves the installed identifier at hermes_cli/skills_hub.py:1161. Preserve available provenance or represent it as unknown rather than changing trust classification.
  • The new default high at hermes_cli/subcommands/security.py:42 conflicts with website/docs/reference/cli-commands.md:485, which documents critical. The new skills commands also need documentation.

Suggested changes

  • Add an exit-code regression test, preserve scan provenance, and update the relevant CLI/skills documentation.

Automated hermes-sweeper review.

Comment thread hermes_cli/skills_hub.py
if not targets:
c.print(f"[bold red]Error:[/] '{name}' is not a hub-installed skill.\n")
return
return 0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an explicit user error, but it returns 0. Since cmd_skills() now forwards nonzero results to the process exit status, automation invoking hermes skills audit missing-name will incorrectly report success; return 1 and add a regression test.

Comment thread hermes_cli/skills_hub.py
if entry.get("symlinked"):
c.print(f"[dim] real path: {entry['real_path']}[/]")
try:
result = scan_skill(skill_path, source=entry.get("source", "active"))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scan_skill() derives trust from source; local and external resolve to community. That loses the HubLockFile identifier provenance used by the existing audit path and can misreport trusted or official installed skills. Preserve known provenance or explicitly model unknown provenance before scanning.

audit_parser.add_argument(
"--fail-on",
default="critical",
default="high",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update website/docs/reference/cli-commands.md, which still documents critical as the default for hermes security audit --fail-on.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data tool/skills Skills system (list, view, manage) type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants