From 3b82cf82ac9dbff1f3b96820d4559dbfb1048c6e Mon Sep 17 00:00:00 2001 From: Jothi Mani Rajendran <250249270+jothimani-rajendran@users.noreply.github.com> Date: Mon, 19 Oct 2026 15:28:22 +0000 Subject: [PATCH 1/2] ci: record catalog and framework commit SHAs in publish (PLUG-1) publish.yml writes generated_from.yaml with both checkouts' SHAs and names them in the commit message. Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01CiuPvvEiB85VM5hMibNC9r --- .github/workflows/publish.yml | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 1865cb8..7197a1f 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -120,6 +120,37 @@ jobs: chock plugin build --repo catalog --policies-dir base --format codex --out-dir dist chock marketplace build --dist dist --tree codex + # What the published tree was built from, as commits rather than names: a tag or branch + # moves, a SHA does not. The file is written at publish time, not by the build, so + # `chock marketplace build` and the generated-only check neither produce nor compare it. + - name: Record the commits this tree was built from + env: + # Dispatch inputs are typed by whoever runs the workflow; expanded by the runner + # into shell text they would execute, through the environment they stay data. + CATALOG_REF: ${{ inputs.catalog_ref }} + FRAMEWORK_REF: ${{ steps.framework.outputs.ref }} + run: | + catalog_sha="$(git -C catalog rev-parse HEAD)" + framework_sha="$(git -C framework rev-parse HEAD)" + echo "catalog_sha=$catalog_sha" >> "$GITHUB_ENV" + echo "framework_sha=$framework_sha" >> "$GITHUB_ENV" + # JSON quoting keeps a ref with a colon or quote valid YAML. + python3 - dist/generated_from.yaml "$CATALOG_REF" "$catalog_sha" "$FRAMEWORK_REF" "$framework_sha" <<'PY' + import json, sys + out, catalog_ref, catalog_sha, framework_ref, framework_sha = sys.argv[1:] + q = json.dumps + with open(out, "w") as f: + f.write("catalog:\n") + f.write(" repository: open-coder-ai/chock-catalog\n") + f.write(f" ref: {q(catalog_ref)}\n") + f.write(f" sha: {q(catalog_sha)}\n") + f.write("framework:\n") + f.write(" repository: open-coder-ai/chock\n") + f.write(f" ref: {q(framework_ref)}\n") + f.write(f" sha: {q(framework_sha)}\n") + PY + cat dist/generated_from.yaml + - name: Show what would change working-directory: dist run: | @@ -151,5 +182,5 @@ jobs: exit 0 fi git add -A - git commit -m "generated: catalog $CATALOG_REF (framework $FRAMEWORK_REF)" + git commit -m "generated: catalog $CATALOG_REF @ $catalog_sha (framework $FRAMEWORK_REF @ $framework_sha)" git push From 7cba9b1305817300b6c89f84874d1124ea8bcbf0 Mon Sep 17 00:00:00 2001 From: Jothi Mani Rajendran <250249270+jothimani-rajendran@users.noreply.github.com> Date: Mon, 19 Oct 2026 15:29:35 +0000 Subject: [PATCH 2/2] docs: say the PreToolUse wiring and the JSON decision channel (PLUG-1) Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01CiuPvvEiB85VM5hMibNC9r --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 6840dca..86c0180 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,12 @@ guard that runs and crashes is a **deny** here, because Codex rejects the confir other clients show, and a gate that cannot reach a decision refuses rather than allowing something it never judged. +**How a deny reaches Codex.** Each guard plugin wires one `PreToolUse` hook, and the hook +answers on stdout with a JSON decision, not an exit code: +`{"hookSpecificOutput": {"hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionDecisionReason": "..."}}` +with exit status 0. Gate plugins wire the same `PreToolUse` hook plus a `Stop` hook. The one +exit-code answer is exit 2, used only when no working Python 3.11+ is found. + ## Install Codex reads this repository as a git marketplace, the same mechanism as its Plugins UI: