Conversation
Adds .refactor/ as the committed home for this program's plan and ledger: - PLAN.md — the loop-drivable work queue (§0-§7) plus the reasoning appendices - REFACTOR.md — the 49-unit refactor program (verification commands, rollback, checkpoint record per unit) - ledger.md — the durable state the loop reads to answer "what is done, what is next, am I mid-item". It lives here rather than under .cladding/ because that path is gitignored, and a ledger that does not survive a clone cannot be reviewed or recovered from. Also completes queue item S1. The event log records 251 distinct commit heads across stop_blocked and gate_run; 29 of 48 block heads and 129 of 247 gate heads are not ancestors of develop (squash-merged feature branches), surviving only in the reflog. The oldest events are 41 days old, past git's default 30-day reflogExpireUnreachable, and loose objects sit at 4,824 against the 6,700 auto-gc threshold. All 251 are now pinned under refs/replay/*, so a gc can no longer make the replay evidence unauditable. Refs only — no history change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
chore(release): prepare 0.9.4
…SMATCH Three divergent language tables meant clad init could seed a label the detector layer then rejected under --strict — measured on realistic repo shapes, the manifest-chain comparison blocked 12 of 19 normal projects (Android C++ SDK under Gradle, Rust core shipped via npm, plain JavaScript, C#, Scala). The vocabulary now lives once in src/core/language-evidence.ts, and the detector judges the observed source distribution instead of the build manifest: unknown language or under 5 classified files → silence, declared absent → one warn naming the evidence, minority under 10% → one non-blocking info. A coverage-ratio rule is deliberately absent — red-teaming showed its denominator list flipped failures between false-warn and missed-drift depending on membership. detectToolchain is untouched: a build-host label answers "what do we run", which stays the right question for gate-command selection. Verified: 22-test impl-blind oracle (authored from the contract only), 32-shape adversarial corpus vs an independent reference (0 mismatches, 0 blocked false positives, 0 missed drifts), strict blocking semantics proven through the built CLI, full suite 2886/2886. F-9e1279d4 · clad done under a GREEN strict pre-push gate Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The module-honesty check chose one extension from a six-language table; declaring cpp, java, or csharp fell through to *.ts, scanned zero files, and passed vacuously — verified by direct scanPatterns calls — on exactly the projects the check exists for. The universe is now derived from evidence: extensions observed in the tree that the shared vocabulary knows, united with extensions of modules claimed under layer roots, so an unknown language (.zig) enters the moment a feature claims it, with no table growth. Scan roots are likewise inferred from claimed module paths (src/main/kotlin comes out of inference), retiring both EXT_BY_LANGUAGE and ROOT_BY_LANGUAGE; the detector no longer reads spec.project.language at all. Root inference alone would over-teach — layer names recur under tests/, skills/, and plugins/, which measured 430 false findings on this repository — so a root must carry at least 25% of layer-claimed modules. The accepted trades (a sub-25% genuine root is not scanned; the share is ratio-noisy at tiny claim counts) are recorded in the spec entry. On this repo the new universe is 133 patterns / 201 files (was 19 / 190) with zero new findings, and the A/B golden scenarios now catch their injected rename drift through UNMAPPED_ARTIFACT as well — the .tsx rename the old table could not see. Verified: 9-test impl-blind oracle (contract-only), 22 unit tests, adversarial root-filter attacks (collision drop at scale, 50/50 dual-root survival, documented 80/20 miss), full suite 2909/2909. F-87bb7ed3 · clad done under a GREEN strict pre-push gate Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
clad init ignored .cladding/ with the directory form, and git never re-includes under an excluded directory — so .cladding/config.yaml (gate.scope, gate.commands, gate.coverage, gate.test_report) could not be committed at all. Every documented gate override was local-only: fresh clones and CI silently ran a different gate than the author tuned, and --strict exists for CI. Found by a live host run during the gate.language E2E, verified with git check-ignore. Fresh projects now get the contents-exclusion pair (.cladding/* plus !.cladding/config.yaml) rendered by a pure policy module. An existing .gitignore carrying any recognized cladding entry — the legacy directory form included — stays byte-identical; instead of rewriting adopters' files, clad doctor reports a blocked gate config in text and JSON, the same read-only posture as the unpinned-CI report. The dogfood repo's own .gitignore moves to the pair form, and the onboarding description no longer promises the directory form. Verified: 23-test impl-blind oracle (contract-only, includes live git check-ignore ground truth) passing on first contact with the implementation, end-to-end harness through the built CLI (fresh init committable, legacy adopter byte-identical + doctor blocked, new-form quiet), full suite 2936/2936. F-b0c2e724 · clad done under a GREEN strict pre-push gate — the gate itself first refused this commit because the new policy module was claimed by no feature: F-87bb7ed3's evidence universe caught its own sibling's spec gap. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…n says so External E2E defect D1: the universe derivation matched layer NAMES as path segments, so a layer named anything but a literal directory — measured with 'native' declaring modules: ["core/src/main/cpp/**"] — produced an empty universe and a silent pass, while the identical spec named 'core' found 21 files. The schema has carried per-layer modules globs all along; the detector ignored a declared surface. A layer that declares globs now gets its universe from them (times the evidenced extensions), bypassing name inference; bare layers keep the existing derivation byte-for-byte, and root-dominance math is untouched. When the active full scan matches nothing at all, one info finding names the layers and roots it searched instead of reading as a clean pass — causal control: HEAD's detector printed zero findings on both fixtures. Also records the external E2E's remaining findings as backlog rows B12-B15 (legacy fallback shape, init language seeding, per-detector language resolution, post-init scaffold probe), and reconciles F-a04cd9's "advisory, not consumed" prose with the new consumer. Verified: oracle grown 9→14 blind cases (5 authored against the amended contract before the implementation landed, then passing untouched), 34 unit tests, full suite 2953/2953, external E2E 7/7 PASS at c41ba2e. F-87bb7ed3 (amended) · clad done under a GREEN strict pre-push gate Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nce contract The F-013 fixture encoded the manifest-chain comparison (one .ts file, python declared, warn expected from the toolchain verdict). Under the evidence model one classified file sits below the floor, so the fixture went silent and CI's stage-contract corpus caught it — the corpus doing its job on a semantics change. The fixture now clears the floor with five observed sources, and F-013's criterion text plus the corpus description state the current contract, with the evidence model owned by the new spec entry. Conformance corpus 33/33 matched, Iron Law L4, full suite 2953/2953. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The gate judges the sources on disk, not the build manifest
A project whose language cladding cannot drive passed the gate with six of nine stages skipped and zero mention of the way out — measured across every adopter-reachable surface, gate.commands appeared once, in a CHANGELOG line, and the gate.language E2E already proved that exact configuration strands a fully-capable agent. Skips were honest but mute. Command-stage skips now carry a structured reason: 'no-runner' when no runner is registered for the language, 'tool-missing' when the resolved tool is absent — by-design skips (missing oracles, no declared deliverable) stay untagged, because prescribing gate.commands there would be a false cure. When at least one no-runner skip occurred, the check prints one trailing line naming those stages and the inline declaration that turns them on, noting the file is committable so CI runs the same gate. The remedy was proven true before the line was written: declaring gate.commands flips all four stages from skip to run through the shipped binary. JSON carries skipReason additively; every skip message, exit code, and skip semantic is byte-identical. Verified: 16-test impl-blind oracle passing on first contact, 12 unit tests, golden matrix untouched, four-environment guard on the built binary (guidance 1/0/0/0: runner-less shows it, declared / self / known-toolchain do not), JSON purity, full suite 2981/2981. F-c17e1edc · clad done under a GREEN strict pre-push gate Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Runner-less skips name their exit
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Version A/B: what the release may and may not claim
The prepared 0.9.4 section predated the language-agnostic core and the skip guidance, so the changelog folds [Unreleased] into it, adds the runner-less-skip entry, re-dates the release, and leads with what changed for users. The measured claims follow the A/B case document's boundaries verbatim: what the old check wrongly blocked and what an honest green cost, with n stated — and nothing the experiment ruled out. README status rows across all six variants move to 281 features (277 done). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Release notes for 0.9.4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
2026-08-26 · develop → main · release 0.9.4The language check reads your sources instead of your build manifest — projects it wrongly blocked now pass honestly — the module-honesty scan works for any language the spec teaches it, the gate config survives a fresh clone, and cladding proves its own host hooks fired.
What ships (folded 0.9.4 — full text in CHANGELOG.md)
▸ Evidence-based language check — the old comparison wrongly blocked 12 of 32 realistic shapes (measured); the new one blocks none, loses no drift catch, and on the motivating C++-under-Gradle shape an honest green went from impossible to 3/3, ~21% cheaper (blinded A/B, n=3, control NULL — docs/ab-evaluation/case-version-ab-093-vs-next.md).
▸ Self-describing module-honesty scan — no more vacuous pass on cpp/java/csharp; declared layer globs are honored; an empty scan discloses itself.
▸ Committable gate config —
.cladding/config.yamlfinally survives a fresh clone; legacy projects get a doctor report, never a rewrite.▸ Runner-less skips name their exit — one line pointing at
gate.commandswhen checks skipped for lack of a runner.▸ Live host-hook health, stop/completion telemetry, pinned generated CI, attestation policy identity, MCP SDK security refresh (the original 0.9.4 prep).
Verification
▸ Full suite 2981/2981 · conformance corpus 33/33 (Iron Law L4) · strict pre-push gate GREEN · CI green on every constituent PR (#253 #255 #256 #257 #258) · two external packed-tarball E2E campaigns · blinded version A/B with pre-registered claims boundaries.
🤖 Generated with Claude Code