Skip to content

refactor: align gaze crap threshold model with gaze report (*int + Flags.Changed) #150

Description

@yvonnedevlinrh

Summary

gaze crap and gaze report use different threshold models for
--max-gaze-crapload, producing different exit codes for the same
unavailable-data condition:

  • gaze report (EvaluateThresholds): *int thresholds +
    cmd.Flags().Changed(). When the threshold is set but GazeCRAPload is
    nil, it fails with "GazeCRAPload (unavailable)".
  • gaze crap (checkCIThresholds): plain int thresholds with
    0 = disabled. When GazeCRAPload is nil, it silently skips the check.

Reproduction

# gaze report: threshold set, GazeCRAP unavailable - FAIL
$ gaze report --format=json --max-gaze-crapload=5 . 2>&1 | grep GazeCRAPload
GazeCRAPload (unavailable): N/A/5 (FAIL)

# gaze crap: threshold set, GazeCRAP unavailable - silently skipped
$ gaze crap --max-gaze-crapload=5 . 2>&1 | grep -i gaze
note: GazeCRAP unavailable - run 'gaze quality' to compute contract coverage
$ echo $?
0

Expected vs Actual

  • Expected: Both commands should produce the same pass/fail result for the
    same threshold flag and the same unavailable-data condition.
  • Actual: gaze report fails the gate; gaze crap silently skips it.

Root cause

checkCIThresholds in cmd/gaze/main.go uses plain int flags with
0 = no limit semantics. The nil-check at line 689 skips the comparison
when GazeCRAPload is nil, but does not fail the gate:

if maxGazeCrapload > 0 && rpt.Summary.GazeCRAPload != nil &&
    *rpt.Summary.GazeCRAPload > maxGazeCrapload {

This also means --max-crapload=0 is treated as "disabled" rather than
"fail if any function exceeds 0" - a second divergence from
gaze report's *int model where zero is a live threshold.

Origin

The ci-gate-integrity design document (PR #148,
openspec/changes/ci-gate-integrity/design.md) lists alignment as a
goal but explicitly defers the refactoring as a non-goal:

Aligning gaze crap's int-based threshold model with gaze report's
*int + cmd.Flags().Changed() model - that's a separate refactoring
task.

The code comment at cmd/gaze/main.go:686-691 also documents the
divergence.

Suggested fix

Refactor gaze crap threshold handling to use *int flags and
cmd.Flags().Changed() for all threshold checks (not just the zero-result
gate added in #148). Unify checkCIThresholds with EvaluateThresholds
or replace it entirely so both commands share the same threshold semantics.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions