Skip to content

S002: Rules System

FieldValue
SpecS002
FeatureRules System
Date2026-04-23
StatusDraft
Authorspec-writer-agent

Overview

The Rules System is the core evaluation engine of Parity. It provides a pluggable architecture where each rule is an independent unit that receives an immutable context about a source file and its corresponding test, evaluates a single concern, and returns a pass/fail result. Rules are registered in a central registry, resolved from YAML configuration, and evaluated per-file during the check command.

The system distinguishes between enforced rules (whose failures cause the overall check to fail) and informational rules (which display data but never cause failures). Each rule declares its own parameters, validates them via the registry, and controls how its results appear in output tables. This design allows both built-in rules and third-party plugin rules (see S005) to participate identically in the evaluation pipeline.

Five built-in rules ship with Parity: test-exists (auto-active), enforce-coverage-link, minimum-coverage, matched-coverage, and coverage-attribution. The Rules System depends on coverage data from S003 (Coverage Readers), coverage linking from S004 (Coverage Linkers), configuration from S006, and path mapping from S007. Custom rules extend the system via S005 (Plugin System).

User Scenarios

S002-US-001 [P1] As a developer, I want Parity to check whether each source file has a matching test file so that I can ensure structural parity across my codebase.

S002-US-002 [P1] As a team lead, I want to enforce minimum per-file coverage thresholds so that no source file falls below the agreed standard.

S002-US-003 [P1] As a developer using Pest or PHPUnit, I want Parity to verify that each test file declares which class it covers so that coverage attribution is explicit.

S002-US-004 [P2] As a developer with PHPUnit XML coverage, I want to see how much coverage comes from the matching test file alone so that I can identify files relying on incidental coverage.

S002-US-005 [P2] As a developer, I want informational rules that show coverage attribution without failing the check so that I have visibility into test distribution.

S002-US-006 [P2] As a plugin author, I want a clear interface contract so that I can write custom rules that integrate seamlessly with Parity's evaluation pipeline.

S002-US-007 [P1] As a developer, I want to configure rule parameters per structure block in parity.yaml so that different parts of my codebase can have different thresholds.

Requirements Summary

IDTypePriorityTitleStatus
S002-FR-001FunctionalP1RuleInterface contractDraft
S002-FR-002FunctionalP1RuleResult value objectDraft
S002-FR-003FunctionalP1RuleContext immutable data carrierDraft
S002-FR-004FunctionalP1RuleRegistry registration and lookupDraft
S002-FR-005FunctionalP1RuleRegistry configuration resolutionDraft
S002-FR-006FunctionalP1Parameter validationDraft
S002-FR-007FunctionalP1test-exists ruleDraft
S002-FR-008FunctionalP1enforce-coverage-link ruleDraft
S002-FR-009FunctionalP1minimum-coverage ruleDraft
S002-FR-010FunctionalP2matched-coverage ruleDraft
S002-FR-011FunctionalP2coverage-attribution ruleDraft
S002-FR-012FunctionalP1Enforcement vs informational distinctionDraft
S002-FR-013FunctionalP1Auto-active test-exists ruleDraft
S002-FR-014FunctionalP2Auto-appended PHPUnit XML rulesDraft
S002-FR-015FunctionalP1Per-structure rule configurationDraft
S002-FR-016FunctionalP2Legacy configuration format supportDraft
S002-FR-017FunctionalP1Table output formattingDraft
S002-FR-018FunctionalP1JSON output formattingDraft
S002-IF-001InterfaceP1RuleInterface method signaturesDraft
S002-IF-002InterfaceP1RuleResult static constructorsDraft
S002-IF-003InterfaceP1RuleContext constructor propertiesDraft
S002-IF-004InterfaceP1RuleRegistry public APIDraft
S002-IF-005InterfaceP2YAML configuration schemaDraft
S002-AS-001AcceptanceP1Rule passes when test existsDraft
S002-AS-002AcceptanceP1Rule fails when test missingDraft
S002-AS-003AcceptanceP1Coverage link detected via pest-coversDraft
S002-AS-004AcceptanceP1Coverage link detected via php-attributeDraft
S002-AS-005AcceptanceP1Minimum coverage passes at thresholdDraft
S002-AS-006AcceptanceP1Minimum coverage fails below thresholdDraft
S002-AS-007AcceptanceP2Matched coverage computed from line dataDraft
S002-AS-008AcceptanceP2Coverage attribution shows test countsDraft
S002-AS-009AcceptanceP1Unknown rule name throws exceptionDraft
S002-AS-010AcceptanceP1Invalid parameters throw exceptionDraft
S002-AS-011AcceptanceP1test-exists auto-prependedDraft
S002-AS-012AcceptanceP2PHPUnit XML rules auto-appendedDraft
S002-AS-013AcceptanceP1Enforced rule failure causes check failureDraft
S002-AS-014AcceptanceP2Informational rule never causes failureDraft
S002-AS-015AcceptanceP1Custom plugin rule evaluated like built-inDraft
S002-SC-001SuccessP1All built-in rules independently testableDraft
S002-SC-002SuccessP1Custom rule integration via RuleInterfaceDraft
S002-SC-003SuccessP1Parameter validation prevents misconfigurationDraft
S002-SC-004SuccessP1Enforced/informational distinction correctDraft
S002-EC-001Edge CaseP1Zero coverage percentDraft
S002-EC-002Edge CaseP1100% coverage percentDraft
S002-EC-003Edge CaseP1No test file with coverage rulesDraft
S002-EC-004Edge CaseP2Zero executable linesDraft
S002-EC-005Edge CaseP1Missing required parameterDraft
S002-EC-006Edge CaseP2Empty rules array in configDraft
S002-EC-007Edge CaseP2Duplicate rule in configDraft
S002-EC-008Edge CaseP2Non-numeric coverage parameterDraft
S002-EC-009Edge CaseP2Coverage percent at exact threshold boundaryDraft
S002-EC-010Edge CaseP2Test file exists but is empty/unreadableDraft
S002-EC-011Edge CaseP2Rule name collision between built-in and pluginDraft
S002-EC-012Edge CaseP2No line coverage data for matched-coverageDraft

Cross-Spec Dependencies

  • Depends on: S003 (Coverage Readers provide coveragePercent, lineCoverage, coveringTests), S004 (Coverage Linkers used by enforce-coverage-link), S006 (Configuration provides min_coverage defaults and structure rule arrays), S007 (Path & Namespace Mapping resolves test file paths and FQCNs)
  • Required by: S001 (CLI check command evaluates rules), S005 (Plugin System extends via RuleInterface), S008 (Output Formats consume RuleResult and formatCell)