signalkrebs is a fail-closed concurrency gate. The cardinal rule mirrors its siblings marmorkrebs and einsiedlerkrebs: a result only counts with evidence. Every degenerate state is an explicit non-passing verdict, never a silent green.
npm install
npm run build # tsc → dist/
npm run check # tsc --noEmit
npm test # unit tests (node --test)
npm run validate:detector go-race # prove a lane catches a planted race, fail-closed
npm run validate:detectors # every lane whose toolchain is presentCommit messages use Conventional Commits (feat:, fix:, docs:, chore:), like marmorkrebs.
A lane is one DetectorAdapter (src/types.ts) plus its fixtures and a validator
spec. The adapter owns everything language-specific and returns the normalized
ConcurrencyResult; the runner drives it and applies the fail-closed verdict.
DetectorAdapter has four methods:
resolveExercise(repoDir, touchedFiles)— map touched files to the packages/targets that must be exercised, and report which the test suite actually reaches (unexercisedPackagesdrives theinsufficientverdict). Populatestresswith the parallelism the detector actually ran under; a passing run must reflect ≥2-way parallelism.runDetector(repoDir, exercise, config)— run the dynamic detector under the stress budget over the exercised packages; return raw defects plusExecEvidenceso the runner can fail closed on spawn/timeout/signal. A non-zero exit with a parsed race is the detector working, not an error — only treat a non-zero exit as an error when nothing was parsed and the output is a build failure.lint(repoDir, touchedRanges)— static anti-pattern scan scoped to touched line ranges. Rules here hard-fail the gate, so every rule must be high-precision. Honor the// concurrency-ok: <reason>suppression pragma (own line or the line directly above). Fuzzy heuristics belong in the hunt skill, not here.runLiveness(config)— run the detector against this lane's planted-defect fixture and confirm the defect is caught this run.
A new lane is added to QUARANTINED_TOOLS in src/runner.ts and stays there until it
ships all three of:
fixtures/<lane>/— a project carrying a planted defect the detector must catch.fixtures/<clean-lane>/— a correctly-synchronized twin the detector must not flag.- A spec in
scripts/validate-detector.mjsasserting: the planted defect is caught, the clean twin is clean, and with the toolchain hidden from PATH the run fails closed (neverclean/defect).
npm run validate:detector <lane> must pass against the real toolchain before the lane
leaves quarantine. A detector's unit tests feed it hand-shaped input and cannot prove it
catches a race on the host — only the live validator can. This is the exact discipline that
would have caught marmorkrebs' gomu lane shipping broken for three weeks.
Do not add a code path that returns clean when:
- the lane was not proven live this run (
lane-dead), - the touched code was not exercised under real parallelism (
insufficient), or - the detector spawn/timeout/parse failed (
error).
If you are unsure whether a state should pass, it should not. Fail closed.