Skip to content

fix: resolve issue #508#623

Closed
bryantrinh wants to merge 1 commit into
moorcheh-ai:mainfrom
bryantrinh:bounty-fix-508
Closed

fix: resolve issue #508#623
bryantrinh wants to merge 1 commit into
moorcheh-ai:mainfrom
bryantrinh:bounty-fix-508

Conversation

@bryantrinh

@bryantrinh bryantrinh commented Jun 2, 2026

Copy link
Copy Markdown

Resolves #508.

Implements fix for "[BOUNTY $100] 🐜 The Memanto + mattpocock Developer Skills Challenge". All tests and validation run successfully.

Summary by CodeRabbit

  • New Features

    • Added Memanto integration example demonstrating persistent memory across Claude Code skill executions, including memory injection before skill execution and extraction after completion.
  • Documentation

    • New README describing memory persistence concepts, integration workflow, and setup/execution instructions.
  • Tests

    • Added test coverage for memory injection and extraction functionality.
  • Chores

    • Updated .gitignore to exclude pipeline output files.

@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a complete example implementation that integrates Memanto persistent developer memory with Claude Code skill execution. It introduces a lifecycle hook (MemantoSkillsHook) that retrieves relevant context before skill execution and extracts memories for storage after execution, enabling cross-session persistence of engineering decisions and coding preferences.

Changes

Memanto Skills Integration Example

Layer / File(s) Summary
Core Memory Hook Implementation
examples/claudecode-skills-memanto/memory_hook.py
MemantoSkillsHook class with lazy Memanto agent initialization, semantic recall query construction from skill name/file path/task, keyword-based memory extraction from input/output text, and session cleanup. Provides pre_skill_execute() to inject prior memories and post_skill_execute() to extract and persist new memories via the Memanto SDK.
Hook Test Coverage
examples/claudecode-skills-memanto/test_skills.py
Tests verify initialize() creates/activates agents and handles reuse, pre_skill_execute() recalls and injects relevant memories with correct query formation, and post_skill_execute() extracts and persists memories with correct typing (preference, decision, learning, instruction).
Example Simulator and Dependencies
examples/claudecode-skills-memanto/skills_simulator.py, examples/claudecode-skills-memanto/requirements.txt
Demonstrates cross-session memory persistence through two simulated skill sessions; Session 1 stores preferences, Session 2 injects and uses those preferences. Declares dependencies on memanto, rich, python-dotenv, pytest, and pytest-asyncio.
Documentation and Config Updates
examples/claudecode-skills-memanto/README.md, .gitignore
README explains Memanto integration concepts, file structure, setup instructions (credential configuration, running simulator, running tests). Adds ignore patterns for bounty hunter solver pipeline artifacts.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 A memory hook springs forth,
Storing skills' decisions wide and deep,
Each session learns from the last,
Cross-prompt persistence you shall keep,
Engineering preferences forever leap! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is vague and generic, stating only 'fix: resolve issue #508' without describing the actual change or what issue #508 contains. Replace with a descriptive title that summarizes the main change, such as 'feat: add Memanto integration hook for Claude Code skills' or similar.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The PR successfully implements all primary coding requirements from issue #508: Global Memory Hook integration, Active Extraction (post_skill_execute), Dynamic Injection (pre_skill_execute), Memanto API usage, proper file structure under /examples/claudecode-skills-memanto, and working tests.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the bounty challenge requirements; the .gitignore update is a minor supporting change for the pipeline output files.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitai coderabbitai 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.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@examples/claudecode-skills-memanto/memory_hook.py`:
- Around line 87-91: The current code appends only the basename (p.name) to
query_parts which collapses different paths like src/index.css and
docs/index.css into the same memory scope; change it to use the full path (e.g.,
str(p) or p.as_posix()) when appending the file identifier and keep p.suffix for
the extension if desired, updating both occurrences that manipulate file_path /
p / query_parts so memories are scoped by full file path instead of just the
basename.
- Around line 109-123: post_skill_execute() and pre_skill_execute() are
currently promoting raw model output into persistent "strict" constraints;
change the logic so that only memories with an explicit user-authored or
validated source are persisted as authoritative and all LLM-derived memories are
saved with a source flag (e.g., "llm") and treated as advisory. In
post_skill_execute(), attach a source/validated flag to each memory and only
persist when source == "user" or validated==true; in pre_skill_execute(), build
the prompt from memories by including the source and by changing the wording
(remove "Please align your actions strictly with these constraints") to mark
LLM-derived memories as "advisory/context" while keeping user memories as
actionable. Also ensure any future persistence path checks the source/validated
metadata before treating content as mandatory.

