Rulebearing Playground Coverage Schemas GitHub

Architecture Decision Records

Every decision that shapes Rulebearing's design is recorded here as an Architecture Decision Record (ADR). The format and the process are set by ADR-0001. Each ADR links to the section of the design document it derives from, to the architecture section it constrains, and to the plan that implements it.

A rule in rulebearing.yaml cites a decision with the token adr:NNNN in its comment. The same convention applies to this repository's own rules once wave 1 lands.

ADR Title Status
0001 Record architecture decisions, plans and artifacts in docs/ Accepted
0002 Rust as the implementation language, one static binary Accepted
0003 The .NET extractor falls back to a C# dotnet tool on a measured trigger Superseded by 0022
0004 The graph document is an additive superset of dependency-cruiser's cruise-result schema Accepted
0005 A native config format that is a strict superset, and dependency-cruiser's format accepted as is Accepted
0006 JavaScript configs are evaluated in a sandboxed embedded QuickJS engine Accepted
0007 A rule whose selection is empty fails by default Accepted
0008 Exit codes: error count, 2 for an untrustworthy run, 3 for an invalid config Accepted
0009 dependency-cruiser's and ArchUnitNET's test suites are the specification Accepted
0010 Crate layout: extractors behind a feature-gated boundary, the engine language-agnostic Accepted
0011 .NET edges come from built assemblies and portable PDBs, not C# source Accepted
0012 oxc_parser and oxc_resolver for TypeScript and JavaScript Accepted
0013 ruff_python_parser and a versioned stdlib list for Python Accepted
0014 No cross-language edges are invented Accepted
0015 Every violation carries a stable id and a line and column Accepted
0016 Linear-time regex engine, with --strict-compat for portability Accepted
0017 CoffeeScript and LiveScript run through a Node sidecar Accepted
0018 70% line coverage is a required check on every crate and wrapper Accepted
0019 MIT licence Accepted
0020 One name, rulebearing, on every registry Accepted
0021 The command line with the agent reporter is the primary agent surface; MCP and LSP are additive Accepted
0022 The .NET extractor stays the Rust metadata reader; the C# fallback is not invoked (trigger figure 0.9929) Accepted
0023 Documentation links are checked on every compile, and every language has a configured linter behind one entry point Accepted
0024 Test quality is gated by mutation testing, property tests and snapshots, not by coverage alone Accepted
0025 CI runs least-privileged, pinned and bounded, and the dependency supply chain is closed Accepted
0026 One crate-scoped licence exception: BSL-1.0 for dragonbox_ecma, which oxc requires Accepted
0027 The configuration sandbox offers pure path and url modules; every other Node built-in stays behind --config-via-node Accepted
0028 Backreferences are matched by instantiation on the linear-time engine; lookaround stays refused Accepted
0029 Ratchets are enforced by cruise and reported in summary.ratchets[]; a missing budget exits 2 Accepted
0030 The reporter decides whether the error count is the exit code, as in dependency-cruiser; 2 and 3 do not depend on it Accepted
0031 A saved result carries everything the exit code counts: summary.expired[]; fmt --exit-code reads it and vacuousRules Accepted
0032 Liveness follows the configuration's format: warn for a dependency-cruiser file, strict for a native one; named exceptions in allowEmpty Accepted
0033 One crate-scoped licence exception: Apache-2.0 WITH LLVM-exception for ar_archive_writer, which the Python parser's build requires Accepted
0034 A slice groups .NET types or TypeScript and Python modules; (*) names a slice as ArchUnitNET does; segments keeps the first segments Accepted
0035 The code layer holds the types the analysed code references, as ArchUnitNET's ReferencedTypes Accepted
0036 Markdown fences are read for a native configuration; a dependency-cruiser one keeps upstream's extraExtensionsToScan Accepted
0037 baseline has three modes of Rulebearing's own (full, shrink-only, format); dependency-cruiser has none Accepted
0038 A rule narrows the graph it sees: graph.ignore, graph.dependencyTypesNot, graph.modulesNot, graph.chainsThrough; import-linter's filters are written with it Accepted
0039 The delivery plans and the exported design are kept local; the link check skips links into them on CI only Accepted
0040 A TypeScript 7 tsconfig resolves as TypeScript resolves it where dependency-cruiser's tsconfig-paths departs; the tsconfig's module decides what is compiled for acorn Accepted
0051 A rule redirects the imports it sees: graph.redirect leads an import to another module; the import-linter importer writes it where grimp, with include_external_packages, attributes an import of an unwalked module to a module it walks Proposed
0052 --affected follows the configuration format: dependency-cruiser's reaches filter byte for byte for a dependency-cruiser configuration, the closure with every violation touching it for a native one; the .NET and Python modules a change affects, --affected-depth and the summary.affected receipt in both Accepted
0053 x-dot-webpage draws its graph with GraphViz' dot from PATH, as dependency-cruiser does, and only for that output type; rb-report decides, rb-cli spawns Accepted
0058 The edit-compile cycle rebuilds only what changed: the link check runs from xtask-gate, which nothing depends on; dev builds carry line tables; sccache is set per machine Accepted
0059 Gates run by tier (inner loop, step merge, sub-wave close); a pull request mutates the lines it changes, a push to main the whole scope Accepted
0060 The guard's 100 ms is set for a developer machine; the Linux runner gates the unchanged-graph save and holds the graph-changing one to a ceiling Accepted
0061 A type is attributed to a file its developer wrote; a source generator's output under obj/ only when the type is in no other Accepted
0062 The Node binding answers extractTSConfig and extractBabelConfig with the caller's own TypeScript and Babel; every other export is the command line's code through rb-node Accepted
0063 The cache's run start is also read from the clock that stamps files, so an edit in the start's tick on Windows is read again Accepted
0064 A .ts file is parsed as TypeScript when the tsconfig sets jsx; upstream's TSX misparse, which drops imports, is a documented divergence Accepted
0065 No unsolicited offers to other projects: no issue or pull request proposing Rulebearing is opened on a test bed or any other repository; the evidence is published here Accepted
0066 Project scope and the project layer: projects[] mirrors folders[] over the project each module belongs to; scope: project compares projects, native configurations only Accepted
0067 The playground's wasm facade joins the crate table; QuickJS becomes rb-config's js-config feature, which the playground builds without Accepted
0068 NuGet publishes by trusted publishing: nuget-publish exchanges its OIDC token for a one-hour key through NuGet/login; the stored NUGET_API_KEY is deleted after the first such release Accepted
0069 npm publishes by trusted publishing: each package's trust setting names release.yml, npm-publish runs npm 11 and falls back to NPM_TOKEN only for a package the release creates; the token is deleted once all eight have a trust setting Accepted
0070 A new NuGet package ID is first pushed with the stored key: the trusted-publishing key cannot create an ID, so a 403 is retried with NUGET_API_KEY, which is kept; amends ADR-0068 Accepted
0071 The rule library ships from this repository: presets/frameworks/ is published as rulebearing-rules / Rulebearing.Rules by release.yml at the release version; the second repository is archived; amends FR-REACH-04 Accepted
0072 The docs site is generated from the tracked docs/ by a small TypeScript generator on markdown-it, with the link check's anchors and a no-inline-script policy; one Pages deployment from main serves it with the schemas of the latest release, and release.yml no longer deploys Pages Accepted
0073 The extractors read files through rb-model's Files (the disk by default, a tree in memory for the playground); explain, its sentences, wants_metrics and optionsUsed move into rb-rules and rb-config; rb-wasm may link both extractors Accepted
0074 The cookbook's question pages are fixtures under cookbook/questions/, beside the guard catalogue: a runner holds their converted form, violations and imported contracts to the binary in the guards job and the docs build, and the site renders each page from those files with a playground preloaded with its repository; amends plan 0004 Step 5's paths Proposed
0075 The coverage tabs' rows are kept in a tracked ledger (conformance/ledger/) with each row's evidence; the gates write per-item results under target/conformance/, a row is proven only when all its evidence holds, and the nightly writes site/data/coverage.json by pull request; amends ADR-0039 for the tabs' rows Proposed
0076 Usage counts are counted and printed on the machine, and not sent: telemetry.enabled counts commands and firing rules per month under .graph/usage/ with salted hashes, --usage-counts print shows the payload, the monthly report and the CI guard run without a send; no send path, HTTP client or send value exists until an ADR names the endpoint; amends plan 0004 Step 13 Proposed
0077 fix --plan prints one verified candidate per template (move, port, invert), the first legal in a fixed order, costed by the import statements the agent edits; legal means can-import allows every added edge and the full evaluation adds no error; cruise --with-plans puts the same plans in the agent report; the eval harness scores fix text on the mutation branch and on violations injected into two .NET oracles Proposed
0078 fleet cruises each repository with its own configuration and cache and evaluates dependency rules over the prefixed union, folding each repository's findings into one report; declared edges attach there only, marked declared with declaredKind and comment; an OpenAPI operation declares an edge only through the x-rulebearing-handler its server document records and a client module that names its operationId exactly Proposed