Diagrams — Module S05: Meta-Harness Architecture for Offensive Operations

All Mermaid validated in Mermaid Live Editor. n8n JSON is structurally valid and importable.


Diagram 1 — The CSI Meta-Harness Architecture (n8n)

Type: n8n workflow (importable JSON) Purpose: The primary visual — the CSI scaffold-combiner architecture. An operator task enters the meta-harness, is classified and routed through a local proxy to one of several sub-harnesses (CAI, Claude Code, Codex CLI), with the security primitives and telemetry aggregation applied at the proxy.

{
  "name": "S05 — CSI Meta-Harness Architecture",
  "nodes": [
    { "name": "Operator Task", "type": "n8n-nodes-base.manualTrigger", "position": [180, 360], "notes": "Bug bounty brief, CTF challenge, pentest scope, code-review request" },
    { "name": "Task Classifier", "type": "n8n-nodes-base.set", "position": [400, 360], "notes": "Reads task + artifacts. Emits domain label. Allowed to be uncertain → TriageAgent." },
    { "name": "Harness Selector", "type": "n8n-nodes-base.set", "position": [600, 360], "notes": "Deterministic lookup: domain → sub-harness + prompt + tool subset + HITL posture + context budget." },
    { "name": "Load Shared Context", "type": "n8n-nodes-base.set", "position": [800, 360], "notes": "scope.json + RoE + engagement memory handle + engagement_id. Loaded once, passed by reference." },
    { "name": "Local Proxy (CSI)", "type": "n8n-nodes-base.set", "position": [1020, 360], "notes": "The ONLY endpoint sub-harnesses can reach. Owns security primitives. Intercepts every tool call." },
    { "name": "CAI", "type": "n8n-nodes-base.set", "position": [1280, 160], "notes": "Cybersecurity sub-harness. Bug bounty / pentest / CTF tool suite. Own scope model (overridden by proxy)." },
    { "name": "Claude Code", "type": "n8n-nodes-base.set", "position": [1280, 360], "notes": "Code-aware reasoning sub-harness. Code review, exploit dev, refactoring. No native scope model." },
    { "name": "Codex CLI", "type": "n8n-nodes-base.set", "position": [1280, 560], "notes": "Agentic software-engineering sub-harness. SDLC tasks. No offensive tools loaded by default." },
    { "name": "Security Primitive Layer", "type": "n8n-nodes-base.set", "position": [1020, 560], "notes": "Scope + evidence + kill chain + signal/noise + RoE. Applied to EVERY sub-harness via the proxy." },
    { "name": "Telemetry + Evidence + Cost", "type": "n8n-nodes-base.set", "position": [1500, 360], "notes": "One ledger per engagement regardless of which sub-harness ran. Findings, evidence chain, token cost." },
    { "name": "Unified Output", "type": "n8n-nodes-base.set", "position": [1720, 360], "notes": "Findings + evidence chain + cost ledger. One query, one schema, one legal record." }
  ],
  "connections": {
    "Operator Task": { "main": [[{ "node": "Task Classifier", "type": "main", "index": 0 }]] },
    "Task Classifier": { "main": [[{ "node": "Harness Selector", "type": "main", "index": 0 }]] },
    "Harness Selector": { "main": [[{ "node": "Load Shared Context", "type": "main", "index": 0 }]] },
    "Load Shared Context": { "main": [[{ "node": "Local Proxy (CSI)", "type": "main", "index": 0 }]] },
    "Local Proxy (CSI)": { "main": [
      [{ "node": "CAI", "type": "main", "index": 0 }],
      [{ "node": "Claude Code", "type": "main", "index": 0 }],
      [{ "node": "Codex CLI", "type": "main", "index": 0 }]
    ] },
    "Local Proxy (CSI)": { "main": [[{ "node": "Security Primitive Layer", "type": "main", "index": 0 }]] },
    "CAI": { "main": [[{ "node": "Telemetry + Evidence + Cost", "type": "main", "index": 0 }]] },
    "Claude Code": { "main": [[{ "node": "Telemetry + Evidence + Cost", "type": "main", "index": 0 }]] },
    "Codex CLI": { "main": [[{ "node": "Telemetry + Evidence + Cost", "type": "main", "index": 0 }]] },
    "Telemetry + Evidence + Cost": { "main": [[{ "node": "Unified Output", "type": "main", "index": 0 }]] }
  }
}

