From e2989d6a4356df4d8fa00ef259ed7381b23be9d7 Mon Sep 17 00:00:00 2001 From: Marcin Obel Date: Fri, 18 Sep 2026 19:06:25 +0200 Subject: [PATCH 1/2] docs(release): document the agent gate hook and its env-var requirement --- docs/releasing.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/docs/releasing.md b/docs/releasing.md index 8955b54..0c89e11 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -171,6 +171,31 @@ Then watch it through: gh run watch $RUN ``` +#### The agent gate hook + +`.qwen/skills/release-revcli/scripts/gate.sh` is a `PreToolUse` hook that mechanically denies any +tool call whose raw input matches `pending_deployments` or `unpublish`. It is the backstop behind +the two hard rules. Its shape matters, because a denied approval looks like a broken release: + +**It reads `REVCLI_GATE_APPROVED` from its own environment — inherited from the agent process — +not from the command it is inspecting.** So neither of these gets through: + +```bash +REVCLI_GATE_APPROVED=1 gh api … /pending_deployments … # still denied +export REVCLI_GATE_APPROVED=1; gh api … /pending_deployments … # still denied +``` + +The hook has already run, in a different process, before your shell exists. To let an agent +approve the gate you must launch it with the variable already in the environment: + +```bash +REVCLI_GATE_APPROVED=1 qwen +``` + +Set that only for a session in which you intend to authorise the approval, and only after the +agent has told you the run id it is about to approve. Approving by hand in the UI needs no flag — +that is the path of least resistance, and the one to prefer. + > **If the reviewer is unavailable**, the run waits indefinitely. The fix is a **second > required reviewer** on the `production` environment — arrange that in advance. Changing the > environment's protection rules (see [publishing.md](publishing.md) §3) is a human-only From 7d613d5d8e7c43ae58223f314f861d5d8ee4a600 Mon Sep 17 00:00:00 2001 From: Marcin Obel Date: Fri, 18 Sep 2026 19:15:40 +0200 Subject: [PATCH 2/2] docs(release): record that the gate hook matches prose, not just commands --- docs/releasing.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/releasing.md b/docs/releasing.md index 0c89e11..4c7e7c4 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -196,6 +196,14 @@ Set that only for a session in which you intend to authorise the approval, and o agent has told you the run id it is about to approve. Approving by hand in the UI needs no flag — that is the path of least resistance, and the one to prefer. +**It matches the raw tool input, not a parsed command, so it fires on prose as well.** A +`gh pr create --body` or a commit message that merely *quotes* one of the two strings is denied, +and so is a read-only `grep` whose pattern contains one. Writing a file that contains them is +fine — file contents do not pass through tool input — but passing that content *as* tool input +(a heredoc inside a command, `write_file`) is not. That is the deliberate trade recorded in the +script's header: it cannot fail open on a malformed payload. The practical rule when writing +*about* the gate is to describe the two strings rather than quote them. + > **If the reviewer is unavailable**, the run waits indefinitely. The fix is a **second > required reviewer** on the `production` environment — arrange that in advance. Changing the > environment's protection rules (see [publishing.md](publishing.md) §3) is a human-only