The gate judges the sources on disk, not the build manifest - #255
Merged
Conversation
…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>
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 · feature/language-agnostic-core → developThe language check now judges the sources on disk instead of the build manifest, the module-honesty scan derives its universe from evidence instead of a six-language table, and the gate config becomes committable — so a fresh clone and CI finally see the same gate the author tuned.
Changed
▸ One language vocabulary, evidence-based mismatch detection. The extension→language map moves to the foundation tier and both the onboarding scan and the detectors read it. The detector's rules: a language it does not know, or a tree with under five classified files, produces silence; a declared language absent from the sources warns with the observed distribution; a minority presence under 10% is disclosed at info and never blocks. Gate-command selection still uses the manifest chain — "what do we run" and "what is this project" are different questions, and only the second one moved.
▸ The module-honesty scan is language-independent. Its universe is now the union of observed known extensions and the extensions of modules the spec claims under its layer roots, with scan roots inferred from the claimed paths (the Kotlin source-set layout comes out of inference, not a table). A layer that declares its own
modulesglobs is scanned exactly where its declaration points, and an empty full scan discloses itself with one info instead of passing silently. Previously, declaring cpp, java, or csharp fell through to a*.tsglob that matched nothing.Fixed
▸ The gate config can be committed.
clad initused the directory exclusion.cladding/, and git never re-includes under an excluded directory — so.cladding/config.yamlwas impossible to commit and CI silently ran a different gate than the author tuned. New projects get.cladding/*plus!.cladding/config.yaml; existing projects are never rewritten —clad doctorreports a blocked gate config in text and JSON instead.Verification
▸ Impl-blind oracles: 59 conformance tests across three suites, authored from the spec contracts only, in contexts that could not read the implementations — all passing on first contact.
▸ Adversarial corpus: 32 realistic repo shapes (polyglot Android/NDK/JNI, React Native, vocabulary-gap languages, unknown languages, true-drift controls, boundary attacks) — implementation matches an independently written reference on every shape; zero blocked false positives, zero missed drifts.
▸ External E2E, twice: packed tarball into an isolated npm prefix (dist SHA-256 proven identical to the repo build), real-shape subjects outside the repo — 7/7 cells at the feature commits, 6/6 at the final commit, including the decisive re-measurement: the Gradle-driven C++ SDK shape passes strict with no declaration of any kind. The E2E also caught one defect (layer names that are not path segments produced a silent empty scan) which is fixed in this branch, and four smaller findings recorded as backlog rows B12–B15.
▸ Full suite 2953/2953 · strict pre-push gate GREEN · every feature completed through
clad done.🤖 Generated with Claude Code