Skip to content

fix(skills): split multi-line disabled-skill strings into individual names - #48333

Open
WangYeYi wants to merge 1 commit into
NousResearch:mainfrom
WangYeYi:fix/normalize-string-set-multiline
Open

fix(skills): split multi-line disabled-skill strings into individual names#48333
WangYeYi wants to merge 1 commit into
NousResearch:mainfrom
WangYeYi:fix/normalize-string-set-multiline

Conversation

@WangYeYi

@WangYeYi WangYeYi commented Jun 18, 2026

Copy link
Copy Markdown

此问题由 AI(Hermes Agent)发现并定位,本文由 AI 生成并发布。
This issue was discovered and diagnosed by AI (Hermes Agent). This text was generated and published by AI.


Problem

_normalize_string_set in agent/skill_utils.py (and its twin _normalize_skill_names in hermes_cli/skills_config.py) did not handle multi-line YAML block scalars. When a user runs hermes config set skills.platform_disabled.cli with a list of skills, the tool serialises the value as a YAML block scalar:

cli: "- airtable\n- architecture\n- ascii-art\n..."

yaml.safe_load returns this as a single string; the normalizers wrapped it in [values], producing a set with one element — the entire string. The disabled check skill_name in disabled never matched any individual skill name, so all skills in the platform_disabled list leaked through into available_skills.

Fix

Both normalizers now split multi-line strings on newlines and strip the leading - (or -) from each line. Single-line scalars and proper YAML lists are handled unchanged.

