From 9636a71dd051ec31137138323b083a270633f0bc Mon Sep 17 00:00:00 2001 From: Devon Hillard Date: Mon, 12 Oct 2026 21:01:59 -0600 Subject: [PATCH] fix: registry note for sandboxed harness builds; guard hook names the remote in its rebase hint --- .claude-plugin/marketplace.json | 2 +- .claude-plugin/plugin.json | 2 +- CHANGELOG.md | 10 ++++++++++ docs/harness.md | 2 ++ hooks/pre-tool-use-guard.sh | 2 +- tests/run.sh | 13 ++++++++++++- 6 files changed, 27 insertions(+), 4 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index c76367f..524454a 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -12,7 +12,7 @@ "name": "ccmagic", "source": "./", "description": "25 dev workflow skills: tracker-aware ticket lifecycle (Linear, GitHub, JIRA) with an autonomous end-to-end driver, adaptive code review, debugging, design/QA, and git workflow utilities", - "version": "3.20.2", + "version": "3.20.3", "author": { "name": "Devon Hillard" }, diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 1213cfa..1c42db5 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "ccmagic", "description": "Dev workflow skills for Claude Code: tracker-aware ticket lifecycle (Linear, GitHub, JIRA), adaptive code review, debugging, design/QA, and git workflow utilities", - "version": "3.20.2", + "version": "3.20.3", "author": { "name": "Devon Hillard", "url": "https://github.com/devondragon" }, "repository": "https://github.com/devondragon/ccmagic", "license": "Apache-2.0" diff --git a/CHANGELOG.md b/CHANGELOG.md index e3ca34e..c446689 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,16 @@ All notable changes to ccmagic are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [3.20.3] - 2026-10 + +### Fixed + +- The guard hook's force-push message now tells agents to run `git pull --rebase origin ` instead of a bare `git pull --rebase`, which fails in a sandboxed session whose branch has no upstream (Cyrus worktrees are created with `--no-track`). + +### Documentation + +- `docs/harness.md` notes that, inside a sandboxed session, a harness Dockerfile's `FROM` images (including the `# syntax=` frontend image) can come only from registries whose token host is on the session's egress allowlist. On the Cyrus deployment that is Docker Hub's `auth.docker.io` today. + ## [3.20.2] - 2026-10 ### Fixed diff --git a/docs/harness.md b/docs/harness.md index 7c77f73..cd10c0a 100644 --- a/docs/harness.md +++ b/docs/harness.md @@ -30,6 +30,8 @@ Rules (`ccm-harness check`): every value literal in the merged model, included a `ccm-harness` runs Docker and Compose with an emptied environment: only `PATH`, `HOME`, `DOCKER_HOST`, `DOCKER_CONFIG`, `TMPDIR`, the proxy variables (`HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY`, `ALL_PROXY`, and their lowercase forms), and the CA bundle paths (`SSL_CERT_FILE`, `SSL_CERT_DIR`) pass through. The last two groups let image builds reach a registry from a sandboxed session whose network goes through a proxy; none of them hold secrets. +Registries: inside a sandboxed session (Cyrus), Buildx fetches registry pull tokens from the client side, through the session's egress proxy. A harness Dockerfile's `FROM` images, including the `# syntax=` frontend image, can therefore come only from registries whose token host is on the session's egress allowlist. On the Cyrus deployment only Docker Hub's `auth.docker.io` is allowed today. An image from ghcr.io, mcr.microsoft.com, quay.io, or another registry in a `FROM` line needs that registry's token host added to the allowlist (`sandbox.networkPolicy.allow` in Cyrus's `config.json`) first. Images the daemon pulls directly (the runner image and `image:` services) are not affected. + `ccm-harness` needs Docker Compose 2.30 or newer. Its `check` tests were run on Compose 2.30.0, 2.38.2, and 5.6.0; older versions are untested. Commands: `check`, `up` (with `--prepare`, `--attach RUN`, `--wait [SECONDS]` for runs longer than one tool call), `seed`, `shoot TICKET SCRIPT`, `down`, `sweep [HOURS]`, `evidence TICKET HEAD PNG...`. Each prints one JSON object; the script's header has the details. diff --git a/hooks/pre-tool-use-guard.sh b/hooks/pre-tool-use-guard.sh index 9251e4c..3adf86f 100644 --- a/hooks/pre-tool-use-guard.sh +++ b/hooks/pre-tool-use-guard.sh @@ -154,7 +154,7 @@ if [ "$is_push" = true ]; then [ "$force" = true ] || continue [ -n "$target" ] || target=$(git branch --show-current 2>/dev/null || true) if [ "$autonomous" = true ]; then - deny "ccmagic: autonomous runs never force-push (target: ${target:-unknown}). If the branch has diverged, rebase onto the remote (git pull --rebase) and push normally; if that conflicts, return needs-human." + deny "ccmagic: autonomous runs never force-push (target: ${target:-unknown}). If the branch has diverged, rebase onto the remote (git pull --rebase origin ${target:-}) and push normally; if that conflicts, return needs-human." fi default=$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null || true) default=${default#origin/} diff --git a/tests/run.sh b/tests/run.sh index a5f9f68..389e6c5 100755 --- a/tests/run.sh +++ b/tests/run.sh @@ -485,6 +485,12 @@ guard_force_push_denied_autonomously() { check "$(denied)" "deny" } +guard_force_push_message_names_the_remote() { + git checkout -q -b feature/ENG-1-x + hook 'git push -fu origin feature/ENG-1-x' ccmagic:auto-push + check "$(printf '%s' "$OUT" | grep -c 'git pull --rebase origin feature/ENG-1-x')" "1" +} + guard_normal_push_allowed_autonomously() { git checkout -q -b feature/ENG-1-x hook 'git pull --rebase && git push -u origin feature/ENG-1-x' ccmagic:auto-push @@ -3856,13 +3862,18 @@ skills_auto_ticket_follow_up_dedupe() { # added lines in hooks/lib-handshake.sh), to check the visual step's handshake # (the changed case arm in hooks/subagent-stop-handshake.sh, spec decision 4 of # the UI harness design), and, for every ticket, by the RV-86 finish guard: its -# own hook file and one PreToolUse entry in hooks.json. +# own hook file and one PreToolUse entry in hooks.json. The guard's +# force-push message also changed (one line): it now says +# `git pull --rebase origin `, because branches in sandboxed sessions +# have no upstream (ccmagic 3.18.3 fixed the same assumption in ccm-pr-reply). skills_hooks_only_accept_tasks_done() { local changed changed=$(git -C "$ROOT" diff "$SPEC_BASELINE" -- hooks ':(exclude)hooks/hooks.json' ':(exclude)hooks/pre-tool-use-finish-guard.sh' | grep -E '^[-+]' | grep -vE '^(\+\+\+|---) ' || true) check "$changed" "+# tasks_done: [ids] (optional: work step on a Reeve spec ticket only) + if (l ~ /^[[:space:]]*tasks_done:/) continue +- deny \"ccmagic: autonomous runs never force-push (target: \${target:-unknown}). If the branch has diverged, rebase onto the remote (git pull --rebase) and push normally; if that conflicts, return needs-human.\" ++ deny \"ccmagic: autonomous runs never force-push (target: \${target:-unknown}). If the branch has diverged, rebase onto the remote (git pull --rebase origin \${target:-}) and push normally; if that conflicts, return needs-human.\" - ccmagic:auto-work|ccmagic:auto-feedback|ccmagic:auto-validate|ccmagic:auto-finish|ccmagic:auto-push) allowed=\"done needs-human\" ;; + ccmagic:auto-work|ccmagic:auto-feedback|ccmagic:auto-validate|ccmagic:auto-finish|ccmagic:auto-push|ccmagic:auto-visual) allowed=\"done needs-human\" ;;" git -C "$ROOT" show "$SPEC_BASELINE:hooks/hooks.json" | jq -S . >"$T/hooks-base"