Skip to content

fosmvvm-doctor and the complete review coverage register - #141

Merged
foscomputerservices merged 10 commits into
mainfrom
feat/fosmvvm-doctor
Aug 25, 2026
Merged

fosmvvm-doctor and the complete review coverage register#141
foscomputerservices merged 10 commits into
mainfrom
feat/fosmvvm-doctor

Conversation

@foscomputerservices

Copy link
Copy Markdown
Owner

What this delivers

Pre-0.14 projects — those generated before fosmvvm-bootstrap — can now be audited against, and brought to, the bootstrap standard, through a two-tier instrument with one door.

Tier 1 — fosmvvm-doctor

Fourteen deterministic rules (R1–R14) over an AuditedProject read model: build settings, linkage and embedding, test plans, entitlements, deployment floors, and the shared-module pair (ViewModels live in a shared module; it imports no server code). Three front doors: swift run fosmvvm-bootstrap doctor, the SPM command plugin swift package fosmvvm-doctor (zero installation for any package depending on FOSUtilities), and --json on both for CI. Design: docs/work/fosmvvm-doctor-design.md.

A first field run against a real pre-0.14 project produced 14 clean structural findings — and caught one doctor bug (R13 matched @ViewModel in comments and manifests), fixed here with regression tests.

Tier 2 — the fosmvvm-review coverage register

The coverage ledger (.claude/skills/fosmvvm-review/coverage-ledger.md) is the standing derivation: every enforceable truth-layer statement mapped to the check or doctor rule enforcing it, completeness measured rule-by-rule. Its register is fully shipped — 86 checks across ten areas — with each stage verified against drifted code where a target existed, every fold carrying a named truth-layer ground, and the generator skills taught their rules in the same stages. The skill runs doctor before triage; structural errors halt area dispatch; one merged summary keeps the CI contract single (jq '.summary.total.blocker == 0'). The full pipeline is qualified end-to-end (halt path, nine-area dispatch, report contract).

The scaffolder, brought to its own standard

The first full review run over a fresh scaffold found the walking skeleton drifting from doctrine ratified after it shipped. The templates now hold it: a CardFields form contract adopted by wire body and record, identity-derived vmId threaded through the factory, a dedicated CardView, noun-first request naming, the FOS ErrorMiddleware installed (typed rejections no longer flatten to 500s), typed-door server tests including an invalid-body drive, and the test-host seam reduced to arrive with the App State. Verified by re-scaffold and a green test run.

FOSTestingUI

tap(provenBy:) — the witnessed tap: taps and proves the tap landed by its effect, re-tapping once inside the dropped-first-event window. Retires the hand-rolled tap-then-poll helpers consumers had to carry.

Release process

docs/RELEASING.md now states that the scaffold's pin bump is automatic at the Release.version stamp, and adds step 6: template edits calling APIs first shipped in a release land only after its tag exists.

Notes for review

  • Plugin version walks 2.42.0 → 2.63.0 across the stages; FOSUtilities itself is unreleased on this branch (next release carries it all).
  • Full per-stage records live in the local planning file (untracked by design).

…s rules

The doctor: fourteen deterministic rules (R1-R14) over an
AuditedProject read model — build settings, linkage and embedding,
test plans, entitlements, deployment floors, the shared-module pair
(ViewModels live in a shared module; it imports no server code).
Three front doors: a CLI subcommand (swift run fosmvvm-bootstrap
doctor), an SPM command plugin (swift package fosmvvm-doctor) that any
package depending on FOSUtilities gets with zero installation, and
--json on both for CI (Codable Finding/Severity report, contract
tests). --shape moves the shape-dependent rules from unchecked into
the audit.

Design: docs/work/fosmvvm-doctor-design.md. The DocC CreatingAProject
article gains § Diagnosing an existing project; README points existing
projects at the doctor; CI gains a fast standalone lint job. The
Xcode-only-projects checkout requirement is recorded in
docs/deferrals.md.
…as a check

The two-tier instrument completed. The coverage ledger
(.claude/skills/fosmvvm-review/coverage-ledger.md) is the standing
derivation: every enforceable statement in the truth layer mapped to
the check or doctor rule enforcing it — completeness measured
rule-by-rule, never by counting areas. Its register (G1-G26) is fully
shipped: 86 checks across ten areas, including the datamodel area
(junction-table principle), the multi-surface view area (SwiftUI, Leaf,
React — LeafKit renders drift silently empty), the serverrequest-test
area (the typed test door), the live-invalidation pairing, request
naming per the dictionary, tests-never-touch-production, the
behavioral-suite standing scope, existentials answering the
principle's question, DocC discipline, shared-state serialization, and
the one-top-level-App-State doctrine authored into
architecture-patterns.md.

