Skip to content

fix: clean up profile clone manifests and slash-command logging - #48290

Open
aniruddhaadak80 wants to merge 1 commit into
NousResearch:mainfrom
aniruddhaadak80:publish/hermes-fixes
Open

fix: clean up profile clone manifests and slash-command logging#48290
aniruddhaadak80 wants to merge 1 commit into
NousResearch:mainfrom
aniruddhaadak80:publish/hermes-fixes

Conversation

@aniruddhaadak80

@aniruddhaadak80 aniruddhaadak80 commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Two fixes to hermes profile create cloning, rebuilt fresh off current main:

  1. Stale bundled-skill manifests after cloning. When a profile is created with --clone-all, skills are copied out of the repo's bundled skills/ tree into <profile>/skills/. The copied .bundled_manifest.json still listed every originally-bundled skill name, including ones stripped by _CLONE_ALL_STRIP (or deleted later), so skills list/sync treated user-visible state as if those skills were still bundled � they could never be "restored" and polluted listings. We now rewrite the manifest post-clone to match what actually landed on disk (frontmatter name: wins over directory name; node_modules/ excluded), preserving the v1 plain-name format so older readers stay compatible. Applies to both clone paths (--clone-all and --clone-config).
  2. Confusing onboarding label: the provider previously titled "Claude Code" is Anthropic OAuth � renamed to "Anthropic OAuth (Claude Code)" in both the web onboarding and desktop providers list.

Related Issue

N/A � reviewer-requested rebuild of #48290 itself.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)

Changes Made

  • hermes_cli/profiles.py: new _read_cloned_bundled_manifest() / _prune_cloned_bundled_manifest() helpers; wired into both clone paths; manifest written atomically via utils.atomic_write_text (tmp_prefix=".bundled_manifest_", mode preserved); reuses tools.skills_sync._discover_bundled_skills via lazy import.
  • hermes_cli/web_server.py + apps/desktop/src/components/onboarding/providers.tsx: claude-code title ? "Anthropic OAuth (Claude Code)".
  • tests/hermes_cli/test_profiles.py: unit tests for the prune helper (frontmatter-name matching, node_modules exclusion, v1-format preservation) + integration tests through both clone paths; two pre-existing 0o600 assertions made Windows-tolerant (file-permission checks that only hold on POSIX).

How to Test

  1. pytest tests/hermes_cli/test_profiles.py -q
  2. Manual: hermes profile create t --clone-all in a checkout whose bundled skills include stripped entries, then inspect <profile>/skills/.bundled_manifest.json � it lists exactly the skills present in <profile>/skills/.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass (59 passed locally; 4 unrelated Windows-local failures reproduce on clean main)
  • I've added tests for my changes
  • I've tested on my platform: Windows 11

Documentation & Housekeeping

  • Documentation � or N/A
  • cli-config.yaml.example � or N/A
  • CONTRIBUTING.md/AGENTS.md � or N/A
  • Cross-platform impact considered (Windows permission assertions gated)
  • Tool descriptions/schemas � or N/A

Screenshots / Logs

N/A.

@alt-glitch alt-glitch added type/bug Something isn't working comp/gateway Gateway runner, session dispatch, delivery comp/cli CLI entry point, hermes_cli/, setup wizard comp/tui Terminal UI (ui-tui/ + tui_gateway/) P3 Low — cosmetic, nice to have labels Jun 18, 2026
@aniruddhaadak80
aniruddhaadak80 marked this pull request as ready for review June 18, 2026 07:11
@alt-glitch

Copy link
Copy Markdown
Collaborator

Related: #48245 and #48288 both implement the slash-command logging portion of this PR (the gateway/run.py logger.info("slash command: ...") line for #48240). This PR overlaps on that fix but also bundles two independent changes — pruning stale .bundled_manifest entries after hermes profile create --clone (hermes_cli/profiles.py) and shortening the Claude Code OAuth display title in desktop onboarding (apps/desktop/*). Flagging the logging overlap so reviewers can decide whether to take the focused #48245 for logging and isolate the profile-clone/desktop fixes here.

@aniruddhaadak80

Copy link
Copy Markdown
Contributor Author

Resolved the slash-command logging overlap by removing that portion from this PR (and its associated tests) to isolate the profile-clone and desktop fixes. Pushed the updates.