Reading the diagram: Left to right. An operator task enters the classifier, which emits a domain label. The selector maps the label to a sub-harness configuration (deterministic lookup). Shared context — scope, RoE, engagement memory handle — is loaded once and passed by reference. The local proxy is the only endpoint any sub-harness can reach; the security primitive layer runs there, intercepting every tool call. CAI, Claude Code, and Codex CLI execute through the proxy, unaware that scope was checked, evidence was logged, or triage ran. All sub-harness output — findings, evidence records, token consumption — aggregates into one ledger per engagement, producing one unified output. The sub-harnesses are not under your control; the proxy is the wrap.


Diagram 2 — The Routing State Machine

Type: Mermaid (stateDiagram) Purpose: The task-classification-and-routing logic as a state machine. Shows the classifier's decision points, the TriageAgent fallback when uncertain, and the deterministic selector that maps a domain label to a sub-harness.

stateDiagram-v2
    [*] --> TaskIn: operator task
    TaskIn --> Classify: read description + artifacts
    Classify --> Confident: domain label + score > threshold
    Classify --> Uncertain: score below threshold
    Uncertain --> TriageAgent: run cheap probes
    TriageAgent --> Classify: re-route with added signal
    Confident --> Select: deterministic lookup
    Select --> CAI: bug_bounty / pentest / ctf
    Select --> ClaudeCode: code_review / exploit_dev
    Select --> CodexCLI: sdlc / refactor / build
    CAI --> Executing: via proxy
    ClaudeCode --> Executing: via proxy
    CodexCLI --> Executing: via proxy
    Executing --> BudgetCheck: per-turn cost accounting
    BudgetCheck --> Executing: budget remains
    BudgetCheck --> Halt: budget exhausted
    Halt --> [*]: surface to operator
    Executing --> [*]: engagement complete

    note right of Select
        Selection is a LOOKUP TABLE,
        not a model call. Once classified,
        the mapping is deterministic.
    end note
    note right of Uncertain
        The classifier is allowed to be
        uncertain. The TriageAgent is not.
    end note

Reading the diagram: A task enters, the classifier reads it and emits a domain label with a confidence score. Above threshold, the selector maps the label to a sub-harness deterministically — no second model call. Below threshold, the TriageAgent runs cheap probes (target type, scope, attached artifacts) and re-routes with the added signal. The selected sub-harness executes through the proxy, with per-turn cost accounting. If the engagement budget is exhausted, the meta-harness halts and surfaces to the operator; otherwise it runs to completion. The classifier is allowed to be uncertain; the TriageAgent and the selector are not.


Diagram 3 — The Security Primitive Layer (middleware wrapping a sub-harness)

Type: Mermaid (flowchart) Purpose: The five primitives applied at the proxy boundary. Shows a sub-harness's tool call passing through scope enforcement, RoE enforcement, kill chain gating, execution, evidence collection, signal/noise filtering, and cost accounting — without the sub-harness's code being modified.

flowchart TD
    SUB["Sub-harness emits tool call<br/>(CAI / Claude Code / Codex CLI)"]
    SCOPE{"1. Scope check<br/>target::action in scope.json?"}
    ROE{"2. RoE check<br/>action prohibited?<br/>rate limit OK?"}
    KILL{"3. Kill chain<br/>action permitted in<br/>current phase?"}
    EXEC["4. Execute<br/>via sub-harness executor"]
    EVID["5. Evidence collection<br/>hash-chained, scope_ref stamped"]
    TRIAGE["6. Signal/noise filter<br/>triage finding if present"]
    COST["7. Cost accounting<br/>tokens + compute to ledger"]
    RESULT["Structured result<br/>back to sub-harness"]

    BLOCKED["BLOCKED<br/>scope_ref stamped, logged"]

    SUB --> SCOPE
    SCOPE -->|"no"| BLOCKED
    SCOPE -->|"yes"| ROE
    ROE -->|"prohibited / over limit"| BLOCKED
    ROE -->|"ok"| KILL
    KILL -->|"not permitted"| BLOCKED
    KILL -->|"permitted"| EXEC
    EXEC --> EVID --> TRIAGE --> COST --> RESULT

    style SCOPE fill:#14141f,stroke:#5eead4,color:#5eead4
    style ROE fill:#14141f,stroke:#5eead4,color:#5eead4
    style KILL fill:#14141f,stroke:#5eead4,color:#5eead4
    style EVID fill:#0d1b2a,stroke:#1b4f72,color:#e4e4e8
    style TRIAGE fill:#0d1b2a,stroke:#1b4f72,color:#e4e4e8
    style EXEC fill:#2a1810,stroke:#a04000,color:#f0a868
    style BLOCKED fill:#2a0d0d,stroke:#a00000,color:#f08080
    style RESULT fill:#0d2818,stroke:#1e8449,color:#82e0aa

Reading the diagram: A sub-harness emits a tool call. The middleware intercepts it before execution. Three gates run first: scope (is the target::action in scope?), RoE (is the action prohibited, or would it exceed the rate cap?), kill chain (is the action permitted in the current phase — e.g., post-exploit actions need confirmation even in CTF). Any gate failing blocks the call, stamps a scope_ref, and logs the block. If all gates pass, the call executes via the sub-harness's own executor. The result is then evidence-logged (hash-chained, scope_ref stamped), triaged if it contains a finding, and cost-accounted. The sub-harness sees only the structured result — it has no idea the primitives ran. This is what makes the layer robust to sub-harness updates: the primitives are not in the sub-harness's code path.


Diagram 4 — Cross-Harness Evidence Aggregation (one log, many sub-harnesses)

Type: Mermaid (flowchart) Purpose: Why the evidence log must be meta-harness-owned. Shows findings from three sub-harnesses landing in one append-only, hash-chained log with one schema, versus the anti-pattern of three separate logs.

flowchart LR
    subgraph correct [Correct: one log, owned by meta-harness]
        direction TB
        CAI1["CAI finding<br/>(nmap + nuclei)"]
        CC1["Claude Code finding<br/>(code review)"]
        CX1["Codex CLI finding<br/>(static analysis)"]
        PROXY1["Local proxy<br/>writes evidence record<br/>transparently"]
        LOG1["ONE evidence log<br/>append-only, hash-chained<br/>one schema, one engagement_id"]
        CAI1 --> PROXY1
        CC1 --> PROXY1
        CX1 --> PROXY1
        PROXY1 --> LOG1
    end

    subgraph wrong [Anti-pattern: three logs, three schemas]
        direction TB
        CAI2["CAI finding"]
        CC2["Claude Code finding"]
        CX2["Codex CLI finding"]
        LOGC["CAI log<br/>(CAI schema)"]
        LOGCL["Claude Code log<br/>(no schema)"]
        LOGX["Codex CLI log<br/>(none — coding tool)"]
        CAI2 --> LOGC
        CC2 --> LOGCL
        CX2 -.->|"no evidence captured"| LOGX
        RECONCILE["Operator reconciles<br/>three logs, three hash chains<br/>useless for legal defense"]
        LOGC --> RECONCILE
        LOGCL --> RECONCILE
        LOGX --> RECONCILE
    end

    style PROXY1 fill:#14141f,stroke:#5eead4,color:#5eead4
    style LOG1 fill:#0d1b2a,stroke:#1b4f72,color:#e4e4e8
    style RECONCILE fill:#2a0d0d,stroke:#a00000,color:#f08080
    style LOGX fill:#2a0d0d,stroke:#a00000,color:#f08080

Reading the diagram: On the left, the correct architecture. Findings from CAI, Claude Code, and Codex CLI all pass through the local proxy, which writes each evidence record transparently — the sub-harnesses do not opt in. One log, one schema, one engagement_id, one hash chain. A client query ("how was this finding obtained?") is a single lookup. On the right, the anti-pattern. Each sub-harness writes (or does not write) its own evidence in its own schema. CAI has a log; Claude Code has a different one; Codex CLI, a coding tool, has none. Reconciling three logs with three hash chains into a defensible legal record is impossible. The cure is the proxy-owned single log on the left.


Diagram 5 — The Benchmarking Pipeline (InjecAgent gate, then the six metrics)

Type: Mermaid (flowchart) Purpose: The S05.3 benchmarking discipline. Shows InjecAgent as a pass/fail gate that runs first, then the six metrics measured against a repeatable lab, producing a scored report compared to baselines.

