Checked as part of closing the C2 coverage gaps, and it was live on main. The content
scan's pattern was `R-[A-Z]+-[0-9]+`, which CANNOT match an ID whose workstream segment
carries a digit: `[A-Z]+` consumes the `C` of `R-C2-01` and then demands a `-` where the
`2` is. `R-C2-01` and `R-C2-02` are the only two such IDs in
conformance/requirements/registry.yaml, and the scan was blind to BOTH.
REPRODUCED before the fix, on a throwaway repo whose only change is a manifest declaring
both IDs on real (non-comment) lines, in a path the map keys to nothing:
$ REPO_ROOT=$T BASE_REF=main ci/touched-requirements.sh
R-NET-06 # the all-letter control ID was the ONLY output
It failed by UNDER-attributing, which is the fail-OPEN direction: a change that retyped a
`conformance.home.k3s/R-C2-01` tag, or a manifest self-declaring R-C2-02, contributed
those IDs to NOBODY, so the C2 tests were filtered out of the merge gate. Same defect
class as the map's `*) : ;;` arm — a miss that reads as "nothing touched".
Every other consumer in the repo already allowed the digit, which is why this was the lone
dissenter: test_requirements_for_path() twenty lines above in this same script,
conformance/lib/coverage.py, conformance/lib/status.py and conformance/lib/
run_l1_offline.py all use `R-[A-Z0-9]+-[0-9]+`. Aligned to that form, with the reason
recorded at the line.
SCOPE OF THE HOLE. path_requirements() has no arm for platform/homepage/* or
platform/headlamp/* either, so before this the ONLY route to R-C2-01/02 was detection rule
3 (editing the C2 conformance test itself). No path-map arm is added here: c2-root-surface
declares `scope: whole-repo`, so ci/l0.sh Stage 3b's --include-scope union selects it on
EVERY gate invocation regardless of the touched set — which is the right mechanism for an
invariant whose input surface is the whole tree, and strictly stronger than a two-component
path arm would be.
REGRESSION-TESTED, in ci/tests/touched-requirements.test.sh (the suite `make -C ci test`
runs): a fixture declaring R-C2-01 / R-C2-02 / R-OBS-04 from `notes/` — a path outside
path_requirements(), so the IDs can only come from the content scan — asserts both digit
IDs ARE attributed, that the all-letter form still is (control), and that a purely numeric
workstream is not invented (the pattern must not widen the gate on noise).
PROVEN TO DETECT BREAKAGE: with the pattern reverted to `R-[A-Z]+-[0-9]+` the suite reports
`FAIL (2 failed, 14 passed)` naming both C2 IDs as missing; restored, all three ci/ suites
pass (16 assertions in this one).
ALSO: conformance/tests/l0-static/whole-repo-invariants-wired/check.sh cites this pattern
in the comment explaining why its BOGUS_REQ fixture is lowercase. Citation updated so the
reasoning still reads true; the fixture is unaffected (grep -E is case-sensitive, and the
check still passes 26/26).
NOTE: another branch may be editing this same script concurrently. This is a one-line
change to one statement plus its comment — expect a trivial conflict and keep the
`[A-Z0-9]` form.
Co-Authored-By: Claude Opus 5 <[email protected]>
175 lines
9.0 KiB
Bash
Executable File
175 lines
9.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# ci/tests/touched-requirements.test.sh — regression tests for the content scan in
|
|
# ci/touched-requirements.sh, focused on rule 3: R-IDs cited only in a whole-line
|
|
# YAML/shell `#` comment are PROSE (a reference), not a declaration, and must NOT be
|
|
# attributed — while R-IDs on real code/spec lines still ARE.
|
|
#
|
|
# The tests point the real script at a THROWAWAY git repo via the REPO_ROOT override
|
|
# (ci/lib.sh honours a pre-set REPO_ROOT); the script itself is run from its true
|
|
# location so it still sources the real lib.sh. No network, no cluster.
|
|
#
|
|
# Run: ci/tests/touched-requirements.test.sh (or `make -C ci test`)
|
|
set -euo pipefail
|
|
|
|
CI_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
SCRIPT="${CI_DIR}/touched-requirements.sh"
|
|
|
|
PASS=0 FAIL=0
|
|
ok() { printf ' ok %s\n' "$*"; PASS=$((PASS+1)); }
|
|
bad() { printf ' FAIL %s\n' "$*"; FAIL=$((FAIL+1)); }
|
|
|
|
# assert_absent <needle> <haystack> <msg>
|
|
assert_absent() {
|
|
if grep -qxF "$1" <<<"$2"; then bad "$3 (found unexpected '$1' in: $(tr '\n' ' ' <<<"$2"))";
|
|
else ok "$3"; fi
|
|
}
|
|
# assert_present <needle> <haystack> <msg>
|
|
assert_present() {
|
|
if grep -qxF "$1" <<<"$2"; then ok "$3";
|
|
else bad "$3 (missing '$1' from: $(tr '\n' ' ' <<<"$2"))"; fi
|
|
}
|
|
|
|
TMP="$(mktemp -d)"
|
|
trap 'rm -rf "$TMP"' EXIT
|
|
|
|
git -C "$TMP" init -q -b main
|
|
git -C "$TMP" config user.email [email protected]
|
|
git -C "$TMP" config user.name t
|
|
git -C "$TMP" config commit.gpgsign false # throwaway repo: never sign (ignore host gpg config)
|
|
mkdir -p "$TMP/notes" # a path OUTSIDE path_requirements() so we isolate the content scan
|
|
echo "baseline" > "$TMP/notes/base.txt"
|
|
git -C "$TMP" add -A && git -C "$TMP" commit -qm baseline
|
|
|
|
git -C "$TMP" checkout -q -b feature
|
|
|
|
# A YAML file: an R-ID in a whole-line comment (must be IGNORED) and an R-ID on a real
|
|
# value line (must be DETECTED). Also an indented comment, to prove leading space is fine.
|
|
cat > "$TMP/notes/example.yaml" <<'YAML'
|
|
# This header explains R-DOC-01 and must NOT be attributed.
|
|
kind: Thing
|
|
metadata:
|
|
name: implements-R-REAL-01
|
|
spec:
|
|
note: value # trailing inline comment mentioning R-INLINE-01 (conservatively still seen)
|
|
# deeply indented comment about R-DOC-02 — also NOT attributed
|
|
YAML
|
|
|
|
# A shell file: a `#` comment R-ID (IGNORED) plus a real command line R-ID (DETECTED).
|
|
cat > "$TMP/notes/example.sh" <<'SH'
|
|
#!/usr/bin/env bash
|
|
# doc: this script relates to R-SHDOC-01 (comment only — ignored)
|
|
echo "runs check for R-SHREAL-01"
|
|
SH
|
|
|
|
git -C "$TMP" add -A && git -C "$TMP" commit -qm feature
|
|
|
|
OUT="$(REPO_ROOT="$TMP" BASE_REF=main "$SCRIPT" 2>/dev/null)"
|
|
printf 'touched set:\n%s\n---\n' "$OUT"
|
|
|
|
# Comment-only citations are dropped (rule 3):
|
|
assert_absent "R-DOC-01" "$OUT" "whole-line YAML comment R-ID is NOT attributed"
|
|
assert_absent "R-DOC-02" "$OUT" "indented YAML comment R-ID is NOT attributed"
|
|
assert_absent "R-SHDOC-01" "$OUT" "shell '#' comment R-ID is NOT attributed"
|
|
# Real code/spec lines still count:
|
|
assert_present "R-REAL-01" "$OUT" "R-ID on a real YAML value line IS attributed"
|
|
assert_present "R-SHREAL-01" "$OUT" "R-ID on a real shell command line IS attributed"
|
|
# Conservative: a trailing inline comment on a REAL line is still seen (only whole-line
|
|
# comments are dropped) — documents the intentional boundary of the fix.
|
|
assert_present "R-INLINE-01" "$OUT" "inline comment on a real line is (conservatively) still seen"
|
|
|
|
# Removed comment lines are also excluded, while removed real lines still count. The file
|
|
# must EXIST at the base, so we diff the removal against the commit that added it.
|
|
git -C "$TMP" checkout -q -b feature2 main
|
|
cat > "$TMP/notes/todelete.yaml" <<'YAML'
|
|
# will delete a comment citing R-DELDOC-01 and a real line citing R-DELREAL-01
|
|
kind: Thing
|
|
name: implements-R-DELREAL-01
|
|
YAML
|
|
git -C "$TMP" add -A && git -C "$TMP" commit -qm add
|
|
ADD_SHA="$(git -C "$TMP" rev-parse HEAD)"
|
|
git -C "$TMP" rm -q "$TMP/notes/todelete.yaml" && git -C "$TMP" commit -qm remove
|
|
OUT2="$(REPO_ROOT="$TMP" BASE_REF="$ADD_SHA" "$SCRIPT" 2>/dev/null)"
|
|
printf 'touched set (removal):\n%s\n---\n' "$OUT2"
|
|
assert_absent "R-DELDOC-01" "$OUT2" "REMOVED whole-line comment R-ID is NOT attributed"
|
|
assert_present "R-DELREAL-01" "$OUT2" "REMOVED real-line R-ID IS attributed"
|
|
|
|
# ---------------------------------------------------------------------------------------
|
|
# PATH MAP — bootstrap/* (added 2026-09-13)
|
|
#
|
|
# WHY THIS IS LOCKED DOWN. path_requirements() keys `bootstrap/*` to R-STATE-03 +
|
|
# R-GITOPS-01, and until 2026-09-13 the comment justifying it described
|
|
# `bootstrap/standup.sh` as a file that carries the placeholder guards. That file has never
|
|
# been on `main` (it landed only on unmerged prod-standup branches), so the comment was
|
|
# stale and the entry looked like dead weight someone would tidy away. It is not dead: it
|
|
# is what SELECTS conformance/tests/l0-static/placeholder-guard-coupling for the change
|
|
# that eventually lands a placeholder guard under bootstrap/ — and that test discovers its
|
|
# guard by content rather than by path, so it activates on exactly that change. Removing
|
|
# the entry would let the change introducing a guard be gated by nothing, which is the
|
|
# 2026-09-05 class. These assertions make the entry's deletion a test failure rather than a
|
|
# silent loss of selection.
|
|
#
|
|
# NOTE the R-ID content scan must not be what produces these: `notes/` is outside the path
|
|
# map precisely so the other cases isolate the scan, and here the file content cites no
|
|
# R-ID at all, so any R-ID in the output came from the PATH.
|
|
git -C "$TMP" checkout -q -b feature3 main
|
|
mkdir -p "$TMP/bootstrap/flux"
|
|
cat > "$TMP/bootstrap/flux/bootstrap.sh" <<'SH'
|
|
#!/usr/bin/env bash
|
|
# a bootstrap-path change that cites no requirement id of its own
|
|
echo "flux bootstrap"
|
|
SH
|
|
git -C "$TMP" add -A && git -C "$TMP" commit -qm "touch bootstrap/"
|
|
OUT3="$(REPO_ROOT="$TMP" BASE_REF=main "$SCRIPT" 2>/dev/null)"
|
|
printf 'touched set (bootstrap/ path map):\n%s\n---\n' "$OUT3"
|
|
assert_present "R-STATE-03" "$OUT3" "bootstrap/* attributes R-STATE-03 (selects placeholder-guard-coupling)"
|
|
assert_present "R-GITOPS-01" "$OUT3" "bootstrap/* attributes R-GITOPS-01 (it IS the GitOps bootstrap path)"
|
|
|
|
# And the neighbouring entry the same test leans on for its other half: clusters/* must
|
|
# attribute R-ENV-02, which is what selects placeholder-guard-coupling's HALF A (the
|
|
# authored-values sweep over clusters/<env> effective cluster-vars).
|
|
git -C "$TMP" checkout -q -b feature4 main
|
|
mkdir -p "$TMP/clusters/base"
|
|
printf 'kind: ConfigMap\nmetadata:\n name: cluster-vars\n' > "$TMP/clusters/base/cluster-vars.yaml"
|
|
git -C "$TMP" add -A && git -C "$TMP" commit -qm "touch clusters/"
|
|
OUT4="$(REPO_ROOT="$TMP" BASE_REF=main "$SCRIPT" 2>/dev/null)"
|
|
printf 'touched set (clusters/ path map):\n%s\n---\n' "$OUT4"
|
|
assert_present "R-ENV-02" "$OUT4" "clusters/* attributes R-ENV-02 (selects placeholder-guard-coupling HALF A)"
|
|
assert_present "R-GITOPS-01" "$OUT4" "clusters/* attributes R-GITOPS-01"
|
|
|
|
# ---------------------------------------------------------------------------------------
|
|
# THE ID PATTERN MUST ALLOW A DIGIT IN THE WORKSTREAM SEGMENT (added 2026-09-13)
|
|
#
|
|
# The content scan's pattern was `R-[A-Z]+-[0-9]+`, which CANNOT match `R-C2-01` or
|
|
# `R-C2-02` — `[A-Z]+` consumes the `C` and then demands a `-` where the `2` is. Those are
|
|
# the only two registry IDs whose workstream segment carries a digit, and the scan was blind
|
|
# to BOTH, in the fail-OPEN direction: a change self-declaring a C2 requirement contributed
|
|
# it to nobody, so the C2 conformance tests were filtered out of the merge gate. Found while
|
|
# wiring conformance/tests/l0-static/c2-root-surface, which closes those two coverage gaps.
|
|
#
|
|
# `notes/` is outside path_requirements() on purpose, so the IDs below can only have come
|
|
# from the CONTENT SCAN. A neighbouring all-letter ID is asserted too, so a regex that
|
|
# somehow matched only the digit form would still fail here.
|
|
git -C "$TMP" checkout -q -b feature5 main
|
|
cat > "$TMP/notes/c2.yaml" <<'YAML'
|
|
kind: Test
|
|
metadata:
|
|
labels:
|
|
conformance.home.k3s/R-C2-01: "true"
|
|
conformance.home.k3s/R-C2-02: "true"
|
|
conformance.home.k3s/R-OBS-04: "true"
|
|
YAML
|
|
git -C "$TMP" add -A && git -C "$TMP" commit -qm "declare R-C2-01 / R-C2-02"
|
|
OUT5="$(REPO_ROOT="$TMP" BASE_REF=main "$SCRIPT" 2>/dev/null)"
|
|
printf 'touched set (digit in the workstream segment):\n%s\n---\n' "$OUT5"
|
|
assert_present "R-C2-01" "$OUT5" "an R-ID with a DIGIT in the workstream segment IS attributed (R-C2-01)"
|
|
assert_present "R-C2-02" "$OUT5" "the second such ID is attributed too (R-C2-02)"
|
|
assert_present "R-OBS-04" "$OUT5" "an all-letter workstream segment still works (control)"
|
|
# The pattern must not become so loose that a non-ID token is read as a requirement: a bare
|
|
# numeric workstream is not a registry shape, and attributing one would WIDEN the gate on
|
|
# noise (over-broad selection, never a false green, but noisy and misleading).
|
|
assert_absent "R-1-01" "$OUT5" "a purely numeric workstream segment is not invented from thin air"
|
|
|
|
echo
|
|
if [ "$FAIL" -eq 0 ]; then echo "touched-requirements tests: PASS ($PASS assertions)"; exit 0;
|
|
else echo "touched-requirements tests: FAIL ($FAIL failed, $PASS passed)"; exit 1; fi
|