Repository navigation
feat: run /idd-all in Claude Code cloud sessions — REST egress and reads, (PR, attended) — 3.6.0 (#416) - #426
Open
kiki830621 wants to merge 17 commits into
Open
kiki830621 wants to merge 17 commits into
kiki830621 wants to merge 17 commits into
Conversation
… Code cloud sessions (#416) Hand-written change artifacts (the spectra CLI is not available in the cloud container): proposal, design, spec deltas for the new cloud-session-runtime capability and the modified idd-pr-hitl-modes mode resolution, and tasks. Refs #416 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJZJ8sbcVVqqLngBfkGNUq
…pes (#416) scripts/lib/cloud-session.sh decides "cloud session" (CLAUDE_CODE_REMOTE exactly "true") and "attended" (CLAUDE_CODE_SESSION_ATTENDED exactly "1"; anything else is unattended, so an unwatched session never waits on a question). scripts/lib/gh-rest.sh (logic in gh_rest.py) reads issues, issue lists, pull requests and repositories through `gh api` REST and returns the same field names and shapes as `gh ... --json`, pages until a short page or the limit, and adds a hint line when a cloud session cannot reach the repo. Read-only: no write subcommands. Refs #416 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJZJ8sbcVVqqLngBfkGNUq
…416) Porcelain `gh issue create|comment|edit` is GraphQL underneath, which Claude Code cloud sessions block, so every issue write failed there. The wrapper keeps every gate (attestation, privacy / mention / tier-floor nets, empty-body guard) and its exit band; only the final dispatch changes: lib/gh_egress_rest.py turns the forwarded `gh issue` arguments into `gh api` REST calls, in every environment. Stdout is one URL line, so `URL=$(gh-egress.sh create ...)` callers are unaffected. The body reaches gh on stdin, never in argv. Flags the REST transport does not support are refused with exit 14 instead of being dropped; an unknown milestone title is refused the same way; a failing gh call passes its own exit code through. Refs #416 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJZJ8sbcVVqqLngBfkGNUq
…efuse in cloud (#416) check-existing-work.sh, check-diagnosis-readiness.sh, process-attachments.sh and idd-worktree.sh used porcelain `gh pr list` / `gh repo view` / `gh issue view`, which are GraphQL and fail with 403 in Claude Code cloud sessions. They now read through scripts/lib/gh-rest.sh. Field names are unchanged, so each script's matching logic is untouched; the test shims serve REST-shaped data and refuse porcelain, proving the normalisation. idd-worktree reads the title from the repo root and keeps its bare-branch fallback (a title-path test is added — it had no coverage). check-existing-work's error labels become `pr-list --state open` / `issue-view N`; idd-close Step 1.5, which fails closed by matching those labels, now matches `issue-view` as well as the old `gh issue view`. discussions_api.GitHub.graphql refuses up front in a cloud session (Discussions have no REST API) instead of sending a request that 403s. Refs #416 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJZJ8sbcVVqqLngBfkGNUq
…e reference (#416) - references/claude-code-remote-tools.md: detection signals, the porcelain -> REST table for the in-scope skills, cloud-session PR routes, the unsupported surfaces with what each prints, and the setup script. - A one-line runtime note in 13 skills: the 9 on the idd-all path (plus idd-list) point to the reference; idd-find, idd-report, idd-discuss and idd-ask stop and say they are unsupported. Skill bodies are not rewritten. - idd-all: a cloud session forces the PR path (direct-commit work dies with the container) and takes the interaction from the attended signal (absent = unattended); --no-pr is overridden with a notice; the rule sits before fork detection, which always 403s there. In a cloud session (PR, unattended) without ralph-loop aborts after unwinding the branch instead of degrading. The auth gate uses `gh api user` (`gh auth status` fails in cloud sessions). Local resolution is unchanged — the test executes the skill's own resolution block per scenario. - idd-verify: Claude-only in a cloud session (codexEnabled: false, no codex-pro governance), stated in the engine line and process gaps. Refs #416 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJZJ8sbcVVqqLngBfkGNUq
…416) - gh_egress_rest.py read body files in text mode, which turns CRLF into LF; gh sent the file's bytes. It now reads with newline="" (test added). - correct-flow's fake gh (added in 3.5.0) understood only `gh issue edit`; it now also takes the transport's `api … -X PATCH --input -` JSON payload, and the assertion names that call. - mention-markdown dispatched `comment` without an issue number, which the porcelain stub never checked; the REST transport refuses it, so the fixture passes one. Refs #416 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJZJ8sbcVVqqLngBfkGNUq
README (plugin + root) documents running /idd-all in a Claude Code cloud session and the setup script that installs the plugins and the egress parser; the runtime-compatibility policy and claude-code-tools.md point to the cloud reference; CHANGELOG 3.6.0; version 3.5.0 -> 3.6.0. The change artifacts record the idd-close label consumer and the byte-exact body-file read found during implementation. Refs #416 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJZJ8sbcVVqqLngBfkGNUq
…te parity, gh semantics (#416) Four independent reviewers (requirements, logic, security, regression; Claude-only, no Codex in the container). Fixed: - security HIGH: an issue URL such as https://github.com/o/r#/issues/5 made the REST transport send DELETE /repos/o/r (and PATCH /repos/o/r). Issue URLs, --repo values and hosts are now parsed strictly; `.`/`..` segments, `#`, `?` and `user@` are refused before any request. Fetched issue / PR numbers are checked before they enter an API path. - gh-egress.sh re-read a flag-shaped value (`-b "--repo=..."`) as a flag while gh took it as the body, so the privacy, mention and empty-body nets could be skipped (present on 3.5.0). The wrapper now reads the next token as the value, as gh does. - REST transport keeps gh's behavior where REST differs: labels must exist (REST would create them), milestones match open milestones ignoring case, `edit --milestone ""` removes it, removing an absent label is a no-op, `-b=x` is `x`. On failure stdout stays empty (gh api prints its JSON error there) and stderr carries a hint; non-UTF-8 args exit 12. - gh-rest: `--sort updated`, `--closed-since`, full comments in issue-list, `mergeable` in pr-list, empty body as "" — what idd-list needs. - check-closed-without-summary.sh reads through gh-rest (the sixth script the user approved), so idd-list --audit-closes works in the cloud. - idd-all: Phase 0.6's cloud stop is an explicit exit (the `abort` convention is undefined in that shell and fell through to the degrade); Step 0.4 / branch setup / unwind / PR creation call REST directly; a PR is opened only after verify PASS, and a cloud run with blocking findings still pushes the branch; PR body and report say when verify was Claude-only; auth gate is `gh auth status || gh api user` (App tokens cannot call /user). - idd-verify: codex-pro governance is explicitly conditional, codexEnabled is a boolean, the engine line no longer claims Codex in the cloud. - Docs: not-migrated skills, experimental status, idd-list mapping, merge is never authorised; spec deltas, design and tasks record the round. Fixtures that spoke porcelain to the converted code (acquisition-truncation, gate-live-path, actionability-gate Phase 5) now answer REST paths. Refs #416 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJZJ8sbcVVqqLngBfkGNUq
Devil's-advocate findings on the round-1 fixes: - gh-egress.sh: every value-taking flag the REST transport accepts now takes the next token as its value in the wrapper too (drift-guarded), so `--remove-label -b --body-file=x` can no longer slip a body file past the gates; `-b=X` / `-t=X` / `-F=X` read as X; edit-comment validates --repo (OWNER/REPO, no dot segments) and the comment id. - idd-all Phase 5: a missing VERIFY_STATE is never read as PASS; push failures and unreadable default branch / issue title stop the run instead of feeding gh's error body into a slug or PR base; the unattended verify-fix loop pushes the branch in a cloud session before giving up; Phase 0.6's cloud abort clears the unattended flag. - gh-rest --closed-since accepts YYYY-M-D and offset timestamps, normalised to UTC; check-closed-without-summary reports a refused argument separately from an auth / network failure. - CHANGELOG, design (D5, D8, D10), spec and tasks record the round. Refs #416 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJZJ8sbcVVqqLngBfkGNUq
Independent re-verify of the round-2 commit: - gh-egress.sh: a dispatching call takes one body source. gh and the transport send only the last --body / --body-file, while the #275 guard checked them all joined, so `--body "<decoy>" --body ""` sent an empty body. `check` (sends nothing) still scans several inputs. Leak tests now assert the privacy-net exit exactly. - idd-all Phase 0.5 PR setup stops through a defined helper instead of the undefined `abort`, which fell through into `git checkout -b` with a slug made from gh's error body; executed by the cloud-session suite. - Phase 0.6 stops instead of degrading when the default branch cannot be read; a cloud run does not auto-push when a blocking finding is a security finding. - gh-rest --closed-since reads a timestamp without a zone as UTC. Refs #416 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJZJ8sbcVVqqLngBfkGNUq
Verify round 4 (re-check of 75ef92b) found nothing blocking; its two non-blocking points: - An attended run that hands back a blocking security finding sets VERIFY_STATE=BLOCKING_SECURITY; Phase 5 then pushes nothing, cloud included, and says the commits must be checked for secrets first. - The local Phase 0.6 degrade keeps the unattended flag on purpose (the caller asked for an unattended run, often /loop); the comment and the notice now say so. Refs #416 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJZJ8sbcVVqqLngBfkGNUq
Refs #416 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJZJ8sbcVVqqLngBfkGNUq
…, docs (#416) - idd-all Phase 5 has an else branch: a lost PATH_AXIS stops the run (with a cloud warning) instead of exiting 0 with nothing pushed. - Phase 0.6 refuses to run on a lost (PATH_AXIS, INTERACTION) or, in PR mode, a lost BRANCH, instead of skipping the gate. - idd-all passes `ORCHESTRATED BY /idd-all` to idd-implement on the PR path and idd-implement skips Step 5.5, so no PR is opened before verify; the old "naturally compatible" note was wrong. - Frontmatter names the cloud (PR, attended) mode; Trace 4 matches the current degrade output; new Trace 5 for (PR, attended). - idd-verify `--engine codex` stops in a cloud session; the reviewer launch task notes there is no Codex call there. Refs #416 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJZJ8sbcVVqqLngBfkGNUq
Independent review of the whole branch diff (scripts lens): nothing blocking introduced here; these were found and are closed: - gh-egress.sh reads body files with `cat --` and refuses a failed read (exit 12). A `-`-named file was read as cat options, scanned as "", and sent in full with --allow-empty-body. Present on 3.5.0. - check-closed-without-summary reads authorAssociation as well as author_association, so the author filter binds on the audit path. - create needs a body, as non-interactive `gh issue create` did. - Issue numbers are length-bounded (no ValueError on 5000 digits); the unused gh_rest.is_cloud_session is removed; a missing label message mentions an unreachable repository; the remove-assignee DELETE path is tested. Refs #416 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJZJ8sbcVVqqLngBfkGNUq
Re-check of e692d4a: the no-early-PR directive reached idd-implement on the Simple path only. On the Plan tier idd-all goes through /idd-plan, whose Step 6 called idd-implement with `#NNN` alone, so Step 5.5 could still open a PR before verify. idd-all now hands the directive to /idd-plan and idd-plan forwards it with --pr; a drift guard pins all three skills. The Failure Modes table and CHANGELOG say that lost-state stops are re-runs (the unattended flag stays). Refs #416 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJZJ8sbcVVqqLngBfkGNUq
…atement (#416) Refs #416 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJZJ8sbcVVqqLngBfkGNUq
Observed while tagging the verified snapshot for this change: the session proxy refuses tag pushes and POST repos/R/git/refs (HTTP 403, "Write access to this GitHub API path is not permitted through this proxy"). idd-verify Step 4.5 already degrades to its graceful-skip warning; the reference, the step and the CHANGELOG now say so and that the tag is made from a local session. Refs #416 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PJZJ8sbcVVqqLngBfkGNUq
This was referenced Oct 26, 2026
This was referenced Oct 26, 2026
This was referenced Oct 26, 2026
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.
Refs #416
Summary
讓
/idd-all能在 Claude Code 雲端 session(web/手機/排程)裡跑(Spectra changecloud-session-idd-all,plugin 3.6.0)。雲端 session 會擋 GitHub GraphQL,所以gh issue|pr|label|repoporcelain 和gh auth status都會失敗,gh apiREST 則可以用。scripts/lib/cloud-session.sh。CLAUDE_CODE_REMOTE必須正好是true才算雲端;CLAUDE_CODE_SESSION_ATTENDED正好是1才算 attended,沒設就是 unattendedgh-egress.sh的 gate 都不動(attestation、四道 net、empty-body guard、exit band),通過之後一律經lib/gh_egress_rest.py走 REST,本機也一樣。stdout 只有一行 URL。gh 和 REST 行為不同的地方照 gh:label 必須已存在、milestone 不分大小寫比對 open milestone、移除不存在的 label 什麼都不做。不支援的旗標 exit 14,不會被悄悄丟掉lib/gh-rest.sh(issue-view/issue-list/pr-list/repo-view)輸出和 porcelain 同名的欄位,會自動翻頁,雲端拒絕時附hint:。check-existing-work、check-diagnosis-readiness、process-attachments、idd-worktree、check-closed-without-summary都改用它idd-all:雲端一律走 PR path(direct commit 會隨 container 消失)。新增(PR, attended)tuple;雲端的--no-pr會被覆寫並印出通知;(PR, unattended)缺 ralph-loop 時 abort,不降級成 direct-commit。只有 verify PASS 才開 PR,有 blocking findings 時雲端仍 push branch。建 branch 和開 PR 直接呼叫 RESTidd-verify:雲端只跑 Claude(codexEnabled: false),報告會寫Codex leg not run — cloud session (degraded: Claude-only)idd-find、idd-report、idd-discuss、idd-ask)在雲端會停下並說明原因。新 referencereferences/claude-code-remote-tools.md收 porcelain→REST 對照、不支援清單和 setup script。CHANGELOG/README/版本 3.6.0本機的模式解析不變。本機看得到的行為變化(都已列在 CHANGELOG):寫入改走 REST;Phase 5 拿不到 verify 結果就不 push;auth gate 是
gh auth status || gh api user。Fixed before merge(verify)
四輪審查(第 1 輪 4 個 lens、第 2 輪 devil's advocate、第 3 輪獨立 re-verify、第 4 輪複查),再加一輪 2 位 reviewer 對整個 diff 的最終全面審查(含 3,600 組隨機參數 fuzz)與複查,都只用 Claude;最後沒有 blocking。報告:Verify、最終審查 addendum。
#、?、..,讓edit <url> --remove-label x變成DELETE /repos/o/r。現在嚴格解析,違規 exit 14-b=X等形式也一致${VERIFY_STATE:-PASS}會在 shell 狀態遺失時開 PR。現在缺值一律停在 push 之前--body/--body-file,guard 卻檢查合併後的內容,--body "<誘餌>" --body ""會清空 issue 本文。現在每次送出只接受一個 body 來源abort,讀不到 title 時照樣建出以錯誤 JSON 命名的 branch。現在用區塊內定義的 stop,測試會實際執行這個區塊PATH_AXIS遺失時原本 exit 0、什麼都不 push(雲端會丟 commit),現在停下並提醒;idd-implement在/idd-all底下不再於 verify 前開 PR(Simple 與 Plan tier 都是);名稱以-開頭的 body file 原本會以空字串通過 gate(3.5.0 就存在);audit 的作者過濾原本沒作用;create必須有 bodyidd-list需要的 server-side 排序、全量 comments、mergeable、--closed-since已補進 gh-rest;git push和gh api失敗會讓流程停下;edit-comment --repo會先驗證Test plan
bash plugins/issue-driven-dev/scripts/run-all-tests.sh:雲端環境變數沒設和有設(CLAUDE_CODE_REMOTE=true CLAUDE_CODE_SESSION_ATTENDED=1)各跑一次,都是 63 / 65。兩個失敗是idd-repo-map、idd-tree-lock,以 root 執行時origin/main上同樣會失敗cloud-session(134;Phase 0.5 PR setup/Phase 0.6/Phase 5 在暫存 repo + bare origin 實際執行)和gh-rest(56);gh-egress(194)改成斷言 REST argv 與 stdin JSONgh-rest.sh能讀真實 API;feat: 在 Claude Code 雲端 session 裡也能跑 /idd-all(gh GraphQL 403、plugin 未載入)(sister of #400) #416 的 Verify comment 是經gh-egress.sh的 REST transport 實際貼出的/idd-all/idd-verify --pr <this PR>,補上 Codex 跨模型那一條腿Merge 後用
/idd-close 416結案,並 archive Spectra change。https://claude.ai/code/session_01PJZJ8sbcVVqqLngBfkGNUq
Generated by Claude Code