Skip to content

Wire garak into the Arsenal: structured parser + report-file capture#128

Open
TengHu wants to merge 1 commit into
elder-plinius:mainfrom
TengHu:feat/garak-parser-report-capture
Open

Wire garak into the Arsenal: structured parser + report-file capture#128
TengHu wants to merge 1 commit into
elder-plinius:mainfrom
TengHu:feat/garak-parser-report-capture

Conversation

@TengHu

@TengHu TengHu commented Jul 26, 2026

Copy link
Copy Markdown

What & why

garak was catalogued but parserStatus: 'planned' — an agent could run it, but its
output could only enter as the model's prose, which the live provenance gate
(src/evidence/gate.ts) refuses to mark verified. So the ai_red_team family had
no verified, tool-backed evidence source.

This wires garak end-to-end:

  1. parseGarak (src/arsenal/parsers.ts) — turns garak's report.jsonl into
    ToolFinding[], one finding per (probe × detector) that registered an attack
    success, with attack-success-rate → severity. It summarises garak's own detector
    verdicts
    (a parser summarises, it does not re-judge) and surfaces only probe/
    detector names + counts — never prompt/response transcript text
    .
  2. Report-file capture (src/arsenal/adapter-tools.ts + src/index.ts) — garak
    writes its results to a report.jsonl file, not stdout. An additive
    ArgTemplate.reportFile hook + optional mkReportPath/readToolReport deps let the
    handler read that file back and use it as both the parse input and the evidence
    of record. Zero behaviour change for every stdout-based adapter.
  3. catalog.ts: garak parserStatus: 'planned' → 'structured'.

Result: an ai_red_team mission can run garak against an authorized model and produce
findings that pass the provenance gate

Scope honesty (please read)

  • "Verified" here = provenance-verified ("garak really reported this"), not
    ground-truth-verified ("the model is really jailbroken"). garak's keyword detectors
    (dan.DAN, mitigation.MitigationBypass, TriggerListDetector) over-report — in
    local testing on a small model, a majority of LatentJailbreak "hits" were refusals
    (false positives). The finding details says so and recommends transcript verification.
    An LLM-judge detector is the natural follow-up (separate PR).

Contribution Receipt

Field Value
Change Wire garak into the Arsenal: parseGarak + report-file capture, so ai_red_team missions produce verified, tool-backed findings instead of unverifiable prose.
Scope class static_fixture
Target authority not_applicable (tests run against a committed static fixture; no live target in this change)
Network use none
Run mode labels static_test, tool_backed
Model/harness labels not_applicable for the change's tests. The committed fixture is derived from a real garak 0.15.1 run against meta-llama/llama-3.2-3b-instruct via OpenRouter/litellm (author's own lab; not part of CI).
Commands run npm run typecheck (tsc --noEmit) → pass. npm test (full vitest run src) → 651/652 pass. The single failure — local-agent-path-resolution.test.ts (codex install detection, issue #78) — reproduces identically on the unmodified baseline (verified by stashing this change) and is environmental: the author's machine has the codex CLI installed, which the temp-home test does not expect. It is unrelated to this change and does not touch any file in it. eslint (changed files) → clean.
Artifacts src/__tests__/fixtures/garak.report.jsonl (committed fixture).
Redaction Parser surfaces only probe/detector names + counts, never transcript text (asserted by test). readToolReport consume-then-deletes the report file so probe transcripts do not linger on disk. Fixture contains no secrets.
Claims changed none — no README/headline claim changed; garak is not added to any benchmark.
Abstentions/refusals not_applicable (no model behaviour measured in this change).
Residual risk (1) Findings reflect garak's over-reporting keyword detectors — transcript verification recommended; an LLM-judge detector is the natural follow-up (separate PR). (2) promptfoo remains planned.

Test evidence

  • parseGarak field-mapping, aggregation, honesty-contract (empty/garbled → []), and
    no-transcript-leak assertions.
  • End-to-end: a parsed garak finding passes gateLiveFinding with provenance: 'tool'.

Turn garak's report.jsonl into structured ToolFinding[] and feed the
report FILE (not stdout) to the parser, so ai_red_team missions produce
verified, tool-backed findings instead of unverifiable prose.

- parsers.ts: parseGarak() aggregates attempts into one finding per
  (probe x detector) with attack-success-rate + severity; registered in
  PARSERS. Summarises garak's own detector verdicts; never emits prompt/
  response transcript text (names + counts only).
- catalog.ts: garak parserStatus planned -> structured.
- adapter-tools.ts: ArgTemplate.reportFile hook + optional
  mkReportPath/readToolReport deps + garak template. The handler reads a
  report-file tool's output from disk and uses it as BOTH the parse input
  and the evidence of record. Zero behaviour change for stdout tools.
- index.ts: real deps — temp-path minter + consume-then-delete report
  reader (probe transcripts do not linger on disk).
- tests: garak fixture + field-mapping, aggregation, no-transcript-leak,
  honesty-contract, gate-pass, and a factory test proving the report file
  (not stdout) is parsed. Updated the invocation-honesty guard (garak is
  now templated).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant