Skip to content

Configuring Gates

A human gate is a hug phase with a review block. This page covers how to define the gate in team.yml, write an effective review brief, and set up reviewer notifications.


The review block on a hug phase tells the hug agent what material to gather and how to handle the review lifecycle.

FieldTypeDefaultDescription
reviewerstring | string[](none)Named reviewer(s) from hug.reviewers in settings
artifactsstring[][]Files or globs to include in the review
timeoutstring"24h"Auto-escalate after this duration. Supports s, m, h, d
remind_everystring(none)Re-notification interval. Omit to notify once

Command results are always included — they’re inherent to any gate. Git diffs are gathered automatically when a git repo is detected. The artifacts list is for specific files the reviewer needs to see. Glob patterns are supported (e.g., src/auth/**/*.ts).

phases:
- name: architect
type: standard
- name: arch-review
type: hug
depends_on: [architect]
commands:
- name: design-doc-exists
run: "test -f .cliq/design/architecture.md"
review:
reviewer: architect
artifacts:
- .cliq/design/architecture.md
timeout: 8h
remind_every: 2h
- name: developer
type: standard
depends_on: [arch-review]

What happens: the architect phase produces a design doc. The gate runs test -f to verify it exists. If the command passes, a review is created with the design doc as an artifact. The named reviewer architect is notified via Slack. They have 8 hours to decide, with reminders every 2 hours. If they approve, the developer phase starts. If they request changes, work routes back. If the timeout expires, the pipeline escalates.

The timeout starts counting when the review is created on the hug server, not when the reviewer opens it. The hug agent tracks the deadline locally and returns ESCALATE if it passes without a verdict.

The server also enforces the timeout — if a reviewer opens an expired link, the page displays “This review has expired” with all interactions disabled. Verdicts submitted after expiry are rejected with 410 Gone.

Supported formats: 30s, 15m, 4h, 2d. Default: 24h.

If a reviewer opens an expired link, the page displays “This review has expired” with all interactions disabled — no verdict can be submitted and no chat messages sent. The pipeline has already moved on.

When remind_every is set, the hug agent re-sends Slack notifications at the configured interval until the reviewer acts or the timeout expires. If omitted, reviewers are notified exactly once.


Every hug gate automatically generates a scaffold brief — a structured message from the pipeline to the reviewer. The scaffold always includes:

  • Preamble — which phase completed, which team, what’s being asked
  • Command summary — “All 3 commands passed” or “2 of 3 commands passed (lint failed)”
  • Artifact summary — lists the deliverables the reviewer should examine
  • Route context — explains what happens on Approve, Request Changes, and Reject

This means a hug gate works with no role file at all. The scaffold provides everything the reviewer needs to orient themselves.

If you want to give the reviewer domain-specific evaluation criteria, create a role file (roles/arch-review.md or whatever your gate phase is named). The scaffold will embed your content under a Review Guidelines heading, wrapped by the standard preamble and context.

You don’t need to include boilerplate — no “Your Options” section, no requirement text, no artifact list. Just write the part that’s unique to your review:

## What to Look For
- Does the proposed architecture align with our existing stack?
- Are there scalability or security concerns?
- Is the test strategy adequate for the scope?
- Does the data model support the access patterns described
in the requirement?

The scaffold handles the rest. If the role file is empty or just a stub, the scaffold stands alone.

VariableValue
$(team_name)Team name (e.g., feature-dev-js)
$(instance_id)Pipeline instance ID (e.g., cliq-a1b2c3)
$(phase)Phase name (e.g., arch-review)
$(date)Current date
  • Be specific about criteria. “Does this look good?” is unhelpful. “Does the caching strategy handle the 10k concurrent user target?” gives the reviewer something to evaluate.
  • Focus on what’s unique. The scaffold already tells the reviewer what phase produced the work, what artifacts are attached, and what the verdict options do. Your role file adds the domain knowledge the scaffold can’t.
  • Reference the requirement. If your evaluation criteria relate to specific aspects of the requirement, mention them — the full requirement is available in a collapsible section on the review page.

When a review is created, the hug agent can notify specific people via Slack. This is separate from pipeline notifications — pipeline notifications tell the team “something happened,” hug notifications tell a specific person “you need to act.”

Reviewers are defined in settings.json under hug.reviewers. There are two kinds of entries:

  • Individuals — a named person with notification channels. Define each person once.
  • Groups — a named collection of members (individuals or other groups) with a policy.

