| 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
- Read local repo config from
~/.claude/hackenproof-repos.yaml.
- Discover all assigned programs via
list_companies + list_programs.
- For each program that has a local repo configured, sync the repo.
- For each program, fetch all open reports.
- For each report, run full triage analysis and produce a recommendation.
- Output a consolidated recommendation report — no actions taken.
- 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)
- Resolve the
repo path (expand ~ if needed).
- Run
git -C {repo} fetch --quiet to update remote refs without modifying working tree.
- Run
git -C {repo} log -1 --oneline to get the current local HEAD.
- 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).
- If local HEAD differs from remote HEAD, run
git -C {repo} pull --ff-only.
- Record the final commit hash and branch for use during report validation.
- 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)
- Record the explorer URL as the version anchor for this program.
- No git operations needed — skip to Step 4.
- 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:
- Call
get_program_info (once per program, cache result).
- Call
get_report_details to get description, target, version, steps.
- Call
get_attachments; read relevant ones with fetch_attachment.
- 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.
- Check Gate 2: scope match (target asset + impact category).
- 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)
- Check Gate 4: PoC presence.
- If all gates pass, assess severity against program rewards and global policy.
- Check existing comments with
get_comments to avoid contradicting prior decisions.
- 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.