diff --git a/tools/ci/pre-push.sh b/tools/ci/pre-push.sh index 1dbc4762..d401750c 100755 --- a/tools/ci/pre-push.sh +++ b/tools/ci/pre-push.sh @@ -80,6 +80,9 @@ never_push_checks() { # A secret or an identity leak must not reach the remote on any branch; together about 20 s on the Mac. run "identity grep of the public export list and the served site" bash tools/ci/identity-check.sh run "no secret file names and no 64-hex secrets in the tree" bash -c 'bash tools/ci/no-secrets-check.sh --self-test && bash tools/ci/no-secrets-check.sh' + # the third never-push class (7 October 2026, 20:5x UK): a founder name on ANY branch, because every branch went to the public host's + # mirror and a branch green-stamped before the check existed carried one onto master through the deferred merge + run "no founder name, personal login, earlier business or personal address in any tracked text file (the pre-public scrub; self-test first, encoded list)" bash -c 'bash tools/ci/founder-strings-check.sh --self-test && bash tools/ci/founder-strings-check.sh' } tree_checks() { @@ -138,7 +141,6 @@ tree_checks() { run "hash-origin report: a known-finished day and a known-failed day" node --test tools/observer/hash-origin.test.mjs run "harness summaries never carry a raw 64-hex key (the writer's own redaction and check)" node infra/fast-time/lib/redact-keys.mjs --self-test run "docs-only pushes skip the compile-or-compute CI jobs (the changes job's classifier)" bash tools/ci/docs-only-check.sh --self-test - run "no founder name, personal login, earlier business or personal address in any tracked text file (the pre-public scrub; self-test first, encoded list)" bash -c 'bash tools/ci/founder-strings-check.sh --self-test && bash tools/ci/founder-strings-check.sh' run "the public ledger (docs/ledger-public.md) is what docs/fud-ledger.md generates: one row per item, no commit ids, times or team names (self-test first)" bash -c 'node tools/ledger/export-public.mjs --self-test && node tools/ledger/export-public.mjs --check' run "every workflow job carries timeout-minutes (site 15, changes 10, pow 60, sims 45; the hung-job class of 7 October 2026)" bash tools/ci/workflow-timeouts-check.sh --self-test run "a box or network check gets one retry before it is red (retry-once self-test)" bash tools/ci/retry-once.sh --self-test @@ -228,6 +230,7 @@ case "$MODE" in # the light gate carries the two never-push classes beside the structural checks, and the full gate runs them too declare -f never_push_checks | grep -q 'tools/ci/no-secrets-check.sh' || { echo "self-test failed: the never-push checks do not run the no-secrets check"; fails=1; } declare -f never_push_checks | grep -q 'tools/ci/identity-check.sh' || { echo "self-test failed: the never-push checks do not run the identity grep"; fails=1; } + declare -f never_push_checks | grep -q 'tools/ci/founder-strings-check.sh' || { echo "self-test failed: the never-push checks do not run the founder-strings check"; fails=1; } grep -qE '^\s+structural_checks; never_push_checks; finish "feature branch"' "$0" || { echo "self-test failed: the hook's light gate does not run the never-push checks"; fails=1; } # the green stamp and the deferral, in a fixture repository: a merge of a stamped branch onto the remote tip defers; an # unstamped branch, a stale stamp, a merge onto an older tip and a plain commit all take the full gate diff --git a/tools/repo/fresh-repo.sh b/tools/repo/fresh-repo.sh index d8f7d217..22ad54be 100755 --- a/tools/repo/fresh-repo.sh +++ b/tools/repo/fresh-repo.sh @@ -85,12 +85,16 @@ TARGET_EMAIL="$STANDING_ID+$TARGET_LOGIN@users.noreply.github.com" TARGET_IDENT="$TARGET_LOGIN <$TARGET_EMAIL>" # every other identity: "name|email" pairs (author and committer) -PERSONAL_PAIRS="$(git log --all --format='%an|%ae%n%cn|%ce' | grep -v "|$STANDING_EMAIL$" | sort -u || true)" +PERSONAL_PAIRS="$(git log --all --format='%an|%ae%n%cn|%ce' | grep -v -F -e "|$STANDING_EMAIL" -e "|$TARGET_EMAIL" | sort -u || true)" # fixed strings: the addresses carry a +, a quantifier under -E (dry run 3, 7 Oct 2026: the target's address was read as personal and matched every rewritten line) # never the standing or the target address (7 Oct 2026: the target's own commits read as personal and every rewritten author line then counted as a hit) PERSONAL_EMAILS="$(printf '%s\n' "$PERSONAL_PAIRS" | awk -F'|' 'NF==2{print $2}' | sort -u)" -PERSONAL_NAMES="$(printf '%s\n' "$PERSONAL_PAIRS" | awk -F'|' 'NF==2{print $1}' | grep -v "^$STANDING_LOGIN$" | sort -u || true)" -FIRST_NAMES="$(printf '%s\n' "$PERSONAL_NAMES" | awk 'NF>=1{print $1}' | sort -u)" -LAST_NAMES="$(printf '%s\n' "$PERSONAL_NAMES" | awk 'NF>=2{print $NF}' | sort -u)" -SECOND_LOGINS="$(printf '%s\n' "$PERSONAL_EMAILS" | sed -nE 's/^[0-9]+\+([A-Za-z0-9-]+)@users\.noreply\.github\.com$/\1/p' | grep -v "^$STANDING_LOGIN$" | sort -u || true)" +PERSONAL_NAMES="$(printf '%s\n' "$PERSONAL_PAIRS" | awk -F'|' 'NF==2 && $1 ~ / /{print $1}' | grep -v -E "^($STANDING_LOGIN|$TARGET_LOGIN)$" | sort -u || true)" # a name has a space; a login is not a name +# the founder's first name, surname and second login from the encoded list (rows 1 to 3, sample column), so the rules never depend on +# which commits a given mirror carries (7 Oct 2026: build-1's mirror holds none of the 40 personal-identity commits) +LIST_ROWS="$(base64 -d < "$ROOT/tools/ci/founder-strings.b64" | grep -vE '^#')" +LIST_FIRST="$(printf '%s\n' "$LIST_ROWS" | sed -n '1p' | cut -f2 | awk '{print $1}')"; LIST_LAST="$(printf '%s\n' "$LIST_ROWS" | sed -n '2p' | cut -f2)"; LIST_SECOND="$(printf '%s\n' "$LIST_ROWS" | sed -n '3p' | cut -f2)" +FIRST_NAMES="$( { printf '%s\n' "$PERSONAL_NAMES" | awk 'NF>=2{print $1}'; printf '%s\n' "$LIST_FIRST"; } | grep . | sort -u)" +LAST_NAMES="$( { printf '%s\n' "$PERSONAL_NAMES" | awk 'NF>=2{print $NF}'; printf '%s\n' "$LIST_LAST"; } | grep . | sort -u)" +SECOND_LOGINS="$( { printf '%s\n' "$PERSONAL_EMAILS" | sed -nE 's/^[0-9]+\+([A-Za-z0-9-]+)@users\.noreply\.github\.com$/\1/p'; printf '%s\n' "$LIST_SECOND"; } | grep . | grep -v -E "^($STANDING_LOGIN|$TARGET_LOGIN)$" | sort -u || true)" # the other businesses named in the plan (brand names, not people), from the encoded list tools/ci/founder-strings.b64 (rows 4 to 8; # no tracked file spells them: the founder-strings check reads every tracked file) OTHER_BUSINESSES="$(base64 -d < "$ROOT/tools/ci/founder-strings.b64" | grep -vE '^#' | sed -n '4,8p' | cut -f1 | sed -E 's/\\b//g' | paste -sd'|' -)" @@ -133,12 +137,12 @@ fi while IFS= read -r first; do [ -n "$first" ] || continue printf 'regex:\\b%s%ss\\b==>the project lead%ss\n' "$first" "'" "'" >> "$REPLACE" - while IFS= read -r last; do [ -n "$last" ] && printf 'regex:\\b%s\\s+%s\\b==>the project lead\n' "$first" "$last" >> "$REPLACE"; done <<< "$LAST_NAMES" + while IFS= read -r last; do [ -n "$last" ] && printf 'regex:(?i)\\b%s\\s+%s\\b==>the project lead\n' "$first" "$last" >> "$REPLACE"; done <<< "$LAST_NAMES" printf 'regex:\\b%s\\b==>the project lead\n' "$first" >> "$REPLACE" done <<< "$FIRST_NAMES" while IFS= read -r last; do [ -n "$last" ] || continue - printf 'regex:\\b%s\\b==>[removed]\n' "$last" >> "$REPLACE" + printf 'regex:(?i)\\b%s\\b==>[removed]\n' "$last" >> "$REPLACE" printf '\\b%s\\b\n' "$last" >> "$IDENT" done <<< "$LAST_NAMES" while IFS= read -r first; do @@ -165,7 +169,7 @@ scan_blobs() { | perl -ne 'BEGIN { open(P, "<", shift) or die; @p = map { chomp; qr/$_/i } grep { /\S/ }

; $n = 0 } for my $p (@p) { if ($_ =~ $p) { $n++; last } } END { print "$n\n" }' "$1" } scan_meta() { git log --all --format='%an%n%ae%n%cn%n%ce%n%s%n%b' | perl -ne 'BEGIN { open(P, "<", shift) or die; @p = map { chomp; qr/$_/i } grep { /\S/ }

; $n = 0 } for my $p (@p) { if ($_ =~ $p) { $n++; last } } END { print "$n\n" }' "$1"; } -DROPPED=(docs/fud-ledger.md docs/fud-fixes.md docs/review site/ledger.html) +DROPPED=(docs/review) # the ledger, its fixes file and the ledger page are published with the repository (decision of 5 October 2026, docs/fud-fixes.md section 5); the review folder stays internal counts() { #