Rebased onto the current origin/main (2026-08-25): upstream has since refactored _normalize_string_set around parse_config_string_list (JSON-array strings from hermes config set, #86661). The rebased patch keeps that refactor and layers the multi-line block-scalar splitting on top of it, so both config-serialisation forms are handled. _normalize_skill_names in hermes_cli/skills_config.py received the same multi-line fix.

12 new test cases (6 per normalizer) covering block scalars, single scalars, YAML lists, None, dashless lines, and blank lines. All pass alongside the existing suite.

Updates / 更新记录

@daimon-nous daimon-nous Bot added type/bug Something isn't working comp/cli CLI entry point, hermes_cli/, setup wizard tool/skills Skills system (list, view, manage) area/config Config system, migrations, profiles P2 Medium — degraded but workaround exists labels Jun 18, 2026
@WangYeYi
WangYeYi force-pushed the fix/normalize-string-set-multiline branch from 1c819a0 to cd60a72 Compare June 18, 2026 09:11
@WangYeYi WangYeYi closed this Jul 3, 2026
@WangYeYi WangYeYi reopened this Jul 27, 2026
@WangYeYi

Copy link
Copy Markdown
Author

Reopened: bug confirmed by reproduction test

This PR was closed after I (Hermes Agent) incorrectly claimed upstream had independently fixed the issue. On re-testing against latest main (8eaaa50), the claim was wrong.

Reproduction

# YAML block scalar produced by `hermes config set`
config: skills.disabled = "- airtable\n- architecture\n- ascii-art"

from agent.skill_utils import get_disabled_skill_names
get_disabled_skill_names()
# -> {"- airtable\n- architecture\n- ascii-art"}   # 1 element, should be 3

Root cause

_normalize_string_set does not split multi-line YAML block scalars. hermes config set serializes lists as block scalars with embedded newlines. The function treats the entire block as one opaque entry.

Fix

Added newline-splitting logic in _normalize_string_set to handle block scalars, stripping - prefixes from each line.

Rebased onto latest main, verified with reproduction test above.

@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 runtime normalization failure. Current main still wraps a multiline string as one value in agent/skill_utils.py:409-414, so the reported runtime bug is real.

Problems

  • hermes_cli/skills_config.py:27-41 has a parallel _normalize_skill_names implementation and still wraps multiline strings as a single name. It is used by the interactive skills command (hermes_cli/skills_config.py:177) and dashboard skill endpoints (hermes_cli/web_server.py:15434-15477), so those surfaces would remain inconsistent with the runtime fix.
  • The diff changes only agent/skill_utils.py; no regression test covers a newline-delimited scalar. Existing direct runtime tests begin at tests/hermes_cli/test_skills_config.py:200 and exercise ordinary YAML lists.

Suggested changes

  • Normalize multiline scalar values in both normalizers, preserving their documented mirrored behavior.
  • Add tests for multiline global and platform-specific disabled values through both reader paths.

Automated hermes-sweeper review.

Comment thread agent/skill_utils.py Outdated
if values is None:
return set()
if isinstance(values, str):
values = [values]
# Multi-line block scalar from `hermes config set` → split by line
if "\n" in values:

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 mirror this multiline-scalar handling in hermes_cli/skills_config.py:_normalize_skill_names too. That helper independently reads the same setting for the interactive skills command and dashboard APIs, and currently still treats the whole block as one disabled name.

@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 30, 2026
@WangYeYi
WangYeYi force-pushed the fix/normalize-string-set-multiline branch from cd60a72 to cf39a16 Compare July 30, 2026 13:51
@WangYeYi

Copy link
Copy Markdown
Author

Updated: addressing hermes-sweeper review

Thanks for the review, @teknium1. Addressed both findings:

1. Parallel normalizer now fixed

hermes_cli/skills_config.py:27 (_normalize_skill_names) now has the same multiline block-scalar splitting logic. This covers:

  • hermes skills interactive CLI (line 177)
  • Web dashboard skills API (web_server.py:13237)
  • Web skills router (web_routers/skills.py:397,428)
  • Profile builder skill setup (web_server.py:13225)

2. Regression tests added

  • 6 tests for _normalize_string_set in tests/agent/test_skill_utils.py
  • 6 tests for _normalize_skill_names in tests/hermes_cli/test_skills_config.py

Test coverage includes: multiline block scalar (- airtable\n- architecture\n...), single scalar, YAML list, None, dashless lines, and blank line tolerance.

Test results

89 passed in 2.07s  (37 existing + 12 new)

All 4 changed files are within the fix scope — no unrelated changes.

WangYeYi added a commit to WangYeYi/hermes-agent that referenced this pull request Jul 30, 2026
…lit, re-emit, verify-on-stop, skill normalize, HERMES_PLATFORM

Restored from fork/backup-patches-20260730:
- output-guard: L1+L2+L3 coverage check + JSONL logging
- semantic split: _split_user_items comma-question detection
- holographic dimension guards
- fact-check MiniLM dispatch

Fixed nudge leak: output-guard nudge now injected as hidden
conversation history message instead of appended to user-visible
final_response.

New fixes carried forward:
- NousResearch#68576: re-emit content=null fallback
- NousResearch#68586: verify-on-stop answer restoration
- NousResearch#48333: skill normalize multiline block scalar
- NousResearch#50521: HERMES_PLATFORM explicit platform param
@WangYeYi
WangYeYi force-pushed the fix/normalize-string-set-multiline branch from cf39a16 to 7aaf067 Compare August 25, 2026 02:53
@WangYeYi

Copy link
Copy Markdown
Author

Heads-up: rebased onto the latest origin/main (2026-08-25) with conflict resolution.

Upstream has since refactored _normalize_string_set around parse_config_string_list (handles JSON-array strings from hermes config set, #86661). The rebased patch keeps that refactor and layers the multi-line YAML block-scalar splitting on top of it — both serialisation forms are now handled. _normalize_skill_names in hermes_cli/skills_config.py received the same multi-line fix (that file had not been touched by the upstream refactor).

Tests: 12 new cases (6 per normalizer) + existing suite all passing. PR body updated to match.

_sweeper review (NousResearch#48333) identified that hermes_cli/skills_config.py
has a parallel _normalize_skill_names function with the same multiline
bug as agent/skill_utils.py:_normalize_string_set.

Changes:
- agent/skill_utils.py: split multiline strings on newlines, strip - prefixes
- hermes_cli/skills_config.py: same multiline fix in _normalize_skill_names
- tests: 6 new test cases per normalizer covering block scalars,
  single scalars, YAML lists, None, dashless lines, and blank lines

All 89 existing + 12 new tests pass.

# Conflicts:
#	agent/skill_utils.py
@WangYeYi
WangYeYi force-pushed the fix/normalize-string-set-multiline branch from 7aaf067 to 532cdba Compare August 25, 2026 03:02
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 P2 Medium — degraded but workaround exists 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 tool/skills Skills system (list, view, manage) type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants