Skip to content

feat: add learned repo memory and MCP product-proof evals - #69

Open
bernoussama wants to merge 7 commits into
masterfrom
fix/skill-mcp
Open

feat: add learned repo memory and MCP product-proof evals#69
bernoussama wants to merge 7 commits into
masterfrom
fix/skill-mcp

Conversation

@bernoussama

@bernoussama bernoussama commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add structured clanker learn workflows with local repo Markdown mirrors, sync/export, deduplication, and private-by-default storage.
  • Extend the MCP server and bundled skills with learn_solution, repo solution resources, stronger search triggers, and untrusted-result guidance.
  • Add ambient hook/setup improvements, product-proof and repo-StackOverflow eval harnesses, tests, and CLI version 1.4.1 plugin metadata.

Validation

  • pnpm --filter @clankeroverflow/cli build
  • pnpm --filter @clankeroverflow/cli test (163 tests)
  • pnpm run lint (passes with existing warnings)
  • pnpm run format
  • uvx --from skills-ref agentskills validate for all three ClankerOverflow skills
  • git diff --cached --check

Review notes

  • Product-proof reports are included as reproducible evaluation artifacts; their current claim gate is intentionally not presented as a performance guarantee.
  • This PR includes the complete confirmed worktree scope.

Summary by CodeRabbit

  • New Features
    • Added a verified learn workflow (dedupe, redaction, repo Markdown mirrors) with learn sync and learn export.
    • Added MCP tools for learning solutions plus repository solution note browsing.
    • Added product-proof and repo StackOverflow benchmark/eval tooling that generates metrics and reports.
    • Added a Pi reminder extension to prompt search when required.
  • Documentation
    • Updated CLI, MCP, plugin, and skill guidance to emphasize search-first and the learn workflow.
  • Bug Fixes
    • Improved hook handling to detect resolved failures and nudge users to save verified fixes.

Copilot AI review requested due to automatic review settings July 10, 2026 14:06
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Walkthrough

The changes add verified solution learning across the CLI and MCP server, repository solution resources, benchmark and recorder workflows, Pi search reminders, failure-resolution hooks, debug fixtures, reports, and updated skill and plugin guidance.

Changes

Learning and MCP integration

