Skip to content
TestLookupTestLookup
Search Ctrl K

Search TestLookup

Enter a term to search the local static index.

    Review and distribution policy

    TestLookup can write AI reports about your test runs. Three things are controlled separately: generating a report, a person’s review of it, and sending it outside TestLookup. Choose the enforcement mode with care, and keep the review state with the report wherever it goes.

    By default, REVIEW_GATE_ENFORCED is false and no enforcement date is set. In this mode the review gate only audits, and nothing is held back. TestLookup still sends each AI report it would have refused, and records the attempt in the audit log as ai_report.distribution_would_refuse. So in this mode, a report that was sent out is not necessarily an accepted one.

    An administrator can set an enforcement date for the whole installation under Settings › AI › Review gate. Until that date, the gate only audits. The page counts what it would have held back in the last 30 days.

    The page shows one of four states:

    • “Audit only — nothing is withheld.” No date is set (unset).
    • “Audit only until [date] — then unreviewed AI reports are withheld.” A future date is set (scheduled).
    • “Enforced since [date]: unreviewed AI reports are withheld on the channels below.” The date has passed (date).
    • “Enforced by the server setting REVIEW_GATE_ENFORCED — the date below does not apply while it is on.” (env)

    Any administrator credential can read the page, including an administrator’s API key. If TestLookup cannot read the audit log, the count reads “Not measured” instead of 0.

    Enforcement is on in either of two cases:

    • the server setting REVIEW_GATE_ENFORCED=true is set, which overrides the date;
    • the saved date has passed. A date in the past turns enforcement on at once.

    Only an administrator signed in to the web app can change the date. Other servers see the change within about 30 seconds.

    While enforcement is on, TestLookup sends accepted reports, and output that is not AI-generated, as the policy allows. Every delivery or replay checks the current policy again. So an earlier successful delivery does not give lasting permission.

    The Review gate page lists the 13 channels under which TestLookup records a sharing decision:

    • PDF export of a run report.
    • Shared report link (web page).
    • Shared report link (PDF).
    • Run intelligence export (JSON).
    • AI history export (JSON).
    • Window analysis report download.
    • Analysis report attached to digests.
    • Run report e-mail.
    • AI summary e-mail and event-driven digests.
    • AI summary in notification relays.
    • AI failure-kind labels in GitHub pull-request comments.
    • AI failure-kind labels in GitLab merge-request notes.
    • release.decided webhooks.

    While enforcement is on and a report is unreviewed, TestLookup also changes two values to PENDING_REVIEW:

    • the release-readiness answer that your CI system reads;
    • the release decision quoted in reports.

    A held-back share link answers HTTP 409, and a browser shows a “Report awaiting review” page.

    An accepted report is one that a person has reviewed and accepted.

    A project-level permission to share drafts exists, but no screen or API can turn it on. So while enforcement is on, there is only one way to share an unreviewed AI report: a run PDF that a QA lead or administrator exports with include_unreviewed=true. The PDF carries the watermark DRAFT - AI-generated, not human-reviewed, and the export is recorded in the audit log.

    That route checks the person’s role (QA lead or administrator) and their access to the run. It does not check how they signed in, so their API key works too. Of all the review-gate controls, only changing the enforcement date needs a person signed in to the web app.

    While enforcement is on, a rejected report, or one replaced by a newer report, cannot use the draft exception. Generate or review a new report instead. Replaying an old message does not get around the current review state.

    When you look into why a report was or was not shared, look at all of these together:

    • the report and its review state;
    • the person or API key that asked for it;
    • the policy result and any draft exception;
    • the destination and the delivery attempt.

    The audit log records three different outcomes:

    • ai_report.distribution_would_refuse: a report TestLookup would have held back, in audit-only mode;
    • ai_report.distribution_refused: a report held back while enforcement is on;
    • ai_report.distributed_unreviewed: a draft sent through the exception.

    HTTP responses can carry the X-TestLookup-AI-Generated and X-TestLookup-Review-State headers. You may pass a report on through downloads, search results, notifications, MCP output for AI assistants, or another integration. If you do, keep its review state with it, so that nobody mistakes a draft or a rejected report for an accepted one.

    A report goes through these steps:

    1. TestLookup gathers the stored evidence for the run or project.
    2. It writes or assembles the report.
    3. It checks the report’s structure, and a separate rule-based checker reviews the report before it goes further.
    4. It opens a review request for a person.
    5. The report ends up accepted by a person, pending review, or rejected or replaced by a newer one.
    6. The distribution policy decides what may leave TestLookup.
    7. The report goes out as a download, a share link, a notification or a result for your CI system.

    The sections above describe the two modes, the draft exception and the headers. The code is in the distribution policy.

    Share links have their own token, access and expiry rules, and they still follow the report policy. A compliance pack, a signed bundle of evidence for auditors, is an export. Generating one is not a legal compliance certification.

    Export generation can fail separately from analysis, and delivery can fail separately from generation. Long exports run in the background. Check each of these on its own: storage, errors from the file renderer, whether the report exists, review refusals, the policy for the destination, and the retry and dead-letter records. Replaying an old webhook does not get around review, because every delivery checks the current policy again.

    To compare review states and release decisions with made-up data, explore the review and release walkthrough.