Skip to content

fix(mcp): MCP_harden review follow-ups (Codex + CodeRabbit) - #184

Merged
tonythethompson merged 7 commits into
MCP_hardenfrom
cursor/mcp-harden-review-squash-5193
Aug 8, 2026
Merged

tonythethompson merged 7 commits into
MCP_hardenfrom
cursor/mcp-harden-review-squash-5193

Conversation

@tonythethompson

@tonythethompson tonythethompson commented Aug 8, 2026 •

Copy link
Copy Markdown
Owner

Summary

Rebuilds the squashed MCP_harden review follow-ups on current MCP_harden and addresses Codex review findings on this PR.

Codex findings addressed

Severity Finding Fix
P1 Smoke could start real Olive setup / downloads Studio child runs with OLIVE_JOB_SETUP_STUB=1; setup parks in setting_up until cancel
P1 SIGINT/SIGTERM left permissive agent policy on disk Exact config file snapshot/restore + signal handlers that always cleanup()
P2 Inherited OLIVE_MCP_ALLOW_JOBS broke deny-path asserts Deleted from Studio child env and mcporter studioEnv
P2 MCP submit lock tails grew without bound withMcpSubmitLocks evicts installed tails when still owned

Also included (former #175–#183)

Former PR Change
#175 mcporter smoke: policy-gated submit / status / cancel / idempotent reuse
#176 pytest conftest: central semantic inflight drain
#177 resetJobRegistry() (detaches venv listeners) in integration beforeEach
#178 MCP tool injection: allowlist + no child_process launch asserts
#179 restore OLIVE_MCP_ACCESS after mcpAccess suite
#180 hoist writeStudioConfig import in olive.stream tests
#181 deterministic QNN preflight host-mode mocks
#182 jobRunner idempotency mocks (executable + python)
#183 MCP submit lock on fingerprint + idempotency key

Validation

node --check scripts/mcp-agent-smoke.mjs
pnpm vitest run --config vitest.server.config.ts \
  src/server/services/olive/jobRunner.idempotency.test.ts \
  src/server/services/olive/jobPreflight.test.ts \
  src/server/services/olive/state.test.ts \
  src/server/routes/olive.stream.test.ts \
  src/server/routes/mcp.test.ts

Base

Stacked on latest MCP_harden (2962d4f).

@vercel

vercel Bot commented Aug 8, 2026

Copy link
Copy Markdown

Deployment failed for project olive-studio with the following error:

Resource is limited - try again in 24 hours (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/trackdub?upgradeToPro=build-rate-limit

@coderabbitai

coderabbitai Bot commented Aug 8, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds deterministic semantic-worker cleanup, explicit budget fallback tests, serialized MCP submission locks, Olive job-registry reset support, Python and Studio configuration utilities, and expanded MCP smoke and route integration validation.

Changes

Semantic retrieval budget handling

Layer / File(s) Summary
Semantic worker drain fixtures
olive-mcp-server/tests/conftest.py, olive-mcp-server/tests/test_capabilities.py, olive-mcp-server/tests/test_docs_search_semantic.py
Shared fixtures drain tracked semantic workers and replace fixed cleanup delays.
Budget fallback coverage
olive-mcp-server/tests/test_docs_search_semantic.py
Tests cover shared-budget exhaustion and explicit zero budgets selecting keyword search without embedding construction.

Olive job state and submission control

Layer / File(s) Summary
Serialized MCP submissions
src/server/services/olive/jobRunner.ts, src/server/services/olive/jobIdempotency.ts, src/server/services/olive/jobRunner.idempotency.test.ts, src/server/services/olive/jobIdempotency.test.ts
Submissions use sorted per-key promise-tail locks. Fingerprint-only jobs can be adopted by keyed submissions. Tests cover reuse, distinct submissions, and lock-tail cleanup.
Job registry reset and test isolation
src/server/services/olive/state.ts, src/server/services/olive/state.test.ts, src/server/__tests__/setup.integration.ts, src/server/__tests__/routes.integration.test.ts
resetJobRegistry() terminates active jobs, removes artifacts, and clears registry and idempotency state. Integration tests track and reset child-process launches.
Preflight and route fixture control
src/server/services/olive/jobPreflight.test.ts, src/server/routes/mcp.test.ts, src/server/routes/olive.stream.test.ts
Tests explicitly control QNN host modes and restore environment and mocked configuration state.

MCP Studio smoke validation

Layer / File(s) Summary
Smoke support utilities
scripts/resolvePython.mjs, scripts/stopStudioThenAlways.mjs, scripts/studioConfigSmokeLock.mjs, scripts/studioConfigSnapshot.mjs, src/lib/__tests__/*
Utilities resolve Python, coordinate Studio configuration access, preserve exact configuration contents, and guarantee shutdown cleanup. Tests cover these behaviors.
Temporary Studio smoke harness
scripts/mcp-agent-smoke.mjs
The smoke script provisions temporary configuration, runs policy and MCP job-control checks, and restores process and file state.
Route launch and allowlist assertions
src/server/__tests__/routes.integration.test.ts, src/server/__tests__/setup.integration.ts
Route tests reject unsafe tool names with HTTP 400 and verify that no child process receives unsafe arguments.

Estimated code review effort: 4 (Complex) | ~75 minutes

Possibly related PRs

Suggested reviewers: greptile-apps

🚥 Pre-merge checks | ✅ 8
✅ Passed checks (8 passed)
Check name Status Explanation
Description check ✅ Passed The description directly covers the MCP smoke hardening, cleanup, locking, configuration restoration, and test changes in the pull request.
Title check ✅ Passed The title accurately identifies the pull request as MCP review follow-up fixes and matches the primary changes.
Docstring Coverage ✅ Passed Docstring coverage is 62.50% which is sufficient. The required threshold is 60.00%.
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.
Pipeline Stage Enum Ordering ✅ Passed The full PR diff versus MCP_harden contains no SessionWorkflowStage enum, member names, or related inequality comparisons; the ordering check is not applicable.
Gpu/Cpu Runtime Boundary ✅ Passed The PR changes no files under inference/, no managed CPU/GPU requirements files, and no C# DiarizationProvider or DiarizationRegistry code; the boundary checks are not applicable.
Managed Host Restart Safety ✅ Passed The full PR diff changes no ManagedVenvHostManager, Containerized* host manager, lease-tracker, or busy-state code; the check is not applicable.
✨ 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 cursor/mcp-harden-review-squash-5193
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch cursor/mcp-harden-review-squash-5193

Warning

Review ran into problems

🔥 Problems

Linked repositories: Public OSS repositories can only analyze public repositories installed in this organization. Analyzed tonythethompson/QuickShell, tonythethompson/numan, tonythethompson/dependency-chain-substrate, skipped Trackdubllc/Trackdub.


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.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Sorry @tonythethompson, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Harden MCP job controls, tool allowlisting, and test isolation

🐞 Bug fix 🧪 Tests ✨ Enhancement 🕐 40+ Minutes

Grey Divider

AI Description

• Centralize flaky single-flight/registry cleanup to prevent cross-test leakage.
• Harden MCP tool proxy with strict allowlist and injection-focused integration assertions.
• Strengthen MCP job idempotency/locking and expand mcporter smoke coverage for job control.
Diagram

graph TD
  A["mcp-agent-smoke.mjs"] --> B["mcporter CLI"] --> C["Olive MCP server (python)"] --> D["Studio API (jobs)"]
  E["Studio /api/mcp/tool proxy"] --> F["Tool allowlist gate"] --> G["callOliveMcpTool (child_process)"] --> C
  D --> H["startOliveJob (idempotency locks)"] --> I[("Job registry + idempotency index")]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Use a keyed async-mutex/lock library
  • ➕ Less bespoke concurrency code to reason about/maintain
  • ➕ Potentially clearer semantics (acquire/release) and better testability
  • ➖ Adds dependency surface area and upgrade risk
  • ➖ May not naturally support multi-key acquisition with deadlock avoidance without extra work
2. Single global MCP submit mutex
  • ➕ Simplest correctness story; eliminates multi-key ordering complexity
  • ➖ Reduces concurrency across unrelated recipes/keys (unnecessary serialization)
  • ➖ Can increase latency under parallel agent submits
3. Lock only fingerprint and enforce key conflicts via atomic index ops
  • ➕ Fewer lock keys to manage; simpler ordering
  • ➕ Still prevents duplicate job spawns for identical recipes
  • ➖ Harder to guarantee conflict semantics between different idempotency keys without reintroducing races
  • ➖ Key-only conflict checks may still need serialization to avoid inconsistent outcomes

Recommendation: The PR’s multi-key tail-chaining lock (sorted keys) is a good balance: it preserves parallelism across unrelated submits while preventing check-then-act races between fingerprint-only and key-bearing calls. If future complexity grows (more lock keys/paths), consider a small internal keyed-lock utility (or vetted library) to centralize correctness tests and reuse.

Files changed (13) +680 / -113

Enhancement (2) +450 / -36
mcp-agent-smoke.mjsExpand mcporter smoke to cover policy-gated submit/status/cancel and reuse +418/-35

Expand mcporter smoke to cover policy-gated submit/status/cancel and reuse

• Reworks the smoke script to generate a temporary mcporter config, resolve a usable python interpreter, and spin up Studio on a free port. Adds JSON tool-call helpers and validates denied submit, concurrent idempotent reuse, status fetch, and cancellation, while restoring Studio disk policy on exit.

scripts/mcp-agent-smoke.mjs

state.tsAdd resetJobRegistry helper to terminate jobs and clear idempotency index +32/-1

Add resetJobRegistry helper to terminate jobs and clear idempotency index

• Adds a test-focused helper that SIGKILLs still-running job processes, cleans up temp recipe artifacts, finalizes jobs, clears the registry, and clears the idempotency index. Intended to prevent test pollution from in-flight jobs and stale idempotency state.

src/server/services/olive/state.ts

Bug fix (1) +47 / -24
jobRunner.tsReplace inflight-promise map with multi-key tail locks for MCP submit serialization +47/-24

Replace inflight-promise map with multi-key tail locks for MCP submit serialization

• Implements a per-key tail-chaining lock and uses it to serialize MCP submit critical sections across both recipe fingerprint and idempotency key. Prevents races where fingerprint-only and key-bearing submits could both observe a miss and spawn duplicate jobs.

src/server/services/olive/jobRunner.ts

Tests (10) +183 / -53
conftest.pyAdd autouse fixture to drain semantic single-flight between pytest tests +53/-0

Add autouse fixture to drain semantic single-flight between pytest tests

• Introduces a shared helper/fixture that polls the retrieval single-flight future and clears it when done. Applies the drain automatically before and after each test to prevent abandoned budget workers from blocking later tests.

olive-mcp-server/tests/conftest.py

test_capabilities.pyReplace sleep-based inflight draining with shared fixture +2/-6

Replace sleep-based inflight draining with shared fixture

• Removes ad-hoc sleeps used to wait out abandoned semantic budget workers. Uses the new wait_inflight_semantic_clear fixture to deterministically unblock follow-on budgeted calls.

olive-mcp-server/tests/test_capabilities.py

test_docs_search_semantic.pyRemove inline single-flight cleanup logic and sleep drains +0/-14

Remove inline single-flight cleanup logic and sleep drains

• Deletes duplicated polling logic and sleep-based cleanup around retrieval single-flight state. Relies on the new autouse conftest fixture to keep tests isolated and deterministic.

olive-mcp-server/tests/test_docs_search_semantic.py

routes.integration.test.tsReset job registry per test and assert allowlist blocks MCP injection without spawning +26/-9

Reset job registry per test and assert allowlist blocks MCP injection without spawning

• Adds per-test resetJobRegistry and child-process launch log clearing. Strengthens the toolName injection test to require a 400 allowlist rejection and asserts that no child_process launch occurs and no unsafe strings reach spawn/exec arguments.

src/server/tests/routes.integration.test.ts

setup.integration.tsRecord child_process exec/spawn calls for integration assertions +10/-1

Record child_process exec/spawn calls for integration assertions

• Extends the child_process mock to log execFile/spawn invocations and exports helpers to clear the log. Enables security assertions that invalid MCP tool requests do not trigger any process launches.

src/server/tests/setup.integration.ts

mcp.test.tsRestore OLIVE_MCP_ACCESS after mcpAccess tests +7/-1

Restore OLIVE_MCP_ACCESS after mcpAccess tests

• Captures the prior OLIVE_MCP_ACCESS value and restores it after each test instead of always deleting it. Prevents environment leakage across test suites.

src/server/routes/mcp.test.ts

olive.stream.test.tsHoist writeStudioConfig import to align with vi.mock hoisting +2/-2

Hoist writeStudioConfig import to align with vi.mock hoisting

• Moves the writeStudioConfig import above the vi.mock block and documents that vi.mock is hoisted. Ensures the mocked config module is consistently used and avoids subtle import-order issues.

src/server/routes/olive.stream.test.ts

jobPreflight.test.tsMake QNN host-mode assertions deterministic via mocked resolveQnnHostMode +23/-9

Make QNN host-mode assertions deterministic via mocked resolveQnnHostMode

• Mocks resolveQnnHostMode to force specific host modes in tests. Adds explicit coverage that local-inference hosts emit a deferred-readiness warning while out-of-scope hosts do not, without introducing runtime hard-fail behavior in validate.

src/server/services/olive/jobPreflight.test.ts

jobRunner.idempotency.test.tsAlign venv/idempotency mocks and expand MCP submit locking expectations +26/-10

Align venv/idempotency mocks and expand MCP submit locking expectations

• Updates venv mocks to match the newer capability/command shapes (python/family and executable). Tightens expectations to require exactly one reused response under contention and adds a case proving distinct idempotency keys can create new jobs after earlier submits settle.

src/server/services/olive/jobRunner.idempotency.test.ts

state.test.tsAdd resetJobRegistry test coverage for process kill, artifacts, and idempotency cleanup +34/-1

Add resetJobRegistry test coverage for process kill, artifacts, and idempotency cleanup

• Introduces a new describe block asserting resetJobRegistry kills active processes, removes temp artifacts, clears the job registry, and clears MCP idempotency keys. Ensures registry/idempotency state cannot leak across tests.

src/server/services/olive/state.test.ts

@tonythethompson

Copy link
Copy Markdown
Owner Author

Pushed follow-up 2e2db52 addressing the CodeRabbit findings from #175 (smoke script stability / correctness / teardown / distinct-key coverage).

@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: 25ced6a26e

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/mcp-agent-smoke.mjs Outdated
Comment thread scripts/mcp-agent-smoke.mjs
Comment thread scripts/mcp-agent-smoke.mjs Outdated
Comment thread src/server/services/olive/jobRunner.ts Outdated
@greptile-apps

greptile-apps Bot commented Aug 8, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR expands the MCP smoke to exercise policy-gated job submission, idempotent reuse, status, and cancellation while adding exact configuration restoration, inter-process locking, and bounded submission-lock state.

  • Adds a stubbed Studio job-control smoke and supporting Python/configuration helpers.
  • Serializes MCP submissions by fingerprint and idempotency key, then evicts idle lock tails.
  • Centralizes semantic-worker and Olive job-registry cleanup across tests.

Confidence Score: 0/5

The PR is not yet safe to merge because configuration restoration can still report success while leaving permissive policy behind, and concurrent configuration updates can still be lost.

The current catch path ignores restoration failure when selecting the default non-strict exit code, while the snapshot-to-write and write-to-reread windows still permit unrelated configuration bytes to be overwritten or treated as smoke-owned.

Files Needing Attention: scripts/mcp-agent-smoke.mjs, scripts/studioConfigSnapshot.mjs

Important Files Changed

Filename Overview
scripts/mcp-agent-smoke.mjs Adds the end-to-end job-control smoke and cleanup protocol, but previously reported configuration restoration and concurrent-write failures remain.
scripts/studioConfigSnapshot.mjs Adds exact snapshot restoration and a conditional final-state check, though that check cannot protect writes occurring before the smoke's first mutation.
scripts/studioConfigSmokeLock.mjs Adds exclusive locking that correctly serializes cooperating smoke processes.
src/server/services/olive/jobRunner.ts Adds ordered MCP submission locks with ownership-checked tail eviction; the previously reported retention issue is resolved.
src/server/services/olive/state.ts Adds registry reset behavior used to isolate integration tests.

Reviews (12): Last reviewed commit: "fix(mcp): stamp smoke config ownership a..." | Re-trigger Greptile

Comment thread src/server/services/olive/jobRunner.ts Outdated
Comment thread scripts/mcp-agent-smoke.mjs
@cursor
cursor Bot force-pushed the cursor/mcp-harden-review-squash-5193 branch from 2e2db52 to 6b99b3c Compare August 8, 2026 05:46
@tonythethompson

Copy link
Copy Markdown
Owner Author

Rebuilt this stack on the rebased MCP_harden tip (cherry-picked the three squash commits cleanly after #171 history rewrite).

@qodo-code-review

qodo-code-review Bot commented Aug 8, 2026 •

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Studio escalation never runs ✓ Resolved 🐞 Bug ☼ Reliability
Description
stopStudio schedules SIGKILL for later, but both completion paths call process.exit immediately
after cleanup, so the timer cannot run. The child.killed guard can also suppress escalation after
SIGTERM was merely sent, allowing a non-terminating Studio child to survive the smoke.
Code

scripts/mcp-agent-smoke.mjs[R268-271]

+  setTimeout(() => {
+    try {
+      if (!child.killed) child.kill("SIGKILL");
+    } catch {
Relevance

●●● Strong

Matches repo precedent: cancellation must SIGTERM then escalate to SIGKILL with timeout;
process.exit breaks that.

PR-#32

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The escalation is deferred by two seconds and unreferenced, while success and failure both invoke
process.exit immediately after calling cleanup. The repository's accepted cancellation guidance
also establishes that process termination requires bounded SIGTERM-to-SIGKILL escalation rather than
reporting cleanup after only sending SIGTERM.

scripts/mcp-agent-smoke.mjs[261-275]
scripts/mcp-agent-smoke.mjs[404-453]
PR-#32

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The smoke exits before its Studio SIGKILL escalation can execute.

## Issue Context
Make shutdown asynchronous: send SIGTERM, await child exit for a bounded grace period, send SIGKILL if still running, await closure, and only then exit. Track actual exit/close state rather than `child.killed`.

## Fix Focus Areas
- scripts/mcp-agent-smoke.mjs[261-275]
- scripts/mcp-agent-smoke.mjs[404-453]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Interrupt leaves submission enabled ✓ Resolved 🐞 Bug ⛨ Security
Description
After persisting allowJobSubmission: true, the script has no SIGINT or SIGTERM cleanup handlers.
Interrupting the smoke bypasses its try/catch, leaving the permissive policy on disk and
potentially leaving the spawned Studio process running.
Code

scripts/mcp-agent-smoke.mjs[R323-326]

+  patchAgentAccessDisk({
+    allowJobSubmission: true,
+    allowJobCancellation: true,
+  });
Relevance

●● Moderate

Signal cleanup for disk mutations is sensible, but adds behavior/complexity; no clear repo precedent
for smoke scripts.

PR-#32

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The script persists permissive submission and cancellation settings, but the only cleanup calls
occur on normal completion and caught promise failures. There are no process signal handlers
anywhere in the script, so default signal termination cannot reach cleanup.

scripts/mcp-agent-smoke.mjs[323-326]
scripts/mcp-agent-smoke.mjs[404-453]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Signals can terminate the smoke after it enables job control without restoring policy or stopping Studio.

## Issue Context
Install idempotent SIGINT/SIGTERM handlers that restore disk state, terminate the child, remove temporary files, and then preserve the appropriate exit status.

## Fix Focus Areas
- scripts/mcp-agent-smoke.mjs[277-280]
- scripts/mcp-agent-smoke.mjs[323-326]
- scripts/mcp-agent-smoke.mjs[404-453]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Python fallback skips python ✓ Resolved 🐞 Bug ☼ Reliability
Description
resolvePython immediately returns python3 without checking whether that PATH command exists,
making the following python candidate unreachable. The smoke fails on environments that lack
python3 but provide python, despite documenting that fallback.
Code

scripts/mcp-agent-smoke.mjs[R71-73]

+  for (const c of candidates) {
+    if (c === "python3" || c === "python") return c;
+    if (existsSync(c)) return c;
Relevance

●●● Strong

Deterministic bug: fallback order is broken; team has history of cross-platform Python path fixes.

PR-#8

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The candidate order includes python3 followed by python, but the shared branch returns either
bare command without availability testing; execution always stops at python3 after the venv paths
fail.

scripts/mcp-agent-smoke.mjs[58-75]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The bare-command fallback always chooses `python3`, even when only `python` is available.

## Issue Context
Use a platform-appropriate PATH lookup or a bounded spawn probe and return the first executable candidate.

## Fix Focus Areas
- scripts/mcp-agent-smoke.mjs[58-75]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. resetJobRegistry leaks venv listener registration ✓ Resolved 🐞 Bug ☼ Reliability
Description
resetJobRegistry() clears job.venvListener by assigning undefined but never calls
detachVenvListener(), unlike the cancel handler in olive.ts which always detaches before clearing.
This leaves the listener callback registered in the shared venv family setup state, so a subsequent,
unrelated venv setup can still invoke a callback tied to a job that resetJobRegistry() already
finalized and cleared, risking stale listener invocations or accumulation across repeated resets
(e.g. tests calling resetJobRegistry() in beforeEach).
Code

src/server/services/olive/state.ts[R68-71]

+  for (const job of [...jobRegistry.values()]) {
+    if (job.venvListener) {
+      job.venvListener = undefined;
+    }
Relevance

●●● Strong

Deterministic reliability fix: detach shared listener before clearing; aligns with existing
cancellation pattern and avoids leaks.

PR-#111

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
olive.ts's cancel handler always pairs clearing job.venvListener with
detachVenvListener(job.venvListener) to remove the listener from the shared family setup registry
(services/venv/index.ts). resetJobRegistry() only performs the local field clear (job.venvListener =
undefined) and skips the detach call, so the shared registry can retain a reference to a listener
whose owning job has already been torn down by this same function.

src/server/services/olive/state.ts[67-88]
src/server/routes/olive.ts[141-144]
src/server/services/venv/index.ts[56-63]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`resetJobRegistry()` in `src/server/services/olive/state.ts` clears `job.venvListener` without deregistering it from the shared venv family setup listener registry, unlike the cancel handler in `src/server/routes/olive.ts` which calls `detachVenvListener()` first.

## Issue Context
`detachVenvListener` (exported from `src/server/services/venv/index.ts`) removes a progress listener from shared, module-level venv setup state. Simply setting `job.venvListener = undefined` on the job object does not unregister the callback from that shared state, so it can remain referenced/invoked after the job has been reset.

## Fix Focus Areas
- src/server/services/olive/state.ts[67-88]
- src/server/routes/olive.ts[141-144]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Lock tails never evicted ✓ Resolved 🐞 Bug ➹ Performance
Description
Every unique MCP fingerprint or idempotency key adds a promise to mcpSubmitLockTails, but
completed tails are never removed. A long-running Studio therefore accumulates lock keys and
promises without bound as distinct jobs are submitted.
Code

src/server/services/olive/jobRunner.ts[R83-86]

+      mcpSubmitLockTails.set(
+        key,
+        prev.then(
+          () => held,
Relevance

●●● Strong

Unbounded Map growth; repo previously accepted adding eviction/bounding for long-lived in-memory
caches.

PR-#73

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The process-global map is created at jobRunner.ts[65-66]; withMcpSubmitLocks stores tails but
its finally block only resolves release callbacks. MCP submissions derive these map keys from
recipe fingerprints and optional client idempotency keys, so the key set can grow with normal
traffic.

src/server/services/olive/jobRunner.ts[65-98]
src/server/services/olive/jobRunner.ts[135-150]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The MCP submit lock map retains every completed lock tail, causing unbounded process-lifetime growth.

## Issue Context
Cleanup must only delete the tail owned by the current acquisition; it must not remove a newer waiter's tail.

## Fix Focus Areas
- src/server/services/olive/jobRunner.ts[72-98]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
6. Smoke changes config permanently ✓ Resolved 🐞 Bug ≡ Correctness
Description
The smoke snapshots optional policy fields as normalized booleans, so cleanup restores missing
values as explicit false and leaves a newly created config file behind. Even a successful run
therefore does not restore the user's original .olive-studio/config.json state.
Code

scripts/mcp-agent-smoke.mjs[R283-287]

+  const diskBefore = readStudioDiskConfig();
+  priorAgentAccess = {
+    allowJobSubmission: diskBefore.agentAccess?.allowJobSubmission === true,
+    allowJobCancellation: diskBefore.agentAccess?.allowJobCancellation === true,
+  };
Relevance

●● Moderate

Likely accepted to avoid leaving user config mutated, but no close precedent on preserving
missing-vs-false state.

PR-#32

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The snapshot converts both absent and explicit-false fields to false, while cleanup merges those
values back through patchAgentAccessDisk. The repository type declares both fields and the entire
agentAccess object optional, proving the original presence information is lost.

scripts/mcp-agent-smoke.mjs[101-118]
scripts/mcp-agent-smoke.mjs[282-293]
scripts/mcp-agent-smoke.mjs[404-420]
src/server/types.ts[157-190]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The smoke must restore the pre-run config exactly, including missing fields and file nonexistence.

## Issue Context
Snapshot the original file's existence and contents before mutation, then restore those contents or remove the newly created file during cleanup.

## Fix Focus Areas
- scripts/mcp-agent-smoke.mjs[101-118]
- scripts/mcp-agent-smoke.mjs[282-293]
- scripts/mcp-agent-smoke.mjs[404-420]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

7. Sanitizer regex comment mismatch in injection test ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
The new integration test computes sanitizedToolName via a regex-strip and asserts its value inline,
but the actual route rejects the raw unsafe tool name outright via isAllowedMcpToolName() against an
exact allowlist before any sanitization-based path runs. The sanitizedToolName block is vestigial
from a prior sanitizer-based implementation and never reflects what code path the request actually
exercises, which can mislead future maintainers about the real protection mechanism.
Code

src/server/tests/routes.integration.test.ts[R626-632]

+      const unsafeToolName = "pass_catalog; rm -rf /";
+      // Allowlist is exact-match; sanitizer strips metacharacters to a non-allowlisted token.
+      const sanitizedToolName = unsafeToolName.replace(/[^a-zA-Z0-9_-]/g, "");
+      expect(sanitizedToolName).toBe("pass_catalogrm-rf");
+      expect(sanitizedToolName).not.toMatch(/[;|&`$]/);
+      expect(isAllowedMcpToolName(unsafeToolName)).toBe(false);
+      expect(isAllowedMcpToolName(sanitizedToolName)).toBe(false);
Relevance

●● Moderate

Test-only maintainability nit; team sometimes accepts tightening integration tests, but this is
somewhat subjective.

PR-#32

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The test defines sanitizedToolName via a regex strip and asserts its value inline, but the actual
route rejects unsafe tool names via isAllowedMcpToolName(unsafeToolName) against an exact allowlist
(asserted separately), never using the computed sanitizedToolName in the request sent to the
endpoint. The sanitizedToolName assertions therefore document dead logic unrelated to the
enforcement path being tested.

src/server/tests/routes.integration.test.ts[626-651]


Grey Divider

Context used
✅ Compliance rules (platform): 87 rules
✅ REVIEW.md
Review mode: 🧠 Deep: This bundles substantial behavioral changes across job idempotency/locking, process-launch security, state cleanup, and a large smoke harness, with 26 independent edit sites where redundant review can catch concurrency, lifecycle, or security defects.

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread src/server/services/olive/jobRunner.ts Outdated
Comment thread scripts/mcp-agent-smoke.mjs Outdated
Comment thread scripts/mcp-agent-smoke.mjs
Comment thread scripts/mcp-agent-smoke.mjs Outdated
Comment thread scripts/mcp-agent-smoke.mjs Outdated
Comment thread src/server/services/olive/state.ts
Comment thread src/server/__tests__/routes.integration.test.ts Outdated
@qodo-code-review

Copy link
Copy Markdown
Contributor

Qodo Fixer

✅ Committed (2) · ☑ Fixed (2)

Grey Divider

Commits pushed directly to this PR — no separate fix PR opened.

Process — 2 fixed
  • ☑ Fixed: Studio escalation never runs
  • ☑ Fixed: Interrupt leaves submission enabled

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 12

🤖 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 `@scripts/mcp-agent-smoke.mjs`:
- Around line 306-310: Update scripts/mcp-agent-smoke.mjs at lines 306-310 to
snapshot the raw config bytes and whether the file existed, rather than coercing
agentAccess booleans; update cleanup() at lines 431-440 to restore those exact
bytes or delete the file when it was originally absent. In readStudioDiskConfig
at lines 101-119, distinguish an absent file from an unreadable or unparsable
file and fail the smoke run on parse errors so patchAgentAccessDisk never
overwrites an invalid existing config.
- Around line 246-255: Update startStudio so its spawned child environment
explicitly removes OLIVE_MCP_ALLOW_JOBS after spreading process.env, ensuring
the variable is unset regardless of the parent environment. Keep the existing
comment aligned with this enforced deny-path behavior.
- Around line 416-423: Update the post-cancellation status check in the smoke
test to poll olive.get_optimization_job until the job reports status "cancelled"
and terminal true, using a bounded deadline and retry delay. Preserve the
existing timeout and error context, and throw only when the deadline expires
without observing the settled state.
- Around line 139-142: Update run() so the expectOk failure path throws an error
containing the mcporter status and signal instead of calling process.exit.
Preserve the existing failure condition, allowing the surrounding try/catch to
invoke cleanup() for temporary resources, child processes, and patched policy
state.
- Around line 147-155: Update parseJsonPayload to locate the true start of the
trailing JSON value instead of using lastIndexOf on opening braces or brackets;
scan forward from the first structural character of the trailing value or parse
the last non-empty line emitted by mcporter --output json. Preserve the existing
empty-output, missing-JSON, and JSON.parse error behavior for valid nested
object and array payloads.
- Around line 62-76: Update resolvePython so bare command candidates are
validated through PATH before returning them, rather than immediately returning
the first bare name and making python unreachable. Preserve the ordered
candidate chain, selecting the first available interpreter—including python when
python3 is unavailable—and retain the final fallback behavior if none can be
found.
- Around line 162-183: Update callToolAsync to preserve the parent environment
when opts.env is omitted by falling back to process.env in the spawn
environment. Also align the timeout error message with the actual timer delay by
reporting timeoutMs plus the additional 15-second grace period.
- Around line 351-368: Prevent the smoke test’s concurrent
olive.submit_optimization_job calls from launching real Olive processes.
Configure a no-op or stub executor for the submit path by default, while
allowing real execution only through an explicit opt-in flag; preserve the
existing idempotency and concurrency assertions.

In `@src/server/__tests__/setup.integration.ts`:
- Line 20: Remove the duplicate childProcessLaunchLog declaration in the
integration test setup module, retaining a single exported const with the
existing type and initialization.

In `@src/server/services/olive/jobRunner.ts`:
- Around line 137-150: The lock admission flow around startMcpOliveJobLocked
must reuse a job registered by an overlapping fingerprint-only submission when a
keyed request arrives afterward, while preserving sequential distinct-key
behavior; retain or propagate sufficient admission state for fingerprint
fallback without weakening explicit-key conflict checks. In
src/server/services/olive/jobRunner.ts lines 137-150, update the
locking/submission path accordingly. In
src/server/services/olive/jobRunner.idempotency.test.ts lines 54-65, add a
regression test that starts the fingerprint-only request before the keyed
request and asserts exactly one job registry entry.
- Around line 65-99: Update withMcpSubmitLocks to retain each assigned tail
promise and, after that tail resolves, delete its key from mcpSubmitLockTails
only when the map still references the same promise. Preserve newer queued tails
by guarding cleanup with exact promise identity, and keep lock release behavior
unchanged.

In `@src/server/services/olive/state.ts`:
- Around line 67-85: Update src/server/services/olive/state.ts:67-85 in
resetJobRegistry to use the normal venv-listener detach function, clear and null
metricsTimer, and reset sampling state for each job before cleanup and
finalization. Update src/server/services/olive/state.test.ts:145-175 to add
listener and timer fixtures and assert that reset detaches the listener and
clears both resources.
🪄 Autofix

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: ASSERTIVE

Plan: Pro Plus

Run ID: 09eec32c-31ba-4189-97dd-7787f453b432

📥 Commits

Reviewing files that changed from the base of the PR and between e154dc4 and 77496b2.

📒 Files selected for processing (13)
  • olive-mcp-server/tests/conftest.py
  • olive-mcp-server/tests/test_capabilities.py
  • olive-mcp-server/tests/test_docs_search_semantic.py
  • scripts/mcp-agent-smoke.mjs
  • src/server/__tests__/routes.integration.test.ts
  • src/server/__tests__/setup.integration.ts
  • src/server/routes/mcp.test.ts
  • src/server/routes/olive.stream.test.ts
  • src/server/services/olive/jobPreflight.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/services/olive/jobRunner.ts
  • src/server/services/olive/state.test.ts
  • src/server/services/olive/state.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • tonythethompson/QuickShell (manual)
  • tonythethompson/numan (manual)
  • tonythethompson/dependency-chain-substrate (manual)
💤 Files with no reviewable changes (1)
  • olive-mcp-server/tests/test_docs_search_semantic.py
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Greptile Review
⚠️ CI failures not shown inline (1)

Commit Status: Vercel: Vercel

Conclusion: failure

Deployment rate limited — retry in 24 hours.
🧰 Additional context used
📓 Path-based instructions (12)
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

src/**/*.{ts,tsx}: Match existing naming, file layout, and TypeScript patterns in src/.
Put shared recipe logic in src/lib/, especially pipelineValidation.ts, oliveRecipeBuilder.ts, and recipePipeline.ts.

src/**/*.{ts,tsx}: Keep validation logic in shared libraries rather than duplicating it in UI cell helpers or inspectors.
Split the InputEnvironmentPanel, IHVIntegrationPanel, and ExecutionWorkspace mega-panels into feature folders with colocated hooks and tests.
Keep server and UI AI provider catalogs synchronized, preferably through a shared provider ID list or synchronization test; register new providers in both catalogs.
Add test coverage for recipe-graph/, passCatalog, oliveRecipeHub, jobHistoryStore, and vramEstimate, and strengthen component tests for the large panels.

src/**/*.{ts,tsx}: All UI state mutations must go through commitUiStateUpdate in src/lib/pipelineValidation.ts so invariants are enforced; use usePipelineState() for state access and replaceState for recipe imports or preset loads.
Avoid export * barrel imports; import directly from the actual module file to preserve Vite tree-shaking and component-test isolation.

Follow the React performance guidance in docs/REACT_BEST_PRACTICES.md, especially eliminating waterfalls, avoiding barrel imports, and deferring non-critical third-party libraries.

Files:

  • src/server/routes/mcp.test.ts
  • src/server/services/olive/jobPreflight.test.ts
  • src/server/services/olive/jobRunner.ts
  • src/server/services/olive/state.ts
  • src/server/services/olive/state.test.ts
  • src/server/__tests__/routes.integration.test.ts
  • src/server/routes/olive.stream.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/__tests__/setup.integration.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.{ts,tsx,js,jsx}: Place imports at the top of modules; use inline imports only for a documented circular dependency.
Run linting and ensure typecheck-related CI checks pass before submitting changes.
For UI or server changes, manually smoke-test development startup, recipe loading/building, validation banners, and live execution when execution behavior is touched.

Use the project's React 19, Vite, Express, and Tauri 2 stack conventions for frontend and server TypeScript/JavaScript code.

Files:

  • src/server/routes/mcp.test.ts
  • src/server/services/olive/jobPreflight.test.ts
  • src/server/services/olive/jobRunner.ts
  • src/server/services/olive/state.ts
  • src/server/services/olive/state.test.ts
  • src/server/__tests__/routes.integration.test.ts
  • src/server/routes/olive.stream.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/__tests__/setup.integration.ts
src/server/routes/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Each API route module must export a mountXxxRoutes(router) function and be wired into server.ts.

Files:

  • src/server/routes/mcp.test.ts
  • src/server/routes/olive.stream.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

When working with React 19 or Vite 8 APIs, consult current Context7 documentation instead of assuming conventions from earlier major versions.

Files:

  • src/server/routes/mcp.test.ts
  • src/server/services/olive/jobPreflight.test.ts
  • src/server/services/olive/jobRunner.ts
  • src/server/services/olive/state.ts
  • src/server/services/olive/state.test.ts
  • src/server/__tests__/routes.integration.test.ts
  • src/server/routes/olive.stream.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/__tests__/setup.integration.ts
src/server/routes/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Organize Express server endpoints as modular route modules under src/server/routes/.

Files:

  • src/server/routes/mcp.test.ts
  • src/server/routes/olive.stream.test.ts
src/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use the unit-test configuration for src/lib/ unit tests and keep unit tests compatible with Vitest.

Files:

  • src/server/routes/mcp.test.ts
  • src/server/services/olive/jobPreflight.test.ts
  • src/server/services/olive/state.test.ts
  • src/server/__tests__/routes.integration.test.ts
  • src/server/routes/olive.stream.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
src/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Do not trigger real Olive optimization runs in tests or CI; use CPU-only recipe building, JSON export, and validation flows instead.

Files:

  • src/server/routes/mcp.test.ts
  • src/server/services/olive/jobPreflight.test.ts
  • src/server/services/olive/state.test.ts
  • src/server/__tests__/routes.integration.test.ts
  • src/server/routes/olive.stream.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
**/*

📄 CodeRabbit inference engine (AGENTS.md)

Do not implement the listed backburner AI providers unless explicitly requested; prefer Custom or OpenAI-compatible providers for OpenAI-shaped hosts.

Files:

  • src/server/routes/mcp.test.ts
  • src/server/services/olive/jobPreflight.test.ts
  • src/server/services/olive/jobRunner.ts
  • src/server/services/olive/state.ts
  • olive-mcp-server/tests/conftest.py
  • src/server/services/olive/state.test.ts
  • src/server/__tests__/routes.integration.test.ts
  • src/server/routes/olive.stream.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • olive-mcp-server/tests/test_capabilities.py
  • scripts/mcp-agent-smoke.mjs
  • src/server/__tests__/setup.integration.ts
src/server/services/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Keep server-side business logic in services, including AI providers, Olive job/virtual-environment handling, and related service modules.

Files:

  • src/server/services/olive/jobPreflight.test.ts
  • src/server/services/olive/jobRunner.ts
  • src/server/services/olive/state.ts
  • src/server/services/olive/state.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
olive-mcp-server/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Pin the Python mcp dependency to a version below 2 because version 2.x removes mcp.server.fastmcp and breaks imports.

Implement the Olive MCP server as a Python FastMCP stdio server compatible with Python >=3.10.

Files:

  • olive-mcp-server/tests/conftest.py
  • olive-mcp-server/tests/test_capabilities.py
olive-mcp-server/tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Run and maintain pytest coverage for the Olive MCP tools; use python -m pytest tests -q from olive-mcp-server.

Files:

  • olive-mcp-server/tests/conftest.py
  • olive-mcp-server/tests/test_capabilities.py
src/server/**/__tests__/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Server tests must use the server Vitest configuration; integration tests mock child_process, AI providers, and fetch and run against a real Express server on a random port.

Files:

  • src/server/__tests__/routes.integration.test.ts
  • src/server/__tests__/setup.integration.ts
🪛 ast-grep (0.45.0)
src/server/services/olive/state.test.ts

[warning] 148-148: Filesystem path is not a string literal; a request-/variable-derived path can enable path traversal. Validate and normalize the path before use.
Context: fs.writeFileSync(tmp, "{}", "utf-8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(detect-non-literal-fs-filename-typescript)

🔍 Remote MCP GitHub Copilot

Review-relevant context

  • MCP lock-tail leak: mcpSubmitLockTails stores a promise for every fingerprint/key, but cleanup only resolves promises; entries are never deleted. Long-lived Studio processes can accumulate these keys indefinitely.

  • Smoke test may execute real Olive: The allowed path starts a real server.ts, whose job setup eventually calls spawn(...). Repository instructions explicitly prohibit real Olive optimization runs in CI/VM checks; a stubbed executor is needed.

  • Smoke configuration restoration is lossy: The script snapshots only boolean policy values and writes them back during cleanup. Missing fields—and potentially a previously nonexistent config file—are not restored exactly. It also inherits OLIVE_MCP_ALLOW_JOBS into the Studio child process, which can override the denied disk policy.

  • Python fallback bug: resolvePython() immediately returns python3 without checking PATH availability, making the documented python fallback unreachable.

  • Listener cleanup: resetJobRegistry() clears job.venvListener without calling detachVenvListener(), while the normal cancellation path explicitly detaches it.

  • Validation status: PR #184’s reported targeted validation passed, and its current CI checks—including CodeQL, Python tests, security, validation, Docker build, and Olive-pass availability—are successful. However, the reported smoke validation only runs node --check; it does not demonstrate execution of the new smoke workflow.

🔇 Additional comments (13)
olive-mcp-server/tests/conftest.py (1)

1-13: LGTM!

Also applies to: 16-39, 42-45, 48-53

olive-mcp-server/tests/test_capabilities.py (1)

123-145: LGTM!

Also applies to: 163-201

src/server/services/olive/jobRunner.idempotency.test.ts (1)

19-25: LGTM!

Also applies to: 39-52, 68-77

src/server/services/olive/state.ts (1)

4-8: LGTM!

src/server/__tests__/routes.integration.test.ts (1)

13-18: LGTM!

Also applies to: 58-59, 626-651

src/server/services/olive/jobPreflight.test.ts (1)

1-13: LGTM!

Also applies to: 124-140

src/server/routes/mcp.test.ts (1)

233-240: LGTM!

src/server/routes/olive.stream.test.ts (1)

11-16: LGTM!

scripts/mcp-agent-smoke.mjs (5)

14-31: LGTM!


33-56: LGTM!


217-243: LGTM!


261-298: LGTM!


427-458: LGTM!

Also applies to: 460-491

Comment thread scripts/mcp-agent-smoke.mjs Outdated
Comment thread scripts/mcp-agent-smoke.mjs
Comment thread scripts/mcp-agent-smoke.mjs
Comment thread scripts/mcp-agent-smoke.mjs Outdated
Comment thread scripts/mcp-agent-smoke.mjs
Comment thread scripts/mcp-agent-smoke.mjs Outdated
Comment thread src/server/__tests__/setup.integration.ts
Comment thread src/server/services/olive/jobRunner.ts
Comment thread src/server/services/olive/jobRunner.ts
Comment thread src/server/services/olive/state.ts
cursor Bot pushed a commit that referenced this pull request Aug 8, 2026
Rebuild the #184 stack on current MCP_harden and fix the Codex findings:
- Stub Olive setup under OLIVE_JOB_SETUP_STUB so agent smoke never downloads
  models or runs olive
- Snapshot/restore exact Studio config on SIGINT/SIGTERM and strip inherited
  OLIVE_MCP_ALLOW_JOBS from the Studio child
- Serialize MCP submits with lock tails that evict when released
- resetJobRegistry detaches venv listeners; restore the review follow-up tests

Co-authored-by: Anthony Thompson <github@trackdub.com>
@cursor
cursor Bot force-pushed the cursor/mcp-harden-review-squash-5193 branch from 77496b2 to e27b48d Compare August 8, 2026 05:55
@tonythethompson

Copy link
Copy Markdown
Owner Author

Addressed Codex review on this PR (rebuilt on current MCP_harden):

  1. P1 real Olive setup — OLIVE_JOB_SETUP_STUB=1 parks jobs in setting_up (no venv/model/olive run).
  2. P1 signal config restore — exact .olive-studio/config.json snapshot/restore on SIGINT/SIGTERM/SIGHUP + normal exit.
  3. P2 OLIVE_MCP_ALLOW_JOBS — stripped from Studio child and smoke studioEnv so disk deny policy wins.
  4. P2 lock-tail growth — withMcpSubmitLocks deletes installed tails when still owned.

Also kept Greptile/Qodo overlap: resetJobRegistry calls detachVenvListener; injection test no longer implies a sanitizer accept path.

@vercel

vercel Bot commented Aug 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
olive-studio Error Error Aug 8, 2026 6:07am

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/server/services/olive/state.ts (1)

68-90: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Mark active jobs as cancelled before registry cleanup.

resetJobRegistry() removes a stubbed job without changing its setting_up status. continueOliveJobSetup() then keeps its polling timer active because no process exists for this reset path to terminate. Set active jobs to cancelled before cleanup so setup code exits.

Proposed fix
 export function resetJobRegistry(): void {
   for (const job of [...jobRegistry.values()]) {
+    if (job.status === "setting_up" || job.status === "running") {
+      job.status = "cancelled";
+    }
     if (job.venvListener) {
🤖 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 `@src/server/services/olive/state.ts` around lines 68 - 90, Update
resetJobRegistry() to mark each active job as cancelled before
cleanupJobArtifacts() and finalizeJob() run. Ensure the setting_up state is
transitioned to cancelled so continueOliveJobSetup() stops polling even when no
process exists, while preserving existing listener detachment and process
termination 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 `@scripts/mcp-agent-smoke.mjs`:
- Around line 509-516: Update the restoration error handling around
restoreStudioConfigFile to retain the caught error, complete all existing
process and temporary-file cleanup, then rethrow the restoration error so the
smoke run fails instead of only warning. Preserve the current cleanup behavior
and error-message handling for successful restoration.

In `@src/lib/__tests__/studioConfigSnapshot.test.ts`:
- Around line 21-24: Replace the JSDoc-only declarations for the fixture
variables root and configPath with native TypeScript string type annotations,
preserving their existing let declarations and usage.

In `@src/server/services/olive/jobRunner.idempotency.test.ts`:
- Around line 28-31: Move the static imports for preflightOliveRecipe,
mcpSubmitLockTailCount, startOliveJob, clearIdempotencyIndex, and jobRegistry to
the module’s top import section before all vi.mock declarations. Preserve the
existing mocked-module behavior and run the Vitest file to verify the hoisted
mocks still work.

---

Outside diff comments:
In `@src/server/services/olive/state.ts`:
- Around line 68-90: Update resetJobRegistry() to mark each active job as
cancelled before cleanupJobArtifacts() and finalizeJob() run. Ensure the
setting_up state is transitioned to cancelled so continueOliveJobSetup() stops
polling even when no process exists, while preserving existing listener
detachment and process termination behavior.
🪄 Autofix

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: ASSERTIVE

Plan: Pro Plus

Run ID: a748a5d8-6092-44b9-b37d-b8d0a2f4b56c

📥 Commits

Reviewing files that changed from the base of the PR and between 77496b2 and 34c88b6.

📒 Files selected for processing (9)
  • scripts/mcp-agent-smoke.mjs
  • scripts/resolvePython.mjs
  • scripts/studioConfigSnapshot.mjs
  • src/lib/__tests__/resolvePython.test.ts
  • src/lib/__tests__/studioConfigSnapshot.test.ts
  • src/server/__tests__/routes.integration.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/services/olive/jobRunner.ts
  • src/server/services/olive/state.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • tonythethompson/QuickShell (manual)
  • tonythethompson/numan (manual)
  • tonythethompson/dependency-chain-substrate (manual)
📜 Review details
⏰ Context from checks skipped due to timeout. (5)
  • GitHub Check: Greptile Review
  • GitHub Check: security
  • GitHub Check: olive-pass-availability
  • GitHub Check: docker-build
  • GitHub Check: python-tests
⚠️ CI failures not shown inline (1)

Commit Status: Vercel: Vercel

Conclusion: failure

Deployment was blocked
🧰 Additional context used
📓 Path-based instructions (8)
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

src/**/*.{ts,tsx}: Match existing naming, file layout, and TypeScript patterns in src/.
Put shared recipe logic in src/lib/, especially pipelineValidation.ts, oliveRecipeBuilder.ts, and recipePipeline.ts.

src/**/*.{ts,tsx}: Keep validation logic in shared libraries rather than duplicating it in UI cell helpers or inspectors.
Split the InputEnvironmentPanel, IHVIntegrationPanel, and ExecutionWorkspace mega-panels into feature folders with colocated hooks and tests.
Keep server and UI AI provider catalogs synchronized, preferably through a shared provider ID list or synchronization test; register new providers in both catalogs.
Add test coverage for recipe-graph/, passCatalog, oliveRecipeHub, jobHistoryStore, and vramEstimate, and strengthen component tests for the large panels.

src/**/*.{ts,tsx}: All UI state mutations must go through commitUiStateUpdate in src/lib/pipelineValidation.ts so invariants are enforced; use usePipelineState() for state access and replaceState for recipe imports or preset loads.
Avoid export * barrel imports; import directly from the actual module file to preserve Vite tree-shaking and component-test isolation.

Follow the React performance guidance in docs/REACT_BEST_PRACTICES.md, especially eliminating waterfalls, avoiding barrel imports, and deferring non-critical third-party libraries.

Files:

  • src/lib/__tests__/studioConfigSnapshot.test.ts
  • src/server/__tests__/routes.integration.test.ts
  • src/lib/__tests__/resolvePython.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/services/olive/state.ts
  • src/server/services/olive/jobRunner.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.{ts,tsx,js,jsx}: Place imports at the top of modules; use inline imports only for a documented circular dependency.
Run linting and ensure typecheck-related CI checks pass before submitting changes.
For UI or server changes, manually smoke-test development startup, recipe loading/building, validation banners, and live execution when execution behavior is touched.

Use the project's React 19, Vite, Express, and Tauri 2 stack conventions for frontend and server TypeScript/JavaScript code.

Files:

  • src/lib/__tests__/studioConfigSnapshot.test.ts
  • src/server/__tests__/routes.integration.test.ts
  • src/lib/__tests__/resolvePython.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/services/olive/state.ts
  • src/server/services/olive/jobRunner.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

When working with React 19 or Vite 8 APIs, consult current Context7 documentation instead of assuming conventions from earlier major versions.

Files:

  • src/lib/__tests__/studioConfigSnapshot.test.ts
  • src/server/__tests__/routes.integration.test.ts
  • src/lib/__tests__/resolvePython.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/services/olive/state.ts
  • src/server/services/olive/jobRunner.ts
src/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use the unit-test configuration for src/lib/ unit tests and keep unit tests compatible with Vitest.

Files:

  • src/lib/__tests__/studioConfigSnapshot.test.ts
  • src/server/__tests__/routes.integration.test.ts
  • src/lib/__tests__/resolvePython.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
src/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Do not trigger real Olive optimization runs in tests or CI; use CPU-only recipe building, JSON export, and validation flows instead.

Files:

  • src/lib/__tests__/studioConfigSnapshot.test.ts
  • src/server/__tests__/routes.integration.test.ts
  • src/lib/__tests__/resolvePython.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
**/*

📄 CodeRabbit inference engine (AGENTS.md)

Do not implement the listed backburner AI providers unless explicitly requested; prefer Custom or OpenAI-compatible providers for OpenAI-shaped hosts.

Files:

  • src/lib/__tests__/studioConfigSnapshot.test.ts
  • src/server/__tests__/routes.integration.test.ts
  • src/lib/__tests__/resolvePython.test.ts
  • scripts/resolvePython.mjs
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/services/olive/state.ts
  • scripts/studioConfigSnapshot.mjs
  • scripts/mcp-agent-smoke.mjs
  • src/server/services/olive/jobRunner.ts
src/server/**/__tests__/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Server tests must use the server Vitest configuration; integration tests mock child_process, AI providers, and fetch and run against a real Express server on a random port.

Files:

  • src/server/__tests__/routes.integration.test.ts
src/server/services/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Keep server-side business logic in services, including AI providers, Olive job/virtual-environment handling, and related service modules.

Files:

  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/services/olive/state.ts
  • src/server/services/olive/jobRunner.ts
🪛 GitHub Check: validate
src/lib/__tests__/studioConfigSnapshot.test.ts

[failure] 55-55:
Variable 'configPath' implicitly has an 'any' type.


[failure] 54-54:
Variable 'configPath' implicitly has an 'any' type.


[failure] 42-42:
Variable 'configPath' implicitly has an 'any' type.


[failure] 40-40:
Variable 'configPath' implicitly has an 'any' type.


[failure] 38-38:
Variable 'configPath' implicitly has an 'any' type.


[failure] 36-36:
Variable 'configPath' implicitly has an 'any' type.


[failure] 32-32:
Variable 'root' implicitly has an 'any' type.


[failure] 24-24:
Variable 'configPath' implicitly has type 'any' in some locations where its type cannot be determined.


[failure] 22-22:
Variable 'root' implicitly has type 'any' in some locations where its type cannot be determined.

src/lib/__tests__/resolvePython.test.ts

[failure] 16-16:
Type 'Mock<(p: string) => boolean>' is not assignable to type '((path: PathLike) => boolean) | undefined'.

🔍 Remote MCP DeepWiki, GitHub Copilot

Review-relevant context

  • Security issue remains: cleanup() catches and suppresses restoreStudioConfigFile() failures, so the smoke can exit successfully while leaving allowJobSubmission: true on disk. This was flagged by Greptile and is still present in the PR diff.
  • CI status: PR #184 is currently blocked; the validate check has failed, while several other checks remain in progress.
  • Other previously reported findings were addressed: async Studio shutdown escalation, signal cleanup, Python fallback probing, venv-listener detachment, lock-tail eviction, and exact config snapshot/restore.
  • Architecture lookup limitation: DeepWiki could not index tonythethompson/Olive-Studio, so no repository-architecture context was available from that source.
🔇 Additional comments (13)
src/server/services/olive/jobRunner.idempotency.test.ts (2)

65-70: Cover the fingerprint-only-first submission order.

Line 68 starts the keyed request before Line 69 starts the fingerprint-only request. This does not cover the prior failure mode where the fingerprint-only request registers first. Start the fingerprint-only request first, then start the keyed request, and assert one job registry entry.


58-63: LGTM!

Also applies to: 77-142

src/server/services/olive/state.ts (1)

78-90: Stop the metrics timer during registry reset.

resetJobRegistry() still leaves job.metricsTimer active. Clearing the registry does not clear its interval. This remains the existing resource-cleanup finding.

src/server/services/olive/jobRunner.ts (2)

68-71: 📐 Maintainability & Code Quality

Resolve the failed validation before merge.

The reported checks do not show successful lint and typecheck results. The validate check is currently failing. Run the required checks and resolve the failure before merge.

As per coding guidelines, “Run linting and ensure typecheck-related CI checks pass before submitting changes.”

Sources: Coding guidelines, MCP tools


77-112: LGTM!

src/server/__tests__/routes.integration.test.ts (2)

58-58: 📐 Maintainability & Code Quality

Run this suite with the server Vitest configuration.

Confirm that the server integration suite completed with its required configuration. Resolve the currently failing validation check before merge.

As per coding guidelines, “Server tests must use the server Vitest configuration; integration tests mock child_process, AI providers, and fetch and run against a real Express server on a random port.”

Sources: Coding guidelines, MCP tools


627-627: LGTM!

scripts/mcp-agent-smoke.mjs (1)

10-11: LGTM!

Also applies to: 30-34, 67-87, 275-325, 350-503, 505-508, 517-539

scripts/resolvePython.mjs (1)

1-58: LGTM!

scripts/studioConfigSnapshot.mjs (1)

1-50: LGTM!

src/lib/__tests__/resolvePython.test.ts (2)

1-12: LGTM!

Also applies to: 23-79


13-17: 🎯 Functional Correctness

No change needed for existsSync parameter typing.

existsSync(c) is only called with string paths, and the untyped mock in the resolvePython() dependency option is acceptable because resolvePython() is JavaScript with JSDoc.

			> Likely an incorrect or invalid review comment.
src/lib/__tests__/studioConfigSnapshot.test.ts (1)

1-20: LGTM!

Also applies to: 26-74

Comment thread scripts/mcp-agent-smoke.mjs Outdated
Comment thread src/lib/__tests__/studioConfigSnapshot.test.ts Outdated
Comment thread src/server/services/olive/jobRunner.idempotency.test.ts Outdated
tonythethompson added a commit that referenced this pull request Aug 8, 2026
Replay the PR #184 tip tree onto MCP_harden after main was merged (vercel.json retained). Intermediate commit rebase conflicted on smoke/jobRunner/state history merges.

Co-authored-by: Cursor <cursoragent@cursor.com>
@tonythethompson
tonythethompson force-pushed the cursor/mcp-harden-review-squash-5193 branch from 02fa7d2 to 38bd8e7 Compare August 8, 2026 06:22

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
scripts/mcp-agent-smoke.mjs (2)

189-201: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Use exitCode/signalCode to decide the escalation kill.

child.killed only means SIGTERM was sent successfully, not that mcporter exited. A process that ignores SIGTERM will skip SIGKILL at line 191 and can leave the smoke flow waiting after rejection.

Proposed fix
       killEscalation = setTimeout(() => {
         try {
-          if (!child.killed) child.kill("SIGKILL");
+          if (child.exitCode === null && child.signalCode === null) {
+            child.kill("SIGKILL");
+          }
         } catch {
           /* ignore */
         }
🤖 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 `@scripts/mcp-agent-smoke.mjs` around lines 189 - 201, Update the escalation
callback in the child-process timeout flow to use exitCode and signalCode to
determine whether mcporter has exited, rather than relying on child.killed. Send
SIGKILL only while both exitCode and signalCode indicate the process is still
running, preserving the existing error rejection and timer behavior.

516-533: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Restore the Studio configuration and remove the temp config in finally.

If stopStudio(studioChild) rejects, cleanup() exits before restoring STUDIO_CONFIG_PATH or removing smokeConfigDir, leaving the smoke run with a modified job-submission policy on disk. Keep the shutdown order, but add the restore and rmSync(smokeConfigDir, ...) cleanup to a finally block surrounding the await, then add a regression test for this path.

🤖 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 `@scripts/mcp-agent-smoke.mjs` around lines 516 - 533, Update cleanup() so the
existing stopStudio(studioChild) await remains first, while restoring
STUDIO_CONFIG_PATH and removing smokeConfigDir execute in a finally block even
when shutdown rejects; preserve configRestoreError handling and add a regression
test covering stopStudio failure.
src/server/services/olive/jobRunner.ts (1)

309-330: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Exit the setup stub loop on finalization.

The stub loop only checks job.status, but finalizeJob() can set finishedAt and drain subscribers without changing the status. A terminal condition like cancelled cleanup can leave this polling promise alive and keep the process running. Add a finishedAt guard or await a job completion signal, and ensure the returned status is terminal before cleanup completes.

🤖 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 `@src/server/services/olive/jobRunner.ts` around lines 309 - 330, The stub
setup polling loop in the job runner must also exit when the job is finalized,
not only when status changes from setting_up. Update the stubSetup branch around
the loop to guard on job.finishedAt or an equivalent completion signal, then
perform cleanup and finalization only after the wait ends and return the
resulting terminal job.status.
🤖 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 `@src/server/services/olive/jobRunner.idempotency.test.ts`:
- Around line 80-95: Extend the test around startOliveJob to submit a third
request using the adopted "after-fp-key" idempotency key. Assert that this
replay succeeds, returns the same jobId as fpOnly, and has reused set to true,
while preserving the existing registry and lock assertions.

In `@src/server/services/olive/state.test.ts`:
- Around line 188-204: Extend the test around resetJobRegistry to spy on
globalThis.clearInterval or use Vitest timer assertions, and verify that the
specific handle created for job.metricsTimer was cleared. Keep the existing
assertions for listener detachment and metricsTimer being set to null.

---

Outside diff comments:
In `@scripts/mcp-agent-smoke.mjs`:
- Around line 189-201: Update the escalation callback in the child-process
timeout flow to use exitCode and signalCode to determine whether mcporter has
exited, rather than relying on child.killed. Send SIGKILL only while both
exitCode and signalCode indicate the process is still running, preserving the
existing error rejection and timer behavior.
- Around line 516-533: Update cleanup() so the existing stopStudio(studioChild)
await remains first, while restoring STUDIO_CONFIG_PATH and removing
smokeConfigDir execute in a finally block even when shutdown rejects; preserve
configRestoreError handling and add a regression test covering stopStudio
failure.

In `@src/server/services/olive/jobRunner.ts`:
- Around line 309-330: The stub setup polling loop in the job runner must also
exit when the job is finalized, not only when status changes from setting_up.
Update the stubSetup branch around the loop to guard on job.finishedAt or an
equivalent completion signal, then perform cleanup and finalization only after
the wait ends and return the resulting terminal job.status.
🪄 Autofix

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: ASSERTIVE

Plan: Pro Plus

Run ID: 1c07bb49-5a14-461d-961e-8a1d3be4707e

📥 Commits

Reviewing files that changed from the base of the PR and between 34c88b6 and 02fa7d2.

📒 Files selected for processing (7)
  • scripts/mcp-agent-smoke.mjs
  • src/server/services/olive/jobIdempotency.test.ts
  • src/server/services/olive/jobIdempotency.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/services/olive/jobRunner.ts
  • src/server/services/olive/state.test.ts
  • src/server/services/olive/state.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • tonythethompson/QuickShell (manual)
  • tonythethompson/numan (manual)
  • tonythethompson/dependency-chain-substrate (manual)
📜 Review details
⚠️ CI failures not shown inline (2)

GitHub Actions: CI / validate: fix(mcp): MCP_harden review follow-ups (Codex + CodeRabbit)

Conclusion: failure

View job details

##[group]Run pnpm lint
 �[36;1mpnpm lint�[0m
 shell: /usr/bin/bash -e {0}
 env:
   PNPM_HOME: /home/runner/setup-pnpm/node_modules/.bin
 ##[endgroup]
 $ tsc --noEmit && eslint
 ##[error]src/lib/__tests__/resolvePython.test.ts(16,9): error TS2322: Type 'Mock<(p: string) => boolean>' is not assignable to type '((path: PathLike) => boolean) | undefined'.

GitHub Actions: CI / 0_validate.txt: fix(mcp): MCP_harden review follow-ups (Codex + CodeRabbit)

Conclusion: failure

View job details

##[group]Run pnpm lint
 �[36;1mpnpm lint�[0m
 shell: /usr/bin/bash -e {0}
 env:
   PNPM_HOME: /home/runner/setup-pnpm/node_modules/.bin
 ##[endgroup]
 $ tsc --noEmit && eslint
 ##[error]src/lib/__tests__/resolvePython.test.ts(16,9): error TS2322: Type 'Mock<(p: string) => boolean>' is not assignable to type '((path: PathLike) => boolean) | undefined'.
🧰 Additional context used
📓 Path-based instructions (7)
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

src/**/*.{ts,tsx}: Match existing naming, file layout, and TypeScript patterns in src/.
Put shared recipe logic in src/lib/, especially pipelineValidation.ts, oliveRecipeBuilder.ts, and recipePipeline.ts.

src/**/*.{ts,tsx}: Keep validation logic in shared libraries rather than duplicating it in UI cell helpers or inspectors.
Split the InputEnvironmentPanel, IHVIntegrationPanel, and ExecutionWorkspace mega-panels into feature folders with colocated hooks and tests.
Keep server and UI AI provider catalogs synchronized, preferably through a shared provider ID list or synchronization test; register new providers in both catalogs.
Add test coverage for recipe-graph/, passCatalog, oliveRecipeHub, jobHistoryStore, and vramEstimate, and strengthen component tests for the large panels.

src/**/*.{ts,tsx}: All UI state mutations must go through commitUiStateUpdate in src/lib/pipelineValidation.ts so invariants are enforced; use usePipelineState() for state access and replaceState for recipe imports or preset loads.
Avoid export * barrel imports; import directly from the actual module file to preserve Vite tree-shaking and component-test isolation.

Follow the React performance guidance in docs/REACT_BEST_PRACTICES.md, especially eliminating waterfalls, avoiding barrel imports, and deferring non-critical third-party libraries.

Files:

  • src/server/services/olive/jobIdempotency.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/services/olive/jobIdempotency.ts
  • src/server/services/olive/state.test.ts
  • src/server/services/olive/jobRunner.ts
  • src/server/services/olive/state.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.{ts,tsx,js,jsx}: Place imports at the top of modules; use inline imports only for a documented circular dependency.
Run linting and ensure typecheck-related CI checks pass before submitting changes.
For UI or server changes, manually smoke-test development startup, recipe loading/building, validation banners, and live execution when execution behavior is touched.

Use the project's React 19, Vite, Express, and Tauri 2 stack conventions for frontend and server TypeScript/JavaScript code.

Files:

  • src/server/services/olive/jobIdempotency.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/services/olive/jobIdempotency.ts
  • src/server/services/olive/state.test.ts
  • src/server/services/olive/jobRunner.ts
  • src/server/services/olive/state.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

When working with React 19 or Vite 8 APIs, consult current Context7 documentation instead of assuming conventions from earlier major versions.

Files:

  • src/server/services/olive/jobIdempotency.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/services/olive/jobIdempotency.ts
  • src/server/services/olive/state.test.ts
  • src/server/services/olive/jobRunner.ts
  • src/server/services/olive/state.ts
src/server/services/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Keep server-side business logic in services, including AI providers, Olive job/virtual-environment handling, and related service modules.

Files:

  • src/server/services/olive/jobIdempotency.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/services/olive/jobIdempotency.ts
  • src/server/services/olive/state.test.ts
  • src/server/services/olive/jobRunner.ts
  • src/server/services/olive/state.ts
src/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use the unit-test configuration for src/lib/ unit tests and keep unit tests compatible with Vitest.

Files:

  • src/server/services/olive/jobIdempotency.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/services/olive/state.test.ts
src/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Do not trigger real Olive optimization runs in tests or CI; use CPU-only recipe building, JSON export, and validation flows instead.

Files:

  • src/server/services/olive/jobIdempotency.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/services/olive/state.test.ts
**/*

📄 CodeRabbit inference engine (AGENTS.md)

Do not implement the listed backburner AI providers unless explicitly requested; prefer Custom or OpenAI-compatible providers for OpenAI-shaped hosts.

Files:

  • src/server/services/olive/jobIdempotency.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/services/olive/jobIdempotency.ts
  • src/server/services/olive/state.test.ts
  • src/server/services/olive/jobRunner.ts
  • scripts/mcp-agent-smoke.mjs
  • src/server/services/olive/state.ts
🔍 Remote MCP GitHub Copilot

Additional review context

  • Validation is failing. PR #184 is blocked; the validate check failed, while CodeQL, Docker, Python tests, security, and Olive-pass checks passed.
  • Actionable compile issue remains: src/lib/__tests__/studioConfigSnapshot.test.ts declares root and configPath using JSDoc-only types in a TypeScript file. The review reports both as implicit any, matching the failed validation output. Replace them with let root: string; and let configPath: string;.
  • Non-blocking maintainability issue: jobRunner.idempotency.test.ts places static imports after vi.mock declarations. Moving imports to the top would align with the repository’s import conventions, but the finding is not inherently functional.
  • Previously reported smoke-test, lock-tail, idempotency, cleanup, signal-handling, and configuration-restoration findings are marked addressed or resolved in the current review threads.
🔇 Additional comments (9)
scripts/mcp-agent-smoke.mjs (1)

357-358: LGTM!

Also applies to: 543-547, 557-577

src/server/services/olive/jobRunner.idempotency.test.ts (2)

28-31: Move the static imports above the mock declarations.

Lines 28-31 remain below vi.mock(...) calls. This repeats the existing finding.

As per coding guidelines, **/*.{ts,tsx,js,jsx} files must place imports at the top of modules; inline imports are allowed only for a documented circular dependency.

Source: Coding guidelines


19-24: LGTM!

Also applies to: 33-45, 58-78, 97-159

src/server/services/olive/jobIdempotency.ts (1)

14-15: LGTM!

Also applies to: 129-138

src/server/services/olive/jobRunner.ts (1)

65-112: LGTM!

Also applies to: 150-163, 197-202

src/server/services/olive/jobIdempotency.test.ts (1)

91-91: LGTM!

Also applies to: 105-117

src/server/services/olive/state.ts (1)

10-10: LGTM!

Also applies to: 79-80

src/server/services/olive/state.test.ts (2)

2-13: LGTM!

Also applies to: 46-52, 156-186


205-207: LGTM!

Comment thread src/server/services/olive/jobRunner.idempotency.test.ts
Comment thread src/server/services/olive/state.test.ts
Comment thread scripts/mcp-agent-smoke.mjs
Restack PR #184 onto the linearized MCP_harden base from stack #185.

Co-authored-by: Cursor <cursoragent@cursor.com>
@tonythethompson
tonythethompson force-pushed the cursor/mcp-harden-review-squash-5193 branch from 38bd8e7 to 2ba92cf Compare August 8, 2026 06:29
Comment thread scripts/mcp-agent-smoke.mjs Outdated
tonythethompson and others added 3 commits August 7, 2026 23:33
Annotate Studio config snapshot locals and PathLike-compatible existsSync mocks so pnpm lint / tsc --noEmit passes on CI validate.

Co-authored-by: Cursor <cursoragent@cursor.com>
Mark non-terminal jobs cancelled during resetJobRegistry so stub setting_up loops exit, and move jobRunner idempotency test imports above vi.mock.

Co-authored-by: Cursor <cursoragent@cursor.com>
Track the smoke's last written config bytes and skip snapshot restore (failing the run) when another process changed the file first.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread scripts/mcp-agent-smoke.mjs
Comment thread scripts/mcp-agent-smoke.mjs
tonythethompson and others added 3 commits August 7, 2026 23:47
Serialize overlapping mcp-agent-smoke runs with a pid lock so one process cannot snapshot or restore another run's temporary allowJobSubmission state.

Co-authored-by: Cursor <cursoragent@cursor.com>
Exit stub setup when the job is finalized, SIGKILL only while mcporter is still alive, restore Studio config in a finally after stop, and cover adopted-key replay plus clearInterval on registry reset.

Co-authored-by: Cursor <cursoragent@cursor.com>
Mark temporary Studio policy patches with a live-pid owner stamp and make cleanup reject when snapshot restore fails so Greptile confidence gating no longer sees silent success.

Co-authored-by: Cursor <cursoragent@cursor.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🤖 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 `@scripts/mcp-agent-smoke.mjs`:
- Around line 609-623: Update failExitCode to return the conventional nonzero
SIGHUP exit code, 129, before the STRICT fallback. Keep the existing SIGINT and
SIGTERM mappings and ensure handleSignal continues routing SIGHUP through
failExitCode.

In `@scripts/studioConfigSmokeLock.mjs`:
- Around line 84-102: Update the EEXIST handling around the lock acquisition
loop: treat a non-finite parsed holder, including an empty or malformed lock
body, as stale and attempt reclamation; only continue immediately after unlink
succeeds, and otherwise fall through to the existing sleep(pollMs) path so
failed reclaim attempts cannot busy-spin.
- Around line 115-122: Use directory-specific removal APIs for empty Studio
config cleanup: in scripts/studioConfigSmokeLock.mjs#115-122, change
tryRemoveEmptyStudioConfigDir to inject and call rmdirSync/rmdir; in
scripts/studioConfigSnapshot.mjs#111-123, import and call rmdirSync instead of
rmSync with recursive options. Update
src/lib/__tests__/studioConfigSmokeLock.test.ts#104-109 to stub rmdirSync.

In `@src/lib/__tests__/resolvePython.test.ts`:
- Around line 47-58: Add a test case for resolvePython where spawnSync reports
both "python3" and "python" as available, and assert that it returns "python3".
Keep the existing Linux configuration and mock setup, ensuring the test locks
the candidate ordering preference.

In `@src/lib/__tests__/studioConfigSmokeLock.test.ts`:
- Around line 12-58: Extend the test "acquires with wx and releases only own
pid" by replacing the stored lock body with a different PID after acquisition
and before calling lock.release(). Assert that release leaves the lock present,
then restore or separately verify the owning-PID case so the test covers both
ownership behaviors.

In `@src/server/services/olive/jobRunner.idempotency.test.ts`:
- Around line 163-169: The test around the concurrent startOliveJob calls must
assert the expected registry and reuse behavior, not just successful results and
an empty lock map. Verify that hold-1 and hold-2 register as distinct jobs, that
the fingerprint-only request reuses hold-2, and that the final registry reflects
exactly those expected jobs; use the existing registry/reuse assertion helpers
or symbols in the test file.
- Around line 22-45: Update the test setup around startOliveJob and
continueOliveJobSetup to mock the child_process spawn boundary and filesystem
operations used for run artifacts, preventing real echo processes and
.olive-runs writes. Track or await detached setup promises so afterEach drains
all pending work before clearing jobRegistry, then retain the existing
idempotency and mock reset cleanup; keep tests limited to CPU-only recipe
building, JSON export, and validation flows.

In `@src/server/services/olive/jobRunner.ts`:
- Around line 309-330: Bound the wait loop in the stubSetup branch of the job
runner with a finite timeout, and ensure expiration exits the loop and finalizes
the job as a deterministic failure rather than hanging indefinitely. Preserve
the existing cancellation and external-finalization exits, and report the stub’s
non-termination through the established job status/logging mechanisms.

In `@src/server/services/olive/state.test.ts`:
- Around line 7-21: Move the static imports from state.ts and jobIdempotency.ts
above the vi.hoisted and vi.mock setup in the test module. Preserve the existing
mock behavior for ../venv/index.ts and ensure lint and typecheck checks continue
to pass.
🪄 Autofix

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: ASSERTIVE

Plan: Pro Plus

Run ID: 4f8e8048-d0f1-435d-8cb6-9b2446ed95a1

📥 Commits

Reviewing files that changed from the base of the PR and between 02fa7d2 and da1866b.

📒 Files selected for processing (12)
  • scripts/mcp-agent-smoke.mjs
  • scripts/stopStudioThenAlways.mjs
  • scripts/studioConfigSmokeLock.mjs
  • scripts/studioConfigSnapshot.mjs
  • src/lib/__tests__/resolvePython.test.ts
  • src/lib/__tests__/stopStudioThenAlways.test.ts
  • src/lib/__tests__/studioConfigSmokeLock.test.ts
  • src/lib/__tests__/studioConfigSnapshot.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/services/olive/jobRunner.ts
  • src/server/services/olive/state.test.ts
  • src/server/services/olive/state.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • tonythethompson/QuickShell (manual)
  • tonythethompson/numan (manual)
  • tonythethompson/dependency-chain-substrate (manual)
📜 Review details
⏰ Context from checks skipped due to timeout. (6)
  • GitHub Check: Greptile Review
  • GitHub Check: olive-pass-availability
  • GitHub Check: security
  • GitHub Check: validate
  • GitHub Check: docker-build
  • GitHub Check: python-tests
🧰 Additional context used
📓 Path-based instructions (7)
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

src/**/*.{ts,tsx}: Match existing naming, file layout, and TypeScript patterns in src/.
Put shared recipe logic in src/lib/, especially pipelineValidation.ts, oliveRecipeBuilder.ts, and recipePipeline.ts.

src/**/*.{ts,tsx}: Keep validation logic in shared libraries rather than duplicating it in UI cell helpers or inspectors.
Split the InputEnvironmentPanel, IHVIntegrationPanel, and ExecutionWorkspace mega-panels into feature folders with colocated hooks and tests.
Keep server and UI AI provider catalogs synchronized, preferably through a shared provider ID list or synchronization test; register new providers in both catalogs.
Add test coverage for recipe-graph/, passCatalog, oliveRecipeHub, jobHistoryStore, and vramEstimate, and strengthen component tests for the large panels.

src/**/*.{ts,tsx}: All UI state mutations must go through commitUiStateUpdate in src/lib/pipelineValidation.ts so invariants are enforced; use usePipelineState() for state access and replaceState for recipe imports or preset loads.
Avoid export * barrel imports; import directly from the actual module file to preserve Vite tree-shaking and component-test isolation.

Follow the React performance guidance in docs/REACT_BEST_PRACTICES.md, especially eliminating waterfalls, avoiding barrel imports, and deferring non-critical third-party libraries.

Files:

  • src/lib/__tests__/stopStudioThenAlways.test.ts
  • src/lib/__tests__/studioConfigSmokeLock.test.ts
  • src/server/services/olive/state.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/services/olive/jobRunner.ts
  • src/lib/__tests__/studioConfigSnapshot.test.ts
  • src/server/services/olive/state.test.ts
  • src/lib/__tests__/resolvePython.test.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.{ts,tsx,js,jsx}: Place imports at the top of modules; use inline imports only for a documented circular dependency.
Run linting and ensure typecheck-related CI checks pass before submitting changes.
For UI or server changes, manually smoke-test development startup, recipe loading/building, validation banners, and live execution when execution behavior is touched.

Use the project's React 19, Vite, Express, and Tauri 2 stack conventions for frontend and server TypeScript/JavaScript code.

Files:

  • src/lib/__tests__/stopStudioThenAlways.test.ts
  • src/lib/__tests__/studioConfigSmokeLock.test.ts
  • src/server/services/olive/state.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/services/olive/jobRunner.ts
  • src/lib/__tests__/studioConfigSnapshot.test.ts
  • src/server/services/olive/state.test.ts
  • src/lib/__tests__/resolvePython.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

When working with React 19 or Vite 8 APIs, consult current Context7 documentation instead of assuming conventions from earlier major versions.

Files:

  • src/lib/__tests__/stopStudioThenAlways.test.ts
  • src/lib/__tests__/studioConfigSmokeLock.test.ts
  • src/server/services/olive/state.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/services/olive/jobRunner.ts
  • src/lib/__tests__/studioConfigSnapshot.test.ts
  • src/server/services/olive/state.test.ts
  • src/lib/__tests__/resolvePython.test.ts
src/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use the unit-test configuration for src/lib/ unit tests and keep unit tests compatible with Vitest.

Files:

  • src/lib/__tests__/stopStudioThenAlways.test.ts
  • src/lib/__tests__/studioConfigSmokeLock.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/lib/__tests__/studioConfigSnapshot.test.ts
  • src/server/services/olive/state.test.ts
  • src/lib/__tests__/resolvePython.test.ts
src/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Do not trigger real Olive optimization runs in tests or CI; use CPU-only recipe building, JSON export, and validation flows instead.

Files:

  • src/lib/__tests__/stopStudioThenAlways.test.ts
  • src/lib/__tests__/studioConfigSmokeLock.test.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/lib/__tests__/studioConfigSnapshot.test.ts
  • src/server/services/olive/state.test.ts
  • src/lib/__tests__/resolvePython.test.ts
**/*

📄 CodeRabbit inference engine (AGENTS.md)

Do not implement the listed backburner AI providers unless explicitly requested; prefer Custom or OpenAI-compatible providers for OpenAI-shaped hosts.

Files:

  • src/lib/__tests__/stopStudioThenAlways.test.ts
  • scripts/stopStudioThenAlways.mjs
  • src/lib/__tests__/studioConfigSmokeLock.test.ts
  • src/server/services/olive/state.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • scripts/studioConfigSmokeLock.mjs
  • src/server/services/olive/jobRunner.ts
  • src/lib/__tests__/studioConfigSnapshot.test.ts
  • src/server/services/olive/state.test.ts
  • scripts/studioConfigSnapshot.mjs
  • src/lib/__tests__/resolvePython.test.ts
  • scripts/mcp-agent-smoke.mjs
src/server/services/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Keep server-side business logic in services, including AI providers, Olive job/virtual-environment handling, and related service modules.

Files:

  • src/server/services/olive/state.ts
  • src/server/services/olive/jobRunner.idempotency.test.ts
  • src/server/services/olive/jobRunner.ts
  • src/server/services/olive/state.test.ts
🪛 ast-grep (0.45.0)
src/server/services/olive/jobRunner.ts

[warning] 424-424: Filesystem path is not a string literal; a request-/variable-derived path can enable path traversal. Validate and normalize the path before use.
Context: fs.writeFileSync(configPath, JSON.stringify(enrichedRecipe, null, 2), "utf-8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(detect-non-literal-fs-filename-typescript)


[warning] 3-3: Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { spawn } from "child_process";
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

src/server/services/olive/state.test.ts

[warning] 159-159: Filesystem path is not a string literal; a request-/variable-derived path can enable path traversal. Validate and normalize the path before use.
Context: fs.writeFileSync(tmp, "{}", "utf-8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(detect-non-literal-fs-filename-typescript)

🔍 Remote MCP GitHub Copilot

Additional review context

  • PR #184’s latest commit is da1866b; all current checks are still in progress, including validate, Python tests, Docker, security, Olive-pass availability, and Greptile review. No current pass/fail result is available yet.
  • The previously reported studioConfigSnapshot.test.ts implicit-any issue appears addressed in the current diff: root and configPath are now explicitly typed as string.
  • The static-import ordering issue in jobRunner.idempotency.test.ts also appears addressed: imports now precede vi.mock declarations.
  • Review threads report fixes for:
    • Python interpreter probing and python fallback.
    • Nested JSON payload parsing.
    • Studio config exact-byte restoration and concurrent-write protection.
    • Signal cleanup and restoration-failure exit handling.
    • Stubbed Olive setup during smoke tests.
    • MCP lock-tail eviction.
    • Fingerprint-only/keyed idempotency adoption.
    • Registry resource cleanup and timer/listener teardown.
  • One remaining review-relevant test-quality suggestion was to assert that the adopted idempotency key works on a later replay; the current diff includes that third replay assertion.

DeepWiki and Context7 were not used because this PR concerns Olive-Studio’s TypeScript/Python MCP tooling and tests, not the specified Babel-Player architectural boundaries or a dependency/API upgrade.

🔇 Additional comments (21)
src/server/services/olive/state.ts (1)

4-10: LGTM!

Also applies to: 65-106, 131-138

src/server/services/olive/state.test.ts (1)

45-52: LGTM!

Also applies to: 69-86, 156-225

src/server/services/olive/jobRunner.ts (3)

65-112: LGTM!


148-223: LGTM!


225-293: LGTM!

Also applies to: 332-485

src/server/services/olive/jobRunner.idempotency.test.ts (2)

47-117: LGTM!


119-146: LGTM!

scripts/stopStudioThenAlways.mjs (1)

10-16: LGTM!

scripts/studioConfigSmokeLock.mjs (1)

21-29: LGTM!

scripts/studioConfigSnapshot.mjs (2)

22-30: LGTM!

Also applies to: 37-40, 46-62


70-88: LGTM!

src/lib/__tests__/stopStudioThenAlways.test.ts (1)

8-22: LGTM!

src/lib/__tests__/studioConfigSnapshot.test.ts (1)

23-24: LGTM!

Also applies to: 35-57, 59-73, 75-95, 97-112

scripts/mcp-agent-smoke.mjs (8)

103-134: LGTM!


161-174: LGTM!


181-260: LGTM!


262-300: LGTM!


302-316: LGTM!


318-354: LGTM!


550-607: LGTM!


526-536: 🩺 Stability & Availability

No change needed.

The stub setup loop does not transition to completed; it exits only when the job status changes to cancelled or when finishedAt is set.

Comment thread scripts/mcp-agent-smoke.mjs
Comment thread scripts/studioConfigSmokeLock.mjs
Comment thread scripts/studioConfigSmokeLock.mjs
Comment thread src/lib/__tests__/resolvePython.test.ts
Comment thread src/lib/__tests__/studioConfigSmokeLock.test.ts
Comment thread src/server/services/olive/jobRunner.idempotency.test.ts
Comment thread src/server/services/olive/jobRunner.idempotency.test.ts
Comment thread src/server/services/olive/jobRunner.ts
Comment thread src/server/services/olive/state.test.ts
@tonythethompson
tonythethompson merged commit da1866b into main Aug 8, 2026
10 of 11 checks passed
@tonythethompson
tonythethompson deleted the cursor/mcp-harden-review-squash-5193 branch August 8, 2026 07:50
@linear-code

linear-code Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

OLI-71

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