Skip to content

feat(memory): capture rejected approaches - #77

Open
ahrav wants to merge 1 commit into
stack/anti-memory-02-rustfrom
stack/anti-memory-03-writers
Open

feat(memory): capture rejected approaches#77
ahrav wants to merge 1 commit into
stack/anti-memory-02-rustfrom
stack/anti-memory-03-writers

Conversation

@ahrav

@ahrav ahrav commented Aug 27, 2026

Copy link
Copy Markdown
Owner

Summary

Correction and retrospective flows can now record a failed approach through one typed ctx_memory operation. Writers preserve the rejected approach, reason, conditions, evidence, and replacement guidance without routing any of it through positive claims.

This is the third PR in the anti-memory stack. It builds on PR #75 and PR #76; PR #78 consumes these records as warn-only search results.

Design

  • Explicit user corrections create rejected-approach records directly.
  • Retrospective learning drafts can emit the same typed record shape.
  • Plugin and Pi tool schemas expose one stable mutation vocabulary.
  • Writer failures remain isolated from the primary task and compartment paths.

Validation

  • bun run check:all
  • Focused correction, retrospective, tool-schema, and compartment-event tests

Stack created with GitHub Stacks CLIGive Feedback 💬

@coderabbitai

coderabbitai Bot commented Aug 27, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 77495ade-f814-42fd-8965-5c495045aaf4

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for security reviews. Please try again later.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e780870ba5

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +202 to +204
const category = requireTaxonomyCategory(args.category?.trim());
const antiArm = category === ANTI_MEMORY_CATEGORY || args.antiMemory !== undefined;
if (antiArm) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Route content-only anti-memory revisions through the typed API

When revise supplies only changed content, this check classifies the request as a positive-memory write without considering the target claim's stored category. If the token belongs to a REJECTED_APPROACH claim, the generic revision path preserves that category but does not insert a claim_anti_memory_revision_payloads row; subsequent reads then throw ClaimGraphCorruptionError. Require the structured antiMemory payload whenever the target is already an anti-memory.

Useful? React with 👍 / 👎.

Comment on lines +122 to +124
FROM compartment_events events
JOIN session_projects projects ON projects.session_id = events.session_id
LEFT JOIN compartments

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Scope compartment-event joins by harness

When OpenCode and Pi contain the same session_id but bind it to different projects—a case supported by the (session_id, harness) key—this join associates each event with both bindings because it ignores events.harness. The corresponding pending-count query has the same join, so one project's retrospective can harvest another project's correction into its durable memory and globally receipt the event before the owning project processes it. Join on both session ID and harness.

Useful? React with 👍 / 👎.

