f891d702df
Sessions started inside a git checkout now source skills from <root>/.hermes/skills/ and <root>/.agents/skills/ (the cross-tool convention shared with other agent harnesses) as the highest-precedence skill tier: project > local > external_dirs. Loading is trust-gated per repo (skills.trusted_project_dirs, managed by 'hermes skills trust'/'untrust') because skills are executable procedure documents — auto-sourcing them from any cloned repo is a prompt-injection vector. Untrusted repos with skills get a one-line banner notice instead. - agent/skill_utils.py: find_project_root, get_project_skills_dirs, get_untrusted_project_skills_root, get_scan_ordered_skills_dirs; project dirs join the curator read-only ownership boundary - agent/prompt_builder.py: project tier scanned first, entries tagged [project], same-named local entries shadowed; cache key extended - tools/skills_tool.py: skills_list scans project dirs first (first-wins); skill_view resolves cross-tier collisions in favor of the project tier (same-tier ambiguity still refuses); security warning recognizes the tier - agent/skill_commands.py + hermes_cli/commands.py: /skill-name slash commands and gateway slash menus include project skills - tools/credential_files.py: project dirs mounted into remote backends - cli.py: banner notice (loaded count / trust hint) - hermes_cli/main.py + subcommands/skills.py: hermes skills trust/untrust - config: skills.project_discovery (default on), skills.trusted_project_dirs - docs: Project-Local Skills section in skills.md - tests: tests/agent/test_project_skills.py (18 cases) Session cwd is fixed at agent build time, so the resolved tier is stable for the conversation and the system prompt stays byte-stable (cache-safe).