mirror of
https://github.com/alirezarezvani/claude-skills.git
synced 2026-10-09 03:17:54 +00:00
Fourth PR-review round on #948. All four reproduced first. 1. The gate was one flag away from opt-out. --waive applied to whatever gate_refusals() returned, including G1 "no review round has been collected", so `close --waive "no time"` exited 0 with nobody having looked at the artifact. That is the most tempting shortcut for an agent under time pressure and it defeats the skill's whole premise. G1 is now unwaivable, with its own refusal message: a waiver accepts objections a reviewer raised, it cannot manufacture a review that never happened. Waiving a genuine objection (G2/G3/G4/G7) still works. 2. Inline `style` was unsanitized, so a reviewed draft containing `background-image:url(https://attacker/beacon.png)` fired a request the moment the reviewer opened the page — no script needed, and directly contrary to the no-network property the README and manifest advertise. Added to DROP_ATTRS. The <style> tag was already dropped, so keeping the attribute was inconsistent as well as leaky. 3. Markdown `` never rendered. LINK's regex was not anchored against a preceding `!`, so an image became `!<a href=...>` — and _safe_href's image=True branch, which exists to allowlist data:image URIs, was dead code on that path. Added an IMAGE regex ahead of LINK, negative-lookbehind on LINK, and real <img> rendering through the same scheme allowlist. Verified a javascript: src degrades to inert alt text. 4. An unterminated <script> silently swallowed the rest of the body — same confusing failure shape as the void-tag bug, though it fails safe. Now emits a named diagnostic to stderr instead of vanishing. Nit: raw-HTML `target="_blank"` anchors get the rel="noreferrer noopener" the Markdown path already added to its own. Re-verified: derive_counters --check, check_plugin_json --all, checklist 6/6 PASS, description validator PASS, all three scripts --help/--sample green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01233Eggb2cjSYf96X6C3pCm
128 lines
4.4 KiB
Markdown
128 lines
4.4 KiB
Markdown
---
|
|
name: "cs-human-gate"
|
|
description: "/cs:human-gate — Get real human review on an artifact and prove it happened. Builds a single-file review page, collects batched feedback as structured data, and runs a gate that refuses to close while a BLOCKER is open, the reviewer is unnamed, or nobody has looked at all. Non-blocking: hands over the path and ends the turn."
|
|
argument-hint: "[path to the .md or .html artifact] [optional: open|status|collect|close]"
|
|
---
|
|
|
|
# /cs:human-gate — Human Verification Gate
|
|
|
|
**Command:** `/cs:human-gate <artifact> [step]`
|
|
|
|
Machine checks answer *"do the tests pass?"*. This answers the other one:
|
|
**has a person actually looked at this, and are their objections resolved?**
|
|
|
|
## When to Run
|
|
|
|
- Before shipping anything external, irreversible, or regulated
|
|
- "Let me review that first" / "get sign-off" / "have someone check this"
|
|
- "Don't ship until I've seen it"
|
|
- You have applied feedback and are about to declare done
|
|
- A plan, spec, RFC, report, migration, or customer-facing artifact is ready
|
|
|
|
## When NOT to Run
|
|
|
|
- To make AI text sound human → `content-humanizer` / `behuman` (different problem entirely)
|
|
- To review a code diff yourself → `md-review` or `code-reviewer`
|
|
- To pressure-test an idea before any artifact exists → `grill-me`
|
|
- For machine-checkable verification → `agent-harness`
|
|
|
|
## Pre-flight
|
|
|
|
Refuse to proceed and say which is missing:
|
|
|
|
1. **Artifact exists** and is `.md` or `.html`.
|
|
2. **A named reviewer** is identified — a person, not "the team". The gate enforces this (G3).
|
|
3. **Round budget agreed** — default 5. An uncapped review loop is a way to avoid deciding.
|
|
4. **Stakes established** — reversible or not? One-way doors need an explicit APPROVE,
|
|
not merely an absence of blockers.
|
|
|
|
## Steps
|
|
|
|
```sh
|
|
S=engineering/human-gate/skills/human-gate/scripts
|
|
```
|
|
|
|
### 1. `open` — start a round
|
|
|
|
```sh
|
|
python3 $S/human_gate.py open "$ARTIFACT" --launch
|
|
```
|
|
|
|
Builds a single-file review page (zero network requests, opens over `file://`) and records
|
|
round N. Prints the sidecar path.
|
|
|
|
**Then end the turn.** Do not poll. On a headless host `open` detects it, skips the browser,
|
|
and tells you to hand over the path — the reviewer can write the sidecar by hand in any editor.
|
|
|
|
### 2. `status` — non-blocking check
|
|
|
|
```sh
|
|
python3 $S/human_gate.py status "$ARTIFACT"
|
|
```
|
|
|
|
| Exit | Meaning |
|
|
|---|---|
|
|
| 0 | collected and clear — `close` would pass |
|
|
| 2 | collected, but `close` would refuse — prints which rules, same code `close` uses |
|
|
| 3 | feedback waiting — collect it |
|
|
| 4 | nothing on disk yet — end the turn again |
|
|
|
|
Branch on the code alone: 0 clear · 2 blocked · 3 collect me · 4 nothing yet.
|
|
|
|
### 3. `collect` — read the batch
|
|
|
|
```sh
|
|
python3 $S/human_gate.py collect "$ARTIFACT" --output json
|
|
```
|
|
|
|
Emits `batch.v1`: every item with severity, block anchor, quote, and the blocking total.
|
|
Quotes are verified against the real file — a mismatch is reported, not swallowed.
|
|
|
|
**Apply every item.** `EDIT` items carry `after` across **verbatim** — that is the
|
|
reviewer's own wording, not a suggestion to paraphrase. If the artifact is generated from
|
|
a source, apply the edit there too or it disappears on the next build.
|
|
|
|
### 4. `close` — the gate
|
|
|
|
```sh
|
|
python3 $S/human_gate.py close "$ARTIFACT"
|
|
```
|
|
|
|
| Rule | Refuses when |
|
|
|---|---|
|
|
| G1 | no round collected — nobody has looked |
|
|
| G2 | a BLOCKER or MAJOR is still open |
|
|
| G3 | no named reviewer |
|
|
| G4 | the sidecar changed after the last collect |
|
|
| G5 | round cap exhausted → escalate |
|
|
| G6 | waiver used without a recorded reason — **G1 can never be waived** |
|
|
| G7 | the round carries unresolved integrity problems (mistyped severity, EDIT with no replacement, quote not in the file) |
|
|
|
|
**Exit 2 means you are not done.** Report what is open, not a summary that implies success.
|
|
|
|
Legitimate override, recorded:
|
|
|
|
```sh
|
|
python3 $S/human_gate.py close "$ARTIFACT" --waive "reviewer on leave; CTO accepted risk in writing"
|
|
```
|
|
|
|
## Output digest
|
|
|
|
Report back exactly this shape:
|
|
|
|
```
|
|
GATE: <PASSED | REFUSED | ESCALATE>
|
|
Reviewer: <name>
|
|
Rounds: <n> of <max>
|
|
Open: <BLOCKER/MAJOR items, by block id>
|
|
Applied: <what you changed, and in which source files>
|
|
Next: <the one action, or "none — done">
|
|
```
|
|
|
|
## Try it
|
|
|
|
```sh
|
|
python3 engineering/human-gate/skills/human-gate/scripts/human_gate.py --sample
|
|
```
|
|
|
|
Runs the whole loop in a temp dir — including the refusals — in about a second.
|