mirror of
https://github.com/garrytan/gbrain.git
synced 2026-08-14 08:53:22 +00:00
chore(ci): re-admit policy docs into ci-cache-hash before doc relocation
docs/**/*.md is deny-listed from the CI cache hash (test-irrelevant). The CLAUDE.md restructure moves test/release POLICY into docs/TESTING.md + docs/RELEASING.md, which DO carry contracts the test suite reads. Without re-admitting them, a policy-only edit would produce the same cache hash and skip the test shard that runs the build-llms + doc-history guards (false-pass). Adds an ALLOW_PATTERNS re-admit step after the deny, scoped to the named policy docs (not a blanket docs un-deny). Lands FIRST, before any doc moves. Pinned by 3 new cases in test/scripts/ci-cache-hash.test.ts: TESTING.md + RELEASING.md edits MUST change the hash; docs/guide.md still must not. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
284c50a488
commit
75992b77fb
@@ -30,6 +30,14 @@
|
||||
# - everything else under src/, test/, scripts/, .github/, package.json,
|
||||
# bun.lock, tsconfig*.json, the schema files — obviously test-affecting
|
||||
#
|
||||
# POLICY-DOC RE-ADMIT (the docs/ exception): some docs/*.md files carry
|
||||
# CI / release / test CONTRACTS that the test suite reads (e.g. the
|
||||
# build-llms content-contract test, the doc-history guard). The broad
|
||||
# `^docs/.*\.md$` deny above would let a policy edit to those skip CI — a
|
||||
# false-pass. The ALLOW_PATTERNS list below re-admits them into the hash
|
||||
# AFTER the deny. ADD a path there whenever you move a policy/contract doc
|
||||
# under docs/ (current entries: docs/TESTING.md, docs/RELEASING.md).
|
||||
#
|
||||
# Locale-stable: LC_ALL=C on the sort step so byte-order is identical
|
||||
# across runners (different default locales would re-order the line list
|
||||
# and change the final hash).
|
||||
@@ -113,6 +121,27 @@ DENY_RE=$(printf '\t(%s)' "$DENY_ALT")
|
||||
# TODOS\.md$|docs/.*\.md$|...)`. Each alternative anchors its own end.
|
||||
INCLUDED=$(printf '%s\n' "$LS_FILES" | grep -vE "$DENY_RE" || true)
|
||||
|
||||
# Re-admit test-affecting policy docs that live under docs/ but carry CI /
|
||||
# release / test contracts. The broad `^docs/.*\.md$` deny above removed
|
||||
# them; without this re-admit a policy edit to docs/TESTING.md or
|
||||
# docs/RELEASING.md would produce the SAME hash and skip the test shard
|
||||
# that runs the build-llms + doc-history guards — a false-pass. Patterns
|
||||
# anchor on the `\t<path>` boundary in `git ls-files -s` output, matching
|
||||
# the deny-list convention above. Re-admitted lines that don't exist yet
|
||||
# (pre-relocation) simply match nothing.
|
||||
ALLOW_PATTERNS=(
|
||||
'\tdocs/TESTING\.md$'
|
||||
'\tdocs/RELEASING\.md$'
|
||||
)
|
||||
ALLOW_ALT=""
|
||||
for p in "${ALLOW_PATTERNS[@]}"; do
|
||||
if [ -z "$ALLOW_ALT" ]; then ALLOW_ALT="$p"; else ALLOW_ALT="$ALLOW_ALT|$p"; fi
|
||||
done
|
||||
READMIT=$(printf '%s\n' "$LS_FILES" | grep -E "($ALLOW_ALT)" || true)
|
||||
if [ -n "$READMIT" ]; then
|
||||
INCLUDED=$(printf '%s\n%s\n' "$INCLUDED" "$READMIT" | grep -v '^$' | LC_ALL=C sort -u)
|
||||
fi
|
||||
|
||||
if [ -z "$INCLUDED" ]; then
|
||||
echo "error: every tracked file is deny-listed — refusing to hash empty set" >&2
|
||||
exit 1
|
||||
|
||||
@@ -400,6 +400,50 @@ describe("ci-cache-hash.sh — edge cases", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("ci-cache-hash.sh — policy-doc re-admit (test-affecting docs under docs/)", () => {
|
||||
// These docs live under docs/ (normally deny-listed) but carry CI/release/
|
||||
// test contracts the suite reads. The re-admit must make edits to them
|
||||
// invalidate the hash, WITHOUT un-denying ordinary docs.
|
||||
const POLICY_FILES: Record<string, string> = {
|
||||
...BASELINE_FILES,
|
||||
"docs/TESTING.md": "# Testing\n\ntest tiers + isolation lint\n",
|
||||
"docs/RELEASING.md": "# Releasing\n\nversion locations + ship process\n",
|
||||
};
|
||||
|
||||
function withSandbox(test: (sb: Sandbox) => void) {
|
||||
const sb = makeSandbox(POLICY_FILES);
|
||||
try {
|
||||
test(sb);
|
||||
} finally {
|
||||
rmSync(sb.dir, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
|
||||
it("docs/TESTING.md edit MUST change hash (re-admitted policy doc)", () => {
|
||||
withSandbox((sb) => {
|
||||
const before = hash(sb);
|
||||
modify(sb, "docs/TESTING.md", "# Testing\n\nNEW POLICY\n");
|
||||
expect(hash(sb)).not.toBe(before);
|
||||
});
|
||||
});
|
||||
|
||||
it("docs/RELEASING.md edit MUST change hash (re-admitted policy doc)", () => {
|
||||
withSandbox((sb) => {
|
||||
const before = hash(sb);
|
||||
modify(sb, "docs/RELEASING.md", "# Releasing\n\nNEW SHIP RULE\n");
|
||||
expect(hash(sb)).not.toBe(before);
|
||||
});
|
||||
});
|
||||
|
||||
it("docs/guide.md edit STILL produces same hash (re-admit is scoped, not a blanket docs un-deny)", () => {
|
||||
withSandbox((sb) => {
|
||||
const before = hash(sb);
|
||||
modify(sb, "docs/guide.md", "# Guide v3\n");
|
||||
expect(hash(sb)).toBe(before);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("ci-cache-hash.sh — usage errors", () => {
|
||||
it("--bogus arg exits 2", () => {
|
||||
const r = spawnSync("bash", [SCRIPT_SRC, "--bogus"], {
|
||||
|
||||
Reference in New Issue
Block a user