{% extends "base.html" %} {% block title %}Glean — guide{% endblock %} {% block content %}

Guide

How to run a scan, read what comes back, and know what the numbers do and don't claim.

Running a scan

The form is four decisions, in order.

What to scan
A bare domain — example.com, not a URL and not an IP. Enter several (one per line, or comma-separated) and each gets its own independent scan; one failing never affects the others.
How to collect
Which tools run. Presets are shortcuts that tick boxes for you — changing a box afterwards is expected, and the preset simply stops being highlighted. {% for name, ids in presets.items() %}{{ name }}{% if not loop.last %}, {% endif %}{% endfor %} are the starting points.
Authorisation
Why you are permitted to scan this target. It is recorded in the brief and kept with the scan. Nothing validates it — it is a record you are keeping for yourself, not a gate.
Output
Optional narration by a local LLM. It changes only how the brief reads: the findings, their ranking and their provenance are byte-for-byte identical either way.

Scans run two at a time; the rest queue. A queued scan can be cancelled before it starts, and cancelling a running one stops its tools rather than just abandoning them.

Passive vs active

This is the distinction the tool is built around, and the only one it enforces in code.

Passive collection asks third parties what they already know — certificate transparency logs, public DNS, search aggregators. The target never sees you.
Active collection sends real requests to the target's own infrastructure. It appears in their logs. It requires a separate, explicit opt-in every time, and is never implied by any default or convenience path.
{% for tool_id, info in tools.items() %} {% endfor %}
ToolMethod
{{ info.display_name }} {{ info.default_method }}

Only scan what you own or have written permission to assess. That constraint is yours to honour — the tool records your stated basis but cannot check it.

Reading a brief

Every scan produces one page, split in two. Top priorities is the highest-ranked {{ top_n }} findings, each with a sentence on what it is, why it ranked there, and which tools saw it. Also found is everything else — sortable, filterable and searchable, because on a large target it runs to hundreds of rows.

The split is by score, not importance-in-general: a finding lands in the tail because nothing about it scored, which is not the same as it being irrelevant to you. The filters exist so you can go looking.

How ranking works

Ranking is computed in code, never by a model. Each finding accumulates points from signals that either did or did not fire; the total is its priority. Hovering a score in a brief shows exactly which signals produced it.

That is the whole rubric, below — there is no hidden component, and the same input always produces the same ranking.

{% for s in signals %} {% endfor %}
SignalWeightMeans
{{ s.name }} {{ "%+d" | format(s.weight) }} {{ s.phrase }}

Negative weights are deprioritisers — a renewed certificate or a host that stopped resolving is recorded, but pushed down rather than dropped.

Checking a finding

Every finding names the tools that reported it under Seen by. Those are links: following one opens the exact record in that tool's archived output that produced the finding — not the whole file, the line.

That is the point of the tool. If a finding looks wrong, you can see what it was derived from without re-running anything.

Triage
Mark a finding Reviewed, Flagged or False positive. It is stored per finding and survives re-scanning — the one thing in a scan that re-running cannot regenerate, because everything else is derived from tool output and this is your judgement.
Relationships
How findings connect — which host resolves to which IP, what a certificate covers. This is the correlation stage's own output, which is otherwise only visible as phrasing inside finding text.
Export
JSON and CSV for feeding onward, or the self-contained HTML file, which needs no server and opens anywhere.

Comparing scans

Any scan with an earlier run of the same target offers Compare to previous scan: what is new, what disappeared, and what changed score or signals since last time. Findings are matched by identity, not position, so a host that moved rank is not reported as a new discovery.

What the numbers claim

glean eval reports faithfulness, provenance retention and prioritisation quality. Two of those need reading carefully.

stage-1 faithfulness only half-fails. Its entity-existence check can't: invented entities are filtered out before a brief is ever built, so that half reads 1.000 by construction. A second, structural check can fail — prose asserting what the graph settles on its own, like a wildcard entry narrated as resolving when nothing records it resolving. On the ten-target evaluation set that catches two real fabrications the stage-2 judge accepts.

Content-level fabrication — a real entity described with a false claim — is measured only by stage 2, which needs --llm and uses a second model as a judge. That judge makes real mistakes of its own, so its score is a lower bound rather than an exact figure. A real narrated brief has scored 1.000 on stage 1 and 0.455 on stage 2 for the same text.

How loose a lower bound is measured, not guessed. Scored against 90 claims labelled by hand, the judge flagged 28 as unsupported where a person found 9 — it catches most real problems (recall 0.778) but over-flags roughly three to one, so about three quarters of what pulls stage 2 down is judge error rather than fabrication. The mistake runs in the safe direction: the number never makes the prose look better than it is.

Three later audits moved that a long way, ending at flag precision 0.800. Each swing traced to how the evidence was presented or what got scored, never to the judge's reasoning — the last fix simply stopped counting "claims" the judge had copied out of its own evidence rather than read from the brief. The safe direction holds throughout, so read stage 2 as a floor rather than a figure, and check ADR-0006 for which audit a given number came from.

Both limits are stated in the tool's own output rather than left to documentation, because the numbers are what gets pasted into a report.

{% endblock %}