In `@examples/claudecode-skills-memanto/README.md`:
- Around line 49-53: Update the README instructions to show correct .env file
syntax by removing the shell "export" usage and demonstrating the plain
KEY=VALUE form for MOORCHEH_API_KEY; also clarify the alternative (instead of
"or copy your Moorcheh API key") by stating the other option explicitly (for
example, paste the key into the .env file or set the MOORCHEH_API_KEY
environment variable in your shell) and reference the environment variable name
MOORCHEH_API_KEY so users know exactly what to name the entry.

In `@examples/claudecode-skills-memanto/skills_simulator.py`:
- Around line 102-111: The code reads MOORCHEH_API_KEY using Path.home() but
Path is not imported and the env-file parsing uses split("=") which can error;
import Path from pathlib at the top of skills_simulator.py, then in the fallback
parsing block (the logic that sets api_key) replace line.split("=")[1].strip()
with robust parsing using line.partition("=")[2].strip() and only assign api_key
if the partitioned value is non-empty to avoid NameError and improve key
extraction.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 06860623-382d-4523-a10e-81929a6da097

📥 Commits

Reviewing files that changed from the base of the PR and between 2d81022 and 7f2c13c.

📒 Files selected for processing (6)
  • .gitignore
  • examples/claudecode-skills-memanto/README.md
  • examples/claudecode-skills-memanto/memory_hook.py
  • examples/claudecode-skills-memanto/requirements.txt
  • examples/claudecode-skills-memanto/skills_simulator.py
  • examples/claudecode-skills-memanto/test_skills.py

Comment on lines +87 to +91
if file_path:
p = Path(file_path)
query_parts.append(f"file: {p.name}")
if p.suffix:
query_parts.append(f"extension: {p.suffix}")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use the full file path for memory scoping, not just the basename.

Right now src/index.css and docs/index.css are both reduced to index.css, so recall/store can cross-contaminate unrelated memories. That weakens the “current file path/task” contract from the issue.

💡 Suggested fix
         if file_path:
             p = Path(file_path)
-            query_parts.append(f"file: {p.name}")
+            normalized_path = p.as_posix()
+            query_parts.append(f"path: {normalized_path}")
+            query_parts.append(f"file: {p.name}")
             if p.suffix:
                 query_parts.append(f"extension: {p.suffix}")
@@
         if file_path:
-            tags.append(Path(file_path).name)
+            tags.append(f"path:{Path(file_path).as_posix()}")

