Skip to content

Fix #1059: Ralph loop recipe doesn't create IMPLEMENTATION_PLAN.md#1281

Open
JiwaniZakir wants to merge 1 commit intogithub:mainfrom
JiwaniZakir:fix/1059-ralph-loop-recipe-doesn-t-create-impleme
Open

Fix #1059: Ralph loop recipe doesn't create IMPLEMENTATION_PLAN.md#1281
JiwaniZakir wants to merge 1 commit intogithub:mainfrom
JiwaniZakir:fix/1059-ralph-loop-recipe-doesn-t-create-impleme

Conversation

@JiwaniZakir
Copy link
Copy Markdown

Closes #1059

Pull Request Checklist

  • I have read and followed the CONTRIBUTING.md guidelines.
  • I have read and followed the Guidance for submissions involving paid services.
  • My contribution adds a new instruction, prompt, agent, skill, or workflow file in the correct directory.
  • The file follows the required naming convention.
  • The content is clearly structured and follows the example format.
  • I have tested my instructions, prompt, agent, skill, or workflow with GitHub Copilot.
  • I have run npm start and verified that README.md is up to date.
  • I am targeting the staged branch for this pull request.

Description

Fixes the Ralph loop recipe failing to create IMPLEMENTATION_PLAN.md (and any other files) due to file write permissions not being granted during unattended operation.

Both the TypeScript (cookbook/copilot-sdk/nodejs/recipe/ralph-loop.ts) and Python (cookbook/copilot-sdk/python/recipe/ralph_loop.py) implementations were using helper abstractions (approveAll / PermissionHandler.approve_all) that did not correctly approve file write operations, causing the agent to silently skip writes.

TypeScript changes:

  • Removed approveAll import from @github/copilot-sdk (was not covering write permissions).
  • Replaced onPermissionRequest: approveAll with an inline handler async () => ({ allow: true }) that explicitly approves all tool calls including file writes.
  • Replaced deprecated session.destroy() with session.disconnect() to eliminate the DeprecationWarning seen in the issue's console output.

Python changes:

  • Removed PermissionHandler import from copilot.
  • Replaced on_permission_request=PermissionHandler.approve_all with lambda _req, _ctx: {"kind": "approved", "rules": []} to explicitly return an approved permission response for all requests including file writes.
  • Replaced deprecated await session.destroy() with await session.disconnect().

Verified that after these changes, the agent successfully writes IMPLEMENTATION_PLAN.md and other files to disk during an unattended build loop run.


Type of Contribution

  • New instruction file.
  • New prompt file.
  • New agent file.
  • New plugin.
  • New skill file.
  • New agentic workflow.
  • Update to existing instruction, prompt, agent, plugin, skill, or workflow.
  • Other (please specify):

Additional Notes

The root cause was that the existing permission handler helpers did not approve file write tool calls, so the agent would loop indefinitely reading files and reporting intent but never writing output. The fix applies the minimal correct permission response shape for both SDKs. The deprecation warning for destroy() reported in the issue is also resolved.


By submitting this pull request, I confirm that my contribution abides by the Code of Conduct and will be licensed under the MIT License.


This PR was created with AI assistance (Claude). The changes were reviewed by quality gates and a critic model before submission.

Replace PermissionHandler.approve_all / approveAll with explicit
permission handlers that return {"kind": "approved", "rules": []} /
{ allow: true }, enabling file-write tool calls needed to create
IMPLEMENTATION_PLAN.md. Also replace deprecated session.destroy()
with session.disconnect() in both Python and TypeScript recipes.
Copilot AI review requested due to automatic review settings April 3, 2026 12:42
@JiwaniZakir JiwaniZakir requested a review from aaronpowell as a code owner April 3, 2026 12:42
Copy link
Copy Markdown
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

⚠️ This PR targets main, but PRs should target staged.

The main branch is auto-published from staged and should not receive direct PRs.
Please close this PR and re-open it against the staged branch.

You can change the base branch using the Edit button at the top of this PR,
or run: gh pr edit 1281 --base staged

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes the Ralph loop cookbook recipes so unattended runs can successfully write output files (e.g., IMPLEMENTATION_PLAN.md) by using explicit “approve all” permission handlers, and updates session teardown to avoid the destroy() deprecation warning.

Changes:

  • Node.js: replace approveAll with an explicit onPermissionRequest handler that allows all tool calls (including writes).
  • Python: replace PermissionHandler.approve_all with an explicit approved permission response for all requests.
  • Node.js + Python: replace deprecated destroy() with disconnect() for session teardown.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
cookbook/copilot-sdk/nodejs/recipe/ralph-loop.ts Uses explicit permission approval for all tool calls and switches session cleanup to disconnect().
cookbook/copilot-sdk/python/recipe/ralph_loop.py Uses explicit permission approval response and switches session cleanup to disconnect().

@@ -57,7 +57,7 @@ async function ralphLoop(mode: Mode, maxIterations: number) {
try {
await session.sendAndWait({ prompt }, 600_000);
} finally {
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

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

The recipe now uses session.disconnect() for cleanup, but the accompanying Ralph loop docs still show session.destroy() (e.g. cookbook/copilot-sdk/nodejs/ralph-loop.md) and most other Node.js recipes still call destroy(). To avoid confusing readers and keep examples consistent, either update the docs/examples to use disconnect() (and explain the deprecation) or stick with the recommended cleanup method across the cookbook.

Suggested change
} finally {
} finally {
// Prefer `disconnect()` for session cleanup; older examples may show
// `destroy()`, but `disconnect()` is the current recommended API.

Copilot uses AI. Check for mistakes.
@@ -62,7 +62,7 @@ def log_tool_event(event):
MessageOptions(prompt=prompt), timeout=600
)
finally:
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

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

The recipe now uses await session.disconnect() for cleanup, but the cookbook Ralph loop doc and other Python recipes still show await session.destroy() as the standard cleanup. Please align the documentation/examples with the deprecation guidance (or clarify the difference between disconnect() and destroy()) so users don’t copy/paste a deprecated call or end up with inconsistent lifecycle behavior.

Suggested change
finally:
finally:
# Prefer `disconnect()` for session cleanup in examples/recipes.
# This keeps the lifecycle guidance aligned and avoids encouraging
# copy/paste use of the older `destroy()` cleanup pattern.

Copilot uses AI. Check for mistakes.
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.

Ralph loop recipe doesn't create IMPLEMENTATION_PLAN.md

2 participants