Skip to content

verify-no-work-records: exit 2 when it cannot run, add --self-test, print counts when green #90

Description

@woksin

Summary

Give verify-no-work-records (and every future governance checker in this repository) a distinct "could not run" exit code (2), a --self-test that plants one defect per rule, and a green result that prints how much it checked. Today a listing failure reports clean.

Current behaviour

.github/workflows/verify-no-work-records.yml:

  • Sets set -euo pipefail (line 33) but feeds each rule from a process substitution: done < <(git ls-files -- '.ai-work/') (line 39), done < <(git ls-files -- '*.md' | grep -E '…' || true) (lines 52 and 61). The shell never checks a process substitution's exit status, and the || true explicitly swallows any pipeline failure, so if git ls-files fails (not a checkout, shallow-clone surprise, wrong working-directory) each loop sees empty input, finds zero violations, and the job prints No AI work records tracked. and exits 0 (line 71).
  • The only non-zero exit is exit 1 on violations (line 69). There is no exit 2, no count of files scanned in the green message, and no --self-test (neither string appears in the file).
  • The logic is inline YAML, so it cannot be unit-tested the way .github/scripts/update-ai-profile-subscription.mjs is (verify-ai-profile-subscription-update.yml runs node --check and node --test on it).

Desired behaviour

  • Extract the checker to .github/scripts/verify-no-work-records.sh (or .mjs), called by the workflow with the same inputs.
  • Exit contract: 0 ran and found nothing, printing scanned: <n> tracked files, rules: 3, violations: 0; 1 ran and found violations (one line per file with the rule id); 2 could not run (git ls-files non-zero, zero files listed in a repository that has tracked files, missing prerequisite), printing the reason. A "pass" over zero listed files is 2, not 0.
  • --self-test: builds a temporary git repository with one planted violation per rule plus a clean control, asserts exactly those violations and exit 1, asserts the control exits 0 with counts, and asserts a broken listing (for example running outside a git checkout) exits 2. A red control (VERIFY_SELF_TEST_BREAK=1) must make the self-test itself fail.
  • A CI job runs --self-test on every change to the script (same pattern as verify-ai-profile-subscription-update.yml).

Acceptance

Done when:

  • The script exists with the exit contract above and the workflow calls it.
  • --self-test passes in CI and fails with VERIFY_SELF_TEST_BREAK=1.
  • Running the checker in an empty directory (not a git checkout) exits 2 and prints the reason.

Verify by:

.github/scripts/verify-no-work-records.sh --self-test               # exit 0, prints "self-test: 3 planted, 3 red, control 0, broken-listing 2"
VERIFY_SELF_TEST_BREAK=1 .github/scripts/verify-no-work-records.sh --self-test; test $? -ne 0
cd "$(mktemp -d)" && "$OLDPWD/.github/scripts/verify-no-work-records.sh"; test $? -eq 2

Mutation proof: replace git ls-files with false in a scratch copy; the checker exits 2, not 0.

Out of scope

What the checker allows (separate allowlist issue); the future verify-decisions checker (it adopts the same contract from day one).

Dependencies

Source: AI-Learning F-95. Depends on: nothing. Related: the allowlist amendment and the verify-decisions issue in this repository.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions