fix(kanban): expand ~ in external_dirs against real user home, not $HOME - #25
Conversation
|
Warning Review limit reached
More reviews will be available in 34 minutes and 30 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📥 CommitsReviewing files that changed from the base of the PR and between 5fad4ec050102c0566c5b897092d7d99a2cb38db and 0155fff. 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR fixes skill directory resolution to use the real OS user home directory instead of the ChangesSkill home resolution against real OS user
Possibly related PRs
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🔎 Lint report:
|
|
auto-review: changes requested.
All other rules pass: U1-U4 clean, C2 (no new type: ignore / cast), C4 (tests added), S2/S3 clean. |
5fad4ec to
8818948
Compare
|
auto-review: changes requested. Blocking findings
All other rules passedU1-U4, U5 (UNSTABLE = non-required only, MERGEABLE), C2 (no new type: ignore / cast()), C3 (ruff enforcement: SUCCESS), C4 (tests touched), U3 (no secrets), S2 (no system leaks). |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@hermes_cli/kanban_db.py`:
- Line 3542: Replace the manual fallback that builds "~/.hermes" when
hermes_home is falsy with a call to get_hermes_home() from hermes_constants so
the code becomes profile-aware: instead of using (_P(_real_user_home()) /
".hermes") as the else branch, call get_hermes_home() and wrap its result with
_P as needed; update the expression that sets base (currently using hermes_home)
to use _P(hermes_home) if hermes_home else _P(get_hermes_home()), referencing
hermes_home and get_hermes_home() to locate the change.
- Line 76: Move the platform-specific pwd usage behind a guarded import and
broaden exception handling: remove the top-level "import pwd" and instead import
pwd inside _real_user_home(), catching (AttributeError, KeyError, OSError)
around pwd.getpwuid(os.getuid()) so Windows or lookup failures don't raise at
module import; and in _resolve_skill_under_home() replace the hermes_home is
None fallback that uses (_real_user_home() / ".hermes") with a call to
hermes_constants.get_hermes_home() (or accept and use the str(get_hermes_home())
value passed from _validate_task_skills(..., _worker_home) when claimed.assignee
is falsy) to ensure Hermes-home is resolved via hermes_constants consistently
and profile-safe.
In `@tests/hermes_cli/test_kanban_db.py`:
- Around line 3765-3802: The test imports the Unix-only pwd module directly and
will fail on Windows; update the
test_resolves_tilde_in_external_dirs_despite_fake_home method (or the test
class) to guard for platforms by calling pytest.importorskip("pwd") at the start
of the test (or add a class-level pytest.mark.skipif using sys.platform), then
proceed to use pwd only when present; ensure references to kb._real_user_home()
and kb._resolve_skill_under_home("kanban-worker", ...) remain unchanged so the
behavior is validated only on supported platforms.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 35d10079-9180-48cb-ab9e-9f8743b38e81
📥 Commits
Reviewing files that changed from the base of the PR and between 38fd1d8 and 5fad4ec050102c0566c5b897092d7d99a2cb38db.
📒 Files selected for processing (2)
hermes_cli/kanban_db.pytests/hermes_cli/test_kanban_db.py
| @@ -3523,7 +3539,7 @@ def _resolve_skill_under_home(skill_name: str, hermes_home: Optional[str]) -> bo | |||
| if not skill_name: | |||
| return True | |||
|
|
|||
| base = _P(hermes_home) if hermes_home else (_P.home() / ".hermes") | |||
| base = _P(hermes_home) if hermes_home else (_P(_real_user_home()) / ".hermes") | |||
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
Use get_hermes_home() for Hermes-home fallback.
When hermes_home is None, constructing ~/.hermes directly bypasses the project’s profile-aware Hermes-home resolver.
💡 Suggested fix
- base = _P(hermes_home) if hermes_home else (_P(_real_user_home()) / ".hermes")
+ if hermes_home:
+ base = _P(hermes_home)
+ else:
+ from hermes_constants import get_hermes_home
+ base = _P(str(get_hermes_home()))As per coding guidelines, "Use get_hermes_home() from hermes_constants for all code paths that reference the Hermes home directory to ensure profile-aware behavior."
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| base = _P(hermes_home) if hermes_home else (_P(_real_user_home()) / ".hermes") | |
| if hermes_home: | |
| base = _P(hermes_home) | |
| else: | |
| from hermes_constants import get_hermes_home | |
| base = _P(str(get_hermes_home())) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@hermes_cli/kanban_db.py` at line 3542, Replace the manual fallback that
builds "~/.hermes" when hermes_home is falsy with a call to get_hermes_home()
from hermes_constants so the code becomes profile-aware: instead of using
(_P(_real_user_home()) / ".hermes") as the else branch, call get_hermes_home()
and wrap its result with _P as needed; update the expression that sets base
(currently using hermes_home) to use _P(hermes_home) if hermes_home else
_P(get_hermes_home()), referencing hermes_home and get_hermes_home() to locate
the change.
| def test_resolves_tilde_in_external_dirs_despite_fake_home(self, tmp_path, monkeypatch): | ||
| """The core bug: config has ``~/.hermes/skills`` (tilde-prefixed) and the | ||
| caller's HOME is set to a sandbox path. The resolver must use the real | ||
| user home from pwd, not $HOME.""" | ||
| import pwd as _pwd | ||
|
|
||
| real_home = _pwd.getpwuid(os.getuid()).pw_dir | ||
|
|
||
| # Build the profile home under the real user home (mirrors real usage). | ||
| profile_home = tmp_path / "profiles" / "bt-optimizer" | ||
| profile_home.mkdir(parents=True) | ||
| (profile_home / "skills").mkdir() | ||
|
|
||
| # Shared skills dir with the skill. | ||
| shared_skills = tmp_path / "shared-skills" | ||
| self._write_skill(shared_skills, "kanban-worker") | ||
|
|
||
| # Config uses tilde — exactly the pattern the bug broke. | ||
| # We can't use the real ~/.hermes/skills path because that would | ||
| # resolve correctly even with the old code (real dir exists). | ||
| # Instead, write the config with the absolute path of shared_skills | ||
| # prefixed by the fake real_home replacement. The simplest | ||
| # end-to-end test is to use the shared_skills absolute path | ||
| # directly in external_dirs (already tested in the other class) | ||
| # and separately test that the tilde-expansion helper itself | ||
| # returns the real home regardless of $HOME. | ||
| fake_home = str(tmp_path / "fake_home") | ||
| monkeypatch.setenv("HOME", fake_home) | ||
|
|
||
| # _real_user_home must ignore $HOME and return the actual home. | ||
| assert kb._real_user_home() == real_home | ||
|
|
||
| # And the resolver must find the skill when external_dirs uses an | ||
| # absolute path (sanity check that fake HOME doesn't break absolute paths). | ||
| (profile_home / "config.yaml").write_text( | ||
| f"skills:\n external_dirs:\n - {shared_skills}\n", encoding="utf-8", | ||
| ) | ||
| assert kb._resolve_skill_under_home("kanban-worker", str(profile_home)) is True |
There was a problem hiding this comment.
Add platform compatibility guard for Unix-only pwd module.
Both tests in this class import pwd (lines 3769, 3807), which is Unix-only and will cause test failures on Windows. The production code has a fallback when pwd is unavailable, but these tests explicitly call pwd.getpwuid().
✅ Add pytest skip marker
Add at the class level:
+@pytest.mark.skipif(not hasattr(__import__('pwd', fromlist=['']), 'getpwuid'), reason="Requires pwd module (Unix only)")
class TestResolveSkillUnderHomeCrossProfile:
"""Regression for the HOME-sandbox mis-expansion bug (2026-05-26).Or use pytest.importorskip("pwd") at the start of each test method.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/hermes_cli/test_kanban_db.py` around lines 3765 - 3802, The test
imports the Unix-only pwd module directly and will fail on Windows; update the
test_resolves_tilde_in_external_dirs_despite_fake_home method (or the test
class) to guard for platforms by calling pytest.importorskip("pwd") at the start
of the test (or add a class-level pytest.mark.skipif using sys.platform), then
proceed to use pwd only when present; ensure references to kb._real_user_home()
and kb._resolve_skill_under_home("kanban-worker", ...) remain unchanged so the
behavior is validated only on supported platforms.
|
auto-review: changes requested.
All other rules passed: U1-U5, C2, C3 (ruff: SUCCESS), C4, S2, S3. |
8818948 to
9bfbe76
Compare
|
auto-review (run 235): changes requested.
All other rules passed: U1, U2, U3, U4, U5 (UNSTABLE/MERGEABLE), C2, C3 (ruff+ty SUCCESS), C4, S2, S3. |
_resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass.
9bfbe76 to
0155fff
Compare
|
auto-review: approved, awaiting human merge + kanban_approve. All rules pass (run 237):
Fix is correct: lazy |
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
…OME (#25) _resolve_skill_under_home() used os.path.expanduser() which expands ~ against the calling process's HOME env var. When the kanban dispatcher runs inside a profile-sandboxed orchestrator (HOME overridden to ~/.hermes/profiles/<orch>/home/), validating another profile's skills.external_dirs config mis-expands the path and returns False even when the skill is present. Fix: - Add _real_user_home() helper using pwd.getpwuid(os.getuid()).pw_dir (unaffected by HOME env var) - Use _real_user_home() when expanding ~ in external_dirs entries - Use _real_user_home() in the None-hermes_home fallback (was Path.home() which also reads HOME) Root cause of t_da084aa4 crashing 3x with 'Unknown skill(s): kanban-worker'. The bt-optimizer / braintrusteng profiles had their external_dirs set to ~/.hermes/skills; the dispatcher running from the orchestrator's sandboxed HOME failed to find kanban-worker and aborted worker spawn. Tests: add TestResolveSkillUnderHomeCrossProfile (2 tests) — simulate cross-profile call with fake HOME, assert both _real_user_home() and _resolve_skill_under_home() return correct results. 196/196 kanban_db tests pass. Co-authored-by: Sahil (AI) <266772320+sahilm-ai@users.noreply.github.com>
Problem
_resolve_skill_under_home()inhermes_cli/kanban_db.pyexpanded~paths in a profile's
skills.external_dirsconfig usingos.path.expanduser(), which reads the calling process'sHOMEenv var.When the kanban dispatcher runs inside a profile-sandboxed orchestrator
(where
HOMEis rewritten to~/.hermes/profiles/<orch>/home/),cross-profile skill validation mis-expands the path and returns
Falseeven when the skill is present.
Real-world impact:
t_da084aa4(Synapse investigation, bt-optimizer)crashed 3 times with
Error: Unknown skill(s): kanban-worker. Blocked theinvestigation for ~3.5 hours. Workaround was changing all 3 BrainTrust
profile configs'
external_dirsto absolute paths.Fix
_real_user_home()helper usingpwd.getpwuid(os.getuid()).pw_dir—unaffected by
HOMEenv var.os.path.expanduser(entry)in_resolve_skill_under_home()'sexternal_dirs loop with a manual tilde substitution using
_real_user_home().None-hermes_home fallback (wasPath.home()which also readsHOME).Tests
TestResolveSkillUnderHomeCrossProfilewith 2 tests:test_resolves_tilde_in_external_dirs_despite_fake_home: verifies_real_user_home()returns the real home whenHOMEis faked, andthat absolute external_dirs entries still work.
test_resolves_tilde_entry_with_fake_home: writes the config entry as~/<unique-subdir>, overridesHOMEto a fake path, asserts theresolver correctly finds the skill via the real home.
test_kanban_db.pytests pass.Follow-up
Profile configs in
~/.hermes/profiles/*/config.yamlthat were converted toabsolute paths as a workaround can be reverted to
~/.hermes/skillsoncethis lands.
Summary by CodeRabbit