[PLAN-0007] Milestone 7: Dogfooding¶
Status: Done
Implements: ADR-0029 (dogfooding strategy, migration-driven evidence, gap decision rubric and five-way classification, required deliverables, bug handling, evidence- driven restraint, and Amendment 4's documentation-architecture deliverable), ADR-0030 (the documentation architecture Phase 5 produces)
Goal¶
ncipollina/cosmere-tracker's AutoFixture-based test kit (test/Cosmere.Tracker.TestKit) is fully, idiomatically migrated to Compono; every discovered finding (the three known candidate gaps plus any further one surfaced) is classified per ADR-0029 (bug / roadmap candidate / acceptable alternative / intentional design difference / migration-only friction) and recorded; docs/migrating-from-autofixture.md is substantially complete; docs/roadmap/post-mvp.md exists and traces every entry to real evidence; Phase 4's final architectural conclusion answers whether dogfooding changed Compono's overall design direction; and Phase 5 produces the complete documentation architecture (ADR-0030, docs/documentation-architecture.md), an initial documentation skeleton, the migration guide's promotion decision, and a scoped Milestone 8 documentation backlog. docs/mvp.md's Milestone 7 and Milestone 8 sections reflect all of the above.
Scope¶
Per ADR-0029's Decision Outcome (including Amendment 4) and docs/mvp.md's Milestone 7 section:
- Migrating
cosmere-tracker'sCosmere.Tracker.TestKitand its consuming test projects (Cosmere.Tracker.Api.Tests,Cosmere.Tracker.Shared.Tests,Cosmere.Tracker.Seeder.Tests) from AutoFixture/AutoFixture.AutoNSubstitute/ AutoFixture.Xunit3 to Compono/Compono.XunitV3/Compono.NSubstitute/Compono.Bogus, favoring idiomatic Compono over a mechanical 1:1 translation (ADR-0029's "Migration idiom") — this happens in thecosmere-trackerrepo, not this one.Compono.Bogusadoption is mandatory, per ADR-0029's "Compono.Bogus adoption is mandatory" — unlike the other packages, there's no existing AutoFixture call site to migrate away from, so it requires deliberate investigation ofcosmere-tracker's domain models rather than falling out of the migration automatically. Per Amendment 1, what's mandatory is the experiment (the investigation and adoption attempt), not a predetermined positive conclusion — a recorded finding thatCompono.Bogusis a poor fit for some or all of the surveyed members is an equally valid outcome. - Recording quantitative and qualitative evidence — including positive findings, not only friction — for the three known gaps (
Freeze<HttpMessageHandler>inHttpClientSpecimenBuilder,AutoNSubstituteCustomization { ConfigureMembers = true }inBaseFixtureFactory,OmitOnRecursionBehaviorin the same factory) and any additional finding the migration turns up, per ADR-0029's "Evidence to collect." - Applying ADR-0029's rubric to classify every finding and producing its recorded outcome in this repo (
docs/research/0001-autofixture-comparison.mdplus the resulting ADR(s)/Amendment(s)/bug-fix PR(s)). - Writing and maintaining
docs/migrating-from-autofixture.mdas a living document throughout the migration, not after it. - Producing
docs/roadmap/post-mvp.mdfrom only the "roadmap candidate" findings. - Updating
docs/mvp.md's Milestone 7 section with the outcome, including the Phase 4 final architectural conclusion. - Per Amendment 4 and ADR-0030: designing Compono's complete documentation architecture (hierarchy, section purposes/audiences/ordering, how forward-looking content stays separated), recorded in
docs/documentation-architecture.md; creating the initial documentation skeleton matching that hierarchy; deciding (and recording) the migration guide's promotion into the primary hierarchy; and producing a scoped documentation-work-item backlog that becomes Milestone 8's own deliverables.
Explicitly deferred (per ADR-0029's "Evidence-driven restraint"): designing the actual API for any finding classified "roadmap candidate" — that finding's Proposed ADR records the problem only, left for a future milestone's own design pass. The one exception is a blocking bug, which may be fixed in its own scoped PR per ADR-0029's "Bug handling."
Phase 0: Baseline and migration-guide skeleton¶
Status: Done
- In
cosmere-tracker: capture a written baseline of the current AutoFixture-based test kit before any Compono change, per ADR-0029's "Evidence to collect" — file/line counts forCosmere.Tracker.TestKit, count of[CosmereTrackerAutoData]/[InlineCosmereTrackerAutoData]call sites across the 18 test files, currentdotnet testrun time, a short readability note per existing fixture-related file (BaseFixtureFactory,CosmereTrackerCustomization,HttpClientSpecimenBuilder,HttpClientSpecification), and the broader maintainability dimensions (framework-specific concepts in play, custom fixture infrastructure present, setup visible per test method, concepts a new contributor would need to know today). Recorded indocs/research/0001-autofixture-comparison.md's new "Baseline (Phase 0)" section — 72 tests passing in 1.346s test-execution time, 8 files/218 lines inCosmere.Tracker.TestKit, 1+7 AutoData call sites, plus one previously-undocumented finding: a three-tier fixture stack (Cosmere.Tracker.TestKit→Cosmere.Tracker.Shared.TestKit→ per-suite local kits) not called out in ADR-0029's Context, and zero live call sites for[ClientAutoData]/[InlineClientAutoData]in the three consuming test projects (gap 1'sHttpClientSpecimenBuilderpath is only exercised from within the test kit's own definitions today — worth confirming during Phase 1). - Confirm the exact
cosmere-trackercommit this baseline was taken against (fordocs/research/0001-autofixture-comparison.md's link back) —2dbd62ec73a8d8ad64b865a22d7b34a056ca537d. - Create
docs/migrating-from-autofixture.mdin this repo with its planned structure and the major AutoFixture concepts expected to be migrated (Freeze<T>(),AutoDataAttribute/ customizations,AutoNSubstituteCustomization, recursion behaviors, specimen builders, and any other conceptcosmere-tracker's test kit exercises) — drafted before migration begins, per ADR-0029's "Required deliverables." Reserve a section forCompono.Boguseven though it has no AutoFixture-side concept to contrast against — it documents an added capability, not a migrated one. Content per concept is filled in during Phase 1, not now. Also reserved sections for two concepts discovered during the baseline survey that ADR-0029 didn't name: reflection-based NSubstitute stubbing (HttpMessageHandlerExtensions) and the multi-tier fixture stack. - Survey
cosmere-tracker's domain models (src/Cosmere.Tracker.Shared/Models/**and any DTOs undersrc/Cosmere.Tracker.Api/Dtos/**) for string-typed members that plausibly warrant realistic data (book titles, character names, world names, etc.) — the starting candidate list for Phase 1's mandatoryCompono.Bogusadoption. Candidates:BookItem.Title/BookDto.Title,CharacterItem.Name/CharacterDto.Name,WorldItem.Name/WorldDto.Name,WorldItem.SystemName/WorldDto.SystemName— recorded in the migration guide'sCompono.Bogussection, along with why*Normalized/Id/timestamp members were excluded.
Phase 1: Migrate the test kit¶
Status: Done
- Replace
Cosmere.Tracker.TestKit's AutoFixture package references withCompono/Compono.XunitV3/Compono.NSubstitute/Compono.Bogus—Compono.Bogusinclusion is mandatory (ADR-0029), not conditional on the migration happening to need it. Referenced as publishedalphaprereleases from nuget.org (pinned incosmere-tracker/Directory.Packages.props, currently0.1.0-alpha.33) — a local NuGet feed packed from this repo's source was tried first and rejected, sincecosmere-tracker's own GitHub Actions CI has no siblingcomponocheckout to pack from and would fail to restore. - Replace
CosmereTrackerAutoDataAttribute/InlineCosmereTrackerAutoDataAttribute(and the three sibling per-project wrapper pairs:ClientAutoDataAttribute,EndpointAutoDataAttribute,PersistenceAutoDataAttribute) with[Compose<TProfile>]/[Compose], per ADR-0022's shape — all four removed entirely (ADR-0029's "Migration idiom"); documented in the migration guide. A further finding beyond scope: pure-inline[Theory]rows (TextNormalizerTests) need no Compono attribute at all, just plain[InlineData]— and[Compose]/[Compose<TProfile>]isAllowMultiple = false, so AutoFixture's "stack multiple[InlineAutoData(...)]rows, each with a composed parameter" idiom has no direct Compono equivalent (not hit by any realcosmere-trackertest, but recorded as a discovered constraint). - Port
CosmereTrackerCustomization's intent into anICompositionProfile(ADR-0018) — turned out to be an empty stub with no real intent to port, deleted outright.SharedCustomization(real logic) becameSharedTestKitProfile. - Migrate
HttpClientSpecimenBuilder's frozen-HttpMessageHandlerpattern. Confirmed zero real call sites anywhere incosmere-trackeroutsideCosmere.Tracker.TestKit's own definition files — this is gap 1's finding (per the rubric's question 1, "zero observed frequency"). Ported anyway, by explicit request, asClientTestProfile/IHttpClientProvider(Cosmere.Tracker.TestKit/Http/,Cosmere.Tracker.TestKit/Profiles/) with a real capability test (ClientTestProfileTests) — zero frequency doesn't mean "delete," a capability the repo owner will need is kept working and documented, not dropped just because nothing uses it yet. This surfaced a real, further finding beyond gap 1's original framing:HttpClientcannot be composed directly as a Compono test parameter at all — its 3 accessible constructors tripCompono.Generators' compile-timeCMP0001diagnostic regardless of any runtime registration/rule, since the generator has no visibility intoCompositionBuilderregistrations (ADR-0002's own anticipated[CompositionConstructor]disambiguation attribute was never implemented). Worked around by composingIHttpClientProvider(an interface, always a provider-resolved leaf) instead ofHttpClientdirectly — full before/after and the workaround in the migration guide. Separately, real[Frozen]-for-substitute usage was found elsewhere (~30 call sites, see gap 2 below) — most needed no[Shared]equivalent at all (zero workaround cost), a handful of genuine cross-object-sharing call sites (CosmereTrackerRepositorypersistence tests) mapped directly to[Shared]at equally low cost. Recorded in the migration guide. - Migrate
AutoNSubstituteCustomization { ConfigureMembers = true }usages toUseNSubstitute(). Real evidence found: most call sites had zero workaround cost (plain composed parameter replaces[Frozen]); genuine sharing call sites mapped to[Shared]at equally low cost; and two tests (ListWorldsAsync_WhenSortEmpty_DefaultsToName,ListCharactersAsync_WhenSortEmpty_DefaultsToName) surfaced a real, previously-hidden dependency onConfigureMembers' auto-configured return values — fixed with an explicitReturns/ReturnsForAnyArgsstub each test should arguably have had regardless. All recorded with before/after snippets in the migration guide (gap 2's evidence). - Migrate away from
OmitOnRecursionBehavior— zero construction-cycle failures were ever triggered during this migration; none ofcosmere-tracker's composed types form a self-referencing graph. This "zero observed frequency" is itself gap 3's Phase 1 finding, recorded in the migration guide. - Adopt
Compono.Bogusagainst the Phase 0 candidate list (BookItem.Title,CharacterItem.Name,WorldItem.Name/SystemName). Real finding:BogusMemberNameProvider's exact member-name matching can't disambiguateCharacterItem.Name(a person's name) fromWorldItem.Name(a place name) sharing the literal member name"Name"— the built-in convention/alias/custom- convention path doesn't fit. Adopted instead viabuilder.UseBogus<T>(faker => ...)— Compono.Bogus's own whole-object sugar — per type, withRuleFor(including sibling-property access forTitleNormalized/NameNormalized/UpdatedAtderived fields). An earlier version of this task bypassedUseBogus<T>()for a hand-rolledRegister<T>factory on the incorrect claim that its callback has no access to the resolvingICompositionContext— caught in PR review:UseBogus<T>already seeds theFaker<T>fromcontext.DeriveSeed()internally before invoking the callback, so there was never a reason to bypass it, and doing so meant this task initially recorded successful dogfooding without ever calling aCompono.BogusAPI. Corrected to useUseBogus<T>()directly. Recommendation recorded in the migration guide: a genuine win for semantic string fields, not just a tradeoff (ADR-0029 Amendment 1). Phase 0's candidate list also named the DTO side of each pair (BookDto.Title,CharacterDto.Name,WorldDto.Name/SystemName) — confirmed during Phase 1 that none ofCosmere.Tracker.Api's DTOs are ever composed as a test parameter anywhere incosmere-tracker; they're production API-response types built by mapping code from the already-Bogus-adopted*Itemtypes, so there was no separate composition call site to adoptCompono.Bogusagainst. Recorded in the migration guide alongside the*Itemfindings. - Further findings recorded (beyond the three named gaps):
DynamoDbResponseSpecimenBuilderhad zero real call sites and was dropped entirely;HttpClientSpecimenBuilder's equivalent (ClientTestProfile/IHttpClientProvider) also had zero real call sites but was ported anyway, by explicit request, and now has a real capability test (ClientTestProfileTests) exercising the previously- uncalledHttpMessageHandlerExtensionshelper too;HttpClientcannot be composed directly as a Compono parameter at all (CMP0001, see above);[Compose]'sAllowMultiple = falseconstraint (see above). No blocking bug found — all 73cosmere-trackertests pass under Compono (dotnet test Cosmere.Tracker.slnx: 73 passed, 0 failed, ~1.2s, matching Phase 0's baseline of 72 passed in 1.346s plus the one new capability test). - Updated
docs/migrating-from-autofixture.mdwith every section's real before/after content, in this same change.
Phase 5: Documentation architecture (Milestone 8 blueprint)¶
Status: Done
Per Amendment 4 and ADR-0030 (including Amendment 1). Originally numbered — and originally intended to run — after Phase 4, on the reasoning that the final architectural conclusion (whether dogfooding changed Compono's design direction, whether the public provider model held up, etc.) is direct input to Architecture's content scope. In practice this phase was designed and closed before Phase 2 even started, since the architecture (hierarchy, section purposes, audiences) didn't end up needing that conclusion as an input the way originally assumed — Architecture's actual page content (a Milestone 8 concern) can still incorporate Phase 4's conclusion whenever it lands.
Positioned here, right after Phase 1, to match when it actually ran — a PR review correctly pointed out that leaving this phase physically after Phase 4 while marking it Done and Phases 2-4 Not Started made phase order and status unreliable signals for what to execute next. The label stays "Phase 5" (not renumbered to "Phase 2") since that identifier is already referenced from ADR-0029 Amendment 4, ADR-0030, docs/mvp.md, and PLAN-0008 — renumbering it would cascade edits across all of those for no real benefit, since the identifier itself (unlike its position in this file) was never the thing causing confusion.
- Write ADR-0030 (developer-journey hierarchy adapted from Diátaxis, migration guide promoted to a top-level entry, dedicated Roadmap area for forward-looking content) and Amendment 4 to ADR-0029 (the scope extension this phase executes). Amendment 1 to ADR-0030 records a further refinement round: documentation as a first-class product, a documentation quality bar, the "every page leads somewhere" rule, Cookbook's expected scale, two new top-level areas (Samples, Best Practices), Learning Paths, Architecture's three-way split (Design Principles/Current Architecture/Historical Decision Log), API reference's supplement-not-replace framing, and the package-count- agnostic structure stated explicitly.
- Write
docs/documentation-architecture.md— the living reference: full proposed tree (12 top-level areas after Amendment 1), purpose/ audience/contents/relationships for every section, the documentation quality bar, suggested reading order, and an Open Items list for decisions this architecture deliberately leaves to Milestone 8 (API reference toolchain, Cookbook navigation/tagging at scale, where Sample applications physically live,public-api.md/manifesto.md's eventual disposition). -
docs/mvp.md: Milestone 7 scope/success measures updated for the documentation-architecture deliverable; Milestone 8 scope rewritten to "write, refine, polish, review, and publish againstdocs/documentation-architecture.md" rather than designing from scratch. -
docs/adr/README.mdindex row for ADR-0030. - Create the initial documentation skeleton matching
docs/documentation-architecture.md's tree — 58 stub pages (a "Status: Skeleton" banner, one purpose paragraph, and a link back todocs/documentation-architecture.md), correct directory structure,mkdocs.ymlnav updated to include every one of them (plus "(legacy)"-labeled entries for the pre-existingarchitecture.md/design-principles.md/public-api.md/performance.md/manifesto.mdpages, until Milestone 8 resolves their Open-Item disposition). - Promote the migration guide:
docs/migration/migrating-from-autofixture.mdmoved todocs/migrating-from-autofixture.md(content unchanged); every cross-reference acrossdocs/mvp.md,docs/documentation-architecture.md,docs/research/0001-autofixture-comparison.md, both ADR-0029/ADR-0030, and this plan updated to the new path. - Produce the Milestone 8 documentation work-item backlog: PLAN-0008, a page-by-page Tasks checklist (grouped by
docs/documentation-architecture.mdsection, in its own reading order) plus the non-page Milestone 8 scope items (Open Items resolution, package publishing, benchmark results, known limitations) — indexed indocs/plans/README.md.
All five originally-scoped Phase 5 deliverables are done, matching ADR-0029 Amendment 4's and docs/mvp.md's stated scope exactly — an earlier draft of this section deferred the skeleton/promotion/backlog to Milestone 8 and marked Phase 5 "Done" anyway, which a PR review correctly flagged as silently overriding the accepted scope without formally amending it. Corrected by actually producing them here instead of amending the scope down.
Phase 2: Evidence collection¶
Status: Done
- Post-migration metrics matching Phase 0's baseline shape (file/line counts,
dotnet testrun time, per-file readability notes, and the broader maintainability dimensions from ADR-0029's "Evidence to collect") — enough to compare directly against the baseline. - Explicit named inventory of concepts that disappeared entirely during migration — not just a rough count — per Amendment 2: which of
IFixture,ICustomization,ISpecimenBuilder,IRequestSpecification, the customAutoDataAttribute/InlineAutoDataAttributesubclasses,BaseFixtureFactory,NamedRequest, and any other Phase 0/1-surfaced concept were dropped entirely versus merely replaced one-for-one with a Compono equivalent, and what (if anything) replaced each one. - Per-finding evidence dossier (frequency, before/after snippet, principle-alignment note, classification per ADR-0029's five-way taxonomy) for each of the three known gaps plus any additional finding, including positive findings.
Evidence written into docs/research/0001-autofixture-comparison.md's "Post-migration metrics," "Concepts removed entirely," and "Per-finding evidence dossier" sections, against cosmere-tracker PR #162's merge commit (4d25e14). Findings included: 227 lines/4 files post-migration vs. baseline's 489 lines/14 files across the two directly-comparable tiers (54% line reduction, 71% file reduction — a separate, previously uncounted third tier adds 57 more lines/2 files with no baseline figure to compare against); 73/73 tests passing, with the one measured post-migration run (1s 292ms) 54ms faster than the one measured baseline run (1s 346ms) — reported as the two observed numbers, not a statistical claim, since neither side has repeated samples; a full named-concept inventory including Freeze<T>()/[Frozen] (eliminated at most of its ~30 call sites, replaced by [Shared] where genuine sharing existed) and four concepts beyond Amendment 2's starting list (DynamoDbResponseSpecimenBuilder, dropped for zero call sites; EndpointAutoDataAttribute/PersistenceAutoDataAttribute, folded into the custom-attribute-subclass entry; NoSpecimen, dropped with nothing replacing it; and ISpecimenContext.Resolve, replaced one-for-one by ICompositionContext.Resolve<TValue>()); and ten dossier entries (the three ADR-0029 gaps — including gap 3, recursion behavior, corrected after an earlier draft mislabeled it as the Compono.Bogus finding — the Compono.Bogus finding itself, the Compose-family binding-validation stacking constraint, Compono.Bogus's exact member-name-matching ambiguity, DynamoDbResponseSpecimenBuilder's zero call sites, CMP0001, the three-tier-stack structural finding, and the pure-inline-[Theory] cleanup finding) with first-pass classification leans — final classification is Phase 3's job, not redone here. A PR review on this phase's own PR (#42) went through many rounds — gap mislabeling and missing dossier entries, arithmetic/inventory errors, several ADR-0029 taxonomy misclassifications (caught more than once — the rubric's material-cost/principle-alignment questions and its one-classification- per-finding rule are easy to get subtly wrong), [Compose]'s method-vs-parameter scope (caught in three separate places in this document), and cross-document staleness against the migration guide — each round's fix pushed as its own commit; see this branch's commit history for the full, exact sequence rather than hand-maintaining a chronology here that would only go stale as further rounds land.
Phase 3: Classify findings and produce the roadmap¶
Status: Done
- Finalize
docs/research/0001-autofixture-comparison.md(created in Phase 0 with its baseline section filled in; Phase 2 has since filled in post-migration metrics, the concepts-removed inventory, and the full ten-entry per-finding evidence dossier with first-pass classification leans) — fill in the dogfooding narrative and finalize every finding's classification (below), turning Phase 2's leans into final verdicts. - Classify every finding per ADR-0029's five-way taxonomy and record its outcome:
- Bug — fixed via its own scoped compono PR (if not already done during Phase 1), documented here, no new capability ADR, linked from PLAN-0007's Notes.
- Roadmap candidate — a new
ProposedADR recording the problem only. - Acceptable Compono-native alternative — documented here and in the migration guide; no ADR/Amendment.
- Intentional design difference — a dated Amendment to the governing existing ADR (ADR-0011/ADR-0022 for gaps ⅓, ADR-0025 for gap 2, or whichever ADR governs a newly-discovered gap).
- Migration-only friction — documented here and, where useful, as a migration-guide tip; no ADR/Amendment.
- Close
docs/research/0001-autofixture-comparison.mdwith a## Decisionssection listing exactly which ADR(s)/Amendment(s)/ bug-fix PR(s) each finding fed into. - Create
docs/roadmap/post-mvp.mdfrom only the "roadmap candidate" findings — per finding: capability, why it matters, observed frequency, readability/maintainability impact, and a relative priority (high/medium/low confidence) — each entry tracing back to the migration guide, the research findings, and itsProposedADR.
Every Phase 2 lean was adopted as the final verdict, unchanged — no finding was reclassified during Phase 3. Final split: 0 bug, 0 roadmap candidate, 4 acceptable Compono-native alternative (gap 1, Compono.Bogus mandatory dogfooding, Finding 5, Finding 8), 4 intentional design difference (gap 2, gap 3, Finding 4, Finding 7), 2 migration-only friction (Finding 6, Finding 9). Four dated Amendments recorded the "no change" verdicts and their evidence: ADR-0025 Amendment 2 (gap 2), ADR-0011 Amendment 3 (gap 3), ADR-0022 Amendment 7 (Finding 4), and ADR-0002 Amendment 1 (Finding 7, CMP0001). docs/roadmap/post-mvp.md documents the zero-roadmap-candidate outcome explicitly and points to docs/research/0001-autofixture-comparison.md for the full per-finding reasoning — per ADR-0029, that page lists only roadmap-candidate findings backed by a Proposed ADR, so the non-candidate findings (including CMP0001 and the Compose-family stacking constraint, both plausible future improvements without the evidence to justify a Proposed ADR yet) stay in the research record and their ADR Amendments, not in the roadmap page itself. docs/documentation-architecture.md and mkdocs.yml updated now that docs/roadmap/post-mvp.md is real content, not a skeleton stub.
Phase 4: Final conclusion, docs, and cleanup¶
Status: Done
- Answer ADR-0029's "Final architectural conclusion" questions in
docs/research/0001-autofixture-comparison.md(or a dedicated closing section): manifesto/design-principle language changes, confidence in explicit-over-implicit, whether profiles remained the right primary mechanism, whether the public provider model was sufficient, any MVP success-criterion revisions, and whether Compono is now the default AutoFixture replacement forcosmere-tracker. - Synthesize the above into one explicit, evidence-backed recommendation per Amendment 3 — a stated next action (e.g. Compono becomes the recommended default for new
cosmere-trackertest code; existing tests migrate incrementally rather than in one pass; specific roadmap-candidate findings should land first; or the current MVP is already sufficient as-is), not just a capability statement that Compono can replace AutoFixture. -
docs/migrating-from-autofixture.md: confirm it needs only editorial cleanup at this point, not new content reconstruction — if it doesn't, that's a sign Phase 1's "update alongside the code" rule wasn't followed and should be fixed before closing the milestone. -
docs/mvp.mdMilestone 7 section: links ADR-0029, PLAN-0007,docs/research/0001-autofixture-comparison.md,docs/migrating-from-autofixture.md, anddocs/roadmap/post-mvp.md; states the outcome per finding; success measures checked against the real migration evidence (readability, understandability, profile-first setup, reproducible failures, performance); records the final architectural conclusion. -
docs/adr/README.md/docs/plans/README.mdindex rows for any new ADR(s) opened in Phase 3 (already added for ADR-0029/PLAN-0007 during the design phase).
No new ADR was opened in Phase 3 (only dated Amendments to four existing ADRs), so no new index rows were needed — confirmed both index files already carry accurate Accepted rows for every ADR this plan touched. docs/migrating-from-autofixture.md needed only editorial cleanup as predicted: several stale "Phase 3's call"/"tracked for Phase 3's classification" cross-references, now pointing at each finding's actual final classification and recorded ADR Amendment — no content reconstruction. docs/research/0001-autofixture-comparison.md's "Final architectural conclusion and recommendation" section answers all six ADR-0029 questions and states the recommendation: Compono is the default for all cosmere-tracker test code effective immediately (every AutoFixture reference is already removed from that project's test/ tree — nothing left to sequence incrementally, no roadmap-candidate finding to wait on).
Milestone 7 is complete — all six phases (0, 1, 2, 3, 4, 5) Done.
Critical Files¶
In compono (this repo):
docs/adr/0029-milestone-7-dogfooding-strategy-and-capability-gap-decision-framework.md— the process this plan executesdocs/migrating-from-autofixture.md— new, drafted Phase 0, written incrementally through Phase 1, substantially complete by Phase 4docs/research/0001-autofixture-comparison.md— created Phase 0 (baseline section), the evidence record; finalized (post-migration metrics, classifications,## Decisions) in Phases 2-3docs/roadmap/post-mvp.md— new, the evidence-backed roadmap (Phase 3); zero roadmap-candidate findings, so no newdocs/adr/00NN-*.mdneededdocs/adr/0002-...md/docs/adr/0011-...md/docs/adr/0022-...md/docs/adr/0025-...md— each gained one dated Amendment (Phase 3) for an "intentional design difference" finding (Finding 7/gap 3/Finding 4/gap 2 respectively)- Any scoped bug-fix PR's changed files in this repo, if a blocking bug is found (per ADR-0029's "Bug handling") — linked from this plan's Notes, not enumerated here in advance since it isn't known yet
docs/mvp.md— Milestone 7 section (Phase 4); Milestone 7 and Milestone 8 sections both (Phase 5)docs/adr/0030-compono-documentation-architecture.md— new, Phase 5docs/documentation-architecture.md— new, Phase 5, the living reference Milestone 8 executes againstdocs/documentation-architecture.md's full tree (see that document) — 58 new stub pages for the skeleton, Phase 5docs/migrating-from-autofixture.md— moved here fromdocs/migration/migrating-from-autofixture.md, Phase 5 (content unchanged; every cross-reference to the old path updated)mkdocs.yml— nav updated to match the full skeleton, Phase 5docs/plans/0008-milestone-8-public-preview.md— new, Phase 5, the Milestone 8 work-item backlogdocs/plans/README.md— index row for PLAN-0008, Phase 5
In cosmere-tracker (separate repo, not tracked by this plan's Critical Files beyond noting where the work happens):
test/Cosmere.Tracker.TestKit/**— the AutoFixture-based test kit being migratedtest/Cosmere.Tracker.Api.Tests/**,test/Cosmere.Tracker.Shared.Tests/**,test/Cosmere.Tracker.Seeder.Tests/**— consumers of the test kit
Test Plan¶
The migrated cosmere-tracker test suites passing under Compono, in that repo, is itself the primary verification. This plan does not itself add product code to the compono repo — but per ADR-0029's "Bug handling," a blocking bug discovered during migration may be fixed here through its own scoped PR, following that PR's own normal test plan (tasks/implement.md/testing.md), tracked in this plan's Notes rather than pre-declared here since it isn't known in advance. If a finding's outcome is a "roadmap candidate" that later gets designed and implemented in a future milestone, that future milestone's own plan carries its test plan, per testing.md.
Notes¶
Anything discovered mid-migration that changes this plan's shape from what was originally scoped gets recorded here, not silently absorbed — a plan being wrong about how doesn't require superseding anything, unlike an ADR being wrong about what/why. Any blocking-bug detour (ADR-0029's "Bug handling") is recorded here with a link to its issue/PR as soon as it happens, not reconstructed later.
Phase 1 (2026-08-03): No blocking bug found; no compono product-code PR needed. One further AutoFixture-era specimen builder discovered to have zero real call sites beyond HttpClientSpecimenBuilder (gap 1's originally-named case): DynamoDbResponseSpecimenBuilder in Cosmere.Tracker.Shared.Tests, dropped entirely rather than migrated (unlike HttpClientSpecimenBuilder's own equivalent, which was ported as ClientTestProfile/IHttpClientProvider despite the same zero-call-site finding — see above; the two builders' zero-frequency evidence doesn't mean the same disposition for both). Cosmere.Tracker.Shared.Tests' ListWorldsAsync_WhenSortEmpty_DefaultsToName/ ListCharactersAsync_WhenSortEmpty_DefaultsToName required an explicit NSubstitute stub they didn't previously need (gap 2 evidence — see the migration guide's AutoNSubstituteCustomization section); fixed inline as part of the migration itself, not a separate PR, since it's a test-only change with no product-code impact. test/Directory.Build.props' project-wide global usings (AutoFixture/AutoFixture.Xunit3/ AutoFixture.Kernel) were replaced with Compono/Compono.XunitV3 — not previously called out in this plan's Critical Files, added here for the record. First attempt at package referencing used a local NuGet feed packed from this repo's source (mirroring Compono.XunitV3.SampleTests); reverted before commit once it was clear cosmere-tracker's own CI can't reach a sibling compono checkout — replaced with pinned published alpha prereleases from nuget.org instead.
Phase 5 (2026-08-03): An interim draft of this phase closed with only the architecture/blueprint done (ADR-0030 plus Amendment 1, docs/documentation-architecture.md), deferring the skeleton, migration guide promotion, and Milestone 8 backlog to Milestone 8 itself. A PR review correctly flagged this as silently narrowing ADR-0029 Amendment 4's/ docs/mvp.md's accepted scope without a formal amendment recording it — by direct instruction, all five originally-scoped Phase 5 deliverables were produced instead (see the Phase 5 checklist above), rather than amending the scope down to match what had been skipped.
A later PR review also flagged that PLAN-0008 (Phase 5's Milestone 8 backlog) has no phase boundaries of its own — a real gap against this repo's "each phase ships as its own PR" convention. By explicit decision, that split is deferred to its own design pass (tasks/design.md) before Milestone 8 begins, rather than restructured inside this documentation-architecture PR — PLAN-0008 is marked as a draft, unphased backlog pending that design work, not treated as finished. Phase 5 itself was also physically repositioned (right after Phase 1, matching when it actually ran) in response to a separate review finding that its prior position — after the still-Not Started Phases 2-4 — made phase order/status unreliable; its "Phase 5" label was kept rather than renumbered, since that identifier is already referenced from several other documents.