| 2026-07-28 |

R15(1): repo-lint can no longer report PASS over zero files
...
Reproduced before fixing, both cases printing "PASS: repo lint (0 fail, 0 warn)"
with exit 0: `repo_lint.py --recordd` and `repo_lint.py /nonexistent-path`. Only
the two known flags were stripped, so any other --flag became argv[0] i.e. the
ROOT; it resolved nowhere, rglob yielded nothing, and zero findings read as
clean. This is the gate whose "0-fail" every GA-R6 stage close in this project's
history cites, and it could not tell a clean repo from an unexamined one.
Fix: reject unrecognised options (the actual root cause) and >1 positional root;
require the root to be a directory carrying repo markers, refusing rather than
defaulting to success; add a files-scanned floor; and PRINT the files-scanned
count -- Phase 0 found repo-lint emitted no such figure at all, so a reader could
not distinguish a thorough pass from a vacuous one.
The floor SCALES, and a flat one was wrong: the first implementation used a flat
100 and failed 20 of the 47 existing harness cases, because tests/repo-lint
legitimately builds ~7-file fixture repos. The strong floor now applies only to a
full checkout of THIS repo, detected by two files no fixture creates; any other
tree must still scan at least one file. Caught by running the harness.
Harness 54/54 (was 47) -- T48-T54 lock each reproduced defect, including that the
floor does NOT punish a legitimate minimal tree. Gauntlet ALL GREEN (82).
repo-lint on the real repo: 0 fail, 1 standing warn, 596 files scanned.
No consumer breaks -- preflight P1 reads the exit code, not the summary text;
harness regexes match the unchanged "PASS: repo lint" prefix. Both verified.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|
| 2026-07-26 |

D-137 tier 2: local half blocking in P5; --pending-stage -> coupled projection
...
Two operator decisions, both taking the recommendation.
GATE SHAPE: local-only blocking, remote operator-run. preflight P5 now runs
creds-matrix.py --tier2 -- tier 1 STATIC plus tier 2 LOCAL, hermetic (no ssh,
no sudo). It already catches SEC-021's three dc0 on-disk absences without
leaving the jumphost. The remote half stays an operator-run check at
DC-standup close and stage close.
Wiring --remote --privileged into the deploy gate would let a host outage, a
NOPASSWD change, or a MAAS snap refresh turn the gate red for reasons that
are not about credentials, and a gate that fails environmentally is one
people learn to bypass. The repo already made this call once
(run-tests-all.sh:7-8, "different cadence"), and preflight already shows the
failure mode: P4 reads "MAAS unreachable" because it runs on vcloud while
MAAS lives on the headend.
STAGE INPUT: --pending-stage replaced by creds-manifests/stages-reached, a
machine-readable projection of CURRENT-STATE, coupled by new repo-lint L12
(the L10 pattern). A hand-typed gate parameter can be widened silently, and
GA-R1 puts status in CURRENT-STATE alone. A drifted projection would make the
gate defer REAL absences -- a false green.
Exhaustive both ways: an unclassified mint-stage is a hard FAIL, a
classified-but-unused one is a stale-declaration FAIL. That caught `stage4`
immediately -- Stage 4 is open and executing but mints no credential.
Self-inflicted break caught by the existing harness: I first renamed L10's
message to "L10/L12", breaking five cases that grep the established L10 id.
Reverted -- new rules get their own message id, they do not rebrand old ones.
Harnesses: creds-matrix 52 -> 56, repo-lint 45 -> 47, preflight 10.
Gauntlet ALL GREEN (80), repo-lint 0-fail, baseline unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HvCyrwvYTTcDYnRErfMsNf
|
| 2026-07-24 |

caveman: disable on live host + SEC-017 + fail-closed compress guardrails
...
Council-reviewed follow-through on the caveman plugin (operator accepted the
recommendations). Three gated deliverables:
1. DISABLED on the live host: enabledPlugins."caveman@caveman"=false at user
(~/.claude, uncommitted) + committed repo scope; env CAVEMAN_DEFAULT_MODE=off
retained; marketplace kept for deliberate re-enable. Stops the per-turn
third-party hook execution (which ran regardless of mode=off) at next
session start.
2. SEC-017 opened (docs/security-ledger.md): supply-chain re-verify obligation
pinning SHA 0d95a81 + self-remeasured baseline hashes; register = OPS (no
D-number per GA-R3; precedent D-129). Open SEC 12->13, reconciled at Stage 4
close (not an L10 trigger; CURRENT-STATE untouched).
3. Guardrails: repo-lint L11 FAILs on any *.original.md (caveman-compress
residue), opt-out marker + harness T42-T44 (45/45 PASS); .claude/settings.json
deny on Bash(*python3 -m scripts*)+Bash(*caveman-compress*); CLAUDE.md
"Tooling guardrails" prohibiting the compressor against any repo-tracked
prose. Rejected the proposed plugin-hash-baseline-in-repo-lint (layering
violation; drift belongs in the SEC-017 re-verify duty).
Harness-config + governance only; no cloud mutation. repo-lint 0 fail;
gauntlet ALL GREEN (77). Changelog: docs/changelog-20260724-caveman-disable.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUjEb7onHpdqFHUnio6iVw
|
| 2026-07-19 |
Batch 1 open: L10 status-coupling flipped WARN -> FAIL (GA-R1/C1)
...
One-constant flip (L10_FAIL = True) per the sweep plan's Batch 0 revert
note ("WARN for one batch before becoming FAIL"). Harness rc
expectations updated for the five firing cases; 42/42 PASS. G3 cell
updated same commit: Batch 0 CLOSED, Batch 1 OPENED by operator.
Revert: git revert this commit (restores WARN severity).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZbUeRE8weySLSGY1odrCi
|

