Add docs/rules-conformance.md documenting how the repo conforms to the vendored canon, the documentation.md vs dependency-free conflict and its scoped resolution, the domain-mismatched rules that do not apply, and the conscious deviations. Add docs/package-import-contract-status.md. State the round-trip law (Lambda1/Lambda2) in DESIGN.md.
4.2 KiB
Rules conformance
This records how PureYAML conforms to the vendored Swift rules canon
(docs/rules-swift/, mirror of rules-swift), including the few places where a
canon rule does not apply to a dependency-free YAML library or conflicts with a
project non-negotiable. Per docs/rules-swift/core/rules.md, conflicts are
resolved by scope: the condition under which each rule applies is named, so
exactly one governs any case.
Conformant (applicable rules)
Every applicable rule passes its acceptance check. Mechanically verified:
check-style, check-namespacing (now namespace-aware, catches one-type-per-file
inside extension blocks), check-forbidden-patterns, check-changelog-touched,
check-roadmap, swiftformat --lint, swiftlint --strict, swift build,
swift test (277 tests). Concurrency, dependency-injection, cross-platform,
framework-policy, namespacing (anchor choice), folder-grouping, domain-first, and
the no-shortcuts mechanical tells are all clean.
Conflict: documentation.md Rule 1 vs the dependency-free non-negotiable
documentation.md Rule 1 mandates a DocC catalog plus swift-docc-plugin as a
package dependency. PureYAML's binding non-negotiable (CLAUDE.md,
AGENTS.md) is no external SwiftPM dependencies (dependencies: []). Both
cannot hold. Resolution by scope: the dependency-free invariant is the
higher-stability project contract and wins. PureYAML is therefore exempt from
documentation.md Rule 1's plugin requirement. API documentation lives in
source /// comments and docs/. If a maintainer later accepts a build-time
plugin dependency, this exemption is revisited.
Not applicable: domain-mismatched canon files
Several canon files describe other domains (OpenAPIKit data parsing, an After-Effects-style tool, app startup, UI). Their domain-specific clauses do not bind a dependency-free YAML library; the transferable clauses are satisfied.
parsing-rules.md: the CSV/XML/Excel/Codable-record and multi-encodingDataclauses are N/A; the applicable parse-then-validate separation and enum-with-associated-values clauses pass.validation-rules.md: the OpenAPI component-store /$ref/ type-erasure and "validate-or-exclude every public type" coverage-gate clauses are N/A (the input model is the 5-caseModel.Valueenum, handled exhaustively, so no input is silently dropped). The applicable rule/validator/issue-path clauses pass.business-rules-and-constraints.md: entirely N/A (no external services, auth, PII, or compliance surface in an offline library).ui/*,openapi-generated.md,exp/app-target.md: N/A (no UI, not generated, no app target).
Conscious deviations (intent met another way)
core/round-trip-transformation.md"by construction" (oneParserPrinter): PureYAML keeps a hand-written parser and emitter rather than a single invertible algebra, because a bijective ParserPrinter is not a faithful model of full YAML (block/flow, anchors, tags, chomping, comments; surface-to-model is many-to-one). The law it protects is enforced by a fixed-point gate:parse(dump(parse(x))) == parse(x)over the corpus and generated documents, plus the empty-collection adversarial regression. The round-trip law is stated indocs/DESIGN.md.code-style.mdfile-naming: the repo uses folder-based bare names in some folders (Parsing/) and dotted<Namespace>.<Type>.swiftin others (Tagged/,Validation/). Both are blessed patterns; the standing convention is dotted for new namespaced files. A full rename to one pattern is deferred as disproportionate churn against the highest-stability rename surface.documentation.mdRule 14 (///on every public decl): the non-trivial public entry points are documented; the remaining gap is the MAY-skip categories (Codableconformance members,CustomStringConvertible.description, self-describing data fields). Tracked, not blanket-filled.
Historical commits
A few commits that predate the commit-message hook have non-Conventional or
over-72-character subjects. They are already on origin/main; rewriting pushed
history is out of scope. The commit-msg hook now enforces Conventional Commits
and the 72-character subject limit going forward.