The skill drives both tiers through one door: doctor runs before
triage, structural errors halt area dispatch, one merged summary keeps
the CI contract single. The full pipeline is qualified end-to-end
against a scratch scaffold — halt path, nine-area dispatch, report
contract — and every fold from those runs is in the check text, each
clause carrying a named truth-layer ground. Generator skills learned
their rules in the same stages; verification-target references live
only in local planning files.
Taps a tagged view and proves the tap landed by the effect it causes,
re-tapping once inside the dropped-first-event window a freshly
launched app exhibits. The witness is any observable effect — a view
appearing, the transported operations recording becoming readable —
and the poll absorbs dispatch-and-transport observability only, never
operation behavior: a stub operation records synchronously, so there
is no work to wait out. Retires the hand-rolled tap-then-poll helpers
consumers had to carry. Catalog entry included.
The first full fosmvvm-review run over a fresh scaffold found the
walking skeleton drifting from doctrine ratified after it shipped; the
templates now hold it. The card gains a CardFields form contract
(protocol + localized en/es messages) adopted by both the wire body
and the record; CardViewModel derives vmId from the record's identity
threaded through the factory, and every screen ViewModel uses the
type-keyed singleton form across all three shapes; the card gets its
own CardView, registered for testing; the create request is renamed
noun-first (CardCreateRequest); the server installs FOSMVVMVapor's
ErrorMiddleware, module-qualified — without it, typed validation
rejections flattened to bare 500s, caught by the scaffold's new tests;
BoardServerTests drives both requests through the typed test door,
including an invalid-body rejection proving the validator runs; stubs
speak the reserved-fake vocabulary; the failed-boot shutdown error is
logged; inert lint directives are removed; the scaffold ships
docs/deferrals.md; the public Operations surface carries
customer-frame DocC with call examples.

Also ruled and applied: the test-host seam arrives with the App State
— a skeleton whose only environment is mvvmEnv uses plain .testHost(),
so the payload-free TestConfiguration and its dead overloads are gone
from both shapes; and scaffolds ship no .VersionedTestJSON baselines
by design — the user's own test runs mint their own. Verified by
re-scaffold and a green swift test run.
… step 6

Release.version is what the scaffold's {{FOS_VERSION}} renders from,
so the pin bump happens automatically at the stamp. The ordering rule
that implies: template edits calling APIs first shipped in X.Y.Z land
only after the tag exists, because the skeleton matrix scaffolds and
builds against the network-resolved pin. Tag promptly after the stamp
for the same reason.
The ViewModel scan matched @viewmodel anywhere in any .swift file, so
a comment mentioning the attribute — or a Package.swift manifest doing
so — produced a false R13 finding (measured on the first field run:
two comment mentions, one of them in the manifest itself). The match
is now anchored to the start of a line, where a Swift attribute leads
its declaration, and SPM manifests are skipped as build scripts rather
than module sources. Two regression tests pin both shapes.
…eHeader

The emitter's expected file sets catch up with the template work this
branch shipped: the Fields pair, CardView, the renamed CardCreateRequest
and writer, the messages YAML, docs/deferrals.md, and the removed
test-host seam (both shapes). The full fast suite runs green locally —
the file-set tests were the one suite the template stages' scoped runs
never executed.

The standalone lint job excludes fileHeader from its --lint run: the
header template's {created.year} resolves from filesystem creation
dates, and a fresh CI checkout stamps every file with today's date, so
committed 2024/2025 headers fail on CI while passing locally. Header
enforcement stays local, where the dates are real.
The rule whitelisted Resources/ViewModels/ alone, so the Fields
messages YAML the fields generator prescribes under
Resources/FieldModels/ — and the scaffold now ships — read as a stray,
failing the walking skeleton's doctor-clean assertion. The store's
search is recursive, so both subtrees load; R8 now accepts both, with
a regression test pinning the FieldModels sibling.
CardViewModel gained a required id parameter when vmId became
identity-derived; the factory was updated but the correlation-seam
unit test's three constructions were not — a target that compiles only
under xcodebuild, which none of the SPM-side verification runs reach.
Both app schemes (clientServer and localOnly) now compile
build-for-testing locally, the gate that catches this class before CI.
@foscomputerservices
foscomputerservices merged commit 0892f3e into main Aug 25, 2026
15 checks passed
@foscomputerservices
foscomputerservices deleted the feat/fosmvvm-doctor branch August 25, 2026 19:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant