refactor(memory,skills): replace tri-state write_mode with boolean write_approval (default off)#43354
Merged
Merged
Conversation
…ite_approval (default off)
The shipped tri-state write_mode (on|off|approve) conflated two concepts —
whether writes are enabled and whether they're gated — so 'on' (writes flow
freely, gate inactive) read like 'gating is on'. Replace it with a single
clear boolean gate that defaults off.
memory.write_approval / skills.write_approval:
false (default) — write freely; the approval gate is off (pre-gate behaviour)
true — require approval: memory foreground prompts inline, memory
background-review + all skill writes stage for review
The old 'off = block all writes' mode is dropped; memory_enabled: false already
disables memory entirely, so a third 'block' state was redundant.
- tools/write_approval.py: get_write_mode/MODE_* → write_approval_enabled() bool;
evaluate_gate() loses the config-driven 'blocked' path (blocked now only comes
from an interactive user denial).
- tools/memory_tool.py, tools/skill_manager_tool.py: comment + behaviour follow.
- hermes_cli/config.py: memory/skills write_mode → write_approval (False);
_config_version 28→29 with a 28→29 migration that renames any persisted
write_mode (approve→true, on/off/unset→false) and drops the old key.
- slash commands: '/memory|/skills mode <on|off|approve>' → 'approval <on|off>'
('mode' kept as a back-compat alias); set_mode_fn callback now takes a bool.
- write_approval_commands.py, cli_commands_mixin.py, gateway/slash_commands.py,
commands.py: handlers + registry args/subcommands updated.
- docs + tests rewritten for the boolean model; added migration tests.
Contributor
🔎 Lint report:
|
| Rule | Count |
|---|---|
unsupported-operator |
3 |
First entries
tests/tools/test_write_approval.py:261: [unsupported-operator] unsupported-operator: Operator `in` is not supported between objects of type `Literal["Invalid value"]` and `str | None`
tests/tools/test_write_approval.py:240: [unsupported-operator] unsupported-operator: Operator `in` is not supported between objects of type `Literal["off"]` and `str | None`
tests/tools/test_write_approval.py:253: [unsupported-operator] unsupported-operator: Operator `in` is not supported between objects of type `Literal["on"]` and `str | None`
✅ Fixed issues (2):
| Rule | Count |
|---|---|
unsupported-operator |
2 |
First entries
tests/tools/test_write_approval.py:224: [unsupported-operator] unsupported-operator: Operator `in` is not supported between objects of type `Literal["approve"]` and `str | None`
tests/tools/test_write_approval.py:232: [unsupported-operator] unsupported-operator: Operator `in` is not supported between objects of type `Literal["Invalid mode"]` and `str | None`
Unchanged: 5577 pre-existing issues carried over.
Diagnostics are surfaced as warnings — this check never fails the build.
teknium1
added a commit
that referenced
this pull request
Jun 10, 2026
…ing, and gateway /skills review (#43452) Follow-ups to #38199/#43354 found in post-merge review: - Inline CLI memory approval never worked: the per-thread approval callback was not passed to prompt_dangerous_approval, so the prompt_toolkit fail-closed guard (#15216) denied every gated foreground write without showing a prompt. Now invokes the registered callback directly; a crashed prompt falls back to staging instead of a silent deny. - Gateway sessions claimed inline support but prompt_dangerous_approval has no gateway round-trip (that lives in the pending-approval queue), so gated gateway memory writes hit the input() fallback and denied. Gateway contexts now stage for /memory pending review. - /skills pending|approve|reject|diff|approval now works on the gateway (gateway_config_gate on skills.write_approval), so skills staged from a messaging session can be reviewed there. Diff output truncated for chat. - memory_tool validates required params before the gate so invalid writes are rejected immediately instead of staged and failing at approve time. - Stale tri-state write_mode docstrings updated to the boolean gate; docs table corrected (inline prompt is interactive-CLI-only). - 6 new tests covering the interactive approve/deny/error paths, gateway staging, skills never-prompt invariant, and pre-gate validation.
changman
pushed a commit
to changman/hermes-agent
that referenced
this pull request
Jun 10, 2026
…ite_approval (default off) (NousResearch#43354) The shipped tri-state write_mode (on|off|approve) conflated two concepts — whether writes are enabled and whether they're gated — so 'on' (writes flow freely, gate inactive) read like 'gating is on'. Replace it with a single clear boolean gate that defaults off. memory.write_approval / skills.write_approval: false (default) — write freely; the approval gate is off (pre-gate behaviour) true — require approval: memory foreground prompts inline, memory background-review + all skill writes stage for review The old 'off = block all writes' mode is dropped; memory_enabled: false already disables memory entirely, so a third 'block' state was redundant. - tools/write_approval.py: get_write_mode/MODE_* → write_approval_enabled() bool; evaluate_gate() loses the config-driven 'blocked' path (blocked now only comes from an interactive user denial). - tools/memory_tool.py, tools/skill_manager_tool.py: comment + behaviour follow. - hermes_cli/config.py: memory/skills write_mode → write_approval (False); _config_version 28→29 with a 28→29 migration that renames any persisted write_mode (approve→true, on/off/unset→false) and drops the old key. - slash commands: '/memory|/skills mode <on|off|approve>' → 'approval <on|off>' ('mode' kept as a back-compat alias); set_mode_fn callback now takes a bool. - write_approval_commands.py, cli_commands_mixin.py, gateway/slash_commands.py, commands.py: handlers + registry args/subcommands updated. - docs + tests rewritten for the boolean model; added migration tests.
changman
pushed a commit
to changman/hermes-agent
that referenced
this pull request
Jun 10, 2026
…ing, and gateway /skills review (NousResearch#43452) Follow-ups to NousResearch#38199/NousResearch#43354 found in post-merge review: - Inline CLI memory approval never worked: the per-thread approval callback was not passed to prompt_dangerous_approval, so the prompt_toolkit fail-closed guard (NousResearch#15216) denied every gated foreground write without showing a prompt. Now invokes the registered callback directly; a crashed prompt falls back to staging instead of a silent deny. - Gateway sessions claimed inline support but prompt_dangerous_approval has no gateway round-trip (that lives in the pending-approval queue), so gated gateway memory writes hit the input() fallback and denied. Gateway contexts now stage for /memory pending review. - /skills pending|approve|reject|diff|approval now works on the gateway (gateway_config_gate on skills.write_approval), so skills staged from a messaging session can be reviewed there. Diff output truncated for chat. - memory_tool validates required params before the gate so invalid writes are rejected immediately instead of staged and failing at approve time. - Stale tri-state write_mode docstrings updated to the boolean gate; docs table corrected (inline prompt is interactive-CLI-only). - 6 new tests covering the interactive approve/deny/error paths, gateway staging, skills never-prompt invariant, and pre-gate validation.
teknium1
added a commit
that referenced
this pull request
Jun 11, 2026
…slash-command docs (#43801) The memory/skill write-approval gate (#38199, #43354, #43452) was only documented inside features/memory.md. Surface it everywhere users will actually look: - features/skills.md: new 'Gating agent skill writes' section under skill_manage, with the staging semantics, review commands, and the distinction from skills.guard_agent_created - configuration.md: memory.write_approval added to the Memory Configuration block; new 'Write approval for skill writes' subsection next to the guard_agent_created scanner - reference/slash-commands.md: /memory and /skills review subcommands in both the CLI and messaging tables; Notes updated since /skills pending/approve/reject/diff/approval now works on the gateway - features/memory.md: cross-link to the new skills section
alt-glitch
pushed a commit
that referenced
this pull request
Jun 14, 2026
…ite_approval (default off) (#43354) The shipped tri-state write_mode (on|off|approve) conflated two concepts — whether writes are enabled and whether they're gated — so 'on' (writes flow freely, gate inactive) read like 'gating is on'. Replace it with a single clear boolean gate that defaults off. memory.write_approval / skills.write_approval: false (default) — write freely; the approval gate is off (pre-gate behaviour) true — require approval: memory foreground prompts inline, memory background-review + all skill writes stage for review The old 'off = block all writes' mode is dropped; memory_enabled: false already disables memory entirely, so a third 'block' state was redundant. - tools/write_approval.py: get_write_mode/MODE_* → write_approval_enabled() bool; evaluate_gate() loses the config-driven 'blocked' path (blocked now only comes from an interactive user denial). - tools/memory_tool.py, tools/skill_manager_tool.py: comment + behaviour follow. - hermes_cli/config.py: memory/skills write_mode → write_approval (False); _config_version 28→29 with a 28→29 migration that renames any persisted write_mode (approve→true, on/off/unset→false) and drops the old key. - slash commands: '/memory|/skills mode <on|off|approve>' → 'approval <on|off>' ('mode' kept as a back-compat alias); set_mode_fn callback now takes a bool. - write_approval_commands.py, cli_commands_mixin.py, gateway/slash_commands.py, commands.py: handlers + registry args/subcommands updated. - docs + tests rewritten for the boolean model; added migration tests.
alt-glitch
pushed a commit
that referenced
this pull request
Jun 14, 2026
…ing, and gateway /skills review (#43452) Follow-ups to #38199/#43354 found in post-merge review: - Inline CLI memory approval never worked: the per-thread approval callback was not passed to prompt_dangerous_approval, so the prompt_toolkit fail-closed guard (#15216) denied every gated foreground write without showing a prompt. Now invokes the registered callback directly; a crashed prompt falls back to staging instead of a silent deny. - Gateway sessions claimed inline support but prompt_dangerous_approval has no gateway round-trip (that lives in the pending-approval queue), so gated gateway memory writes hit the input() fallback and denied. Gateway contexts now stage for /memory pending review. - /skills pending|approve|reject|diff|approval now works on the gateway (gateway_config_gate on skills.write_approval), so skills staged from a messaging session can be reviewed there. Diff output truncated for chat. - memory_tool validates required params before the gate so invalid writes are rejected immediately instead of staged and failing at approve time. - Stale tri-state write_mode docstrings updated to the boolean gate; docs table corrected (inline prompt is interactive-CLI-only). - 6 new tests covering the interactive approve/deny/error paths, gateway staging, skills never-prompt invariant, and pre-gate validation.
alt-glitch
pushed a commit
that referenced
this pull request
Jun 14, 2026
…slash-command docs (#43801) The memory/skill write-approval gate (#38199, #43354, #43452) was only documented inside features/memory.md. Surface it everywhere users will actually look: - features/skills.md: new 'Gating agent skill writes' section under skill_manage, with the staging semantics, review commands, and the distinction from skills.guard_agent_created - configuration.md: memory.write_approval added to the Memory Configuration block; new 'Write approval for skill writes' subsection next to the guard_agent_created scanner - reference/slash-commands.md: /memory and /skills review subcommands in both the CLI and messaging tables; Notes updated since /skills pending/approve/reject/diff/approval now works on the gateway - features/memory.md: cross-link to the new skills section
AIalliAI
pushed a commit
to AIalliAI/Hermes
that referenced
this pull request
Jun 14, 2026
…slash-command docs (NousResearch#43801) The memory/skill write-approval gate (NousResearch#38199, NousResearch#43354, NousResearch#43452) was only documented inside features/memory.md. Surface it everywhere users will actually look: - features/skills.md: new 'Gating agent skill writes' section under skill_manage, with the staging semantics, review commands, and the distinction from skills.guard_agent_created - configuration.md: memory.write_approval added to the Memory Configuration block; new 'Write approval for skill writes' subsection next to the guard_agent_created scanner - reference/slash-commands.md: /memory and /skills review subcommands in both the CLI and messaging tables; Notes updated since /skills pending/approve/reject/diff/approval now works on the gateway - features/memory.md: cross-link to the new skills section
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The memory/skill write-approval gate (shipped in #38199) used a tri-state
write_mode: on | off | approvethat conflated two ideas — whether writes are enabled and whether they're gated — soon(writes flow freely, gate inactive) read like "gating is on." This replaces it with a single clear boolean that defaults off.false(default) — write freely; the approval gate is off (exactly the pre-gate behaviour).true— require approval: memory foreground writes prompt inline, memory background-review writes + all skill writes stage for review.The old
off = block all writesmode is dropped —memory_enabled: falsealready disables memory entirely, so a third "block" state was redundant and confusing.Changes
tools/write_approval.py:get_write_mode()/MODE_*→write_approval_enabled() -> bool;evaluate_gate()loses the config-drivenblockedpath (blocked now only comes from an interactive user denial, not from config).hermes_cli/config.py:memory.write_mode/skills.write_mode→write_approval(defaultFalse);_config_version28 → 29 with a migration that renames any persistedwrite_mode(approve→true,on/off/unset→false) and drops the old key./memory|/skills mode <on|off|approve>→approval <on|off>(modekept as a back-compat alias). The persist callback now takes a bool.tools/memory_tool.py,tools/skill_manager_tool.py,hermes_cli/write_approval_commands.py,hermes_cli/cli_commands_mixin.py,gateway/slash_commands.py,hermes_cli/commands.py: handlers, registry args/subcommands, comments updated.Validation
tests/tools/test_write_approval.pytests/hermes_cli/test_commands.pytests/hermes_cli/test_config.py/skills approval onpersists + stages;modealias works;offre-disablesContext
Follow-up to #38199 per maintainer feedback: the gate should be a plain on/off toggle that's clearly off by default, not a tri-state where
onmeans "ungated."Infographic