feat: full Clone MCP session integration (start/record/feedback/stop)#7
Draft
Turtle-Hwan wants to merge 7 commits into
Draft
feat: full Clone MCP session integration (start/record/feedback/stop)#7Turtle-Hwan wants to merge 7 commits into
Turtle-Hwan wants to merge 7 commits into
Conversation
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 exportingstartCloneSession,stopCloneSession,recordAgentPrompt,recordAgentResponse,submitFeedback. Hooks keep their inlinepredict_next_promptimplementation; the new module handles the session/recording/feedback tools only.scripts/setup-clone-loop.mjs: on/clone:loopstartup, callsstart_session+record_agent_prompt(source=user)and writesclone_session_id,mcp_session_id,last_prompt_event_idto the state file frontmatter. Failures are non-fatal (warning to stderr, loop continues without session context). Gate:CLONE_LOOP_DISABLE_SESSION=1skips the bootstrap (used by unit tests).hooks/stop-hook.mjs: before predicting, callsrecord_agent_responsewith the iteration's assistant output. After a confident prediction, callsrecord_agent_prompt(source=clone-prediction)and updateslast_prompt_event_id. On escalation (low confidence / incomplete / MCP error), callssubmit_feedback(status=rejected)(when a prediction id is available) andstop_session. Max-iterations and empty-state terminal branches also callstop_session.hooks/ask-user-question-hook.mjs: passesclone_session_idas the MCP session id (falling back to the Claude Code session id to preserve existing behaviour). Ondefer-no-options, callssubmit_feedback(status=rejected).scripts/cancel-clone-loop.mjs(new) +commands/cancel-loop.mdrewrite:/clone:cancel-loopnow invokes a Node script that reads the Clone session id from frontmatter, callsstop_session, then removes the state file.Test plan
pnpm test— 29 tests pass (includes 3 new session-integration cases instop-hook-v2.test.mjsand 3 new cases intests/cancel-clone-loop.test.mjs)pnpm test:mcp:e2e— live remote MCP smoke passes/clone:loop "..."in a real session → verifyclone-loop.local.mdgetsclone_session_idin frontmatter after setuprecord_agent_response/record_agent_promptcalls appear in.claude/clone-loop.history.local.jsonlsubmit_feedback+stop_sessionevents in history/clone:cancel-loop→ confirm state file removed andsession-stoppedevent in history🤖 Generated with Claude Code