Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# =============================================================================
# 🎩 Hat Stack — Environment Configuration Template
# =============================================================================
#
# INSTRUCTIONS:
# 1. Copy this file: cp .env.example .env
# 2. Fill in YOUR values below
# 3. NEVER commit .env — it's already in .gitignore
#
# For GitHub Actions (recommended):
# Don't use this file at all. Instead, add these as Repository Secrets
# in your fork: Settings → Secrets and variables → Actions → New repository secret
#
# =============================================================================

# ---------------------------------------------------------------------------
# REQUIRED — Ollama Cloud API
# ---------------------------------------------------------------------------
# Your Ollama Cloud API key. Get one at https://ollama.ai/cloud
# This is YOUR key — it stays in YOUR secrets, never in code.
OLLAMA_API_KEY=

# Ollama Cloud API base URL (default works for most users)
OLLAMA_BASE_URL=https://api.ollama.ai/v1

# ---------------------------------------------------------------------------
# OPTIONAL — GitHub Callback (for dispatch mode)
# ---------------------------------------------------------------------------
# A GitHub Personal Access Token (PAT) with repo scope, used to post
# Hats review results back to PRs in OTHER repos via the dispatch handler.
# Only needed if you want hat_stack to comment on external repos' PRs.
#
# Create at: https://github.com/settings/tokens
# Required scopes: repo (for private repos) or public_repo (for public repos)
HAT_STACK_CALLBACK_TOKEN=

# ---------------------------------------------------------------------------
# OPTIONAL — CLI Configuration (for the `hat` command)
# ---------------------------------------------------------------------------
# Your hat_stack fork — used by the `hat` CLI to dispatch tasks.
# Default: Grumpified-OGGVCT/hat_stack (the original repo)
# Set this to YOUR fork so tasks run with YOUR API keys.
HAT_STACK_REPO=

# ---------------------------------------------------------------------------
# OPTIONAL — Model Overrides
# ---------------------------------------------------------------------------
# Override the default primary model for all Tier 1 hats (security, safety, adjudication)
# Default: glm-5.1 (per Implementation Guide §E2.2)
# Alternatives: kimi-k2.5, deepseek-v3.1
# HATS_TIER1_MODEL=glm-5.1

# Override the default primary model for all Tier 2 hats (architectural reasoning)
# Default: glm-5.1
# Alternatives: deepseek-v3.1, minimax-m2.7
# HATS_TIER2_MODEL=glm-5.1

# Override the default model for Tier 3 hats (quality analysis)
# Default: nemotron-3-super
# Alternatives: qwen3-coder
# HATS_TIER3_MODEL=nemotron-3-super

# Override the default model for Tier 4 hats (fast scanning)
# Default: nemotron-3-nano or ministral-3
# HATS_TIER4_MODEL=nemotron-3-nano

# ---------------------------------------------------------------------------
# OPTIONAL — Budget Limits
# ---------------------------------------------------------------------------
# Maximum cost per PR review in USD (default: $0.15 for Ollama Cloud)
# HATS_MAX_USD_PER_PR=0.15

# Maximum tokens per PR review (default: 150000)
# HATS_MAX_TOKENS_PER_PR=150000
144 changes: 144 additions & 0 deletions .github/actions/run-hats/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# 🎩 Run Hats Review — Composite Action
#
# Use this action in any workflow to run the Hats pipeline on a diff.
#
# Usage:
# - name: Run Hats Review
# uses: Grumpified-OGGVCT/hat_stack/.github/actions/run-hats@main
# with:
# diff_file: /tmp/pr.diff
# env:
# OLLAMA_API_KEY: ${{ secrets.OLLAMA_API_KEY }}

name: "🎩 Run Hats Review"
description: "Run the Hat Stack AI review pipeline on a code diff"

inputs:
diff_file:
description: "Path to the diff file to review"
required: false
default: ""
diff:
description: "Inline diff text (for small diffs; use diff_file for large ones)"
required: false
default: ""
hats:
description: "Comma-separated hat IDs to run (default: auto-select based on triggers)"
required: false
default: ""
context:
description: "Additional context for the review (e.g., PR description)"
required: false
default: ""
config:
description: "Path to custom hat_configs.yml (default: uses built-in config)"
required: false
default: ""
output_format:
description: "Output format: json, markdown, or both"
required: false
default: "both"