Layer / File(s) Summary
Structured learning and repository notes
packages/cli/src/{learn.ts,learn.test.ts,index.ts,index.test.ts}, packages/cli/commands/*
Adds validated and sanitized learning, deduplication, local persistence, Markdown mirroring, sync/export workflows, and CLI subcommands.
MCP learning surface
packages/cli/src/mcp/*
Adds learn_solution, learning prompts, repository resources, expanded search guidance, and backend cleanup.
Agent guidance and packaging
packages/cli/skills/*, skills/*, packages/cli/*plugin.json
Updates search-first behavior, learning/logging distinctions, authentication guidance, plugin metadata, and the CLI version.

Evaluation and product-proof workflows

Layer / File(s) Summary
Benchmark core and reports
packages/cli/src/evals/product-proof.*, clankeroverflow-mcp-workspace/product-proof/*
Adds scenario and fixture loading, grading, retrieval checks, cost and pair metrics, generated reports, sample runs, and debug workspace verification.
Claude and Codex recorders
packages/cli/src/evals/record-{claude,codex}-product-proof.*
Runs isolated evaluations, parses event logs, captures usage and tool calls, verifies workspace changes, supports resumption, and writes run artifacts.
Repository reuse evaluation
packages/cli/src/evals/repo-stackoverflow.*, clankeroverflow-mcp-workspace/repo-stackoverflow/*
Adds a deterministic learn, sync, retrieval, sensitive-content, and report-generation evaluation.
Pi triggering evaluation
packages/cli/src/evals/pi-triggering.*, clankeroverflow-mcp-workspace/pi-triggering/*
Adds prompt classification, JSONL turn auditing, search-before-debug grading, and recall/precision metrics.

Hooks and agent setup

Layer / File(s) Summary
Failure-resolution learning
packages/cli/hooks/post-tool-use.mjs, packages/cli/hooks/session-start.mjs
Tracks recent failures and emits a learn_solution prompt after stop or verification-success events.
Pi reminder extension
packages/cli/extensions/clankeroverflow-reminder.ts, packages/cli/src/setup.ts, packages/cli/src/pi-reminder.test.ts, packages/cli/src/setup.test.ts
Adds prompt and tool-error fingerprint detection, installs the Pi reminder extension, and verifies installation and removal.
Stop-hook installation
packages/cli/src/hooks/install.*, packages/cli/hooks/hooks.json
Registers the post-tool-use hook for Stop events across supported generated configurations.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Poem

A rabbit learned a fix today,
Then tucked its notes away.
Hooks search when errors hop,
Reports bloom atop the crop.
MCP remembers what was true—
And shares the fix with you!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title captures the main additions: learned repo memory plus MCP/product-proof evals.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/skill-mcp

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copilot AI 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.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

@bernoussama

Copy link
Copy Markdown
Owner Author

@coderabbitai review

Generated benchmark summaries and raw run captures were removed. The PR is now 148 changed files and 14,237 added lines, below the automated review limits.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

@bernoussama Thanks for trimming the generated benchmark summaries and raw run captures — I'll kick off a fresh review of the PR now that it's within limits.

ヽ(・∀・)ノ

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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: 10

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

🟡 Minor comments (14)
clankeroverflow-mcp-workspace/product-proof/README.md-11-12 (1)

11-12: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Update the scenario count in README.md clankeroverflow-mcp-workspace/product-proof/README.md:11-12 says scenarios.json has 30 prompts, but the file now contains 38; align the doc with the current fixture set or note that it refers to an older revision.

🤖 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 `@clankeroverflow-mcp-workspace/product-proof/README.md` around lines 11 - 12,
Update the scenarios.json description in the product-proof README to reflect the
current 38 prompts, or explicitly label the documented count as belonging to an
older revision.
clankeroverflow-mcp-workspace/iteration-1/prisma-neon-timeout/without_skill/outputs/response.md-28-30 (1)

28-30: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add a language identifier to the fenced dotenv example.

Markdownlint MD040 flags Line 28. Use a language such as text or dotenv after the opening fence.

🤖 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
`@clankeroverflow-mcp-workspace/iteration-1/prisma-neon-timeout/without_skill/outputs/response.md`
around lines 28 - 30, Add a language identifier to the opening fence of the
dotenv example containing DIRECT_URL, using text or dotenv to satisfy
Markdownlint MD040.

Source: Linters/SAST tools

packages/cli/src/evals/repo-stackoverflow.ts-190-194 (1)

190-194: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reject missing option values instead of treating the next flag as a path.

For example, --output-json --workspace-root /tmp assigns --workspace-root as the JSON output path. Validate that the next argument exists and does not start with --, or fail with a clear usage error.

🤖 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 `@packages/cli/src/evals/repo-stackoverflow.ts` around lines 190 - 194, The
parseArg function currently accepts another flag as an option value; validate
that index + 1 exists and the next argument does not start with “--”. If
validation fails, raise a clear usage error instead of returning the flag as a
path.
clankeroverflow-mcp-workspace/product-proof/reports/report-claude-smoke-low-r2.md-54-60 (1)

54-60: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Fix or remove the port leak-check loop.

ss -ltn only checks listening sockets, not TIME_WAIT, and the ! ... || { ... break; } condition breaks on the first successful ss invocation regardless of whether a matching socket exists. This loop neither waits nor validates the suspected failure state.

🤖 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
`@clankeroverflow-mcp-workspace/product-proof/reports/report-claude-smoke-low-r2.md`
around lines 54 - 60, Fix or remove the port leak-check loop in the report
methodology: replace the flawed ss -ltn condition with an explicit check that
validates whether the target port is present and, if retaining the loop, waits
and retries until the intended state is reached; otherwise remove the loop and
document the limitation that listening-socket checks do not detect TIME_WAIT.
clankeroverflow-mcp-workspace/product-proof/reports/report-claude-smoke-low-r2.md-38-42 (1)

38-42: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Don’t describe this as an explicit SO_REUSEADDR fix. The sample only calls server.listen(...); it doesn’t set a reuse option. Since Node already enables SO_REUSEADDR on net servers, this wording overstates the change and implies the bind issue is resolved when it isn’t.

🤖 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
`@clankeroverflow-mcp-workspace/product-proof/reports/report-claude-smoke-low-r2.md`
around lines 38 - 42, The report incorrectly characterizes the change as an
explicit SO_REUSEADDR fix. Revise the affected wording to state only that the
server uses server.listen(...) and avoid claiming reuse options were set or that
the bind issue was resolved.
packages/cli/src/evals/record-codex-product-proof.test.ts-54-59 (1)

54-59: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert the final enabled value for without_mcp.
The test only checks that both mcp_servers.clankeroverflow.enabled=true and ...=false are present, so it still passes if the override order changes. Assert that ...=false is the final clankeroverflow.enabled entry.

🤖 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 `@packages/cli/src/evals/record-codex-product-proof.test.ts` around lines 54 -
59, Update the “disables ClankerOverflow for the without_mcp config” test to
verify the final clankeroverflow enabled override, rather than merely checking
both values are present. Use the args produced by codexArgs and assert that the
last mcp_servers.clankeroverflow.enabled entry is exactly false.
clankeroverflow-mcp-workspace/iteration-1/ts2307-pnpm-workspaces/without_skill/outputs/response.md-13-15 (1)

13-15: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

node10 doesn’t support exports
moduleResolution: "node"/"node10" is legacy and should not be described as partially resolving package.json exports; if the package relies on exports, use node16, nodenext, or bundler instead.

🤖 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
`@clankeroverflow-mcp-workspace/iteration-1/ts2307-pnpm-workspaces/without_skill/outputs/response.md`
around lines 13 - 15, Correct the module-resolution comparison in the referenced
guidance: update the description of moduleResolution "node"/"node10" to state
that it does not support package.json exports, rather than partially resolving
them, and direct exports-based packages to use "node16", "nodenext", or
"bundler".
clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-neon-first-query/test.mjs-3-5 (1)

3-5: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Limit the assertion to the createBranch implementation.

The current regex matches any return sql appearing anywhere after createBranch(), including a later function, so valid fixtures can fail. Scope the check to the function body or use a more precise structural/runtime assertion.

🤖 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
`@clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-neon-first-query/test.mjs`
around lines 3 - 5, Refine the assertion in the test fixture so it inspects only
the body of the createBranch implementation, rather than any later return sql in
the file. Update the regex to capture the createBranch function body or replace
it with a precise structural/runtime check, and assert only that this
implementation does not immediately execute a query after branch creation.
clankeroverflow-mcp-workspace/iteration-1/ts2307-pnpm-workspaces/with_skill/outputs/response.md-24-60 (1)

24-60: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Clarify the pnpm vs TypeScript boundary
At clankeroverflow-mcp-workspace/iteration-1/ts2307-pnpm-workspaces/with_skill/outputs/response.md:24-60, separate pnpm’s dependency/linking requirement from TypeScript’s module resolution. Declaring workspace:* makes the package available to the consuming workspace; TypeScript then reads exports/types/main from that package, and built .d.ts files are only required when the package ships compiled types.

🤖 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
`@clankeroverflow-mcp-workspace/iteration-1/ts2307-pnpm-workspaces/with_skill/outputs/response.md`
around lines 24 - 60, Clarify the separation between pnpm and TypeScript: state
that adding the workspace:* dependency in the consuming package enables pnpm
linking, after which TypeScript resolves the package using its package.json
fields such as exports, types, and main. Revise the guidance around built .d.ts
files to say they are required only when the dependency ships compiled
declarations, rather than implying TypeScript always requires a build; preserve
the relevant verification steps.
packages/cli/src/mcp/server.ts-484-487 (1)

484-487: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Tighten repo-solution lookup to exact matches. readSolutionResource() only reads from listRepoSolutionFiles(), so this isn’t a path-traversal vector, but candidate.includes(idOrSlug) can resolve the wrong note for partial ids/slugs. Match the basename exactly (or key by basename) instead.
packages/cli/src/learn.ts:444-450

🤖 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 `@packages/cli/src/mcp/server.ts` around lines 484 - 487, Update
readSolutionResource to select a repository solution only when its basename
exactly equals the requested idOrSlug, replacing the partial
candidate.includes(idOrSlug) lookup with an exact basename comparison or
basename-keyed lookup; preserve the existing not-found behavior and ensure the
MCP resource handler continues using readSolutionResource.
packages/cli/src/evals/record-codex-product-proof.ts-400-407 (1)

400-407: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Check result.error for spawn failures (e.g., ENOENT).

When spawnSync fails to spawn the process (codex binary not found), result.error is set and result.status is null. The code enters the error branch via result.status !== 0, but the error message is built only from result.stderr and event errors — both empty on ENOENT. The resulting message "Codex exec failed with status unknown." doesn't indicate the binary was missing.

🛡️ Proposed fix to include spawn error in error output
   if (result.status !== 0) {
+    const spawnError = result.error?.message ?? "";
     const stderrExcerpt = (result.stderr ?? "").split(/\r?\n/).slice(-12).join("\n").trim();
     const eventErrors = eventErrorMessages(eventsPath).join("\n").trim();
-    const errorText = [eventErrors, stderrExcerpt].filter(Boolean).join("\n");
+    const errorText = [spawnError, eventErrors, stderrExcerpt].filter(Boolean).join("\n");
     return {
       scenario_id: scenario.id,
       config,
       repetition,
       status: "failed",
       error: errorText,
-      transcript: `Codex exec failed with status ${result.status ?? "unknown"}.\n${errorText}`,
+      transcript: `Codex exec failed with status ${result.status ?? "unknown"}.\n${errorText}`,
       usage,
🤖 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 `@packages/cli/src/evals/record-codex-product-proof.ts` around lines 400 - 407,
Handle spawn failures explicitly in the code surrounding the spawnSync
invocation: check result.error and include its details in the constructed
failure message before or alongside status and stderr handling. Update the error
branch so ENOENT and other process-launch errors identify the underlying spawn
error instead of reporting only an unknown status.

Source: Linters/SAST tools

packages/cli/src/learn.ts-82-83 (1)

82-83: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Env var redaction misses quoted values.

The regex value group [^\s"']+excludes quote characters, so common patterns likeDATABASE_URL="postgres://..."orAPI_KEY='sk_...'are not redacted. Only unquoted values likeFOO=bar` are caught.

🛡️ Proposed fix to also match quoted env var values
-    [/\b([A-Z][A-Z0-9_]{2,})=([^\s"'`]+)/g, "$1=<redacted>", "env var value"],
+    [/\b([A-Z][A-Z0-9_]{2,})=("[^"]*"|'[^']*'|[^\s"'`]+)/g, "$1=<redacted>", "env var value"],
🤖 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 `@packages/cli/src/learn.ts` around lines 82 - 83, Update the env-var
replacement regex in the `replacements` array to match both unquoted values and
single- or double-quoted values, while preserving the existing variable-name
matching and replacing the entire value with `<redacted>`.
packages/cli/src/learn.ts-300-348 (1)

300-348: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Close the backend in learnSolution. createSolutionBackend() opens a new LocalBackend/SQLite handle per call, but SolutionBackend has no cleanup path. In the MCP server, repeated learn_solution calls can leave handles open; add a close()/dispose() hook and call it in a finally block, or reuse a shared backend.

🤖 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 `@packages/cli/src/learn.ts` around lines 300 - 348, Ensure learnSolution
always releases the backend created by createSolutionBackend: add a
close/dispose lifecycle method to the SolutionBackend interface and its
implementations, then wrap the duplicate-checking, logging, and mirror-writing
flow in a try/finally that invokes the backend cleanup method. Preserve existing
return behavior while guaranteeing cleanup on success, duplicates, and errors.
clankeroverflow-mcp-workspace/iteration-1/grade_and_aggregate.py-286-290 (1)

286-290: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Delta formatting breaks for negative deltas.

f"+{...:.2f}" always prepends +, so a negative delta renders as "+-0.15" instead of "-0.15". This string is written to benchmark.json and consumed by review.html's deltaClass(), which does parseFloat(val)parseFloat("+-0.15") is NaN, silently dropping the positive/negative color coding for that cell.

🐛 Suggested fix
-            "delta": {"pass_rate": f"+{stats(ws_runs)['mean'] - stats(wo_runs)['mean']:.2f}"},
+            "delta": {"pass_rate": f"{stats(ws_runs)['mean'] - stats(wo_runs)['mean']:+.2f}"},
🤖 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 `@clankeroverflow-mcp-workspace/iteration-1/grade_and_aggregate.py` around
lines 286 - 290, Fix the delta formatting in the run_summary construction by
replacing the unconditional “+” prefix with sign-aware formatting, so positive
values render with “+”, negative values with “-”, and zero consistently; ensure
the resulting string remains parseable by review.html’s deltaClass() via
parseFloat.
🧹 Nitpick comments (5)
packages/cli/src/mcp/server.ts (2)

466-477: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Consider async file reads in the list callback to avoid blocking the event loop.

readFileSync is called synchronously inside the async list callback for every solution file. For repos with many learned solutions, this blocks the event loop during enumeration. Switching to fs/promises readFile would be more consistent with the async handler pattern.

🤖 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 `@packages/cli/src/mcp/server.ts` around lines 466 - 477, Update the MCP
resource `list` callback to use asynchronous file reads instead of
`readFileSync`. Import `readFile` from `fs/promises`, make the mapping await
each file read and parse its contents, and use `Promise.all` so `list` returns
all resource entries without blocking the event loop.

466-477: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use path.basename instead of file.split("/") for cross-platform compatibility.

file.split("/").at(-1) won't extract the filename correctly on Windows where paths use backslashes. Use path.basename(file, ".md") for robust cross-platform behavior.

♻️ Proposed fix
+import { basename } from "node:path";
+
 // ... in the list callback:
         resources: listRepoSolutionFiles().map((file) => {
           const parsed = parseLearnMarkdown(readFileSync(file, "utf8"));
-          const name = file.split("/").at(-1)?.replace(/\.md$/, "") ?? file;
+          const name = basename(file, ".md");
           return {
🤖 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 `@packages/cli/src/mcp/server.ts` around lines 466 - 477, Replace the manual
filename extraction in the MCP resource list callback with path.basename(file,
".md"), ensuring the path module is imported and the existing fallback behavior
is preserved if needed.
packages/cli/src/evals/record-codex-product-proof.ts (1)

347-353: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Use shell-safe single-quote escaping for path substitution in verifyWorkspace.

spawnSync with shell: true and a string command is a command-injection surface. JSON.stringify produces double-quoted strings, but shell double quotes still interpret $, backticks, and !. While the verification command comes from trusted fixture data and workspacePath is from mkdtempSync, benchmarkWorkspaceDir is user-controlled via --workspace. Switching to single-quote shell escaping eliminates all metacharacter interpretation.

🔒️ Proposed fix using single-quote shell escaping
 function verifyWorkspace(scenario: Scenario, benchmarkWorkspaceDir: string, workspacePath: string) {
   if (scenario.task_type !== "debug_workspace" || !scenario.verification_command) {
     return {};
   }
-  const quote = (value: string) => JSON.stringify(value);
+  const quote = (value: string) => `'${value.replaceAll("'", "'\\''")}'`;
   const command = scenario.verification_command
     .replaceAll("{workspace}", quote(workspacePath))
     .replaceAll("{workspaceDir}", quote(benchmarkWorkspaceDir));
🤖 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 `@packages/cli/src/evals/record-codex-product-proof.ts` around lines 347 - 353,
Update verifyWorkspace and the command construction before spawnSync to
shell-escape benchmarkWorkspaceDir/workspacePath with single quotes, replacing
each embedded single quote with the standard '\'' sequence. Do not use
JSON.stringify or double-quoted substitutions for user-controlled paths, while
preserving shell: true and the existing command behavior.

Source: Linters/SAST tools

packages/cli/src/learn.ts (1)

379-413: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Export loses structured fields during round-trip.

parseStructuredSolution returns the entire "Reusable Context" section as repoNote, but doesn't extract framework, runtime, packageManager, or fingerprints back into individual fields. After export → re-import via syncRepoSolutions, these fields are empty — degrading duplicate detection (falls back to problem text instead of fingerprints) and tag normalization.

♻️ Proposed fix to parse individual fields from Reusable Context
 function parseStructuredSolution(solution: string) {
+  const context = markdownSection(solution, "Reusable Context");
+  const extractItem = (label: string) => {
+    const match = context.match(new RegExp(`^- ${label}:\\s*(.+)$`, "m"));
+    return match?.[1]?.trim() ?? "";
+  };
   return {
     rootCause: markdownSection(solution, "Root Cause") || "See verified fix.",
     solution: markdownSection(solution, "Verified Fix") || solution,
     verification:
       markdownSection(solution, "Verification") || "Previously logged in ClankerOverflow.",
-    repoNote: markdownSection(solution, "Reusable Context"),
+    repoNote: extractItem("Repo note"),
+    framework: extractItem("Framework"),
+    runtime: extractItem("Runtime"),
+    packageManager: extractItem("Package manager"),
+    fingerprints: extractItem("Fingerprints"),
   };
 }

Then update exportLocalSolutions to pass the extracted fields to writeLearnMarkdown:

     return writeLearnMarkdown(repoRoot, row.id, {
       problem: row.problem,
       rootCause: parsed.rootCause,
       solution: parsed.solution,
       verification: parsed.verification,
       repoNote: parsed.repoNote,
+      framework: parsed.framework,
+      runtime: parsed.runtime,
+      packageManager: parsed.packageManager,
+      fingerprints: parsed.fingerprints,
       tags: row.tags ?? "clankeroverflow",
     });
🤖 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 `@packages/cli/src/learn.ts` around lines 379 - 413, Update
parseStructuredSolution to parse framework, runtime, packageManager, and
fingerprints individually from the “Reusable Context” section, while retaining
repoNote as needed. In exportLocalSolutions, pass these parsed fields to
writeLearnMarkdown so export→syncRepoSolutions preserves duplicate-detection
fingerprints and tag normalization metadata.
packages/cli/src/evals/product-proof.ts (1)

410-412: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Confusing literal-key fallback in pricingForModel.

pricing?.model reads the literal property named "model" on the pricing config — it is NOT pricing?.[model] (the parameter). This is confirmed intentional (the test suite passes pricing: { model: {...} } as a generic default rate), but the dot-notation makes it read exactly like a copy/paste bug where [model]was intended. Consider renaming the special key (e.g.pricing?.defaultis already used right after it — two different "default" mechanisms is itself confusing) or adding a comment clarifying that"model"` is a magic fallback key, not a dynamic lookup.

🤖 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 `@packages/cli/src/evals/product-proof.ts` around lines 410 - 412, Clarify the
intentional literal-key fallback in pricingForModel by adding a concise comment
identifying pricing.model as the magic generic default rate, distinct from the
dynamic pricing[model] lookup and pricing.default fallback; preserve the
existing fallback behavior.
🤖 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
`@clankeroverflow-mcp-workspace/iteration-1/ts2307-pnpm-workspaces/without_skill/outputs/response.md`:
- Around line 52-58: Clarify the package exports example so the "./src/index.ts"
target is explicitly limited to bundlers or configured TypeScript loaders. For
stock Node consumers, show runtime exports targeting compiled ".js" files and
type exports targeting ".d.ts" declarations, and update the surrounding
explanation accordingly.

In
`@clankeroverflow-mcp-workspace/product-proof/reports/report-debug-cost-hidden-r2.md`:
- Around line 9-19: Reconcile the report’s 24-sample recall denominators with
the current scenario catalog and trigger-eval-set.json inputs. Regenerate the
metrics from those inputs, or document the exact dataset and revision that
produced 24 cases, and update the report’s headline metrics so every denominator
is reproducible.

In
`@clankeroverflow-mcp-workspace/product-proof/workspace-verifiers/debug-prisma-neon.mjs`:
- Around line 4-7: Update the `directUrl` validation in the schema-checking
script to capture the environment variable used by the `directUrl = env(...)`
assignment, then validate that captured value against `DIRECT_URL`,
`DIRECT_DATABASE_URL`, or `DATABASE_DIRECT_URL`. Remove the file-wide
environment-variable regex so unrelated comments or fields cannot satisfy the
check.

In
`@clankeroverflow-mcp-workspace/product-proof/workspace-verifiers/debug-react-query-rollback.mjs`:
- Line 5: Fix the regex in the verifier’s source check by grouping the
alternatives so “context” is only accepted as part of the intended return
pattern, rather than matching anywhere in the file. Update the condition around
the existing source test and preserve case-insensitive matching.

In
`@clankeroverflow-mcp-workspace/product-proof/workspace-verifiers/debug-sentry-sourcemaps.mjs`:
- Around line 5-6: The verifier currently accepts unrelated text containing
configuration keywords; update the validation in the sourcemap verifier to
assert the expected property/value combinations for hidden sourcemaps,
post-upload file deletion, and release configuration. Replace the broad regex
check with targeted patterns or parsed configuration checks that cannot be
satisfied by comments, arbitrary strings, or variable names.

In
`@clankeroverflow-mcp-workspace/product-proof/workspace-verifiers/debug-stripe-workers.mjs`:
- Around line 5-8: Update the verifier assertions around the fixture source
checks to validate the actual webhook implementation rather than arbitrary token
presence: inspect or execute the handler path to confirm it calls Stripe’s
asynchronous event-construction API with the raw request body, while still
rejecting synchronous constructEvent usage. Replace the broad checks in the
debug-stripe-workers verifier with assertions tied to the handler’s call and
raw-body expression.

In `@packages/cli/skills/clankeroverflow-cli/SKILL.md`:
- Around line 72-101: Pin `@clankeroverflow/cli` to an approved explicit version
in every new npx example, including the learn and log command snippets in the
SKILL.md section. Replace the unversioned package references consistently and
preserve the existing command options and guidance.

In `@packages/cli/src/evals/product-proof.ts`:
- Around line 678-701: Remove or broaden the duplicate headline metrics in the
report: update the calculations and output references around mustSearchRecall,
knownFixTriggerRecall, usefulRetrievalRate, and knownFixRetrievalRate so
identical values are not presented under different labels. Prefer widening one
metric’s scope to represent a distinct population; otherwise remove the
redundant rows and keep a single canonical label for each signal.

In `@packages/cli/src/evals/repo-stackoverflow.ts`:
- Around line 138-143: Update the leakage measurement around unsafeText to
include the generated repository note and the solution content returned by
pass-2 search, rather than only the controlled expoScenario fields. Combine
these persisted and retrieved artifacts with the scenario text before applying
the existing unsafeText regular-expression check.

In `@packages/cli/src/index.ts`:
- Around line 294-311: Propagate parent learn options into the sync subcommand
instead of allowing child defaults to override them. Update the sync command
definition and its option-reading logic to avoid redeclaring defaulted --source
and --no-dedupe values, or explicitly resolve those options from the parent
learn command, preserving values supplied to learn before sync.

---

Minor comments:
In `@clankeroverflow-mcp-workspace/iteration-1/grade_and_aggregate.py`:
- Around line 286-290: Fix the delta formatting in the run_summary construction
by replacing the unconditional “+” prefix with sign-aware formatting, so
positive values render with “+”, negative values with “-”, and zero
consistently; ensure the resulting string remains parseable by review.html’s
deltaClass() via parseFloat.

In
`@clankeroverflow-mcp-workspace/iteration-1/prisma-neon-timeout/without_skill/outputs/response.md`:
- Around line 28-30: Add a language identifier to the opening fence of the
dotenv example containing DIRECT_URL, using text or dotenv to satisfy
Markdownlint MD040.

In
`@clankeroverflow-mcp-workspace/iteration-1/ts2307-pnpm-workspaces/with_skill/outputs/response.md`:
- Around line 24-60: Clarify the separation between pnpm and TypeScript: state
that adding the workspace:* dependency in the consuming package enables pnpm
linking, after which TypeScript resolves the package using its package.json
fields such as exports, types, and main. Revise the guidance around built .d.ts
files to say they are required only when the dependency ships compiled
declarations, rather than implying TypeScript always requires a build; preserve
the relevant verification steps.

In
`@clankeroverflow-mcp-workspace/iteration-1/ts2307-pnpm-workspaces/without_skill/outputs/response.md`:
- Around line 13-15: Correct the module-resolution comparison in the referenced
guidance: update the description of moduleResolution "node"/"node10" to state
that it does not support package.json exports, rather than partially resolving
them, and direct exports-based packages to use "node16", "nodenext", or
"bundler".

In `@clankeroverflow-mcp-workspace/product-proof/README.md`:
- Around line 11-12: Update the scenarios.json description in the product-proof
README to reflect the current 38 prompts, or explicitly label the documented
count as belonging to an older revision.

In
`@clankeroverflow-mcp-workspace/product-proof/reports/report-claude-smoke-low-r2.md`:
- Around line 54-60: Fix or remove the port leak-check loop in the report
methodology: replace the flawed ss -ltn condition with an explicit check that
validates whether the target port is present and, if retaining the loop, waits
and retries until the intended state is reached; otherwise remove the loop and
document the limitation that listening-socket checks do not detect TIME_WAIT.
- Around line 38-42: The report incorrectly characterizes the change as an
explicit SO_REUSEADDR fix. Revise the affected wording to state only that the
server uses server.listen(...) and avoid claiming reuse options were set or that
the bind issue was resolved.

In
`@clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-neon-first-query/test.mjs`:
- Around line 3-5: Refine the assertion in the test fixture so it inspects only
the body of the createBranch implementation, rather than any later return sql in
the file. Update the regex to capture the createBranch function body or replace
it with a precise structural/runtime check, and assert only that this
implementation does not immediately execute a query after branch creation.

In `@packages/cli/src/evals/record-codex-product-proof.test.ts`:
- Around line 54-59: Update the “disables ClankerOverflow for the without_mcp
config” test to verify the final clankeroverflow enabled override, rather than
merely checking both values are present. Use the args produced by codexArgs and
assert that the last mcp_servers.clankeroverflow.enabled entry is exactly false.

In `@packages/cli/src/evals/record-codex-product-proof.ts`:
- Around line 400-407: Handle spawn failures explicitly in the code surrounding
the spawnSync invocation: check result.error and include its details in the
constructed failure message before or alongside status and stderr handling.
Update the error branch so ENOENT and other process-launch errors identify the
underlying spawn error instead of reporting only an unknown status.

In `@packages/cli/src/evals/repo-stackoverflow.ts`:
- Around line 190-194: The parseArg function currently accepts another flag as
an option value; validate that index + 1 exists and the next argument does not
start with “--”. If validation fails, raise a clear usage error instead of
returning the flag as a path.

In `@packages/cli/src/learn.ts`:
- Around line 82-83: Update the env-var replacement regex in the `replacements`
array to match both unquoted values and single- or double-quoted values, while
preserving the existing variable-name matching and replacing the entire value
with `<redacted>`.
- Around line 300-348: Ensure learnSolution always releases the backend created
by createSolutionBackend: add a close/dispose lifecycle method to the
SolutionBackend interface and its implementations, then wrap the
duplicate-checking, logging, and mirror-writing flow in a try/finally that
invokes the backend cleanup method. Preserve existing return behavior while
guaranteeing cleanup on success, duplicates, and errors.

In `@packages/cli/src/mcp/server.ts`:
- Around line 484-487: Update readSolutionResource to select a repository
solution only when its basename exactly equals the requested idOrSlug, replacing
the partial candidate.includes(idOrSlug) lookup with an exact basename
comparison or basename-keyed lookup; preserve the existing not-found behavior
and ensure the MCP resource handler continues using readSolutionResource.

---

Nitpick comments:
In `@packages/cli/src/evals/product-proof.ts`:
- Around line 410-412: Clarify the intentional literal-key fallback in
pricingForModel by adding a concise comment identifying pricing.model as the
magic generic default rate, distinct from the dynamic pricing[model] lookup and
pricing.default fallback; preserve the existing fallback behavior.

In `@packages/cli/src/evals/record-codex-product-proof.ts`:
- Around line 347-353: Update verifyWorkspace and the command construction
before spawnSync to shell-escape benchmarkWorkspaceDir/workspacePath with single
quotes, replacing each embedded single quote with the standard '\'' sequence. Do
not use JSON.stringify or double-quoted substitutions for user-controlled paths,
while preserving shell: true and the existing command behavior.

In `@packages/cli/src/learn.ts`:
- Around line 379-413: Update parseStructuredSolution to parse framework,
runtime, packageManager, and fingerprints individually from the “Reusable
Context” section, while retaining repoNote as needed. In exportLocalSolutions,
pass these parsed fields to writeLearnMarkdown so export→syncRepoSolutions
preserves duplicate-detection fingerprints and tag normalization metadata.

In `@packages/cli/src/mcp/server.ts`:
- Around line 466-477: Update the MCP resource `list` callback to use
asynchronous file reads instead of `readFileSync`. Import `readFile` from
`fs/promises`, make the mapping await each file read and parse its contents, and
use `Promise.all` so `list` returns all resource entries without blocking the
event loop.
- Around line 466-477: Replace the manual filename extraction in the MCP
resource list callback with path.basename(file, ".md"), ensuring the path module
is imported and the existing fallback behavior is preserved if needed.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 12b500a9-1036-44cb-9e70-f5335e93968c

📥 Commits

Reviewing files that changed from the base of the PR and between eeb29ff and 434f677.

📒 Files selected for processing (143)
  • .gitignore
  • clankeroverflow-mcp-workspace/description-optimization/2026-06-23_233329/results.json
  • clankeroverflow-mcp-workspace/evals/evals.json
  • clankeroverflow-mcp-workspace/iteration-1/benchmark.json
  • clankeroverflow-mcp-workspace/iteration-1/billing-discount/eval_metadata.json
  • clankeroverflow-mcp-workspace/iteration-1/billing-discount/with_skill/grading.json
  • clankeroverflow-mcp-workspace/iteration-1/billing-discount/with_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-1/billing-discount/without_skill/grading.json
  • clankeroverflow-mcp-workspace/iteration-1/billing-discount/without_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-1/billing-discount/without_skill/outputs/response.md
  • clankeroverflow-mcp-workspace/iteration-1/dark-mode-toggle/eval_metadata.json
  • clankeroverflow-mcp-workspace/iteration-1/dark-mode-toggle/with_skill/grading.json
  • clankeroverflow-mcp-workspace/iteration-1/dark-mode-toggle/with_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-1/dark-mode-toggle/without_skill/grading.json
  • clankeroverflow-mcp-workspace/iteration-1/dark-mode-toggle/without_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-1/eaddrinuse-ci/eval_metadata.json
  • clankeroverflow-mcp-workspace/iteration-1/eaddrinuse-ci/with_skill/grading.json
  • clankeroverflow-mcp-workspace/iteration-1/eaddrinuse-ci/with_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-1/eaddrinuse-ci/with_skill/outputs/response.md
  • clankeroverflow-mcp-workspace/iteration-1/eaddrinuse-ci/without_skill/grading.json
  • clankeroverflow-mcp-workspace/iteration-1/eaddrinuse-ci/without_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-1/event-loop-explain/eval_metadata.json
  • clankeroverflow-mcp-workspace/iteration-1/event-loop-explain/with_skill/grading.json
  • clankeroverflow-mcp-workspace/iteration-1/event-loop-explain/with_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-1/event-loop-explain/without_skill/grading.json
  • clankeroverflow-mcp-workspace/iteration-1/event-loop-explain/without_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-1/grade_and_aggregate.py
  • clankeroverflow-mcp-workspace/iteration-1/inertia-noindex-ssr/eval_metadata.json
  • clankeroverflow-mcp-workspace/iteration-1/inertia-noindex-ssr/with_skill/grading.json
  • clankeroverflow-mcp-workspace/iteration-1/inertia-noindex-ssr/with_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-1/inertia-noindex-ssr/without_skill/grading.json
  • clankeroverflow-mcp-workspace/iteration-1/inertia-noindex-ssr/without_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-1/prisma-neon-timeout/eval_metadata.json
  • clankeroverflow-mcp-workspace/iteration-1/prisma-neon-timeout/without_skill/grading.json
  • clankeroverflow-mcp-workspace/iteration-1/prisma-neon-timeout/without_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-1/prisma-neon-timeout/without_skill/outputs/response.md
  • clankeroverflow-mcp-workspace/iteration-1/promise-async-await/eval_metadata.json
  • clankeroverflow-mcp-workspace/iteration-1/promise-async-await/with_skill/grading.json
  • clankeroverflow-mcp-workspace/iteration-1/promise-async-await/with_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-1/promise-async-await/without_skill/grading.json
  • clankeroverflow-mcp-workspace/iteration-1/promise-async-await/without_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-1/review.html
  • clankeroverflow-mcp-workspace/iteration-1/stripe-cf-workers-webcrypto/eval_metadata.json
  • clankeroverflow-mcp-workspace/iteration-1/stripe-cf-workers-webcrypto/with_skill/grading.json
  • clankeroverflow-mcp-workspace/iteration-1/stripe-cf-workers-webcrypto/with_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-1/stripe-cf-workers-webcrypto/without_skill/grading.json
  • clankeroverflow-mcp-workspace/iteration-1/stripe-cf-workers-webcrypto/without_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-1/swr-vs-reactquery/eval_metadata.json
  • clankeroverflow-mcp-workspace/iteration-1/swr-vs-reactquery/with_skill/grading.json
  • clankeroverflow-mcp-workspace/iteration-1/swr-vs-reactquery/with_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-1/swr-vs-reactquery/without_skill/grading.json
  • clankeroverflow-mcp-workspace/iteration-1/swr-vs-reactquery/without_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-1/ts2307-pnpm-workspaces/eval_metadata.json
  • clankeroverflow-mcp-workspace/iteration-1/ts2307-pnpm-workspaces/with_skill/grading.json
  • clankeroverflow-mcp-workspace/iteration-1/ts2307-pnpm-workspaces/with_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-1/ts2307-pnpm-workspaces/with_skill/outputs/response.md
  • clankeroverflow-mcp-workspace/iteration-1/ts2307-pnpm-workspaces/without_skill/grading.json
  • clankeroverflow-mcp-workspace/iteration-1/ts2307-pnpm-workspaces/without_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-1/ts2307-pnpm-workspaces/without_skill/outputs/response.md
  • clankeroverflow-mcp-workspace/iteration-2/dark-mode-toggle/with_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-2/event-loop-explain/with_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-2/grade_iter2.py
  • clankeroverflow-mcp-workspace/iteration-2/inertia-noindex-ssr/with_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-2/swr-vs-reactquery/with_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/iteration-2/ts2307-pnpm-workspaces/with_skill/outputs/metrics.json
  • clankeroverflow-mcp-workspace/product-proof/README.md
  • clankeroverflow-mcp-workspace/product-proof/fixtures.json
  • clankeroverflow-mcp-workspace/product-proof/reports/report-claude-debug-cost-low-r1.md
  • clankeroverflow-mcp-workspace/product-proof/reports/report-claude-smoke-low-r1.md
  • clankeroverflow-mcp-workspace/product-proof/reports/report-claude-smoke-low-r2.md
  • clankeroverflow-mcp-workspace/product-proof/reports/report-debug-cost-hidden-r2.md
  • clankeroverflow-mcp-workspace/product-proof/reports/report-debug-cost-hidden-r3.md
  • clankeroverflow-mcp-workspace/product-proof/reports/report-debug-cost-hidden.md
  • clankeroverflow-mcp-workspace/product-proof/reports/report-debug-cost.md
  • clankeroverflow-mcp-workspace/product-proof/reports/report.md
  • clankeroverflow-mcp-workspace/product-proof/runs/sample-runs.json
  • clankeroverflow-mcp-workspace/product-proof/scenarios.json
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-eaddrinuse-ci/package.json
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-eaddrinuse-ci/server.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-eaddrinuse-ci/test.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-inertia-noindex/app.blade.php
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-inertia-noindex/package.json
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-inertia-noindex/test.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-neon-first-query/db.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-neon-first-query/package.json
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-neon-first-query/test.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-prisma-neon/package.json
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-prisma-neon/schema.prisma
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-prisma-neon/test.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-react-query-rollback/mutation.js
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-react-query-rollback/package.json
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-react-query-rollback/test.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-sentry-sourcemaps/package.json
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-sentry-sourcemaps/sentry.config.js
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-sentry-sourcemaps/test.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-stripe-workers/package.json
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-stripe-workers/test.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-stripe-workers/webhook.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-ts2307-pnpm/package-under-test.json
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-ts2307-pnpm/package.json
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-ts2307-pnpm/src/app.js
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-ts2307-pnpm/test.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-verifiers/debug-eaddrinuse-ci.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-verifiers/debug-inertia-noindex.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-verifiers/debug-neon-first-query.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-verifiers/debug-prisma-neon.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-verifiers/debug-react-query-rollback.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-verifiers/debug-sentry-sourcemaps.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-verifiers/debug-stripe-workers.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-verifiers/debug-ts2307-pnpm.mjs
  • clankeroverflow-mcp-workspace/repo-stackoverflow/reports/repo-stackoverflow-local-smoke.md
  • clankeroverflow-mcp-workspace/repo-stackoverflow/runs/repo-stackoverflow-local-smoke.json
  • clankeroverflow-mcp-workspace/trigger-eval-set.json
  • package.json
  • packages/cli/.claude-plugin/plugin.json
  • packages/cli/.codex-plugin/plugin.json
  • packages/cli/commands/learn.md
  • packages/cli/commands/log-solution.md
  • packages/cli/hooks/hooks.json
  • packages/cli/hooks/post-tool-use.mjs
  • packages/cli/hooks/session-start.mjs
  • packages/cli/openclaw.plugin.json
  • packages/cli/package.json
  • packages/cli/skills/clankeroverflow-cli/SKILL.md
  • packages/cli/skills/clankeroverflow-mcp/SKILL.md
  • packages/cli/src/evals/product-proof.test.ts
  • packages/cli/src/evals/product-proof.ts
  • packages/cli/src/evals/record-claude-product-proof.test.ts
  • packages/cli/src/evals/record-claude-product-proof.ts
  • packages/cli/src/evals/record-codex-product-proof.test.ts
  • packages/cli/src/evals/record-codex-product-proof.ts
  • packages/cli/src/evals/repo-stackoverflow.test.ts
  • packages/cli/src/evals/repo-stackoverflow.ts
  • packages/cli/src/hooks/install.test.ts
  • packages/cli/src/hooks/install.ts
  • packages/cli/src/index.test.ts
  • packages/cli/src/index.ts
  • packages/cli/src/learn.test.ts
  • packages/cli/src/learn.ts
  • packages/cli/src/mcp/server.test.ts
  • packages/cli/src/mcp/server.ts
  • skills/clanker-overflow/SKILL.md
  • skills/cli-version-bump/SKILL.md

import { join } from "node:path";

const source = readFileSync(join(process.argv[2], "mutation.js"), "utf8");
if (!/return\s+.*previous|context/i.test(source)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Regex alternation precedence causes false-positive passes.

/return\s+.*previous|context/i matches either return\s+.*previous or the bare word context anywhere in the file. If mutation.js contains the word "context" in a comment, import, or variable name — but onMutate never returns it — the verifier still passes.

🐛 Proposed fix: group the alternation
-if (!/return\s+.*previous|context/i.test(source)) {
+if (!/return\s+.*(previous|context)/i.test(source)) {
📝 Committable suggestion

‼️ 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.

Suggested change
if (!/return\s+.*previous|context/i.test(source)) {
if (!/return\s+.*(previous|context)/i.test(source)) {
🤖 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
`@clankeroverflow-mcp-workspace/product-proof/workspace-verifiers/debug-react-query-rollback.mjs`
at line 5, Fix the regex in the verifier’s source check by grouping the
alternatives so “context” is only accepted as part of the intended return
pattern, rather than matching anywhere in the file. Update the condition around
the existing source test and preserve case-insensitive matching.

Comment thread packages/cli/skills/clankeroverflow-cli/SKILL.md
Comment thread packages/cli/src/evals/product-proof.ts
Comment thread packages/cli/src/evals/repo-stackoverflow.ts Outdated
Comment thread packages/cli/src/index.ts
@bernoussama

Copy link
Copy Markdown
Owner Author

@coderabbitai review\n\nPlease re-review the latest commit c5c8a05; it addresses the prior actionable findings.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

@bernoussama Got it — I'll re-review commit c5c8a05 now.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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: 1

🧹 Nitpick comments (3)
packages/cli/src/mcp/backend.ts (1)

36-36: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Close backends created by backendForSource after use.

Now that close() is part of the SolutionBackend interface, backendForSource in server.ts creates new backends for non-"configured" sources (search, upvote, downvote) that are never closed. For LocalBackend, each call opens a new SQLite connection that leaks. Consider closing backends after each operation or caching them per source.

🤖 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 `@packages/cli/src/mcp/backend.ts` at line 36, Update backendForSource usages
in server.ts so every backend created for non-"configured" sources is closed
after its operation completes, including when the operation throws. Reuse the
SolutionBackend.close method and ensure LocalBackend SQLite connections are
released without changing the existing operation behavior.
packages/cli/extensions/clankeroverflow-reminder.ts (1)

77-91: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider documenting the relationship between the two prompt classifiers.

The extension's shouldRemindForPrompt and the eval module's classifyPiPrompt (in pi-triggering.ts) are independent classifiers for the same conceptual goal. They use different pattern sets and could diverge over time, making eval results less representative of actual runtime behavior. Consider adding a brief comment noting the relationship, or eventually unifying the pattern sources.

🤖 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 `@packages/cli/extensions/clankeroverflow-reminder.ts` around lines 77 - 91,
Document near the runtime classifier used by shouldRemindForPrompt that the eval
module’s classifyPiPrompt is an independent classifier for the same goal, with
separate pattern sets that may diverge. Keep the classifiers unchanged and add
only a brief relationship note.
packages/cli/src/evals/pi-triggering.ts (1)

152-189: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider renaming the "debug" action kind for clarity.

Line 187 classifies any non-search/learn/skill_read tool call as "debug". While the semantics are correct for searchBeforeDebug (any non-search action should be preceded by a search), the name "debug" is misleading for tools like write or edit. A name like "other_action" or "non_search" would better convey the intent.

🤖 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 `@packages/cli/src/evals/pi-triggering.ts` around lines 152 - 189, The fallback
action returned by actionsForEvent should no longer be named "debug", since it
also represents tools such as write and edit. Rename this action kind to a
clearer non-search/other-action name and update all consumers, including
searchBeforeDebug-related logic, to preserve the existing behavior.
🤖 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 `@packages/cli/src/mcp/server.ts`:
- Around line 468-480: Update the resource list callback around Promise.all to
handle per-file failures from readFile or parseLearnMarkdown without rejecting
the entire listing, omitting or otherwise safely handling failed entries. Add
error handling to the read callback around readSolutionResource so invalid or
missing ids return the established MCP error response instead of propagating an
exception.

---

Nitpick comments:
In `@packages/cli/extensions/clankeroverflow-reminder.ts`:
- Around line 77-91: Document near the runtime classifier used by
shouldRemindForPrompt that the eval module’s classifyPiPrompt is an independent
classifier for the same goal, with separate pattern sets that may diverge. Keep
the classifiers unchanged and add only a brief relationship note.

In `@packages/cli/src/evals/pi-triggering.ts`:
- Around line 152-189: The fallback action returned by actionsForEvent should no
longer be named "debug", since it also represents tools such as write and edit.
Rename this action kind to a clearer non-search/other-action name and update all
consumers, including searchBeforeDebug-related logic, to preserve the existing
behavior.

In `@packages/cli/src/mcp/backend.ts`:
- Line 36: Update backendForSource usages in server.ts so every backend created
for non-"configured" sources is closed after its operation completes, including
when the operation throws. Reuse the SolutionBackend.close method and ensure
LocalBackend SQLite connections are released without changing the existing
operation behavior.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d0f28e66-7ede-4a4d-894a-61eb0c8a5165

📥 Commits

Reviewing files that changed from the base of the PR and between 434f677 and 06fda01.

📒 Files selected for processing (45)
  • clankeroverflow-mcp-workspace/iteration-1/grade_and_aggregate.py
  • clankeroverflow-mcp-workspace/iteration-1/prisma-neon-timeout/without_skill/outputs/response.md
  • clankeroverflow-mcp-workspace/iteration-1/ts2307-pnpm-workspaces/with_skill/outputs/response.md
  • clankeroverflow-mcp-workspace/iteration-1/ts2307-pnpm-workspaces/without_skill/outputs/response.md
  • clankeroverflow-mcp-workspace/pi-triggering/cases.json
  • clankeroverflow-mcp-workspace/product-proof/README.md
  • clankeroverflow-mcp-workspace/product-proof/reports/report-debug-cost-hidden-r2.md
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-neon-first-query/test.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-prisma-neon/test.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-react-query-rollback/test.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-sentry-sourcemaps/test.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-stripe-workers/test.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-verifiers/debug-neon-first-query.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-verifiers/debug-prisma-neon.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-verifiers/debug-react-query-rollback.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-verifiers/debug-sentry-sourcemaps.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-verifiers/debug-stripe-workers.mjs
  • package.json
  • packages/cli/.claude-plugin/plugin.json
  • packages/cli/.codex-plugin/plugin.json
  • packages/cli/extensions/clankeroverflow-reminder.ts
  • packages/cli/openclaw.plugin.json
  • packages/cli/package.json
  • packages/cli/skills/clankeroverflow-cli/SKILL.md
  • packages/cli/skills/clankeroverflow-mcp/SKILL.md
  • packages/cli/src/evals/pi-triggering-run.ts
  • packages/cli/src/evals/pi-triggering.test.ts
  • packages/cli/src/evals/pi-triggering.ts
  • packages/cli/src/evals/product-proof.ts
  • packages/cli/src/evals/record-codex-product-proof.test.ts
  • packages/cli/src/evals/record-codex-product-proof.ts
  • packages/cli/src/evals/repo-stackoverflow.test.ts
  • packages/cli/src/evals/repo-stackoverflow.ts
  • packages/cli/src/index.test.ts
  • packages/cli/src/index.ts
  • packages/cli/src/learn.test.ts
  • packages/cli/src/learn.ts
  • packages/cli/src/mcp/backend.ts
  • packages/cli/src/mcp/local-backend.ts
  • packages/cli/src/mcp/remote-backend.ts
  • packages/cli/src/mcp/server.test.ts
  • packages/cli/src/mcp/server.ts
  • packages/cli/src/pi-reminder.test.ts
  • packages/cli/src/setup.test.ts
  • packages/cli/src/setup.ts
✅ Files skipped from review due to trivial changes (7)
  • clankeroverflow-mcp-workspace/product-proof/README.md
  • packages/cli/.codex-plugin/plugin.json
  • clankeroverflow-mcp-workspace/pi-triggering/cases.json
  • clankeroverflow-mcp-workspace/iteration-1/ts2307-pnpm-workspaces/with_skill/outputs/response.md
  • clankeroverflow-mcp-workspace/iteration-1/prisma-neon-timeout/without_skill/outputs/response.md
  • clankeroverflow-mcp-workspace/iteration-1/ts2307-pnpm-workspaces/without_skill/outputs/response.md
  • clankeroverflow-mcp-workspace/product-proof/reports/report-debug-cost-hidden-r2.md
🚧 Files skipped from review as they are similar to previous changes (13)
  • packages/cli/openclaw.plugin.json
  • clankeroverflow-mcp-workspace/product-proof/workspace-verifiers/debug-prisma-neon.mjs
  • clankeroverflow-mcp-workspace/product-proof/workspace-fixtures/debug-neon-first-query/test.mjs
  • packages/cli/src/evals/record-codex-product-proof.test.ts
  • package.json
  • packages/cli/src/index.test.ts
  • packages/cli/src/evals/repo-stackoverflow.ts
  • packages/cli/src/index.ts
  • packages/cli/skills/clankeroverflow-mcp/SKILL.md
  • packages/cli/skills/clankeroverflow-cli/SKILL.md
  • clankeroverflow-mcp-workspace/iteration-1/grade_and_aggregate.py
  • packages/cli/src/mcp/server.test.ts
  • packages/cli/src/evals/product-proof.ts

Comment on lines +468 to +480
resources: await Promise.all(
listRepoSolutionFiles().map(async (file) => {
const parsed = parseLearnMarkdown(await readFile(file, "utf8"));
const name = basename(file, ".md");
return {
uri: `clankeroverflow://repo/solutions/${name}`,
name,
title: parsed.problem,
mimeType: "text/markdown",
};
}),
),
}),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Add error handling to resource callbacks.

The list callback uses Promise.all, which fails entirely if any file read rejects (e.g., file deleted between listRepoSolutionFiles() and readFile). The read callback doesn't catch errors from readSolutionResource — a non-existent id propagates unhandled.

🛡️ Proposed fix: resilient resource callbacks
       list: async () => ({
-        resources: await Promise.all(
+        resources: (
+          await Promise.allSettled(
           listRepoSolutionFiles().map(async (file) => {
             const parsed = parseLearnMarkdown(await readFile(file, "utf8"));
             const name = basename(file, ".md");
             return {
               uri: `clankeroverflow://repo/solutions/${name}`,
               name,
               title: parsed.problem,
               mimeType: "text/markdown",
             };
           }),
-        ),
+        ))
+          .filter((r) => r.status === "fulfilled")
+          .map((r) => r.value),
       }),
     async (uri, variables) => {
-      const { text } = readSolutionResource(String(variables.id));
-      return { contents: [{ uri: uri.href, mimeType: "text/markdown", text }] };
+      try {
+        const { text } = readSolutionResource(String(variables.id));
+        return { contents: [{ uri: uri.href, mimeType: "text/markdown", text }] };
+      } catch {
+        return { contents: [{ uri: uri.href, mimeType: "text/markdown", text: `Solution "${variables.id}" not found.` }] };
+      }
     },

Also applies to: 488-488

🤖 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 `@packages/cli/src/mcp/server.ts` around lines 468 - 480, Update the resource
list callback around Promise.all to handle per-file failures from readFile or
parseLearnMarkdown without rejecting the entire listing, omitting or otherwise
safely handling failed entries. Add error handling to the read callback around
readSolutionResource so invalid or missing ids return the established MCP error
response instead of propagating an exception.

@bernoussama bernoussama left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Nightly review — clankeroverflow#69 (feat: add learned repo memory and MCP product-proof evals)

Verdict: Comment (no blockers).

  • Eval artifacts committed to git: timestamped results.json files (1.4k lines each) under clankeroverflow-mcp-workspace/. You already gitignore product-proof/runs/* — do the same for description-optimization/*/results.json and keep only curated samples, or history will bloat fast.
  • The committed eval itself shows trigger_rate: 0.0 on most train queries and best score 4/8 — i.e. the learned description didn't generalize. Worth a short conclusion in the README/eval notes so the artifact isn't misleading.
  • Mixes real feature code (learned repo memory) with bulk data files — split data from code next time so the code delta is actually reviewable.

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