Skip to content

feat: full Clone MCP session integration (start/record/feedback/stop)#7

Draft
Turtle-Hwan wants to merge 7 commits into
mainfrom
worktree-clone-mcp-full-integration
Draft

feat: full Clone MCP session integration (start/record/feedback/stop)#7
Turtle-Hwan wants to merge 7 commits into
mainfrom
worktree-clone-mcp-full-integration

Conversation

@Turtle-Hwan
Copy link
Copy Markdown
Contributor

@Turtle-Hwan Turtle-Hwan commented May 12, 2026

Warning

Holding — this PR adds Clone memory recording and storage integration (session tracking, prompt/response recording, feedback submission). Because it writes interaction data to Clone's backend, it carries higher risk and needs careful review before merge.

Summary

  • scripts/clone-mcp.mjs (new): shared MCP client exporting startCloneSession, stopCloneSession, recordAgentPrompt, recordAgentResponse, submitFeedback. Hooks keep their inline predict_next_prompt implementation; the new module handles the session/recording/feedback tools only.
  • scripts/setup-clone-loop.mjs: on /clone:loop startup, calls start_session + record_agent_prompt(source=user) and writes clone_session_id, mcp_session_id, last_prompt_event_id to the state file frontmatter. Failures are non-fatal (warning to stderr, loop continues without session context). Gate: CLONE_LOOP_DISABLE_SESSION=1 skips the bootstrap (used by unit tests).
  • hooks/stop-hook.mjs: before predicting, calls record_agent_response with the iteration's assistant output. After a confident prediction, calls record_agent_prompt(source=clone-prediction) and updates last_prompt_event_id. On escalation (low confidence / incomplete / MCP error), calls submit_feedback(status=rejected) (when a prediction id is available) and stop_session. Max-iterations and empty-state terminal branches also call stop_session.
  • hooks/ask-user-question-hook.mjs: passes clone_session_id as the MCP session id (falling back to the Claude Code session id to preserve existing behaviour). On defer-no-options, calls submit_feedback(status=rejected).
  • scripts/cancel-clone-loop.mjs (new) + commands/cancel-loop.md rewrite: /clone:cancel-loop now invokes a Node script that reads the Clone session id from frontmatter, calls stop_session, then removes the state file.

Test plan

  • pnpm test — 29 tests pass (includes 3 new session-integration cases in stop-hook-v2.test.mjs and 3 new cases in tests/cancel-clone-loop.test.mjs)
  • pnpm test:mcp:e2e — live remote MCP smoke passes
  • Manual: /clone:loop "..." in a real session → verify clone-loop.local.md gets clone_session_id in frontmatter after setup
  • Manual: let loop run 2+ iterations → confirm record_agent_response / record_agent_prompt calls appear in .claude/clone-loop.history.local.jsonl
  • Manual: trigger escalation (lower threshold) → confirm submit_feedback + stop_session events in history
  • Manual: /clone:cancel-loop → confirm state file removed and session-stopped event in history

🤖 Generated with Claude Code

Extract the MCP RPC machinery into a single scripts/clone-mcp.mjs so the
hooks and setup script can share it. Exports clonePredictNextPrompt,
startCloneSession, stopCloneSession, recordAgentPrompt, recordAgentResponse,
and submitFeedback. Each helper accepts an existing mcpSessionId so callers
that already hold one can skip the initialize round-trip, while keeping a
lazy initialize fallback for fresh invocations.
Call start_session and record_agent_prompt with source=user when the loop
launches. The resulting clone_session_id, mcp_session_id, and first
last_prompt_event_id are appended to .claude/clone-loop.local.md frontmatter
so the stop hook can reuse them. Bootstrap failures are non-fatal: a
warning is logged to stderr and the loop continues without session context.
Tests can opt out of the network call via CLONE_LOOP_DISABLE_SESSION=1.
…p hook

Before predicting, the stop hook calls record_agent_response with the
iteration's accumulated assistant text and in_response_to set to the prior
last_prompt_event_id. When the prediction clears the threshold it calls
record_agent_prompt(source=clone-prediction) for the predicted next user
turn and rewrites last_prompt_event_id in the state file. Confidence misses
and incomplete predictions submit_feedback(status=rejected) and stop_session;
max-iterations, no-assistant-text, and empty-prompt terminal branches also
close the Clone session. Every Clone MCP call is best-effort: failures are
logged to clone-loop.history.local.jsonl but never block the loop.

Tests cover the new flow end-to-end (record + predict + record + state
update, rejection feedback + stop_session on low confidence, stop_session on
max-iterations) and the prior arguments.session_id assertion is updated to
reflect that no session_id is passed when no Clone session has been
bootstrapped.
Switch the AskUserQuestion PreToolUse hook to the shared clone-mcp.mjs
client and pass clone_session_id (from frontmatter) to predict_next_prompt
instead of the Claude Code session id that was being sent before. When a
prediction comes back but no option matches, the hook now submits
submit_feedback(status=rejected) so Clone learns from the miss.
Replace the inline Bash rm with a Node script that reads frontmatter,
calls stop_session when a clone_session_id is present, removes the state
file, and reports the cancelled iteration. The cancel command now mirrors
the loop command shape (node script via CLAUDE_PLUGIN_ROOT). Adds a test
that exercises the no-loop, no-session, and with-session paths and wires
the new test file into the pnpm test script.
- Remove clonePredictNextPrompt from clone-mcp.mjs imports in both hooks
  since the inline implementation is retained from main; re-add the
  resolveCloneToken import it depends on
- Fall back to hookSession (Claude Code session id) when no Clone session
  has been bootstrapped, preserving main's existing behaviour
- Restore tests/stop-hook-v2.test.mjs from main as the base and append
  only the three new session-integration test cases on top
- setup-clone-loop.mjs: bootstrapCloneSession() function body was missing
  after rebase — add CLONE_LOOP_DISABLE_SESSION guard, start_session +
  record_agent_prompt calls, frontmatter update, and history event
- hooks: update CLIENT_VERSION 0.6.0 → 0.7.0 to match origin/main
- tests: add CLONE_LOOP_DISABLE_SESSION=1 to the second setup test case
@Turtle-Hwan Turtle-Hwan marked this pull request as draft May 12, 2026 10:58
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