Skip to content
Open
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
47 changes: 47 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,55 @@ All notable changes to BugHunter are documented here.

## [Unreleased]

### Added — V56.1: Per-Detector MCP Harness Infrastructure

V56.1 lands the load-bearing infrastructure for the per-detector harness. No detector contracts ship in this release — V56.2 populates the first 10.

**A. Detector contract type system (`packages/cli/src/detectors/contracts.ts`)**
- `DetectorContract` type with `requires` (phases, tools, surface, role, pageContext), `fixture`, `defaultBudgetMs`, `note`
- `ClusterAssertion` discriminated union (`fires` | `silent`)
- `DETECTOR_CONTRACTS: ReadonlyArray<DetectorContract>` — empty in V56.1, populated in V56.2+
- `harness?: boolean` field added to `DetectorRegistryEntry` in `registry.ts`
- V56 lockstep assertions added to `registry.lockstep.test.ts`: 1:1 between `harness:true` rows and `DETECTOR_CONTRACTS`

**B. MCP tool: `bughunt_run_detector` (`packages/mcp/src/tools/run-detector.ts`)**
- Registered in `packages/mcp/src/server.ts` alongside existing tools
- Input: `kind: BugKind | BugKind[]`, `target`, `scope?`, `budgetMs?`, `reset?`, `project?`
- Output: `{ clusters, telemetry: { plannedTests, runTests, skippedTests, durationMs, perDetectorElapsed, budgetExceeded, phasesRun }, warnings }`
- Returns `unknown_detector_kind` error while `DETECTOR_CONTRACTS` is empty (V56.1 only)
- Runtime AbortSignal compliance check at tool startup (warns, does not fail — per resolved decision 4)

**C. Run-store schema: `runMode` field**
- `RunState.runMode?: 'full-scan' | 'detector-call'` added to `packages/cli/src/types.ts`
- Read path tolerates missing field (pre-V56 records default to `'full-scan'`)
- `bughunt_run_detector` persists runs with `runMode: 'detector-call'` when `project` is supplied

**D. AbortSignal propagation**
- `packages/cli/src/harness/executor.ts`: `runHarness` accepts `signal?: AbortSignal` and combines with internal budget `AbortController`
- Budget hard-stop propagated through phase loop; returns `budgetExceeded: true` on abort
- `checkAdapterSignalCompliance` runtime check at MCP tool startup
- TODO comment referencing V57+ for comprehensive adapter audit

**E. CLI: `bughunter test-detector` and `bughunter self-test --tier`**
- `bughunter test-detector <kind|all> [--target <url>] [--verbose] [--no-up] [--keep] [--json]`
- `bughunter self-test --tier <1|2|3|all> [--bail] [--json]`
- Tier 1: per-detector fixture runs (parallelized at 8), passes vacuously with 0 contracts
- Tier 2: phase-level smoke infrastructure ready; `_phase-smoke` fixture created (full execution in V56.2)
- Tier 3: existing comprehensive-bench self-test (unchanged); `bughunter self-test` (no --tier) = Tier 3
- Tier gating: Tier 1 failure blocks Tier 2/3 from running

**F. Fixture scaffolding**
- `fixtures/detector-calibration/_phase-smoke/` — meta-fixture for Tier 2; stub server in V56.1
- `fixtures/detector-calibration/_template/` — reference template for V56.2+ coder

**G. Documentation**
- README: "Per-detector MCP tool" section with 3 usage examples
- CHANGELOG: this entry

### Fixed



- **fix(transport): friendly error for mcp-http on legacy camofox-mcp (#115)**
When `browserTransport` is `mcp-http` (the default since v0.42) and the configured
camofox-mcp server does not advertise the Streamable HTTP MCP transport, BugHunter
Expand Down
67 changes: 67 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,73 @@ Depends on:

The skill is the smooth UX; the CLI is the load-bearing thing.

## Per-detector MCP tool (V56)

BugHunter exposes a third invocation path: `bughunt_run_detector`, a write-side MCP tool that runs a single detector (or list of detectors) against a target right now and returns clusters — without a full 17-hour scan.

**When to use it:**
- "Did my XSS fix take?" → run only `xss_reflected` against the patched URL
- "Recheck CSP after a header change" → target only `missing_csp_header`
- "Re-run all IDOR detectors after an auth refactor" → pass an array of kinds

**Examples (MCP call via `POST /mcp`):**

Single-kind invocation:
```json
{
"method": "tools/call",
"params": {
"name": "bughunt_run_detector",
"arguments": {
"kind": "missing_csp_header",
"target": { "appBaseUrl": "http://localhost:3000", "surfaceMcpUrl": "http://localhost:3200" },
"budgetMs": 30000
}
}
}
```

Multi-kind (IDOR category) with cookie auth:
```json
{
"method": "tools/call",
"params": {
"name": "bughunt_run_detector",
"arguments": {
"kind": ["idor_horizontal", "idor_horizontal_read", "idor_vertical_role_escalate"],
"target": {
"appBaseUrl": "http://localhost:3000",
"surfaceMcpUrl": "http://localhost:3200",
"browserMcpUrl": "http://localhost:9377",
"auth": { "kind": "cookie", "cookie": "session=abc123" }
},
"budgetMs": 60000
}
}
}
```

Scoped to specific route with persistence:
```json
{
"method": "tools/call",
"params": {
"name": "bughunt_run_detector",
"arguments": {
"kind": "xss_reflected",
"target": { "appBaseUrl": "http://localhost:3000", "browserMcpUrl": "http://localhost:9377" },
"scope": { "routes": ["/search"], "maxTests": 50 },
"project": "/path/to/project",
"budgetMs": 30000
}
}
}
```

**Output includes:** `clusters[]`, `telemetry.budgetExceeded`, `telemetry.perDetectorElapsed`, `warnings[]`.

**Note:** V56.1 ships the infrastructure. `bughunt_run_detector` returns `unknown_detector_kind` for all kinds until V56.2 populates `DETECTOR_CONTRACTS` with the first 10 detectors.

## Companion projects

- [SurfaceMCP](https://github.com/cunninghambe/SurfaceMCP) — the API surface
Expand Down
Loading
Loading