@alt-glitch alt-glitch added comp/desktop Electron desktop app (apps/desktop/*) and removed comp/tui Terminal UI (ui-tui/ + tui_gateway/) labels Jun 26, 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 isolating the clone-manifest and provider-title work after the logging overlap was removed.

Problems

  • tests/e2e/test_platform_commands.py:14 adds logging, but the current PR diff contains no use after the logging test was removed.
  • hermes_cli/profiles.py:199 writes .bundled_manifest directly. The existing writer is deliberately atomic at tools/skills_sync.py:150-180; retain that crash-safety for clone cleanup.
  • Current main requires symlinks=True for the skills clone at hermes_cli/profiles.py:1099 (commit b7192b1cb). The older PR copytree call would drop that protection.

Suggested changes

  • Remove the unused import, preserve symlink handling, and port the title/test to the extracted onboarding files (apps/desktop/src/components/onboarding/providers.tsx and index.test.tsx).

Automated hermes-sweeper review.

Comment thread tests/e2e/test_platform_commands.py Outdated
@@ -11,6 +11,7 @@
"""

import asyncio
import logging

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 import is now unused: the slash-command logging test was removed in the follow-up commit, and no remaining code in this file references logging. Please remove it.

Comment thread hermes_cli/profiles.py Outdated

pruned = {name: hash_value for name, hash_value in manifest.items() if name in live_names}
if pruned == manifest:
return

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 keep manifest rewrites atomic. tools/skills_sync.py:150-180 uses a temp file and atomic replacement specifically to avoid leaving .bundled_manifest truncated if the process is interrupted; this direct write reintroduces that failure mode.

Comment thread hermes_cli/profiles.py
@@ -889,7 +955,9 @@ def create_profile(
# same agent capabilities as the source profile.
source_skills = source_dir / "skills"
if source_skills.is_dir():
shutil.copytree(source_skills, profile_dir / "skills", dirs_exist_ok=True)
dest_skills = profile_dir / "skills"

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.

When this is salvaged onto current main, retain symlinks=True on this copytree call. Commit b7192b1 added it to prevent recursive cloning through parent-pointing symlinks.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 14, 2026
@teknium1 teknium1 added the area/profiles Multi-profile isolation, HERMES_HOME scoping label Jul 19, 2026
aniruddhaadak80 added a commit to aniruddhaadak80/hermes-agent that referenced this pull request Aug 23, 2026
…e title

profile create --clone / --clone-all copy the source profile's whole
skills tree including its .bundled_manifest. Bundled skills are re-seeded
per profile only while missing, so manifest entries whose skill no longer
exists keep reporting phantom bundled provenance forever and block the
skill's absence from being treated as a deliberate deletion. Prune those
entries right after the copy using the shared skills-sync discovery rules
(frontmatter names, excluded-path filtering), writing the pruned manifest
through the shared atomic writer so mode bits survive.

Also give the claude-code OAuth catalog entry a readable display name in
the dashboard and desktop onboarding ("Anthropic OAuth (Claude Code)")
instead of leaking the internal eligibility note into the UI, and make
two .env permission assertions Windows-tolerant (no POSIX bits there).

Fixes feedback on NousResearch#48290.
@aniruddhaadak80

Copy link
Copy Markdown
Contributor Author

All four points are addressed in the current head:

  1. Unused import - gone; tests/e2e/test_platform_commands.py is no longer part of the diff.
  2. Atomic manifest write - .bundled_manifest\ pruning now writes through \�tomic_write_text\ (utils) with a temp file + replace, matching the skills_sync crash-safety pattern.
  3. Symlink handling - the skills clone keeps \copytree(..., symlinks=True, dirs_exist_ok=True)\ (b7192b1 semantics preserved).
  4. Onboarding title port - providers.tsx now carries \Anthropic OAuth (Claude Code)\ in the extracted PROVIDER_DISPLAY table.

Verification: 9/9 clone/manifest/prune tests pass on Windows. The 4 remaining test_profiles.py failures on this host (symlink WinError 1314 privilege, POSIX wrapper-script naming, custom-alias .bat suffix) reproduce identically on a clean origin/main worktree - pre-existing Windows-environmental, not introduced here.

…e title

profile create --clone / --clone-all copy the source profile's whole
skills tree including its .bundled_manifest. Bundled skills are re-seeded
per profile only while missing, so manifest entries whose skill no longer
exists keep reporting phantom bundled provenance forever and block the
skill's absence from being treated as a deliberate deletion. Prune those
entries right after the copy using the shared skills-sync discovery rules
(frontmatter names, excluded-path filtering), writing the pruned manifest
through the shared atomic writer so mode bits survive.

Also give the claude-code OAuth catalog entry a readable display name in
the dashboard and desktop onboarding ("Anthropic OAuth (Claude Code)")
instead of leaking the internal eligibility note into the UI, and make
two .env permission assertions Windows-tolerant (no POSIX bits there).

Fixes feedback on NousResearch#48290.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/profiles Multi-profile isolation, HERMES_HOME scoping comp/cli CLI entry point, hermes_cli/, setup wizard comp/desktop Electron desktop app (apps/desktop/*) comp/gateway Gateway runner, session dispatch, delivery 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 type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants