Guide 055 decision guide

How to choose between PR scans and scheduled assessments

Choose PR, scheduled and event-driven security assessments by their decision purpose, with revision-aware handling of overlapping results and missed runs.

Use a PR scan when the result can change the decision to merge a particular revision and can finish inside the team's review window. Use a scheduled assessment to revisit the default branch, broader code paths and risks that change even when nobody edits the affected file. Add a targeted, on-demand assessment when an urgent advisory or sensitive change cannot wait for the schedule. Most teams need all three triggers, with different scopes and decisions. A clean PR scan does not substitute for a whole-application review; a weekly assessment does not protect a PR that merges on Tuesday. The choice changes with the tool's analysis model, repository size, release cadence and the consequence of missing a particular path.

GitHub's CodeQL workflow documentation describes PR, push and scheduled scanning for different reasons: change-time feedback and discovery of newly known issues in code that may not be actively maintained. This is a useful model even if your team runs another scanner. Define the reader's decision first, then configure its trigger.

Choose by the question, not the tool name

Question to answer Best initial trigger Output and limit
“Does this PR introduce a prohibited issue?” PR at the exact head revision. Timely merge evidence for the configured scope; may miss a flaw whose alert is outside the diff.
“What is wrong in the code we already ship?” Default-branch or scheduled broad assessment. Backlog and risk review for an immutable revision; not a pre-merge verdict for later changes.
“Did a new advisory make an unchanged component risky?” Scheduled plus urgent on-demand when warranted. Updated affected-component review; schedule alone may be too slow.
“Did this patch actually remove a known harmful path?” Targeted reassessment at the new revision, with related paths. Fixed, still present or inconclusive based on evidence; a missing alert alone is insufficient.
“Does a cross-service authorization rule hold?” Broader assessment and, for relevant PRs, a human or targeted review. Trace caller, middleware, service and data access; a diff-only view can be incomplete.

Do not read the “best initial trigger” column as a promise that a tool will catch the issue. GitHub's code scanning alert documentation says a PR alert appears only when all lines associated with it are in the diff. A scheduled scan may see older code that the PR view will not surface. Conversely, a scheduled result from last night cannot decide a PR pushed this morning.

Follow the artifacts through a week

Constructed trigger exercise: Mosaic Ledger has an API and a reporting worker. Its local policy schedules a broad default-branch assessment every Sunday and requests targeted review for consequential new advisories. The revisions and results below are supplied case facts, not actual scans.

Event What the assessment establishes What remains outside it
Monday: authorization PR head A11 Quick analysis and targeted review of the helper and named callers at A11 Unchanged worker dependency applicability and later releases
Wednesday: new parser advisory On-demand review Q1 identifies affected package in deployed worker image W20 and traces relevant input A future worker image cannot inherit this version result
Friday: release W21 Package receipt shows the selected parser version outside that advisory range; wrapper reassessment completed for stated paths Whole API/worker broad assessment has not run
Sunday: scheduled run missing No result; freshness check alerts the assessment owner No Sunday coverage may be claimed
Monday: recovery run Q2 at default-branch commit M24 Broad declared source scope at M24, with exclusions recorded M24 is not automatically the deployed release W21

Wednesday's advisory does not wait for Sunday, because its consequence and input path warrant an earlier decision. Q1 produces owned worker work, not an automatic failure of the unrelated API PR. Friday's receipt resolves the original package-range question for W21; it does not retrospectively assess the API or complete the missed broad run.

On Monday, the release manifest maps W21 to source M22. Default-branch recovery Q2 examined M24, which includes later changes. The owner therefore requests a targeted comparison of the deployed worker's relevant paths at M22 and maps Q2's consequential findings to that artifact. The output records both revisions. Re-running “latest” alone would recover discovery activity while leaving the deployed-version question unanswered.

Write the trigger contract that exposes a missing run

Mosaic uses the following local contract. Its times are illustrative operational commitments, not provider guarantees:

Lane Scope and revision Freshness/decision Failure action and owner
PR Exact candidate and relevant caller/control dependencies; record actual analyzed SHA Before that candidate's merge decision Platform reports failure; designated reviewer holds or applies authorized fallback under merge policy
Sunday broad Default-branch commit, API and worker; intended versus examined components Completion expected by Monday 09:00 UTC AppSec notices absence at deadline, assigns recovery and marks gap; Platform investigates execution failure
Advisory event Affected deployed artifacts, package identity/range and relevant application path AppSec sets a decision date from consequence and exposure Service owner supplies missing artifact; credible urgent exposure uses response procedure
Fix reassessment New artifact/configuration plus original unsafe and permitted behaviors Before closure, and before restoration when required Reviewer records still present or inconclusive instead of silently advancing status

