Skip to content

fix(config): parse list literals in config set; tolerate string-typed scan roots - #82227

Closed
gtmacdonald wants to merge 1 commit into
NousResearch:mainfrom
gtmacdonald:fix/config-set-list-coercion
Closed

fix(config): parse list literals in config set; tolerate string-typed scan roots#82227
gtmacdonald wants to merge 1 commit into
NousResearch:mainfrom
gtmacdonald:fix/config-set-list-coercion

Conversation

@gtmacdonald

Copy link
Copy Markdown

Symptom

hermes config set desktop.repo_scan_roots '["~/src"]' stores the value as a quoted string, not a list:

desktop:
  repo_scan_roots: '["/Users/me/src"]'

The desktop repo-discovery policy loader (_repo_discovery_policy in tui_gateway/server.py) guards with isinstance(roots, list), so the string fails the check and silently falls back to the default roots: [] — which means "scan all of $HOME". The discovered_repos cache then keeps refilling with every git checkout under the user's home (old coursework, backups, vendored trees), and stale entries keep resurfacing in the desktop Projects sidebar no matter how often the cache is purged. No warning is emitted anywhere; the persisted policy in projects.db (repo_discovery_policy"roots":[]) is the only visible evidence.

Hit this in the wild: configured scan root ignored, 40+ junk repos resurfacing in the picker after every purge.

Fix (both sides of the bug class)

Write side — hermes_cli/config.py set_config_value: values starting with [ / { for non-string-typed keys are parsed with fast_safe_load and stored as real YAML collections. String-typed keys (e.g. display.skin) keep literal text — the existing enum-preservation contract is untouched. Malformed literals stay strings (historical behavior).

Read side — tui_gateway/server.py _repo_discovery_policy: new _coerce_scan_path_list helper heals a string-typed list literal already sitting in user config (logs a warning telling the user to re-save), accepts a bare path string as a one-element list, and only falls back to defaults for genuinely unusable values. Existing broken configs written by older CLI versions stop silently scanning $HOME.

Tests

9 new tests, all asserting behavior contracts (no snapshots):

  • tests/hermes_cli/test_set_config_value.py — list literal → real YAML list; empty list; string-typed default keeps literal text; malformed literal stays a string
  • tests/tui_gateway/test_projects_rpc.py — string literal parsed; bare path → one-element list; real list unchanged; garbage falls back to default; excludes get the same treatment
scripts/run_tests.sh tests/hermes_cli/test_set_config_value.py tests/tui_gateway/test_projects_rpc.py tests/hermes_cli/test_desktop_repo_discovery_config.py
=== Summary: 3 files, 112 tests passed, 0 failed ===

Branch is cut from current upstream/main (73997c4).

…typed scan roots

Two sides of one bug class: `hermes config set desktop.repo_scan_roots
'["~/src"]'` stored the literal as a quoted STRING, and the desktop
repo-discovery policy loader's isinstance-list guard silently discarded
it — falling back to roots=[] (scan all of $HOME). The discovered_repos
cache kept refilling with stale entries and the Projects sidebar showed
long-dead repos no matter how often the cache was purged.

- hermes_cli/config.py set_config_value: values starting with [ or {
  for non-string-typed keys are YAML/JSON-parsed and stored as real
  collections. String-typed keys (display.skin etc.) keep literal text;
  malformed literals stay strings.
- tui_gateway/server.py _repo_discovery_policy: new _coerce_scan_path_list
  parses a string-typed list literal already sitting in user config (with
  a warning), accepts a bare path as a one-element list, and only then
  falls back to defaults — so existing broken configs heal instead of
  silently scanning $HOME.
@teknium1

Copy link
Copy Markdown
Contributor

Resolved via PR #88163 (merged) — hermes config set now parses structured list/dict values (yaml.safe_load, string-typed-key guard respected, conservative trigger). This was an 8-PR duplicate cluster: first submitter was @liuhao1024 (#37460), and the merged base was #59182 (@sam7894604) with authorship preserved; all cluster authors are credited in the PR body. Thanks for taking a run at it!

@teknium1 teknium1 closed this Aug 17, 2026
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard comp/tui Terminal UI (ui-tui/ + tui_gateway/) area/config Config system, migrations, profiles sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades labels Aug 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/cli CLI entry point, hermes_cli/, setup wizard comp/tui Terminal UI (ui-tui/ + tui_gateway/) P2 Medium — degraded but workaround exists 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