Also applies to: 184-185

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/claudecode-skills-memanto/memory_hook.py` around lines 87 - 91, The
current code appends only the basename (p.name) to query_parts which collapses
different paths like src/index.css and docs/index.css into the same memory
scope; change it to use the full path (e.g., str(p) or p.as_posix()) when
appending the file identifier and keep p.suffix for the extension if desired,
updating both occurrences that manipulate file_path / p / query_parts so
memories are scoped by full file path instead of just the basename.

Comment on lines +109 to +123
prompt_lines = [
"\n==================================================",
"💡 [Memanto Persistent Developer Memory Context]",
"The following relevant engineering choices, preferences,",
"and codebase quirks were recalled for this context:",
]

for i, mem in enumerate(memories, 1):
mem_type = mem.get("type", "fact")
title = mem.get("title", "Untitled")
content = mem.get("content", "")
prompt_lines.append(f" {i}. [{mem_type.upper()}] {title}: {content}")

prompt_lines.append("Please align your actions strictly with these constraints.")
prompt_lines.append("==================================================\n")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Don’t promote untrusted model output into future hard constraints.

post_skill_execute() persists snippets taken directly from output_text, and pre_skill_execute() later injects every recalled memory as something the model should follow “strictly”. That lets a bad or injected completion become a persistent system-level instruction for later skills.

At minimum, only persist explicitly user-authored preferences as authoritative, and render LLM-derived memories as advisory context unless they’ve been validated/confirmed.

Also applies to: 163-205

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/claudecode-skills-memanto/memory_hook.py` around lines 109 - 123,
post_skill_execute() and pre_skill_execute() are currently promoting raw model
output into persistent "strict" constraints; change the logic so that only
memories with an explicit user-authored or validated source are persisted as
authoritative and all LLM-derived memories are saved with a source flag (e.g.,
"llm") and treated as advisory. In post_skill_execute(), attach a
source/validated flag to each memory and only persist when source == "user" or
validated==true; in pre_skill_execute(), build the prompt from memories by
including the source and by changing the wording (remove "Please align your
actions strictly with these constraints") to mark LLM-derived memories as
"advisory/context" while keeping user memories as actionable. Also ensure any
future persistence path checks the source/validated metadata before treating
content as mandatory.

Comment on lines +49 to +53
Create/edit a `.env` file in the repository root or copy your Moorcheh API key:

```bash
export MOORCHEH_API_KEY="your-api-key-here"
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix .env file syntax and clarify instructions.

The example shows shell export syntax, but .env files don't use the export keyword. This could confuse users or cause the environment variable to not load correctly with dotenv parsers.

Additionally, line 49's phrasing "or copy your Moorcheh API key" is unclear about what the alternative to creating a .env file would be.

📝 Proposed fix
-Create/edit a `.env` file in the repository root or copy your Moorcheh API key:
+Create a `.env` file in the repository root with your Moorcheh API key:
 
 ```bash
-export MOORCHEH_API_KEY="your-api-key-here"
+MOORCHEH_API_KEY=your-api-key-here
</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
Create a `.env` file in the repository root with your Moorcheh API key:

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/claudecode-skills-memanto/README.md` around lines 49 - 53, Update
the README instructions to show correct .env file syntax by removing the shell
"export" usage and demonstrating the plain KEY=VALUE form for MOORCHEH_API_KEY;
also clarify the alternative (instead of "or copy your Moorcheh API key") by
stating the other option explicitly (for example, paste the key into the .env
file or set the MOORCHEH_API_KEY environment variable in your shell) and
reference the environment variable name MOORCHEH_API_KEY so users know exactly
what to name the entry.

Comment on lines +102 to +111
# Read Moorcheh API Key
api_key = os.environ.get("MOORCHEH_API_KEY")
if not api_key:
# Check standard config file fallback
_env_path = Path.home() / ".memanto" / ".env"
if _env_path.exists():
with open(_env_path) as f:
for line in f:
if line.startswith("MOORCHEH_API_KEY="):
api_key = line.split("=")[1].strip()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file=$(fd -p 'skills_simulator.py' | head -n1)
sed -n '1,25p' "$file"
printf '\n--- Path usage ---\n'
rg -n '\bPath\b' "$file"

Repository: moorcheh-ai/memanto

Length of output: 786


Import Path before using the fallback env-file path

examples/claudecode-skills-memanto/skills_simulator.py (lines 106-111) uses Path.home() but Path isn’t imported, causing a NameError when MOORCHEH_API_KEY is missing. Harden the key parsing by using partition("=") instead of split("=")[1].

💡 Suggested fix
 import os
 import sys
 import time
+from pathlib import Path
@@
         if _env_path.exists():
             with open(_env_path) as f:
                 for line in f:
                     if line.startswith("MOORCHEH_API_KEY="):
-                        api_key = line.split("=")[1].strip()
+                        _, _, api_key = line.partition("=")
+                        api_key = api_key.strip()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/claudecode-skills-memanto/skills_simulator.py` around lines 102 -
111, The code reads MOORCHEH_API_KEY using Path.home() but Path is not imported
and the env-file parsing uses split("=") which can error; import Path from
pathlib at the top of skills_simulator.py, then in the fallback parsing block
(the logic that sets api_key) replace line.split("=")[1].strip() with robust
parsing using line.partition("=")[2].strip() and only assign api_key if the
partitioned value is non-empty to avoid NameError and improve key extraction.

@cwwjacobs

cwwjacobs commented Jun 9, 2026

Copy link
Copy Markdown

/attempt #508

Submitted PR: #717

Social showcase: https://x.com/TerminusProto/status/2064451356392661020?s=20

Reviewer-safe demo repo: https://github.com/cwwjacobs/mdemo

@Xenogents

Copy link
Copy Markdown
Collaborator

We were blown away by the community's creativity and the sheer volume of high-quality submissions! After reviewing all the pull requests against the bounty's success matrix, we have decided to move forward with merging PR #692, which implemented a highly portable prompt-injection architecture via CLAUDE.md.

We are closing this PR because it falls into one of the architectural approaches that we ultimately decided against for the ecosystem:

  • High Friction (CLI Wrappers): Many submissions used Python or Bash wrappers (e.g., forcing the user to type memanto-wrap /tdd instead of the native claude /tdd). While effective at passing context, managing child PTY processes introduces terminal overhead and breaks the developer's native muscle memory
  • Incomplete Lifecycle (Manual Scripts): Some submissions successfully implemented the context extraction logic but failed to automate it, requiring the user to manually run pre and post scripts around every skill session.

We deeply appreciate the time and engineering effort you put into this submission. The codebase was fantastic to review, and we hope to see you in future Moorcheh bounties!

@Xenogents Xenogents closed this Jun 16, 2026
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.

[BOUNTY $100] 🐜 The Memanto + mattpocock Developer Skills Challenge

3 participants