outputs:
verdict:
description: "The final Hats verdict: ALLOW, ESCALATE, or QUARANTINE"
value: ${{ steps.run.outputs.verdict }}
risk_score:
description: "Composite risk score (0-100)"
value: ${{ steps.run.outputs.risk_score }}
hats_executed:
description: "Number of hats that ran"
value: ${{ steps.run.outputs.hats_executed }}
report_markdown:
description: "Path to the Markdown report file"
value: ${{ steps.run.outputs.report_markdown }}
report_json:
description: "Path to the JSON report file"
value: ${{ steps.run.outputs.report_json }}

runs:
using: composite
steps:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install dependencies
shell: bash
run: |
HAT_STACK_ROOT="$GITHUB_ACTION_PATH/../../.."
pip install -r "$HAT_STACK_ROOT/scripts/requirements.txt"

- name: Prepare diff
id: prep
shell: bash
run: |
DIFF_FILE="/tmp/hats-action-diff.patch"

if [ -n "${{ inputs.diff_file }}" ] && [ -f "${{ inputs.diff_file }}" ]; then
cp "${{ inputs.diff_file }}" "$DIFF_FILE"
elif [ -n "${{ inputs.diff }}" ]; then
cat <<'HATS_DIFF_EOF' > "$DIFF_FILE"
${{ inputs.diff }}
HATS_DIFF_EOF
else
echo "⚠️ No diff provided. Set either 'diff_file' or 'diff' input." >&2
echo "verdict=ALLOW" >> "$GITHUB_OUTPUT"
echo "risk_score=0" >> "$GITHUB_OUTPUT"
echo "hats_executed=0" >> "$GITHUB_OUTPUT"
exit 0
fi

echo "diff_file=$DIFF_FILE" >> "$GITHUB_OUTPUT"

- name: Run Hats Pipeline
id: run
shell: bash
env:
OLLAMA_API_KEY: ${{ env.OLLAMA_API_KEY }}
OLLAMA_BASE_URL: ${{ env.OLLAMA_BASE_URL || 'https://api.ollama.ai/v1' }}
HAT_STACK_ACTION_PATH: ${{ github.action_path }}
run: |
HAT_STACK_ROOT="$HAT_STACK_ACTION_PATH/../../.."
CONFIG="$HAT_STACK_ROOT/scripts/hat_configs.yml"
if [ -n "${{ inputs.config }}" ] && [ -f "${{ inputs.config }}" ]; then
CONFIG="${{ inputs.config }}"
fi

ARGS=(
--diff "${{ steps.prep.outputs.diff_file }}"
--config "$CONFIG"
--output "${{ inputs.output_format }}"
--markdown-file /tmp/hats-report.md
--json-file /tmp/hats-report.json
)

if [ -n "${{ inputs.hats }}" ]; then
ARGS+=(--hats "${{ inputs.hats }}")
fi

if [ -n "${{ inputs.context }}" ]; then
ARGS+=(--context "${{ inputs.context }}")
fi

set +e
python "$HAT_STACK_ROOT/scripts/hats_runner.py" "${ARGS[@]}"
EXIT_CODE=$?
set -e

if [ -f /tmp/hats-report.json ]; then
VERDICT=$(python3 -c "import json; print(json.load(open('/tmp/hats-report.json'))['verdict'])")
RISK_SCORE=$(python3 -c "import json; print(json.load(open('/tmp/hats-report.json'))['risk_score'])")
HATS_EXECUTED=$(python3 -c "import json; print(json.load(open('/tmp/hats-report.json'))['hats_executed'])")
else
VERDICT="ALLOW"
RISK_SCORE="0"
HATS_EXECUTED="0"
fi

echo "verdict=$VERDICT" >> "$GITHUB_OUTPUT"
echo "risk_score=$RISK_SCORE" >> "$GITHUB_OUTPUT"
echo "hats_executed=$HATS_EXECUTED" >> "$GITHUB_OUTPUT"
echo "report_markdown=/tmp/hats-report.md" >> "$GITHUB_OUTPUT"
echo "report_json=/tmp/hats-report.json" >> "$GITHUB_OUTPUT"
Loading
Loading