# hackenproof-bulk-triage

Bulk triage workflow for all assigned HackenProof programs. Discovers all open reports across every assigned program, syncs local codebases, analyzes each report, and outputs structured recommendations for human review — without applying any changes automatically.

- **Kind:** skill
- **Source:** https://github.com/hackenproof-public/skills
- **Page:** https://forefy.com/skills/e8a0c898-6a21-4552-9f9b-bb5c548d1810
- **API (JSON + files):** https://forefy.com/api/asr/e8a0c898-6a21-4552-9f9b-bb5c548d1810

---

## SKILL.md

---
name: hackenproof-bulk-triage
description: Bulk triage workflow for all assigned HackenProof programs. Discovers all open reports across every assigned program, syncs local codebases, analyzes each report, and outputs structured recommendations for human review — without applying any changes automatically.
---

# HackenProof Bulk Triage

Analyze all open reports across all assigned programs and produce a structured recommendation report for human review. Never change state, severity, labels, or post comments without explicit user confirmation.

## Workflow

1. Read local repo config from `~/.claude/hackenproof-repos.yaml`.
2. Discover all assigned programs via `list_companies` + `list_programs`.
3. For each program that has a local repo configured, sync the repo.
4. For each program, fetch all open reports.
5. For each report, run full triage analysis and produce a recommendation.
6. Output a consolidated recommendation report — no actions taken.
7. Ask the user which recommendations to apply, then execute only confirmed ones.

## Step 1: Load Config

Read `~/.claude/hackenproof-repos.yaml` using the Read tool. See `references/setup-guide.md` for file format and examples.
Parse the `programs` mapping: `program-slug → { repo?, branch?, explorer?, enabled? }`.

Skip any program entry where `enabled: false`.

A program entry may have:
- `repo` — path to a local git clone (for source-based validation)
- `explorer` — a blockchain explorer URL to a deployed contract (e.g. `https://nearblocks.io/address/intents.near`)
- both, if the repo is known and the deployed address is also useful
- neither, in which case analysis is API-only

## Step 1.5: Program Selection

After loading the config, present the user with a numbered list of all enabled programs and ask which to include in this run:

```
Programs available for triage:

  1. near-intents-smart-contracts  (repo: ~/hackenproof/bb/near/intents)
  2. bluefin-dex-contracts          (repo: ~/hackenproof/private_programs/bluefin/...)
  3. kai-finance-yield-protocol     (repo: ~/hackenproof/bb/kai-finance/...)
  ...

Which programs to triage? (default: all)
  → Type numbers separated by commas (e.g. 1, 3), program slugs, or "all"
```

- Wait for user input before proceeding.
- If the user responds with `all` or just presses enter (empty input), include all enabled programs.
- Otherwise, filter to only the selected programs (by number or slug).
- If the user references a slug that is not in config, note it but continue with the valid selection.

## Step 2: Discover Programs

- Call `list_companies` to get all companies with assigned roles.
- For each company, call `list_programs` to enumerate programs.
- Build a flat list of `(company_slug, program_slug)` pairs, filtered to the selection from Step 1.5.
- If a program appears in config with `enabled: false`, exclude it from this list.

## Step 3: Sync Local Repos

For each program in config, determine validation mode:

### Mode A: `repo` is set (source repo)

1. Resolve the `repo` path (expand `~` if needed).
2. Run `git -C {repo} fetch --quiet` to update remote refs without modifying working tree.
3. Run `git -C {repo} log -1 --oneline` to get the current local HEAD.
4. Run `git -C {repo} rev-parse origin/{branch}` to get the remote HEAD (use `branch` from config, or detect with `git -C {repo} rev-parse --abbrev-ref HEAD`).
5. If local HEAD differs from remote HEAD, run `git -C {repo} pull --ff-only`.
6. Record the final commit hash and branch for use during report validation.
7. If pull fails (e.g. local changes, diverged), report the sync error and fall back to Mode C for that program.

### Mode B: `explorer` is set (deployed contract, no local repo)

