Skip to content

fix(profiles,kanban): normalize profile IDs for assignees (salvage of #18518)#19700

Merged
teknium1 merged 2 commits into
mainfrom
hermes/hermes-6c8ebd95
May 4, 2026
Merged

fix(profiles,kanban): normalize profile IDs for assignees (salvage of #18518)#19700
teknium1 merged 2 commits into
mainfrom
hermes/hermes-6c8ebd95

Conversation

@teknium1

@teknium1 teknium1 commented May 4, 2026

Copy link
Copy Markdown
Contributor

Closes #18498. Salvage of @changchun989's PR #18518 onto current main with a follow-up to keep validate_profile_name strict.

Summary

Kanban tasks assigned to a mixed-case profile name (Jules from the dashboard UI, hermes kanban assign ... Librarian from the CLI, etc.) now dispatch correctly. The dispatcher previously crashed with Invalid profile name 'Jules'. Must match [a-z0-9][a-z0-9_-]{0,63} because the assignee was stored verbatim and _default_spawn re-validated it before building the hermes -p <assignee> argv.

Root cause

Profile directories are strictly lowercase (enforced by _PROFILE_ID_RE in hermes_cli/profiles.py), but ingress points (dashboard POST body, CLI args, import archive names) accepted arbitrary casing and stored it verbatim. The dispatcher's validate-then-spawn path exploded on the capital letter.

Approach

  • Commit 1 (@changchun989's cherry-pick): Adds normalize_profile_name() in profiles.py and threads it through every profile entry point — get_profile_dir, profile_exists, check_alias_collision, create_wrapper_script, remove_wrapper_script, create_profile, delete_profile, set_active_profile, export_profile, import_profile, rename_profile, resolve_profile_env — plus kanban's create_task, list_tasks, assign_task, and _default_spawn. Adds _canonical_assignee helper in kanban_db.py.
  • Commit 2 (follow-up): Keeps validate_profile_name strict — it checks input as-given against the regex, rather than silently normalizing. Callers that accept mixed-case user input normalize first, then validate. This keeps validate honest about what the on-disk directory name must look like; inputs like ' jules ' (trailing whitespace) get rejected instead of silently trimmed and accepted. 8 call sites in profiles.py updated to the new order.

Validation

E2E tested with real imports against an isolated HERMES_HOME:

scenario before after
create_task(assignee="Jules") stored Jules stored jules
assign_task(tid, "Librarian") stored Librarian stored librarian
list_tasks(assignee="Jules") no match finds the jules task
_default_spawn argv hermes -p Jules (crash) hermes -p jules
validate_profile_name("Jules") rejected rejected (unchanged)
validate_profile_name("UPPER") rejected rejected (unchanged)

Targeted test runs:

  • tests/hermes_cli/test_profiles.py, tests/hermes_cli/test_kanban_db.py, tests/hermes_cli/test_kanban_core_functionality.py → 268/268 pass
  • tests/tools/test_kanban_tools.py, tests/plugins/test_kanban_dashboard_plugin.py → 73/73 pass

Duplicate PR closed

AUTHOR_MAP

Added changchun989@proton.me -> changchun989 so release.py doesn't choke.

changchun989 and others added 2 commits May 4, 2026 04:41
- Add normalize_profile_name() for lowercase canonical IDs and Default alias
- Use canonical names in create/delete/rename/export/import/set_active paths
- Canonicalize Kanban assignee on create/assign, list filter, and worker spawn
- Tests for mixed-case assignees and profile resolution (fixes #18498)
…irst

Follow-up to @changchun989's cherry-pick: reverts the validate-via-
normalize change so validate_profile_name remains a strict regex check
on the input AS-GIVEN. Callers that accept mixed-case user input
(dashboard UI, CLI args, import flows) call normalize_profile_name()
first, then validate the result. This keeps validate honest about
what the on-disk directory name must look like — e.g. '  jules '
(trailing whitespace) is now rejected instead of silently trimmed
and accepted.

- validate_profile_name: strict lowercase/regex check again, 'UPPER'
  back in the invalid-names parametrize
- 8 call sites in profiles.py (create_profile, delete_profile,
  set_active_profile, export_profile, import_profile, rename_profile,
  resolve_profile_env, plus the clone_from branch): swap the
  normalize-then-validate order
- scripts/release.py: add changchun989@proton.me -> changchun989 to
  AUTHOR_MAP so CI doesn't block on the unmapped contributor email

All kanban + profile tests pass (268 across test_profiles.py +
test_kanban_db.py + test_kanban_core_functionality.py, plus 73 in
test_kanban_tools.py + test_kanban_dashboard_plugin.py).

Closes #18498.
@teknium1 teknium1 merged commit ae40fca into main May 4, 2026
7 of 10 checks passed
@teknium1 teknium1 deleted the hermes/hermes-6c8ebd95 branch May 4, 2026 11:44
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/cli CLI entry point, hermes_cli/, setup wizard comp/plugins Plugin system and bundled plugins labels May 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Kanban dispatcher fails to claim tasks assigned to "jules" due to case sensitivity in profile validation

3 participants