flowchart TD
    GATE["InjecAgent pass/fail gate<br/>(runs FIRST, no exceptions)"]
    PASS{"Harness refused every<br/>injected action?"}
    FIX["FIX injection resistance<br/>before benchmarking anything else"]
    LAB["Repeatable benchmark lab<br/>isolated targets, seeded vulns,<br/>fixed compute envelope"]
    M1["Detection rate<br/>(of seeded, how many found)"]
    M2["Exploit success rate<br/>(of detected, how many exploitably shown)"]
    M3["False positive rate<br/>(of surfaced, how many not real)"]
    M4["Evidence completeness<br/>(of findings, chain complete?)"]
    M5["Time-to-first-finding<br/>(wall-clock)"]
    M6["Cost per finding<br/>(dollars / confirmed findings)"]
    BASELINE["Compare against baselines<br/>CAI CTF · EVMbench · RedTeamLLM"]
    REPORT["Scored report<br/>six metrics + InjecAgent pass<br/>vs previous run + published baselines"]

    GATE --> PASS
    PASS -->|"yes"| LAB
    PASS -->|"no — single injected command executed"| FIX
    FIX --> GATE
    LAB --> M1 & M2 & M3 & M4 & M5 & M6
    M1 & M2 & M3 & M4 & M5 & M6 --> BASELINE --> REPORT

    style GATE fill:#14141f,stroke:#5eead4,color:#5eead4
    style PASS fill:#0d2818,stroke:#1e8449,color:#82e0aa
    style FIX fill:#2a0d0d,stroke:#a00000,color:#f08080
    style LAB fill:#0d1b2a,stroke:#1b4f72,color:#e4e4e8
    style REPORT fill:#0d2818,stroke:#1e8449,color:#82e0aa

Reading the diagram: Benchmarking begins with the InjecAgent gate — a pass/fail test, not a performance metric. The harness must refuse every injected action in the suite. A single execution of an injected command is a fail, regardless of how the harness scores on the six metrics, because the failure mode (executing attacker-controlled actions from target output) is catastrophic. Once the gate is passed, the repeatable lab runs: isolated Docker targets with seeded vulnerabilities, a fixed compute envelope (same model, same token budget, same wall-clock), and a consistent scoring script. The six metrics — detection rate, exploit success rate, false positive rate, evidence completeness, time-to-first-finding, cost per finding — are computed and compared against the previous run and published baselines (CAI CTF, EVMbench, RedTeamLLM). The output is a scored report you can publish.

# Diagrams — Module S05: Meta-Harness Architecture for Offensive Operations

> All Mermaid validated in Mermaid Live Editor. n8n JSON is structurally valid and importable.

---

## Diagram 1 — The CSI Meta-Harness Architecture (n8n)

**Type**: n8n workflow (importable JSON)
**Purpose**: The primary visual — the CSI scaffold-combiner architecture. An operator task enters the meta-harness, is classified and routed through a local proxy to one of several sub-harnesses (CAI, Claude Code, Codex CLI), with the security primitives and telemetry aggregation applied at the proxy.

