Skip to content

feat(learning): revert applied learned adjustments - #44

Open
localrivet wants to merge 1 commit into
mainfrom
claude/revert-learned-adjustments
Open

feat(learning): revert applied learned adjustments#44
localrivet wants to merge 1 commit into
mainfrom
claude/revert-learned-adjustments

Conversation

@localrivet

Copy link
Copy Markdown
Contributor

Problem

A learned adjustment — a review-fork learned skill or a workflow tuning edit — had no restore point once applied, so it was effectively baked in:

  • Learned skills stored only a hash of the prior SKILL.md (for conflict detection), not the content.
  • Auto-mode skill writes left no pending_writes row at all — nothing to anchor an undo to.
  • Workflow tuning overwrote the binding, keeping the prior JSON only as a conflict token.
  • The user-facing skill DELETE endpoint doesn't even reach the learned tree (handlers/skills.rs).

The only escape was waiting for the fork to overwrite it, or deleting files by hand. This is the same failure class as the memory-poisoning that started this line of work, one layer up.

Fix

Capture a real restore point and add a first-class revert.

  • prior_content on pending_writes (migration 0126): the FULL prior SKILL.md / prior binding JSON, NULL for a create. Captured at every apply point — staged skill writes (skill_tool::stage_learned_write), workflow tuning (workflow_manager), and a new approved audit row for AUTO-mode skill writes (record_applied_write / record_applied_learning), which previously left no trace.
  • POST /api/v1/agents/learnings/{id}/revert (handlers::agents::revert_learning): reverses an approved row by writing prior_content back through the same pathway that applied it — the skill-tool inverse action (create→delete, update→update(prior), delete→create(prior)) or apply_workflow_binding. It refuses (never clobbers) when the target no longer matches what the learning produced, returning conflict.
  • learned_write_reapply ctx flag: distinguishes a genuine auto-mode learning (records an audit row) from an approve/revert re-application (does not), so approve/revert never mint duplicate learn: records.
  • Inbox: applied learnings show a Revert action; a reverted/conflict chip reflects the outcome (routes/inbox/+page.svelte, regenerated nebo client, i18n).

Learning modes (unchanged, for context)

auto applies directly (now with an audit row), staged routes to Inbox approval, off disables learning. Revert works for anything that reached the approved state under auto or staged.

Tests / verification

  • nebo-db: prior_content round-trip, record_applied_write lands approved, revert only transitions applied rows — 3 pass.
  • nebo-tools: existing skill-tool suite — 7 pass, no regression.
  • nebo-db / nebo-tools / nebo-agent / nebo-server libraries compile clean; pnpm check on the app — 0 errors.
  • Note: the full server binary and Rust test-harness links, and the frontend build, could not run in this sandbox (missing libwayland-dev/protoc/BLAS + no app/build); CI should exercise the full build.

🤖 Generated with Claude Code


Generated by Claude Code

A learned adjustment — a review-fork learned skill or a workflow tuning edit —
had no restore point once applied. Skills stored only a HASH of the prior
SKILL.md (for conflict detection), auto-mode skill writes left no row at all,
and workflow edits kept the prior binding JSON only as a conflict token. So an
applied learning was effectively baked in: the only escape was waiting for the
fork to overwrite it or deleting files by hand (the user-facing skill DELETE
endpoint doesn't even reach the learned tree).

Capture a real restore point and add a first-class revert:

- pending_writes gains prior_content (migration 0126): the FULL prior SKILL.md
  or prior binding JSON, NULL for a create. Captured at every apply point —
  staged skill writes, workflow tuning, and (new) an approved audit row for
  AUTO-mode skill writes, which previously left no trace to undo.
- POST /agents/learnings/{id}/revert reverses an 'approved' row by writing
  prior_content back through the SAME pathway that applied it (skill tool
  inverse action / apply_workflow_binding). It refuses — never clobbers — when
  the target no longer matches what the learning produced.
- A learned_write_reapply ctx flag distinguishes a genuine auto-mode learning
  (records an audit row) from an approve/revert re-application (does not), so
  approve/revert never mint duplicate learn: records.
- Inbox: applied learnings show a Revert action; a reverted/conflict chip
  reflects the outcome.

Tests: pending_writes prior_content round-trip, record_applied_write lands
approved, revert only transitions applied rows.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0157ARXoiSR35pfppJT7vLeX
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants