fix: save /plan output in workspace (#1381)

This commit is contained in:
Teknium 2026-03-14 21:28:51 -07:00 committed by GitHub
parent ff3473a37c
commit b14a07315b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 44 additions and 31 deletions

View file

@ -2,6 +2,7 @@
import os
from datetime import datetime
from pathlib import Path
from unittest.mock import patch
import tools.skills_tool as skills_tool_module
@ -277,32 +278,34 @@ Generate some audio.
class TestPlanSkillHelpers:
def test_build_plan_path_uses_hermes_home_and_slugifies_request(self, tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
def test_build_plan_path_uses_workspace_relative_dir_and_slugifies_request(self):
path = build_plan_path(
"Implement OAuth login + refresh tokens!",
now=datetime(2026, 3, 15, 9, 30, 45),
)
assert path == tmp_path / "plans" / "2026-03-15_093045-implement-oauth-login-refresh-tokens.md"
assert path == Path(".hermes") / "plans" / "2026-03-15_093045-implement-oauth-login-refresh-tokens.md"
def test_plan_skill_message_can_include_runtime_save_path_note(self, tmp_path):
with patch("tools.skills_tool.SKILLS_DIR", tmp_path):
_make_skill(
tmp_path,
"plan",
body="Save plans under $HERMES_HOME/plans and do not execute the work.",
body="Save plans under .hermes/plans in the active workspace and do not execute the work.",
)
scan_skill_commands()
msg = build_skill_invocation_message(
"/plan",
"Add a /plan command",
runtime_note="Save the markdown plan with write_file to /tmp/plans/plan.md",
runtime_note=(
"Save the markdown plan with write_file to this exact relative path inside "
"the active workspace/backend cwd: .hermes/plans/plan.md"
),
)
assert msg is not None
assert "Save plans under $HERMES_HOME/plans" in msg
assert "Save plans under $HERMES_HOME/plans" not in msg
assert ".hermes/plans" in msg
assert "Add a /plan command" in msg
assert "/tmp/plans/plan.md" in msg
assert ".hermes/plans/plan.md" in msg
assert "Runtime note:" in msg

View file

@ -83,7 +83,7 @@ description: Plan mode skill.
# Plan
Use the current conversation context when no explicit instruction is provided.
Save plans under $HERMES_HOME/plans.
Save plans under the active workspace's .hermes/plans directory.
"""
)
@ -96,7 +96,6 @@ class TestGatewayPlanCommand:
runner = _make_runner()
event = _make_event("/plan Add OAuth login")
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
monkeypatch.setattr(gateway_run, "_resolve_runtime_agent_kwargs", lambda: {"api_key": "***"})
monkeypatch.setattr(
"agent.model_metadata.get_model_context_length",
@ -112,7 +111,9 @@ class TestGatewayPlanCommand:
forwarded = runner._run_agent.call_args.kwargs["message"]
assert "Plan mode skill" in forwarded
assert "Add OAuth login" in forwarded
assert str(tmp_path / "plans") in forwarded
assert ".hermes/plans" in forwarded
assert str(tmp_path / "plans") not in forwarded
assert "active workspace/backend cwd" in forwarded
assert "Runtime note:" in forwarded
@pytest.mark.asyncio

View file

@ -29,14 +29,13 @@ description: Plan mode skill.
# Plan
Use the current conversation context when no explicit instruction is provided.
Save plans under $HERMES_HOME/plans.
Save plans under the active workspace's .hermes/plans directory.
"""
)
class TestCLIPlanCommand:
def test_plan_command_queues_plan_skill_message(self, tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
cli_obj = _make_cli()
with patch("tools.skills_tool.SKILLS_DIR", tmp_path):
@ -49,11 +48,12 @@ class TestCLIPlanCommand:
queued = cli_obj._pending_input.put.call_args[0][0]
assert "Plan mode skill" in queued
assert "Add OAuth login" in queued
assert str(tmp_path / "plans") in queued
assert ".hermes/plans" in queued
assert str(tmp_path / "plans") not in queued
assert "active workspace/backend cwd" in queued
assert "Runtime note:" in queued
def test_plan_without_args_uses_skill_context_guidance(self, tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
cli_obj = _make_cli()
with patch("tools.skills_tool.SKILLS_DIR", tmp_path):
@ -63,4 +63,5 @@ class TestCLIPlanCommand:
queued = cli_obj._pending_input.put.call_args[0][0]
assert "current conversation context" in queued
assert "conversation-plan" in queued
assert ".hermes/plans/" in queued
assert "conversation-plan.md" in queued