1. Record the explorer URL as the version anchor for this program.
2. No git operations needed — skip to Step 4.
3. During report validation (Step 5), when checking commit/version:
   - Treat the explorer URL as the canonical deployed version.
   - If the report references a specific tx hash or contract address, verify it matches the scoped explorer URL from config and from `get_program_info` scopes.
   - Use `get_program_info` scopes to confirm the contract address is in scope.
   - Do not attempt to read source files; rely on report attachments, PoC, and `get_report_details`.

### Mode C: neither set (API-only)

No local validation possible. Analyze using `get_report_details`, `get_program_info`, and attachments only. Note "no local code validation" in the recommendation output.

## Step 4: Fetch Open Reports

For each `(company, program)` pair:

- Call `list_reports` with `state=["New", "In review", "Need more info"]` and `page=1` first.
- If page 1 returns 10 results, fetch subsequent pages until exhausted.
- Skip programs with zero open reports.

## Step 5: Analyze Each Report

For each report, apply the full single-report triage logic from `hackenproof-triage-marketplace`:

1. Call `get_program_info` (once per program, cache result).
2. Call `get_report_details` to get description, target, version, steps.
3. Call `get_attachments`; read relevant ones with `fetch_attachment`.
4. Check Gate 1: commit/version match against program scope.
   - Mode A (local repo): use `git -C {repo} log --oneline` or `git -C {repo} show {commit}` to verify the reported commit exists and is in scope.
   - Mode B (explorer URL): verify the reported contract address or tx hash matches the scoped explorer URL. Check that the address in the report matches what `get_program_info` scopes list.
   - Mode C (API-only): rely solely on program rules and report description; note inability to verify version locally.
