feat(memory,skills): approve/deny gate for memory + skill writes#38199
Merged
Conversation
Contributor
🔎 Lint report:
|
| Rule | Count |
|---|---|
unsupported-operator |
5 |
invalid-argument-type |
2 |
unresolved-attribute |
2 |
not-subscriptable |
1 |
unresolved-import |
1 |
First entries
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`
tests/tools/test_write_approval.py:159: [invalid-argument-type] invalid-argument-type: Argument to function `skill_pending_diff` is incorrect: Expected `dict[str, Any]`, found `dict[str, Any] | None`
tests/tools/test_write_approval.py:211: [unsupported-operator] unsupported-operator: Operator `in` is not supported between objects of type `Literal["Rejected"]` and `str | None`
gateway/slash_commands.py:1984: [unresolved-attribute] unresolved-attribute: Object of type `Self@_handle_memory_command` has no attribute `_evict_cached_agent`
tests/tools/test_write_approval.py:187: [unsupported-operator] unsupported-operator: Operator `in` is not supported between objects of type `Literal["No pending memory"]` and `str | None`
tests/tools/test_write_approval.py:200: [unsupported-operator] unsupported-operator: Operator `in` is not supported between objects of type `Literal["Approved 2"]` and `str | None`
tests/tools/test_write_approval.py:173: [not-subscriptable] not-subscriptable: Cannot subscript object of type `None` with no `__getitem__` method
gateway/slash_commands.py:1972: [unresolved-attribute] unresolved-attribute: Object of type `Self@_handle_memory_command` has no attribute `_session_key_for_source`
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`
tools/skill_manager_tool.py:888: [invalid-argument-type] invalid-argument-type: Argument to function `skill_manage` is incorrect: Expected `str`, found `Any | None`
tests/tools/test_write_approval.py:14: [unresolved-import] unresolved-import: Cannot resolve imported module `pytest`
✅ Fixed issues: none
Unchanged: 5567 pre-existing issues carried over.
Diagnostics are surfaced as warnings — this check never fails the build.
dd0c623 to
bab8356
Compare
Adds memory.write_mode and skills.write_mode (on|off|approve), applied to both foreground turns and the background self-improvement review fork — the source of the unprompted 'wrong assumption' saves users reported. - on (default): write freely, unchanged behaviour - off: never write; the tool returns a clean disabled result - approve: don't commit. Memory foreground writes prompt inline (small, reviewable in a chat bubble); background memory writes and ALL skill writes stage to a pending store instead (a SKILL.md is too large to review inline, and a daemon thread can't block on a prompt) Review staged writes from CLI or any messaging platform: /memory pending|approve|reject|mode /skills pending|approve|reject|diff|mode Skill review respects the size asymmetry: inline you see a one-line gist; the full unified diff stays out-of-band (/skills diff, dashboard, or the staged JSON file). New: tools/write_approval.py (gate + pending store), hermes_cli/ write_approval_commands.py (shared CLI+gateway handlers). Gates wired at the single entry points memory_tool() and skill_manage(), using the existing write-origin ContextVar to distinguish foreground from background_review.
bab8356 to
8064417
Compare
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
…sResearch#38199) Adds memory.write_mode and skills.write_mode (on|off|approve), applied to both foreground turns and the background self-improvement review fork — the source of the unprompted 'wrong assumption' saves users reported. - on (default): write freely, unchanged behaviour - off: never write; the tool returns a clean disabled result - approve: don't commit. Memory foreground writes prompt inline (small, reviewable in a chat bubble); background memory writes and ALL skill writes stage to a pending store instead (a SKILL.md is too large to review inline, and a daemon thread can't block on a prompt) Review staged writes from CLI or any messaging platform: /memory pending|approve|reject|mode /skills pending|approve|reject|diff|mode Skill review respects the size asymmetry: inline you see a one-line gist; the full unified diff stays out-of-band (/skills diff, dashboard, or the staged JSON file). New: tools/write_approval.py (gate + pending store), hermes_cli/ write_approval_commands.py (shared CLI+gateway handlers). Gates wired at the single entry points memory_tool() and skill_manage(), using the existing write-origin ContextVar to distinguish foreground from background_review.
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
) Adds memory.write_mode and skills.write_mode (on|off|approve), applied to both foreground turns and the background self-improvement review fork — the source of the unprompted 'wrong assumption' saves users reported. - on (default): write freely, unchanged behaviour - off: never write; the tool returns a clean disabled result - approve: don't commit. Memory foreground writes prompt inline (small, reviewable in a chat bubble); background memory writes and ALL skill writes stage to a pending store instead (a SKILL.md is too large to review inline, and a daemon thread can't block on a prompt) Review staged writes from CLI or any messaging platform: /memory pending|approve|reject|mode /skills pending|approve|reject|diff|mode Skill review respects the size asymmetry: inline you see a one-line gist; the full unified diff stays out-of-band (/skills diff, dashboard, or the staged JSON file). New: tools/write_approval.py (gate + pending store), hermes_cli/ write_approval_commands.py (shared CLI+gateway handlers). Gates wired at the single entry points memory_tool() and skill_manage(), using the existing write-origin ContextVar to distinguish foreground from background_review.
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
Memory and skill writes can now be gated per-subsystem with a tri-state
write_mode— including writes the background self-improvement review fork makes on its own (the source of the unprompted "wrong assumption" saves users reported).Default is
on(current behaviour — writes flow freely), so existing installs are unaffected until a user opts in.How it works
Both
memory.write_modeandskills.write_modeaccept:on— write freely (default)off— never write; the tool returns a clean "disabled" resultapprove— don't commit; route the write for reviewPending writes persist under
<HERMES_HOME>/pending/{memory,skills}/<id>.json(survive restarts) and are reviewed via slash commands:/memory [pending|approve <id>|reject <id>|mode <on|off|approve>]— works on CLI and every gateway platform/skills [pending|approve <id>|reject <id>|diff <id>|mode <...>]—diffshows the full skill diff (CLI/dashboard/file), never crammed into a chat bubbleChanges
tools/write_approval.py(new): gate decision + file-backed pending store; reuses the existing dangerous-command approval machinery for inline prompts and the skill-provenance ContextVar for foreground/background origin.hermes_cli/write_approval_commands.py(new): shared pending-review handlers (list/approve/reject/diff/mode) used by both CLI and gateway.tools/memory_tool.py,tools/skill_manager_tool.py: evaluate the gate before mutating;apply_*_pendingreplay paths bypass the gate (skills via a ContextVar) for approved writes.hermes_cli/commands.py: register/memoryand the new/skillsreview subcommands.hermes_cli/cli_commands_mixin.py,gateway/slash_commands.py: CLI + gateway handlers.hermes_cli/config.py:memory.write_mode/skills.write_modedefaults (on) with documenting comments.website/docs/user-guide/features/memory.md: document the gate.Validation
tests/tools/test_write_approval.pytests/hermes_cli/test_commands.pyInfographic