docs: record rules conformance, import contract, and round-trip law
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.
This commit is contained in:
parent
7270359d14
commit
44abc12e80
@ -240,3 +240,19 @@ source.
|
||||
Yams and its bundled `CYaml` / libyaml-derived C parser are compatibility
|
||||
references for PureYAML. They should guide test cases and behavior questions.
|
||||
They are not source material to copy into this package.
|
||||
|
||||
## Round-trip law
|
||||
|
||||
PureYAML keeps the parser (`PureYAML.parse`) and the emitter (`PureYAML.dump`)
|
||||
as separate hand-written implementations, not one invertible grammar. The
|
||||
guarantee they jointly hold is a fixed point over the emitter's normal form, not
|
||||
a bijection over arbitrary author formatting (the surface-to-model relation is
|
||||
many-to-one: spacing, flow vs block, and comments do not survive into the model):
|
||||
|
||||
- Lambda1 (model fidelity): for a `Model.Value` `x`, `parse(dump(x)) == x`.
|
||||
- Lambda2 (idempotence): `parse(dump(parse(s))) == parse(s)` for any input `s`.
|
||||
|
||||
These are enforced as gates, not hoped for: corpus and generated-document
|
||||
round-trip tests assert reparsed equality, and the empty-collection degenerate
|
||||
values are pinned as passing regressions. `dump` is total: no force-unwraps, and
|
||||
every empty collection renders to `[]` / `{}` at every position.
|
||||
|
||||
13
docs/package-import-contract-status.md
Normal file
13
docs/package-import-contract-status.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Package import contract status
|
||||
|
||||
One row per target. The contract: the library target imports nothing beyond the
|
||||
Swift standard library; the test target imports only `PureYAML`, `Testing`, and
|
||||
`Foundation`.
|
||||
|
||||
| Target | Allowed imports | Actual | State |
|
||||
|---|---|---|---|
|
||||
| `PureYAML` (library, `Sources/`) | Swift standard library only (no `Foundation`, no external packages) | zero `import` statements | matches |
|
||||
| `PureYAMLTests` (`Tests/`) | `PureYAML`, `Testing`, `Foundation` | `@testable import PureYAML`, `import Testing`, `import Foundation` | matches |
|
||||
|
||||
Enforced mechanically by `scripts/check-forbidden-patterns.sh` (no `import` in
|
||||
`Sources/`) and `Package.swift` (`dependencies: []`).
|
||||
74
docs/rules-conformance.md
Normal file
74
docs/rules-conformance.md
Normal file
@ -0,0 +1,74 @@
|
||||
# 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-encoding
|
||||
`Data` clauses 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-case `Model.Value` enum, 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" (one `ParserPrinter`):
|
||||
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
|
||||
in `docs/DESIGN.md`.
|
||||
- `code-style.md` file-naming: the repo uses folder-based bare names in some
|
||||
folders (`Parsing/`) and dotted `<Namespace>.<Type>.swift` in 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.md` Rule 14 (`///` on every public decl): the non-trivial public
|
||||
entry points are documented; the remaining gap is the MAY-skip categories
|
||||
(`Codable` conformance 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.
|
||||
Loading…
Reference in New Issue
Block a user