```json
{
  "name": "S05 — CSI Meta-Harness Architecture",
  "nodes": [
    { "name": "Operator Task", "type": "n8n-nodes-base.manualTrigger", "position": [180, 360], "notes": "Bug bounty brief, CTF challenge, pentest scope, code-review request" },
    { "name": "Task Classifier", "type": "n8n-nodes-base.set", "position": [400, 360], "notes": "Reads task + artifacts. Emits domain label. Allowed to be uncertain → TriageAgent." },
    { "name": "Harness Selector", "type": "n8n-nodes-base.set", "position": [600, 360], "notes": "Deterministic lookup: domain → sub-harness + prompt + tool subset + HITL posture + context budget." },
    { "name": "Load Shared Context", "type": "n8n-nodes-base.set", "position": [800, 360], "notes": "scope.json + RoE + engagement memory handle + engagement_id. Loaded once, passed by reference." },
    { "name": "Local Proxy (CSI)", "type": "n8n-nodes-base.set", "position": [1020, 360], "notes": "The ONLY endpoint sub-harnesses can reach. Owns security primitives. Intercepts every tool call." },
    { "name": "CAI", "type": "n8n-nodes-base.set", "position": [1280, 160], "notes": "Cybersecurity sub-harness. Bug bounty / pentest / CTF tool suite. Own scope model (overridden by proxy)." },
    { "name": "Claude Code", "type": "n8n-nodes-base.set", "position": [1280, 360], "notes": "Code-aware reasoning sub-harness. Code review, exploit dev, refactoring. No native scope model." },
    { "name": "Codex CLI", "type": "n8n-nodes-base.set", "position": [1280, 560], "notes": "Agentic software-engineering sub-harness. SDLC tasks. No offensive tools loaded by default." },
    { "name": "Security Primitive Layer", "type": "n8n-nodes-base.set", "position": [1020, 560], "notes": "Scope + evidence + kill chain + signal/noise + RoE. Applied to EVERY sub-harness via the proxy." },
    { "name": "Telemetry + Evidence + Cost", "type": "n8n-nodes-base.set", "position": [1500, 360], "notes": "One ledger per engagement regardless of which sub-harness ran. Findings, evidence chain, token cost." },
    { "name": "Unified Output", "type": "n8n-nodes-base.set", "position": [1720, 360], "notes": "Findings + evidence chain + cost ledger. One query, one schema, one legal record." }
  ],
  "connections": {
    "Operator Task": { "main": [[{ "node": "Task Classifier", "type": "main", "index": 0 }]] },
    "Task Classifier": { "main": [[{ "node": "Harness Selector", "type": "main", "index": 0 }]] },
    "Harness Selector": { "main": [[{ "node": "Load Shared Context", "type": "main", "index": 0 }]] },
    "Load Shared Context": { "main": [[{ "node": "Local Proxy (CSI)", "type": "main", "index": 0 }]] },
    "Local Proxy (CSI)": { "main": [
      [{ "node": "CAI", "type": "main", "index": 0 }],
      [{ "node": "Claude Code", "type": "main", "index": 0 }],
      [{ "node": "Codex CLI", "type": "main", "index": 0 }]
    ] },
    "Local Proxy (CSI)": { "main": [[{ "node": "Security Primitive Layer", "type": "main", "index": 0 }]] },
    "CAI": { "main": [[{ "node": "Telemetry + Evidence + Cost", "type": "main", "index": 0 }]] },
    "Claude Code": { "main": [[{ "node": "Telemetry + Evidence + Cost", "type": "main", "index": 0 }]] },
    "Codex CLI": { "main": [[{ "node": "Telemetry + Evidence + Cost", "type": "main", "index": 0 }]] },
    "Telemetry + Evidence + Cost": { "main": [[{ "node": "Unified Output", "type": "main", "index": 0 }]] }
  }
}
```

**Reading the diagram**: Left to right. An operator task enters the classifier, which emits a domain label. The selector maps the label to a sub-harness configuration (deterministic lookup). Shared context — scope, RoE, engagement memory handle — is loaded once and passed by reference. The local proxy is the only endpoint any sub-harness can reach; the security primitive layer runs there, intercepting every tool call. CAI, Claude Code, and Codex CLI execute through the proxy, unaware that scope was checked, evidence was logged, or triage ran. All sub-harness output — findings, evidence records, token consumption — aggregates into one ledger per engagement, producing one unified output. The sub-harnesses are not under your control; the proxy is the wrap.

---

## Diagram 2 — The Routing State Machine

**Type**: Mermaid (stateDiagram)
**Purpose**: The task-classification-and-routing logic as a state machine. Shows the classifier's decision points, the TriageAgent fallback when uncertain, and the deterministic selector that maps a domain label to a sub-harness.

```mermaid
stateDiagram-v2
    [*] --> TaskIn: operator task
    TaskIn --> Classify: read description + artifacts
    Classify --> Confident: domain label + score > threshold
    Classify --> Uncertain: score below threshold
    Uncertain --> TriageAgent: run cheap probes
    TriageAgent --> Classify: re-route with added signal
    Confident --> Select: deterministic lookup
    Select --> CAI: bug_bounty / pentest / ctf
    Select --> ClaudeCode: code_review / exploit_dev
    Select --> CodexCLI: sdlc / refactor / build
    CAI --> Executing: via proxy
    ClaudeCode --> Executing: via proxy
    CodexCLI --> Executing: via proxy
    Executing --> BudgetCheck: per-turn cost accounting
    BudgetCheck --> Executing: budget remains
    BudgetCheck --> Halt: budget exhausted
    Halt --> [*]: surface to operator
    Executing --> [*]: engagement complete

    note right of Select
        Selection is a LOOKUP TABLE,
        not a model call. Once classified,
        the mapping is deterministic.
    end note
    note right of Uncertain
        The classifier is allowed to be
        uncertain. The TriageAgent is not.
    end note
```