5. Check Gate 2: scope match (target asset + impact category).
6. Check Gate 3: duplicate check via `list_reports` search on same component/root cause.
   - If a `dup-{id}` label is already set, fetch the original report with `get_report_details` and verify the root cause actually matches (don't trust the label blindly).
   - Once confirmed as a duplicate, check the **original report's current state**:
     - If original is `In review` / `Triaged` / `New` → recommend closing as `Duplicate`
     - If original is `Not applicable` / `Out of scope` / `Informative` / `Spam` → recommend the **same state** as the original, with the same reasoning (the new report fails on the same grounds, not merely because it's a duplicate)
7. Check Gate 4: PoC presence.
8. If all gates pass, assess severity against program rewards and global policy.
9. Check existing comments with `get_comments` to avoid contradicting prior decisions.
10. Derive a recommendation (see Recommendation Format below).

Do NOT call `change_state`, `change_severity`, `add_labels`, or `add_comment` during this step.

## Step 6: Output Recommendation Report

Before printing, classify each report into one of two buckets:

**Can Be Closed** — recommended state is `Invalid`, `Out of scope`, `Duplicate`, `Spam`, or `Informational` with no further action needed. Safe to act on without broader team input.

**Needs Team Review** — any of the following:
- Recommended state is `Triaged` (valid vulnerability)
- Severity is Medium, High, or Critical
- Confidence is Low or Medium
- Novel or unusual attack vector
- Ambiguity about scope or impact

Print a structured report grouped by program:

```
## Program: {program_slug} ({company_slug})
Source: [repo: {path} — commit {hash} on {branch} — synced/up-to-date/sync failed: {reason}]
      | [explorer: {url}]
      | [API-only — no local source configured]
Open reports: {count}

---
### 🟢 CAN BE CLOSED ({n} reports)

#### {report_id}: {title}
Recommend: {state} | Severity: {severity}
Labels to add: {labels}
Reason: {one-line rationale}
Comment to post: "{draft comment}"
Confidence: High

---
### 🔴 NEEDS TEAM REVIEW ({n} reports)

#### {report_id}: {title}
Recommend: {state} | Severity: {severity}
Labels to add: {labels}
Why team: {one-line reason it needs review}
Comment to post: "{draft comment}"
Confidence: Medium/Low — {what's unclear or what evidence is missing}
```

- Within each bucket, order reports by severity (Critical first).
- If a gate failed, show which gate and what was missing.
- If confidence is Low, explain what additional evidence is needed.
- At the end, print a summary table with a Bucket column:

```
| Report      | Program       | Current State | Recommended State | Severity | Bucket            | Confidence |
|-------------|---------------|---------------|-------------------|----------|-------------------|------------|
| HACK-123    | citrea-sc     | New           | Invalid           | -        | Can be closed     | High       |
| HACK-124    | citrea-sc     | New           | Triaged           | High     | Needs team review | Medium     |
```

## Step 7: Confirm and Execute

After printing the full recommendation report, ask:

> "Which recommendations should I apply?
> - `apply closeable` — apply all 'Can be closed' recommendations
> - `apply all` — apply everything including team-review items
> - List specific report IDs (e.g. `apply HACK-123, HACK-125`)
> - `none` — exit without changes"

- Wait for explicit user response before taking any action.
- For each confirmed report, execute the recommended `change_state`, `change_severity`, `add_labels`, and `add_comment` calls using the standard triage tool sequence.
- Report the outcome for each applied action.

## Rules

- Never apply any action before Step 7 user confirmation.
- Read-only operations (fetching reports, comments, attachments, program info) do NOT require user confirmation — proceed automatically throughout Steps 1–6.
- Only pause at Step 7 before executing write actions (`change_state`, `change_severity`, `add_labels`, `add_comment`).
- Never guess a commit exists in the local repo — verify with `git log` or `git cat-file`.
- If local repo sync fails, still analyze the report using API data only; note "no local code validation" in the recommendation.
- Use cached `get_program_info` results — call it once per program, not once per report.
- Keep recommendations concise: one-line rationale, draft comment under 3 sentences.
- Confidence is High when all evidence is clear, Medium when one piece is ambiguous, Low when PoC or version is missing.
- When closing a confirmed duplicate, mirror the original report's state — do not default to `Duplicate` if the original was closed as `Not applicable`, `Out of scope`, etc.

## agents

```

```

## agents/openai.yaml

```yaml
interface:
  display_name: "HackenProof Bulk Triage"
  short_description: "Bulk triage all open reports across assigned programs"
  default_prompt: "Use $hackenproof-bulk-triage to analyze all open reports and produce a recommendation report for review."
```

## references

```

```

## references/setup-guide.md

# Bulk Triage Setup Guide

## Prerequisites

Create `~/.claude/hackenproof-repos.yaml` before running the bulk triage skill. This file maps HackenProof program slugs to local repositories and/or blockchain explorers so the skill can validate reports against source code or deployed contracts.

## File Format

```yaml
programs:
  program-slug:
    repo: ~/path/to/local/clone       # optional — local git repo for source validation
    branch: main                       # optional — branch to track (defaults to current)
    explorer: https://explorer/address # optional — deployed contract URL
    enabled: true                      # optional — set false to skip (defaults to true)
```

## Validation Modes

Each program entry determines how reports are validated:

| Config                    | Mode       | Behavior                                              |
|---------------------------|------------|-------------------------------------------------------|
| `repo` set                | Source     | Git fetch + commit verification + source code review  |
| `explorer` set (no repo)  | Explorer   | Contract address matching against program scope       |
| Both `repo` and `explorer`| Hybrid     | Source validation + explorer as deployment anchor      |
| Neither                   | API-only   | Relies on report details and attachments only          |

## Example

```yaml
programs:
  # Source repo — validates commits and reads code
  near-intents-smart-contracts:
    repo: ~/hackenproof/bb/near/intents
    branch: main

  # Explorer only — deployed contract, no source
  some-defi-protocol:
    explorer: https://etherscan.io/address/0xABC123...

  # Both — source repo + deployed address
  multipli-smart-contracts:
    repo: ~/hackenproof/bb/multipli/Barebones-MultipliVault
    branch: v2
    explorer: https://snowtrace.io/address/0xCF0Eb4...

  # Temporarily disabled
  paused-program:
    repo: ~/hackenproof/bb/paused
    enabled: false
```

## Finding Program Slugs

Program slugs must match the HackenProof dashboard URL:

```
https://dashboard.hackenproof.com/manager/companies/{company}/{program-slug}/...
```

Or run the skill without the config file — it will list all assigned programs by slug so you know what to add.

## Notes

- Paths support `~` expansion.
- If `branch` is omitted, the skill uses the repo's current checked-out branch.
- Programs not listed in the file are still triaged using API-only mode.
- Multiple `explorer` values for the same program are not supported in YAML — use the primary contract address.

