Adapter contract
Purpose
cofferdam_core::adapter::Adapter is a small, descriptive trait that lets a language pipeline declare its own identity: which Language it produces facts for, which files it claims, and which schema namespace its corpus/graph facts live under. It exists to formalize — as a type, not just prose in a module doc — the shape cofferdam's polylingual architecture already has (the TS pipeline via oxc, the Rust pipeline via tree-sitter in crates/cofferdam-rust), ahead of a larger future refactor that would route dispatch through it.
This is a deliberately scoped-down slice of a larger ticket. It adds the trait and two thin implementations; it does not change how the engine actually parses or dispatches files today.
The trait
pub trait Adapter {
fn language(&self) -> Language;
fn file_globs(&self) -> &[&str];
fn schema_namespace(&self) -> &str;
}language(&self) -> Language— theLanguagevariant (cofferdam_core::source::Language) this adapter produces facts for.file_globs(&self) -> &[&str]— the glob patterns / extensions this adapter claims, mirroring whatLanguage::from_pathalready encodes for that language.schema_namespace(&self) -> &str— the schema-extension namespace this adapter's corpus/graph facts live under (e.g."ts","rust").
The one-way contract (documented, not enforced)
The intended relationship between adapters and checks is one-way: adapters produce facts from source; they do not see rule configuration, and they do not construct Issues directly (that stays the Check trait's job).
This iteration does not enforce that contract. There is no runtime check that stops an Adapter impl from reading rule config or building an Issue, and no test that exercises a deliberate violation. The trait is a type-level description of intent, not a sandbox.
What implements it today
TypeScriptAdapter(crates/cofferdam-core/src/adapter.rs) — describes the existing oxc-based TS/JS pipeline.language()returnsLanguage::TypeScript;file_globs()returns["*.ts", "*.tsx", "*.js", "*.jsx", "*.cjs", "*.mjs", "*.mts", "*.cts"], matchingLanguage::from_path's extension list;schema_namespace()returns"ts".RustAdapter(crates/cofferdam-rust/src/lib.rs) — describes the existing tree-sitter-based Rust pipeline.language()returnsLanguage::Rust;file_globs()returns["*.rs"];schema_namespace()returns"rust".
Both impls are additive metadata: they describe existing behavior without changing it. Neither cofferdam-engine's discovery loop nor its parse/ dispatch loop routes through these impls yet — file-extension dispatch still happens via Language::from_path exactly as before.
Not yet built
The following are explicitly deferred, not implied by this change:
- Runtime forbidden-surface enforcement. No mechanism stops an adapter from reading rule config or emitting
Issues directly, and there is no deliberate-violation fixture test. [adapters]registration incofferdam.toml. Adapters are not configurable or discoverable via config today.- Adapter identity scheme for non-byte-offset findings. Tracked separately; not addressed here.
- A non-TS/non-Rust adapter (e.g. a SQL migrations adapter) as end-to-end proof-of-life that a third language fits the trait shape.
- Engine rewiring.
cofferdam-engine's discovery and parse/dispatch loops are untouched; they do not consultAdapterimpls at runtime.