review-fix(comments): restore lost #NNNN rationale comments across non-test source (mechanical sweep, condensed, code unchanged)

For each issue anchor present in BASE 63279301bc non-test .py and absent on HEAD, the BASE comment/docstring block was re-attached at the HEAD location of the code it explained (matched by the distinctive code line / enclosing def). Sentences already covered by an existing HEAD comment were deduped; the issue number always survives. Insert-only: no code lines changed.
This commit is contained in:
Teknium
2026-09-03 09:44:26 -07:00
parent ad62a15e94
commit e83816a4d1
586 changed files with 13883 additions and 829 deletions
+39 -3
View File
@@ -132,16 +132,38 @@ class PluginLoaderMixin:
"""Register a deferred platform's *client* tools without its adapter. Deferring the plugin would
otherwise defer its outbound tools too, so CLI/TUI processes (which never materialize platforms)
would miss them in ``hermes tools`` / ``platform_toolsets``. Opt-in is explicit via ``provides_tools``;
tools live in a ``tools`` submodule so ``__init__`` stays import-light."""
tools live in a ``tools`` submodule so ``__init__`` stays import-light.
A platform plugin can ship two independent things: an inbound adapter (heavy — it imports the
platform SDK) and outbound client tools the agent calls like any other tool. Deferring the plugin
defers both, so in a CLI/TUI process the client tools never register at all: ``resolve_toolset()``
returns ``[]``, the toolset is missing from the ``hermes tools`` checklist, and even an explicit
``platform_toolsets`` entry is dropped because the key is unknown. The same tools work in
gateway/web processes only because those materialize every platform at startup (issue #78050).
Opting in is explicit: the manifest must declare ``provides_tools`` (the field the plugin list and
web server already read to name a plugin's tools, per #78538). Keying off the mere presence of a
``tools.py`` would opt a plugin in by accident — a platform is free to put internal helpers there —
and would leave the contract invisible to anyone reading the manifest. ``tools.py`` remains where
the code is imported from; ``provides_tools`` is what asks for it. A platform that does not declare
the field is untouched and stays fully deferred.
"""
from hermes_cli.plugins import PluginContext, _PLUGINS_DEBUG
if not manifest.provides_tools:
return
lookup_key = manifest_key(manifest)
# Never let a client-tool import break discovery — the platform stays deferred and behaves exactly
# as it did before. But a broken tools.py produces the #78050 symptom itself (declared tools missing
# from the session), so this has to be visible without turning on debug logging to find it. Where it
# failed is the first thing an operator needs: nothing registered points at the import or the module
# body, a partial run points at one tool's definition, and a full run that still raised points past
# the registrations entirely.
declared = list(manifest.provides_tools)
plugin_dir = Path(manifest.path) if manifest.path else None
if plugin_dir is None or not (plugin_dir / "tools.py").is_file():
# Declared but undeliverable — staying quiet reproduces the very symptom this fixes.
logger.warning(
# Staying quiet here reproduces the exact symptom this path exists to fix — tools the
# manifest promises, silently absent from the session (#78050) — so say so.
"Plugin '%s' declares provides_tools %s but has no tools.py; "
"those tools will not be available in CLI/TUI sessions.", lookup_key, declared,
)
@@ -195,7 +217,14 @@ class PluginLoaderMixin:
)
def _warn_python_dependencies(self, manifest: PluginManifest) -> None:
"""Warn about missing declared pip dependencies with an install hint — NEVER auto-install."""
"""Warn about missing declared pip dependencies with an install hint — NEVER auto-install.
See #64165.
python_dependencies is a declaration seam ONLY: Hermes validates and prints the requirements with an
install hint but NEVER auto-installs them. The isolation design (constraints installs vs. vendored
dirs vs. conflict-detection-and-refusal) is an explicitly deferred follow-up — see the round-2
review on #64165 and #15220.
"""
deps = manifest.python_dependencies
if not deps:
return
@@ -212,7 +241,10 @@ class PluginLoaderMixin:
logger.debug("Plugin %s python_dependencies satisfied: %s", key, ", ".join(deps))
def _validate_plugin_config_schema(self, manifest: PluginManifest) -> None:
"""Warn (never block) on plugins.entries.<id> settings that violate config_schema."""
"""Warn (never block) on plugins.entries.<id> settings that violate config_schema.
See #64165.
"""
if not manifest.config_schema:
return
plugin_id = manifest_key(manifest)
@@ -251,6 +283,7 @@ class PluginLoaderMixin:
self._track_tool_override_policy(manifest, module_name)
try:
# Reuse a deferred platform's already-imported package so its body doesn't run twice.
# See #78050.
module = self._predeclared_modules.pop(plugin_key, None)
if module is None and manifest.source in {"user", "project", "bundled"}:
module = self._load_directory_module(manifest, module_name=module_name)
@@ -276,6 +309,9 @@ class PluginLoaderMixin:
logger.warning("Failed to load plugin '%s': %s", manifest.name, exc, exc_info=_PLUGINS_DEBUG)
# The failure path swept this plugin's whole ledger (not just the registration_start slice), so
# discovery-time pre-registrations are gone too.
# There is no live tool left to credit — attribution and the registry agree at zero. Only the
# success path pops _predeclared_tools, so drop the entry here rather than let the bookkeeping
# outlive the load attempt (#78050).
if not loaded.enabled:
self._predeclared_tools.pop(plugin_key, None)
self._plugins[plugin_key] = loaded