For GitHub Actions, scheduled workflows run on the default branch and can be delayed or dropped under load. A scheduler entry is therefore not a completion receipt. Monitor successful completion and scope, not only whether a cron expression exists. The freshness check must be able to notice that no run started—for example, a separate service queries the last successful assessment receipt and alerts its owner after the deadline. A final step inside the missing workflow cannot detect that workflow's absence. The recovery record says “Monday assessment of M24 after missed Sunday run”; it does not backdate the result.

Diagnose the broad finding before changing the PR lane

Suppose Q2 reports a cross-account read in an unchanged worker helper. The lead asks why the PR lane did not surface it. Three histories lead to different repairs:

History established from records Correction justified by that history
The earlier PR changed a customer message producer, but its configured analysis excluded the consuming worker Add the producer-to-worker authority boundary to sensitive-change review; reassess relevant releases
The relevant detector or advisory did not exist when the PR was reviewed, and the prior scope completed as declared Route the newly known issue; retain scheduled/event-driven reassessment rather than calling the old run a failure
The required PR scan timed out, but an aggregator emitted success Repair fail/inconclusive handling and inspect other affected decisions; rerun or review the missing scope

In Mosaic's supplied history, the first case applies: the producer changed, but the worker consumer was omitted. Policy version 2 therefore treats changes to the message's account authority as a cross-service review trigger. It does not require an expensive whole-repository assessment for every documentation edit. The broad finding still needs ordinary verification; discovering a scope weakness does not independently prove the scanner claim.

The finished weekly record has three separate statements: W21 is outside the named parser advisory range with its integration checks recorded; M24 received the recovered broad source assessment; the deployed producer/worker authority path needs its newly assigned review. They answer different questions, so none should replace the others with a single green badge.

When one lane cannot provide a reliable answer

If the PR lane regularly misses cross-service behavior, add a targeted control-path review for sensitive changes or expand its analysis. If that makes every PR wait too long, reserve the most expensive broad work for the schedule while keeping a visible merge decision for the risky subset. The CI performance guide shows how to measure that tradeoff without erasing coverage.

If the broad assessment returns many unresolved candidates, do not turn its raw count into a release ban or an approved vulnerability count. Verify the claims and route actual work. If the schedule misses a run, rerun against a named revision or record the gap; do not backdate coverage. If a developer fixes a finding, reassess the original actor-to-effect path on the new revision. A code move, vanished alert or changed line number is not positive fix evidence.

Resolve overlapping runs without letting the newest timestamp win

Suppose Mosaic's scheduled assessment completes after the PR check, but it examined an older revision. Its later completion time does not give it authority over the newer candidate. Keep the analyzed revision, configured scope and completion time as separate fields. Route a result to the code and deployment it actually describes before deciding whether it changes the current release decision.

Consider three constructed overlaps:

Overlap Interpretation Next action
A scheduled run reports an old worker path omitted from the quick lane Possible coverage gap in the PR policy and a candidate issue in the worker Assess the worker claim; separately decide whether future worker changes should trigger a different check
A PR run reports a path that the previous scheduled run did not report Different revisions or analysis scope may explain the difference Compare the decisive path and detector configuration before calling either result a contradiction
A reassessment finds the repaired path correct while an old queued run later repeats the original signal The older result may remain valid history for its own revision Preserve it without reopening the repaired revision automatically; confirm no old deployment still needs work

These outcomes require a stable issue record, not one ticket for every job completion. Link each observation with its own revision and limits. The issue owner can then distinguish new evidence, repeated historical evidence and a new affected consumer. Deduplication must not erase a real deployment still running the older code.

Give the scheduled lane an operating contract

Deferring work from a PR creates an obligation. State when the broader assessment is expected, which repositories or service relationships it covers, who notices if it does not complete and who accepts its output. A calendar entry without an accepted result owner merely moves uncertainty out of the merge screen.

For Mosaic, the operating contract could require a weekly worker-and-API assessment and an event-driven review when the shared account contract changes. These are example local choices, not universal intervals. The owner checks the last successfully completed assessment against the expected coverage. A failed attempt does not renew that evidence. If the task repeatedly overruns, the manager changes capacity, scope or scheduling explicitly and records the period of reduced coverage.

A broader assessment also needs a stopping condition. Define a bounded set of service relationships or questions for the run, retain unexplored scope, and route useful findings while further work continues. Waiting for an unbounded “complete review” can delay an already supported repair just as an overgrown PR check can delay a release.

Review lane placement when the work changes. A new shared dependency, generated route or external integration may make the old PR trigger insufficient. Conversely, a long assessment that repeatedly examines unchanged low-impact material may be a candidate for a narrower event trigger. Decide from the evidence and service context, then keep a record of what the revised schedule no longer covers.

The next step is to fill the trigger map for one repository: each trigger, revision, scope, owner, decision and failure action. Review a recent missed issue against it. Then use the PR security-check guide to turn the merge lane into a rule that developers can predict.