Comment on lines +315 to +319
? stageCreateAntiMemoryInCurrentTransaction(
db,
{
projectId,
payload: item.value.payload,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Exclude anti-memories from generic maintenance writes

Once this path creates a REJECTED_APPROACH claim, readDreamerProjectClaims includes it in both hygiene and verification lanes, whose prompts and apply paths still treat every item as one of the five positive categories. A curator or verifier update therefore calls the generic revision stage, retains the anti-memory category, and creates a revision without a typed payload row; later reads fail with ClaimGraphCorruptionError. Either filter anti-memories out of those lanes or add typed anti-memory handling before enabling these creation paths.

Useful? React with 👍 / 👎.

Comment on lines +125 to +129
for (const event of getProjectCompartmentEvents(
args.db,
args.projectIdentity,
"trajectory_correction",
)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Filter consumed correction events before harvesting

After a project accumulates processed correction events, every later retrospective still loads and iterates the entire historical set because this reader does not apply the receipt predicate used by countPendingCorrectionEvents. For each valid old event the loop also reruns payload validation, message-history corroboration SQL, and receipt replay while holding the lease-guarded write transaction, so runtime and lock duration grow without bound even when only one new correction is pending. Fetch only events without a matching consumer receipt.

Useful? React with 👍 / 👎.

content: "string",
category: { type: "enum", values: V2_MEMORY_CATEGORIES },
category: { type: "enum", values: WRITABLE_MEMORY_CATEGORIES },
antiMemory: {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CRITICAL: unwrapImitatedReducedArgs fails when antiMemory contains optional fields

validObjectField in unwrap-imitated-reduced-args.ts validates objects by requiring exact key count equality (Object.keys(record).length !== declared.length). Declaring only 3 fields here causes any decoded imitated reduced tool call that supplies optional/nullable fields (such as saferAlternative, preconditions, rootCause, etc.) to fail validation. The unparsed wrapper is returned and args.action evaluates to undefined, rejecting valid agent tool calls.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

content: "string",
category: { type: "enum", values: V2_MEMORY_CATEGORIES },
category: { type: "enum", values: WRITABLE_MEMORY_CATEGORIES },
antiMemory: {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CRITICAL: unwrapImitatedReducedArgs fails when antiMemory contains optional fields

validObjectField validates decoded objects by asserting Object.keys(record).length === declared.length. Because only trigger, rejectedStrategy, and rejectionReason are declared in this schema, any imitated reduced argument payload containing valid optional fields (like saferAlternative) fails unwrapping, leaving rawAction as undefined and throwing an action error.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

}

function childText(inner: string, tag: string): string | null {
const match = inner.match(new RegExp(`<${tag}>([\\s\\S]*?)<\\/${tag}>`, "i"));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Exact tag match in childText drops fields formatted with attributes or whitespace

Matching <${tag}> without allowing for tag attributes or trailing whitespace causes any XML tag produced by the model with whitespace (e.g. <trigger >) or optional attributes (e.g. <safer_alternative note="...">) to fail to match. When required fields like trigger, rejected_strategy, or rejection_reason fail extraction, the learning is silently discarded. Consider matching <${tag}\b[^>]*>([\s\S]*?)<\/${tag}>.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

projectPath,
options.retrospectiveWatermarkMs ?? null,
);
const pending = pendingSessions + countPendingCorrectionEvents(db, projectPath);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Unbounded backlog count when retrospectiveWatermarkMs option is omitted

When getDreamTaskBacklog is called without explicit options (such as in status queries), options.retrospectiveWatermarkMs defaults to null, causing countProjectSessionsSince(db, projectPath, null) to count all historical sessions across the project's lifetime instead of falling back to the persisted watermark from getTaskScheduleState.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

@kilo-code-bot

kilo-code-bot Bot commented Aug 27, 2026

Copy link
Copy Markdown

Code Review Summary

Status: 4 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 2
WARNING 2
SUGGESTION 0
Issue Details (click to expand)

CRITICAL

File Line Issue
packages/plugin/src/tools/ctx-memory/tools.ts 113 unwrapImitatedReducedArgs fails when antiMemory contains optional fields
packages/pi-plugin/src/tools/ctx-memory.ts 144 unwrapImitatedReducedArgs fails when antiMemory contains optional fields

WARNING

File Line Issue
packages/plugin/src/features/magic-context/dreamer/retrospective-learnings.ts 111 Exact tag match in childText drops fields formatted with attributes or whitespace
packages/plugin/src/features/magic-context/dreamer/task-gates.ts 353 Unbounded backlog count when retrospectiveWatermarkMs option is omitted
Files Reviewed (16 files)
  • crates/mc-module/src/lib.rs
  • packages/pi-plugin/src/tools/ctx-memory.test.ts
  • packages/pi-plugin/src/tools/ctx-memory.ts - 1 issue
  • packages/plugin/src/features/magic-context/compartment-events.ts
  • packages/plugin/src/features/magic-context/dreamer/anti-memory-from-corrections.test.ts
  • packages/plugin/src/features/magic-context/dreamer/anti-memory-from-corrections.ts
  • packages/plugin/src/features/magic-context/dreamer/retrospective-learnings.test.ts
  • packages/plugin/src/features/magic-context/dreamer/retrospective-learnings.ts - 1 issue
  • packages/plugin/src/features/magic-context/dreamer/task-executor.ts
  • packages/plugin/src/features/magic-context/dreamer/task-gates.ts - 1 issue
  • packages/plugin/src/features/magic-context/dreamer/task-prompts.ts
  • packages/plugin/src/features/magic-context/memory/storage-anti-memory.ts
  • packages/plugin/src/tools/ctx-memory/claim-actions.ts
  • packages/plugin/src/tools/ctx-memory/tools.test.ts
  • packages/plugin/src/tools/ctx-memory/tools.ts - 1 issue
  • packages/plugin/src/tools/ctx-memory/types.ts

Fix these issues in Kilo Cloud


Reviewed by gemini-3.7-flash · Input: 231.8K · Output: 22.6K · Cached: 1.4M

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.

1 participant