**Reading the diagram**: A task enters, the classifier reads it and emits a domain label with a confidence score. Above threshold, the selector maps the label to a sub-harness deterministically — no second model call. Below threshold, the TriageAgent runs cheap probes (target type, scope, attached artifacts) and re-routes with the added signal. The selected sub-harness executes through the proxy, with per-turn cost accounting. If the engagement budget is exhausted, the meta-harness halts and surfaces to the operator; otherwise it runs to completion. The classifier is allowed to be uncertain; the TriageAgent and the selector are not.

---

## Diagram 3 — The Security Primitive Layer (middleware wrapping a sub-harness)

**Type**: Mermaid (flowchart)
**Purpose**: The five primitives applied at the proxy boundary. Shows a sub-harness's tool call passing through scope enforcement, RoE enforcement, kill chain gating, execution, evidence collection, signal/noise filtering, and cost accounting — without the sub-harness's code being modified.

```mermaid
flowchart TD
    SUB["Sub-harness emits tool call<br/>(CAI / Claude Code / Codex CLI)"]
    SCOPE{"1. Scope check<br/>target::action in scope.json?"}
    ROE{"2. RoE check<br/>action prohibited?<br/>rate limit OK?"}
    KILL{"3. Kill chain<br/>action permitted in<br/>current phase?"}
    EXEC["4. Execute<br/>via sub-harness executor"]
    EVID["5. Evidence collection<br/>hash-chained, scope_ref stamped"]
    TRIAGE["6. Signal/noise filter<br/>triage finding if present"]
    COST["7. Cost accounting<br/>tokens + compute to ledger"]
    RESULT["Structured result<br/>back to sub-harness"]

    BLOCKED["BLOCKED<br/>scope_ref stamped, logged"]

    SUB --> SCOPE
    SCOPE -->|"no"| BLOCKED
    SCOPE -->|"yes"| ROE
    ROE -->|"prohibited / over limit"| BLOCKED
    ROE -->|"ok"| KILL
    KILL -->|"not permitted"| BLOCKED
    KILL -->|"permitted"| EXEC
    EXEC --> EVID --> TRIAGE --> COST --> RESULT

    style SCOPE fill:#14141f,stroke:#5eead4,color:#5eead4
    style ROE fill:#14141f,stroke:#5eead4,color:#5eead4
    style KILL fill:#14141f,stroke:#5eead4,color:#5eead4
    style EVID fill:#0d1b2a,stroke:#1b4f72,color:#e4e4e8
    style TRIAGE fill:#0d1b2a,stroke:#1b4f72,color:#e4e4e8
    style EXEC fill:#2a1810,stroke:#a04000,color:#f0a868
    style BLOCKED fill:#2a0d0d,stroke:#a00000,color:#f08080
    style RESULT fill:#0d2818,stroke:#1e8449,color:#82e0aa
```

**Reading the diagram**: A sub-harness emits a tool call. The middleware intercepts it before execution. Three gates run first: scope (is the target::action in scope?), RoE (is the action prohibited, or would it exceed the rate cap?), kill chain (is the action permitted in the current phase — e.g., post-exploit actions need confirmation even in CTF). Any gate failing blocks the call, stamps a scope_ref, and logs the block. If all gates pass, the call executes via the sub-harness's own executor. The result is then evidence-logged (hash-chained, scope_ref stamped), triaged if it contains a finding, and cost-accounted. The sub-harness sees only the structured result — it has no idea the primitives ran. This is what makes the layer robust to sub-harness updates: the primitives are not in the sub-harness's code path.

---

## Diagram 4 — Cross-Harness Evidence Aggregation (one log, many sub-harnesses)

**Type**: Mermaid (flowchart)
**Purpose**: Why the evidence log must be meta-harness-owned. Shows findings from three sub-harnesses landing in one append-only, hash-chained log with one schema, versus the anti-pattern of three separate logs.

