Skip to content

fix(gate): accept .github/ and docs/ CONTRIBUTING (launch-scaffolder#37) - #979

Merged
hyperpolymath merged 2 commits into
mainfrom
fix/docs-presence-github-dir
Sep 22, 2026
Merged

hyperpolymath merged 2 commits into
mainfrom
fix/docs-presence-github-dir

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Stacked on #978. Base is fix/scorecard-codeql-4380 so this PR shows only the docs-gate diff; it auto-retargets to main when #978 merges. Merge #978 first.

The defect

check-docs-presence.sh searched only the repository root for CONTRIBUTING, while estate repos have been deliberately relocating the file to .github/ — the location GitHub itself auto-discovers.

From launch-scaffolder d426ea4d:

the estate canonical location is .github/CONTRIBUTING.md, which GitHub auto-discovers

So the gate asked "is there a CONTRIBUTING at the repo root?" while its consumers had been told to answer "is there a CONTRIBUTING GitHub can find?" — a guard asking a different question than its consumer, and the gate lost.

Census — 516 local clones, 2026-09-22

location repos
root 401
.github/ 96
docs/ 1
none anywhere 94

19 unique repos were being reported missing a document they demonstrably have, against 94 genuine misses. For scale, the script's own header records a 2026-07-21 measurement over 412 real repo-root callers: README 0/412 missing, LICENSE 0/412, CONTRIBUTING 54/412.

This widens WHERE the gate looks without widening WHAT it asks — the 94 still block.

Second defect, same file

The failure message named only the root locations, so it prescribed a cure narrower than the code accepts. Surfaced only by reading the negative control's output rather than just its exit code. Same class as #930.

Tests

Four new accept cases — one per added path, because a single .github/CONTRIBUTING.md case would pass even if only that one path had been added — plus an anti-overreach case proving a CONTRIBUTING at an undiscoverable depth (src/internal/) still BLOCKS. That last one guards against a future "fix" by recursive find, which would silently pass all 94 genuinely-missing repos.

Suite 29/29.

Mutants killed

Both leave the pre-existing cases green, so detection is attributable:

mutant result
gate fully reverted to root-only 25 passed, 4 failed — exactly the new accept cases
only .github/CONTRIBUTING.md added 26 passed, 3 failed — each path individually load-bearing

Real-world controls

repo rc meaning
launch-scaffolder 0 the repo issue #37 reported missing
standards itself 0 via 3-practice/
cicd-suite 1 genuine miss, message correct

⚠ This does not close launch-scaffolder#37 by itself

launch-scaffolder's governance job runs this script from its pinned standards SHA, so it will not see the fix until that pin is bumped. Its ec-linux-amd64 failure is a separate pre-existing cause and the job conclusion will not flip on this change alone — verify the CONTRIBUTING sub-check by name in the log.

Refs hyperpolymath/launch-scaffolder#37, #930

🤖 Generated with Claude Code

https://claude.ai/code/session_01WPSJ7fBhVAMcpSffCBWUDo

hyperpolymath and others added 2 commits September 22, 2026 13:31
Dependabot #977 (68acee7, merged 2026-09-22) bumped codeql-action from
4.38.0 back to 4.38.1 -- the version #973 had just escaped because it
fails GitHub's workflow-startup validation estate-wide (nexia-list#100).
Measured on hyperpolymath/standards within the hour: codeql.yml red from
12:09Z after four greens, scorecard.yml red from 11:51Z, and the newest
run of each reports jobs=0. That is startup death, not a failing job;
note GitHub surfaces it here as conclusion=failure, not startup_failure,
because the death is in the called reusable.

Five refs across three workflows went back to 1c5b675 (v4.38.1):

  codeql-reusable.yml        init, analyze
  hypatia-scan-reusable.yml  upload-sarif
  scorecard-reusable.yml     upload-sarif x2

The first three are the more dangerous shape: #977 replaced the SHA but
inherited #973's comment, so each line reads
"@1c5b675... # v4.38.0 (4.38.1 blocked estate-wide)" -- an annotation
asserting the exact opposite of the value it annotates. A reviewer
reading the comment sees the safe version. scorecard-reusable.yml was
never swept by #973 at all and kept honest "# v3" / "# v4.38.1" comments.

Also widens the dependabot hold, which did not hold. The ignore entry
named "github/codeql-action" while the workflows reference the subpath
actions, and Dependabot treats github/codeql-action/init as its own
dependency name -- #977's own body says "Updates
`github/codeql-action/init` from 4.38.0 to 4.38.1". So the ignore
matched nothing. The entry is now "github/codeql-action*". Without this
the next scheduled run reopens the same PR and re-breaks both workflows.

actions.lock is deliberately untouched: it already carried b96794f for
all three workflows, so the lockfile was the correct side of the drift
and the workflows were the stale side. Regenerating it instead -- the
cure the gate's own error text prescribes -- would have written 1c5b675
back into the lock and re-legitimised the blocked version.

Verified: zero refs to 1c5b675 remain under .github/; the actions-lock
gate reports no error-severity and no stale findings (93 pre-existing
sha-as-ref warnings are unchanged); git diff on actions.lock is empty.

Refs: #973, #977, nexia-list#100, nexia-list#101, nexia-list#104

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WPSJ7fBhVAMcpSffCBWUDo
Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com>
check-docs-presence.sh searched only the repository root for
CONTRIBUTING, while estate repos have been deliberately relocating the
file to .github/ -- the location GitHub itself auto-discovers
(launch-scaffolder d426ea4d: "the estate canonical location is
.github/CONTRIBUTING.md, which GitHub auto-discovers"). The gate and its
consumers were therefore asking different questions, and the gate lost.

Census of 516 local clones on 2026-09-22: 401 repos carry CONTRIBUTING at
the root, 96 under .github/, 1 under docs/, and 94 have none anywhere. So
19 unique repos were being reported missing a document they demonstrably
have, against 94 genuine misses. This widens WHERE the gate looks without
widening WHAT it asks: the 94 still block.

Also corrects the failure message, which named only the root locations and
so prescribed a cure narrower than the code accepts (cf. standards#930).

Tests: four new accept cases, one per added path, plus an anti-overreach
case proving a CONTRIBUTING at an undiscoverable depth still BLOCKS -- that
one guards against a future 'fix' by recursive find, which would silently
pass all 94. Suite 29/29.

Mutants killed, both leaving the pre-existing cases green:
  gate fully reverted                -> the 4 new accept cases fail
  only .github/CONTRIBUTING.md added -> 3 fail (each path load-bearing)

Real-world controls: launch-scaffolder rc=0 (was the reported miss),
standards itself rc=0 via 3-practice/, cicd-suite rc=1 (genuine miss).

Refs: hyperpolymath/launch-scaffolder#37

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WPSJ7fBhVAMcpSffCBWUDo
Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Next included review available in 49 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 23c5c83a-c15f-4b98-a5eb-cfce6c05736e

📥 Commits

Reviewing files that changed from the base of the PR and between 7b931ef and 9dfdb66.

📒 Files selected for processing (6)
  • .github/dependabot.yml
  • .github/workflows/codeql-reusable.yml
  • .github/workflows/hypatia-scan-reusable.yml
  • .github/workflows/scorecard-reusable.yml
  • scripts/check-docs-presence.sh
  • scripts/tests/governance-gates-505-test.sh

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sonarqubecloud

Copy link
Copy Markdown

@hyperpolymath

Copy link
Copy Markdown
Owner Author

The five new cases are CI-enforced automatically — no wiring needed.

Checked rather than assumed, because grepping for the filename gives the wrong
answer: governance-gates-505-test.sh appears nowhere in .github/workflows/.
It still runs, because discovery is by glob, not by name:

  • .github/workflows/self-test.yml:55 → bash scripts/run-shell-test-suite.sh
  • that runner does find scripts/tests -maxdepth 1 -name '*.sh' -type f and
    invokes each as bash "$test_file"

Two consequences worth stating:

  1. Self Test triggers on pull_request: with no paths: filter, so the
    four new accept cases and the src/internal/ anti-overreach case gate every
    PR from now on.
  2. Because the runner invokes via bash <path> rather than ./<path>, the
    mode-100644 exit-126 trap does not apply here.

The runner is also fail-closed on empty discovery (exit 1), so a future
refactor that moved the suite out of scripts/tests/ would fail loudly rather
than silently stop testing this gate.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WPSJ7fBhVAMcpSffCBWUDo

Base automatically changed from fix/scorecard-codeql-4380 to main September 22, 2026 12:42
@hyperpolymath
hyperpolymath merged commit 79991c7 into main Sep 22, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant