GCA · CORE CONCEPTS

    Execution Layers

    Gadriel Code runs at four points in the development lifecycle — each layer explained.

    Execution Layers

    Gadriel Code runs at four points in the development lifecycle. Each layer is a trigger with its own output shape and blocking behavior. The layers are canonical and named verbatim throughout the product.

    A guiding principle underlies all four: quality over latency. Latency is explicitly not a priority. A full CI scan is allowed to take minutes (and, on large repos, longer) if that buys thorough analysis — deeper graph algorithms, full-repo reachability, attack simulation, git-history secret sweeps. The one hard constraint is that the earliest layer (Watch) must never block the developer's editor.


    The four layers

    L1 — Watch

    TriggerFile save (filesystem notify event)
    Commandgadriel code watch
    PostureAsynchronous, non-blocking
    OutputFindings streamed to the terminal as they arrive; dashboard refresh
    Blocks?Never

    Watch mode observes the working tree and re-scans changed files on save. It is strictly non-blocking: the watcher captures the save event, queues the work, and returns immediately so keystrokes are never delayed. Results surface in the terminal (or the dashboard) whenever they are ready — seconds for fast cases, longer for cross-file flows.

    As shipped today, Watch is L1-lite: a 300 ms-debounced watcher that runs Secrets + SAST per changed file and merges results into .security/findings.json. It skips .git/, node_modules/, target/, and .security/. The full async pipeline (all scanners, graph integration, daemon coordination) is future work. --fail-on is ignored at L1 — Watch never gates.

    L2 — Pre-Commit

    Triggergit commit
    Commandgadriel code scan --staged (invoked from the git hook)
    PostureSynchronous to the commit; allowed to take minutes
    OutputTerminal findings
    Blocks?Yes — blocks the commit when --fail-on matches

    Installed by gadriel code init / gadriel code install, the pre-commit hook scans staged changes. Installation is non-destructive: an existing .git/hooks/pre-commit is not overwritten — Gadriel appends its call between named markers (# >>> gadriel-code-security >>>), and recognized hook managers (husky, lefthook, pre-commit-rs) get a manager-native entry instead. Re-runs are idempotent, and --uninstall removes only the marked section. If any finding meets the --fail-on threshold (default high at L2), the commit is blocked.

    L3 — Pull Request

    TriggerPR open or branch push
    Commandgadriel code scan --diff <base>
    PostureSynchronous to the PR check; minutes are fine
    OutputA structured PR comment
    Blocks?Via the CI check (posts a BLOCKING banner; job exits 2)

    At the PR layer Gadriel posts a single structured comment — an overall score, a per-pillar table, finding counts by scan type, and graph statistics, with the top critical findings in a collapsible section. Rules governing the comment:

    • One comment per branch, edited in place — pushes replace the comment, so the PR does not accumulate a wall of stale scan results.
    • Resolved findings are struck through, not deleted — reviewers can see a finding existed and was fixed.
    • Secret values are never included — matches are shown as e.g. ANTHROPIC_API_KEY, never the value.

    L3 runs on a clean CI checkout with full git history available, so the git-history secret sweep is enabled here. Its default --fail-on threshold is critical. GitHub is fully supported; GitLab/Bitbucket get a degraded "new comment per push" experience until their adapters ship.

    L4 — CI/CD

    TriggerMerge to main / full-repo scan
    Commandgadriel code scan --ci (= --report --sbom --fail-on critical)
    PostureWhatever it takes (default budget 60 min, configurable)
    OutputThe full artifact set
    Blocks?Sets the CI exit code per the contract below

    L4 is self-contained: CI runners have no graph daemon, so it builds the codebase graph from scratch, runs all six scan types, sweeps the full git history for secrets, and produces the complete .security/ artifact set — findings.json (OCSF), pillar scores, SBOMs (SPDX 2.3 + CycloneDX 1.4), the branded PDF/Markdown report, and dashboard/metrics data. It also writes a deduplicated history snapshot for trend analysis. This is the layer where a scan legitimately takes minutes and where thoroughness matters most.


    The --layer selector

    The active layer determines defaults (which scanners/algorithms run, whether git-history is swept, what output is produced, and the default --fail-on threshold). In practice each layer is entered through its natural command surface:

    • L1gadriel code watch
    • L2 — the installed pre-commit hook (gadriel code scan --staged)
    • L3gadriel code scan --diff <base> in PR CI
    • L4gadriel code scan --ci on merge

    gadriel code install writes turnkey templates for L2 (git hooks) and L4 (GitHub Actions, GitLab CI, CircleCI, Jenkins), each tagged with a GADRIEL_MANAGED sentinel so re-runs are idempotent and --uninstall removes only Gadriel-authored files.


    Exit codes

    gadriel code scan communicates its verdict through the process exit code. Writing the .security/ artifacts always succeeds; the exit code is the gate signal.

    CodeMeaningFires when
    0Clean / gate passedAll findings are below the --fail-on threshold.
    1Gate tripped (warning-class)Findings below threshold but at least one warning signal — e.g. a finding above the previous severity tier, drift-degrading components, or dependency-health flags.
    2Failure / tooling errorA finding meets or exceeds --fail-on, or the scan could not complete (timeout, malformed input, OSV snapshot stale beyond threshold).
    7License gateA license-policy violation (SCA license finding) trips the dedicated license exit code.

    Layer behavior:

    • L1 always exits 0 — it never gates.
    • L2 exits 0 or 2 only — the commit either proceeds or it doesn't; no warning-class on commit.
    • L3 and L4 honor the full 0 / 1 / 2 contract. At L3 the CI job exits 2 when the PR comment carries the BLOCKING banner.

    --fail-on <severity>

    --fail-on <severity> means "gate the layer if any finding is at or above this severity." Thresholds follow the score bands info (0–3.99), low (4–5.99), medium (6–7.99), high (8–8.99), critical (≥9.0). Defaults are high for L2 and critical for L3/L4. --fail-on never runs the scan but never gates — useful for soak-testing a new policy bundle. Defaults are written into a version-controlled .gadriel.toml by gadriel code init, with per-user overrides in ~/.gadriel/config.toml.


    Why quality over latency

    Earlier drafts imposed strict per-layer latency budgets (sub-2s at Watch, sub-15s at Pre-Commit). Those were dropped. A developer waiting a few minutes for a thorough result is an acceptable trade; a developer blocked in their editor is not. That is why L1 is asynchronous and non-blocking while L2–L4 are allowed to run as long as the analysis needs. Operators can extend the L4 budget (default 3600s; 0 disables the cap); an overrun surfaces an Operational-pillar finding (CODE-W4-OPS-LATENCY-001) rather than silently failing.