```mermaid
flowchart LR
    subgraph correct [Correct: one log, owned by meta-harness]
        direction TB
        CAI1["CAI finding<br/>(nmap + nuclei)"]
        CC1["Claude Code finding<br/>(code review)"]
        CX1["Codex CLI finding<br/>(static analysis)"]
        PROXY1["Local proxy<br/>writes evidence record<br/>transparently"]
        LOG1["ONE evidence log<br/>append-only, hash-chained<br/>one schema, one engagement_id"]
        CAI1 --> PROXY1
        CC1 --> PROXY1
        CX1 --> PROXY1
        PROXY1 --> LOG1
    end

    subgraph wrong [Anti-pattern: three logs, three schemas]
        direction TB
        CAI2["CAI finding"]
        CC2["Claude Code finding"]
        CX2["Codex CLI finding"]
        LOGC["CAI log<br/>(CAI schema)"]
        LOGCL["Claude Code log<br/>(no schema)"]
        LOGX["Codex CLI log<br/>(none — coding tool)"]
        CAI2 --> LOGC
        CC2 --> LOGCL
        CX2 -.->|"no evidence captured"| LOGX
        RECONCILE["Operator reconciles<br/>three logs, three hash chains<br/>useless for legal defense"]
        LOGC --> RECONCILE
        LOGCL --> RECONCILE
        LOGX --> RECONCILE
    end

    style PROXY1 fill:#14141f,stroke:#5eead4,color:#5eead4
    style LOG1 fill:#0d1b2a,stroke:#1b4f72,color:#e4e4e8
    style RECONCILE fill:#2a0d0d,stroke:#a00000,color:#f08080
    style LOGX fill:#2a0d0d,stroke:#a00000,color:#f08080
```

**Reading the diagram**: On the left, the correct architecture. Findings from CAI, Claude Code, and Codex CLI all pass through the local proxy, which writes each evidence record transparently — the sub-harnesses do not opt in. One log, one schema, one engagement_id, one hash chain. A client query ("how was this finding obtained?") is a single lookup. On the right, the anti-pattern. Each sub-harness writes (or does not write) its own evidence in its own schema. CAI has a log; Claude Code has a different one; Codex CLI, a coding tool, has none. Reconciling three logs with three hash chains into a defensible legal record is impossible. The cure is the proxy-owned single log on the left.

---

## Diagram 5 — The Benchmarking Pipeline (InjecAgent gate, then the six metrics)

**Type**: Mermaid (flowchart)
**Purpose**: The S05.3 benchmarking discipline. Shows InjecAgent as a pass/fail gate that runs first, then the six metrics measured against a repeatable lab, producing a scored report compared to baselines.

```mermaid
flowchart TD
    GATE["InjecAgent pass/fail gate<br/>(runs FIRST, no exceptions)"]
    PASS{"Harness refused every<br/>injected action?"}
    FIX["FIX injection resistance<br/>before benchmarking anything else"]
    LAB["Repeatable benchmark lab<br/>isolated targets, seeded vulns,<br/>fixed compute envelope"]
    M1["Detection rate<br/>(of seeded, how many found)"]
    M2["Exploit success rate<br/>(of detected, how many exploitably shown)"]
    M3["False positive rate<br/>(of surfaced, how many not real)"]
    M4["Evidence completeness<br/>(of findings, chain complete?)"]
    M5["Time-to-first-finding<br/>(wall-clock)"]
    M6["Cost per finding<br/>(dollars / confirmed findings)"]
    BASELINE["Compare against baselines<br/>CAI CTF · EVMbench · RedTeamLLM"]
    REPORT["Scored report<br/>six metrics + InjecAgent pass<br/>vs previous run + published baselines"]

    GATE --> PASS
    PASS -->|"yes"| LAB
    PASS -->|"no — single injected command executed"| FIX
    FIX --> GATE
    LAB --> M1 & M2 & M3 & M4 & M5 & M6
    M1 & M2 & M3 & M4 & M5 & M6 --> BASELINE --> REPORT

    style GATE fill:#14141f,stroke:#5eead4,color:#5eead4
    style PASS fill:#0d2818,stroke:#1e8449,color:#82e0aa
    style FIX fill:#2a0d0d,stroke:#a00000,color:#f08080
    style LAB fill:#0d1b2a,stroke:#1b4f72,color:#e4e4e8
    style REPORT fill:#0d2818,stroke:#1e8449,color:#82e0aa
```

**Reading the diagram**: Benchmarking begins with the InjecAgent gate — a pass/fail test, not a performance metric. The harness must refuse every injected action in the suite. A single execution of an injected command is a fail, regardless of how the harness scores on the six metrics, because the failure mode (executing attacker-controlled actions from target output) is catastrophic. Once the gate is passed, the repeatable lab runs: isolated Docker targets with seeded vulnerabilities, a fixed compute envelope (same model, same token budget, same wall-clock), and a consistent scoring script. The six metrics — detection rate, exploit success rate, false positive rate, evidence completeness, time-to-first-finding, cost per finding — are computed and compared against the previous run and published baselines (CAI CTF, EVMbench, RedTeamLLM). The output is a scored report you can publish.