This separates who reviews (portable, in the team definition) from how to reach them (environment-specific, in settings). An individual’s channels are defined once and reused across any number of groups.

{
"hug": {
"server_url": "https://hug.example.com",
"token": "hug-auth-token",
"reviewers": [
{ "name": "alice", "channels": ["slack:alice"] },
{ "name": "bob", "channels": ["slack:bob"] },
{ "name": "carol", "channels": ["slack:carol", "slack:security-team"] },
{ "name": "architects", "members": ["alice", "bob"], "policy": "any" },
{ "name": "security", "members": ["carol"], "policy": "any" }
],
"chat": {
"enabled": true,
"provider": "anthropic"
}
}
}

Chat is optional. When hug.enable_chat is true, hug.llm.provider must be set and an API key must be available. See LLM provider defaults for provider details.

Reference by name in team.yml — individuals and groups are both valid:

review:
reviewer: architects

Or multiple reviewer policies — all are notified, first verdict wins:

review:
reviewer: [architects, security]

Important implementation note: With policy: "any" (the only supported policy today), all members across all referenced reviewers are notified and the first person to submit a verdict decides. Groups are a configuration convenience for organizing notification channels — they do not currently enforce per-group approval.

channels is an array of strings. Each string references a configured integration channel, or provides an ad hoc webhook URL.

Use colon notation to reference Slack webhooks from integrations.slack:

  • "slack" — default webhook (integrations.slack.webhook_url)
  • "slack:security" — named channel (integrations.slack.channels.security.webhook_url)
  • "url:https://..." — ad hoc webhook URL

Single channel:

{ "name": "architect", "channels": ["slack"] }

Explicit webhook:

{ "name": "ops", "channels": ["url:https://hooks.slack.com/services/..."] }

Multiple channels (all fire):

{ "name": "lead", "channels": ["slack", "slack:security"] }

The Slack notification is deliberately concise:

:eyes: Human review requested — feature-dev-js | cliq-a1b2c3 :hourglass_flowing_sand: Expires: Apr 5, 2026 at 3:42 PM Open Review

All detail — brief, artifacts, commands, diff — lives on the review page. The notification is a call to action, not a summary.

If the review block omits reviewer, the review is still created on the hug server. No targeted notification is sent — the human discovers the review through pipeline notifications or the review link in logs.


Every human gate writes a permanent record to .cliq/reviews/:

# Human Review: arch-review
**Reviewer**: [email protected]
**Verdict**: Approved (PASS)
**Date**: 2026-04-03T16:42:00Z
**Review ID**: a1b2c3d4e5f6...
## Comment
Architecture looks solid. The caching strategy is well-reasoned
and the test plan covers the critical paths.
## Chat Transcript
**Human**: What was the rationale for Redis over Memcached?
**Assistant**: The architect chose Redis based on the requirement
for sorted sets in the leaderboard feature. Memcached doesn't
support sorted data structures natively...

After the agent acknowledges the verdict, the review is marked as completed on the hug server. The review link remains accessible as a read-only archive for the retention period (default 30 days, configurable via --retention-days). Anyone with the link can see the verdict, comment, artifacts, and chat transcript.

After the retention period, the server purges the review. The .cliq/reviews/ directory on the cliq instance is the permanent record — it stays with the project, in version control if you choose.


cliq validates HUG configuration at multiple points:

  • cliq assemble — throws a hard error if hug.server_url is missing for any team that uses hug phases. Verifies that review.reviewer names exist in hug.reviewers in settings. Verifies that the review block only appears on hug phases. When enable_chat is true, validates that hug.llm.provider is set and an API key is available.
  • cliq doctor — checks hug server reachability when hug.server_url is configured. When enable_chat is true, verifies the LLM provider is valid and the required API key is present (in settings or env var).

Missing server_url is a hard error — cliq assemble will not proceed:

Error: hug.server_url is required in settings.json when using human gates.

If a reviewer name is missing, you get a clear error:

Phase 'arch-review' references reviewer 'architect' but no reviewer
with that name is configured in settings.json under hug.reviewers.

If chat is enabled but misconfigured:

Error: hug.llm.provider is required when enable_chat is true.
Specify "anthropic", "openai", or "google".
Error: No API key for hug LLM provider "anthropic".
Set hug.llm.api_key in settings or export ANTHROPIC_API_KEY in your environment.