Skip to content

feat(config): profile config inheritance from default (#20270)#41741

Closed
teknium1 wants to merge 2 commits into
mainfrom
hermes/hermes-587e489c
Closed

feat(config): profile config inheritance from default (#20270)#41741
teknium1 wants to merge 2 commits into
mainfrom
hermes/hermes-587e489c

Conversation

@teknium1

@teknium1 teknium1 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Profiles can now inherit their config from the default profile and store only the values they override — instead of every profile being a standalone full copy. A profile opts in with inherit: true in its config.yaml; at load time the default profile's config is deep-merged underneath the profile's overrides.

Salvaged from @frap129's #20964 (closes #20270), with follow-up fixes so inheritance actually takes effect in real agent sessions — not just under hermes config show.

Changes

  • hermes_constants.pyget_default_config_path().
  • hermes_cli/config.py_should_inherit(), resolve_inherited_raw_config() / _apply_inheritance() (single source of truth), _compute_overrides_only(); load_config() resolves inheritance and folds the parent config's (mtime_ns, size) into its cache key; save_config() writes overrides-only against the parent's fully-resolved config and keeps inherit: true; hermes config show gains a Profile/inheritance section.
  • cli.pyload_cli_config() resolves through the shared resolver (CLI sessions now see inherited values).
  • gateway/run.py — both config→env bridges resolve through the shared resolver (gateway sees inherited values).
  • hermes_cli/profiles.pyINHERITANCE_SKELETON_YAML / FULL_CONFIG_SKELETON_YAML; fresh profiles seed a skeleton (inherits param); cloning paths untouched.
  • hermes_cli/main.py — real --no-inherit flag (replaces an invalid Click-style --inherits/--no-inherit that never bound a dest).
  • scripts/release.py — AUTHOR_MAP: joe@maples.devfrap129.
  • docs — profiles.md inheritance section + configuration.md precedence.

Root cause of the follow-up fixes

The original PR only taught load_config() to inherit. Hermes has three config readers (load_config, the CLI's load_cli_config, and the gateway's raw env bridges); the other two read the profile's config.yaml directly, so an inherit: true profile would resolve correctly in hermes config show but silently drop inherited values in actual CLI/gateway sessions. The fix routes all three through one resolver. Also fixed: a cache key that ignored the parent config (stale on default edits) and an argparse flag that could never be triggered.

Validation

Result
load_config / load_cli_config / gateway resolver all resolve inherited model+provider+nested values
Edit default config.yaml, no manual cache clear inheriting profile sees new value (parent-stat cache fold)
Standalone profile (inherit: false) ignores parent; unset keys fall to DEFAULT_CONFIG
save_config on inheriting profile writes overrides-only (~3 lines), keeps inherit: true
Corrupt config warn/backup path preserved (regression-guarded)
--no-inherit flag parses (default inherit, flag → standalone)
Targeted tests tests/hermes_cli/test_config.py + test_profiles.py (231) + config/gateway env-bridge suites (99) green; 13 new inheritance tests

Infographic

Profile config inheritance

Original PR #20964 by @frap129 — cherry-picked authorship preserved in git log.

frap129 and others added 2 commits June 7, 2026 20:10
New profiles created with `hermes profile create` get a skeleton
config.yaml with `inherit: true` and store only overrides; all other
values are read from the default profile's config.yaml.

- hermes_constants: add get_default_config_path()
- profiles.py: INHERITANCE/FULL skeleton templates + inherits param on
  create_profile (fresh profiles only; cloning paths untouched)
- docs: profiles.md inheritance section + configuration.md precedence

Co-authored-by: teknium1 <127238744+teknium1@users.noreply.github.com>
Salvage follow-up to make profile inheritance actually take effect in
real sessions, not just `hermes config show`:

- Single resolver: resolve_inherited_raw_config() / _apply_inheritance()
  are the source of truth; load_config(), the CLI's load_cli_config(),
  and the gateway env bridges all resolve through it. Previously only
  load_config() inherited, so `hermes -p work chat` and the gateway saw
  only the skeleton and silently dropped inherited values.
- Cache integrity: fold the parent config's (mtime_ns, size) into the
  load_config cache key so editing the default config.yaml invalidates
  inheriting profiles' caches.
- save_config writes overrides-only against the parent's FULLY-RESOLVED
  config (DEFAULT_CONFIG + default profile), keeping inherit: true.
- main.py: replace the invalid Click-style "--inherits/--no-inherit"
  argparse flag (which never bound a dest) with a real --no-inherit
  store_false; wire inherits through cmd_profile.
- _should_inherit never inherits from itself (active == default profile).
- AUTHOR_MAP: joe@maples.dev -> frap129.
- Tests: 13 inheritance tests (all three loaders, cache-bust, standalone,
  save round-trip, skeleton seeding, clone-no-seed).
@alt-glitch alt-glitch added type/feature New feature or request P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard comp/gateway Gateway runner, session dispatch, delivery area/config Config system, migrations, profiles labels Jun 8, 2026
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: hermes/hermes-587e489c vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 10037 on HEAD, 10033 on base (🆕 +4)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 5201 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@teknium1

teknium1 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

Closing — profile isolation is intentional design, not a gap. Profiles are meant to be independent islands; we don't want a live config link that lets the default profile silently change a named profile's behavior. The existing hermes profile create --clone (copy-at-creation) covers the legitimate "start from my default" case without coupling profiles together afterward.

Thanks @frap129 for the implementation in #20964 — the work was sound, the design direction just isn't one we're taking.

@teknium1 teknium1 closed this Jun 8, 2026
@teknium1 teknium1 deleted the hermes/hermes-587e489c branch June 8, 2026 06:42
teknium1 added a commit that referenced this pull request Jun 9, 2026
AGENTS.md was almost entirely how-to/mechanics with the want/don't-want
guidance implicit and scattered. Adds a single authoritative intent layer
near the top, calibrated against what actually merges and what actually
gets rejected.

- 'What Hermes Is': framing + the two properties that drive design
  (prompt-cache integrity, narrow-waist core).
- 'Contribution Rubric': dual-purpose intent doc — (1) for humans/own work:
  what gets merged vs rejected; (2) for the triage sweeper: when a PR is safe
  to close on the three allowed reasons AND when NOT to close one. Taste-based
  'won't implement / out of scope' closes stay human-only by design.
  - 'What we want' calibrated against the last ~55 merges: fix real bugs well,
    expand reach at the edges (platforms/channels/providers/models/desktop —
    large features land routinely), refactor god-files into clean modules,
    keep the CORE narrow. 'Expansive at the edges, conservative at the waist.'
  - 'What we don't want': speculative hooks, .env-for-non-secrets, needless
    core tools, lazy-read escape hatches, feature-destroying fixes, ungated
    telemetry, change-detector tests, core-touching plugins.
  - 'Before you call it a bug — verify the premise (and when NOT to close)':
    distilled from real closes (#41741 intentional-design-not-a-gap, #41610
    wrong-premise, #42327 fix-never-executes, #42393 deliberate-omission,
    #41999 overreach). Doubles as sweeper guidance to avoid wrongly closing
    legitimate PRs.
- 'The Footprint Ladder' (core-tool decision): extend > CLI+skill > gated tool
  > plugin > MCP server in the catalog > new core tool (last resort).

Trim: 'Adding New Tools' intro points at the ladder. Detailed mechanics stay
where readers need them.
teknium1 added a commit that referenced this pull request Jun 10, 2026
#42641)

AGENTS.md was almost entirely how-to/mechanics with the want/don't-want
guidance implicit and scattered. Adds a single authoritative intent layer
near the top, calibrated against what actually merges and what actually
gets rejected.

- 'What Hermes Is': framing + the two properties that drive design
  (prompt-cache integrity, narrow-waist core).
- 'Contribution Rubric': dual-purpose intent doc — (1) for humans/own work:
  what gets merged vs rejected; (2) for the triage sweeper: when a PR is safe
  to close on the three allowed reasons AND when NOT to close one. Taste-based
  'won't implement / out of scope' closes stay human-only by design.
  - 'What we want' calibrated against the last ~55 merges: fix real bugs well,
    expand reach at the edges (platforms/channels/providers/models/desktop —
    large features land routinely), refactor god-files into clean modules,
    keep the CORE narrow. 'Expansive at the edges, conservative at the waist.'
  - 'What we don't want': speculative hooks, .env-for-non-secrets, needless
    core tools, lazy-read escape hatches, feature-destroying fixes, ungated
    telemetry, change-detector tests, core-touching plugins.
  - 'Before you call it a bug — verify the premise (and when NOT to close)':
    distilled from real closes (#41741 intentional-design-not-a-gap, #41610
    wrong-premise, #42327 fix-never-executes, #42393 deliberate-omission,
    #41999 overreach). Doubles as sweeper guidance to avoid wrongly closing
    legitimate PRs.
- 'The Footprint Ladder' (core-tool decision): extend > CLI+skill > gated tool
  > plugin > MCP server in the catalog > new core tool (last resort).

Trim: 'Adding New Tools' intro points at the ladder. Detailed mechanics stay
where readers need them.
changman pushed a commit to changman/hermes-agent that referenced this pull request Jun 10, 2026
NousResearch#42641)

AGENTS.md was almost entirely how-to/mechanics with the want/don't-want
guidance implicit and scattered. Adds a single authoritative intent layer
near the top, calibrated against what actually merges and what actually
gets rejected.

- 'What Hermes Is': framing + the two properties that drive design
  (prompt-cache integrity, narrow-waist core).
- 'Contribution Rubric': dual-purpose intent doc — (1) for humans/own work:
  what gets merged vs rejected; (2) for the triage sweeper: when a PR is safe
  to close on the three allowed reasons AND when NOT to close one. Taste-based
  'won't implement / out of scope' closes stay human-only by design.
  - 'What we want' calibrated against the last ~55 merges: fix real bugs well,
    expand reach at the edges (platforms/channels/providers/models/desktop —
    large features land routinely), refactor god-files into clean modules,
    keep the CORE narrow. 'Expansive at the edges, conservative at the waist.'
  - 'What we don't want': speculative hooks, .env-for-non-secrets, needless
    core tools, lazy-read escape hatches, feature-destroying fixes, ungated
    telemetry, change-detector tests, core-touching plugins.
  - 'Before you call it a bug — verify the premise (and when NOT to close)':
    distilled from real closes (NousResearch#41741 intentional-design-not-a-gap, NousResearch#41610
    wrong-premise, NousResearch#42327 fix-never-executes, NousResearch#42393 deliberate-omission,
    NousResearch#41999 overreach). Doubles as sweeper guidance to avoid wrongly closing
    legitimate PRs.
- 'The Footprint Ladder' (core-tool decision): extend > CLI+skill > gated tool
  > plugin > MCP server in the catalog > new core tool (last resort).

Trim: 'Adding New Tools' intro points at the ladder. Detailed mechanics stay
where readers need them.
alt-glitch pushed a commit that referenced this pull request Jun 14, 2026
#42641)

AGENTS.md was almost entirely how-to/mechanics with the want/don't-want
guidance implicit and scattered. Adds a single authoritative intent layer
near the top, calibrated against what actually merges and what actually
gets rejected.

- 'What Hermes Is': framing + the two properties that drive design
  (prompt-cache integrity, narrow-waist core).
- 'Contribution Rubric': dual-purpose intent doc — (1) for humans/own work:
  what gets merged vs rejected; (2) for the triage sweeper: when a PR is safe
  to close on the three allowed reasons AND when NOT to close one. Taste-based
  'won't implement / out of scope' closes stay human-only by design.
  - 'What we want' calibrated against the last ~55 merges: fix real bugs well,
    expand reach at the edges (platforms/channels/providers/models/desktop —
    large features land routinely), refactor god-files into clean modules,
    keep the CORE narrow. 'Expansive at the edges, conservative at the waist.'
  - 'What we don't want': speculative hooks, .env-for-non-secrets, needless
    core tools, lazy-read escape hatches, feature-destroying fixes, ungated
    telemetry, change-detector tests, core-touching plugins.
  - 'Before you call it a bug — verify the premise (and when NOT to close)':
    distilled from real closes (#41741 intentional-design-not-a-gap, #41610
    wrong-premise, #42327 fix-never-executes, #42393 deliberate-omission,
    #41999 overreach). Doubles as sweeper guidance to avoid wrongly closing
    legitimate PRs.
- 'The Footprint Ladder' (core-tool decision): extend > CLI+skill > gated tool
  > plugin > MCP server in the catalog > new core tool (last resort).

Trim: 'Adding New Tools' intro points at the ladder. Detailed mechanics stay
where readers need them.
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/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Profile config inheritance from default

3 participants