Batch 0.1: repo-lint gains L10 status-coupling check (GA-R1 rule 8 / C1)
...
L10: a change set modifying state-bearing surfaces (docs/audit/ incl.
ga-rulings.md; design-decisions.md **Status: lines; session-ledger.md
gate rows) without touching docs/CURRENT-STATE.md is flagged -- pending
working-tree set when dirty, HEAD commit when clean. WARN this batch
(L10_FAIL=False); flips to FAIL at Batch 1 open per the sweep plan.
Divergence noted: the sweep plan's paraphrase listed "CURRENT-STATE gate
rows" (vacuous -- such an edit touches CURRENT-STATE by construction);
implemented per the ratified C1 utterance, "ledger gate rows"
(docs/audit/ga-rulings.md:129). G3 evidence cell updated same commit
per the rule this check enforces.
Harness: tests/repo-lint T34-T41 added, 42/42 PASS; live lint 0 fail,
1 legacy WARN (unchanged).
Revert: git revert this commit (check + tests self-contained; restores
the prior G3 cell).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZbUeRE8weySLSGY1odrCi
|
| 2026-07-09 |

DOCFIX-139..141: repo-rename sweep (ipv4->dc-dc) + repo-lint L9 self-reference guard
...
New repo openstack-caracal-dc-dc still had stale operational references to the
source repo it was seeded from (openstack-caracal-ipv4), plus, after the
mechanical fix, hardcoded references to its own new name -- both break on any
future fork/rename. Fixes:
- DOCFIX-139/140: repaired 8 stale clone-path/URL references across the skill
and 4 runbook RUN blocks; fixed a repo_lint.py Windows path-separator bug
that silently turned a documented WARN into a FAIL (rel comparison used
str() instead of as_posix()).
- DOCFIX-141: new repo-lint check L9 fails any script/RUN-block/skill file
that hardcodes the current repo's own directory name. Narrowed the
.claude exclusion in repo_lint.py to .claude/worktrees/ only (it was
blanket-hiding checked-in .claude/skills and .claude/hooks from all
lint checks). Established a $REPO session-variable convention
(runbooks/README.md Conventions) and converted the 8 hardcoded paths to
require it explicitly, fail loud if unset.
repo-lint: 0 fail / 1 documented legacy WARN. tests/repo-lint harness 34/34.
Full details + per-item revert instructions in the two changelogs.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QrcJx8TUar7pYAvpGJw57A
|
| 2026-07-08 |
DOCFIX-137: repo-lint L8 -- enforceable guide<->skill coupling guard
...
Make 'sweep the skill when the guide changes' a hard gate, not a note (skill-lag hit
twice: DOCFIX-135/136). L8 pins the Jenkins+K8s guide's sha256 in
clientdocs/guide-skill-coupling.txt; any guide change FAILS repo-lint (naming the
skill files to review) until re-recorded with --record-guide-skill-coupling. Mirrors
the L7 sweep-receipt pattern. Harness +5 (28/28), gauntlet 39/39, lint 0 fail.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
| 2026-07-07 |
addendum 32: DOCFIX-111 lint excludes .claude/ session worktrees; orphan-sweep first live audit (0 orphans, 3 protected, verify-live OK-paths cleared)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QFdCdEuxynmM8Q6HichbHn
|
addendum 30: client handover package complete -- DOCFIX-108 starter kit + DOCFIX-109 tenant AI skill (union-merged, deduped), L7 coverage recursive, receipt 29 files, gauntlet 37/37
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QFdCdEuxynmM8Q6HichbHn
|
| 2026-07-06 |
addendum 28: operator-away batch integrated -- DOCFIX-098..105 (H4 drift detector, offboard orphan sweep + E0 guard, handover pack, cloud-snapshot, tenant-acceptance harness, lint L7 sweep rule, ledger-scan 099-boundary fix)
...
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QFdCdEuxynmM8Q6HichbHn
|
| 2026-07-03 |
|