Skip to content

fix(dummies): qualify exhaustion replay hint for foreign generators#278

Merged
Reefact merged 4 commits into
mainfrom
claude/issue-212-discussion-zm86xo
Jul 21, 2026
Merged

fix(dummies): qualify exhaustion replay hint for foreign generators#278
Reefact merged 4 commits into
mainfrom
claude/issue-212-discussion-zm86xo

Conversation

@Reefact

@Reefact Reefact commented Jul 21, 2026

Copy link
Copy Markdown
Owner

Summary

When a distinct collection is driven to exhaustion and its element generator is foreign (carries no IHasRandomSource), the failure message no longer promises a full Any.Reproducibly replay of the elements. The collection falls back to the ambient source for its count and layout, but a foreign generator's own draws ignore that seed — so replaying it reproduced neither the elements nor the shortfall. The hint is now scoped to the count and layout instead, honoring ADR-0013's "fails explicitly and reproducibly."

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Refactoring
  • Analyzer / diagnostic change
  • Tests
  • Documentation
  • Build / CI / tooling

Changes

  • RandomSource: add PartialReplayHint(seed) (abstract + ambient/fixed implementations). It states the count and layout are reproducible but the elements are not, phrased per source — the ambient source names Any.Reproducibly(seed, ...), a fixed context names Any.WithSeed(seed).
  • CollectionState.Exhausted: take the generator that exhausted and key the hint on AnyDerivation.SourceOf(culprit) is null. When it is null — a foreign IAny, or an As/Combine derivation built over one (DerivedAny carries a null source there) — emit the qualified hint; otherwise keep the faithful full-replay hint unchanged. The discriminator is the null source, not an is IHasRandomSource type test.
  • Both exhaustion sites are covered, keyed on the specific failing generator: the element generator (FillDistinct_item) and a ContainingAny(...) generator (DrawFresh → that operand).
  • Tests: four new in AnyCollectionTests — foreign element generator, As-over-foreign, foreign ContainingAny over a fixed Any.WithSeed(...) source (asserts Any.WithSeed is named, never the inapplicable Any.Reproducibly), and the unchanged library case — plus a ForeignPair test double.

Note: the dead seed is not null guard the issue also flagged was already removed by #211; the scope here is the over-promise only. See the issue comment for the two acceptance-criteria refinements (the As-derived criterion and the added ContainingAny site).

Testing

  • dotnet build FirstClassErrors.sln — 0 warnings, 0 errors.
  • dotnet test FirstClassErrors.sln — not run as a whole; ran dotnet test Dummies.UnitTests380 passed, 0 failed (including the 4 new tests, confirmed via filter).
  • Analyzer tests (FirstClassErrors.Analyzers.UnitTests) — not run; analyzers are untouched.

Documentation

  • Public API / error documentation updated
  • README / doc/ updated
  • French translation (doc/handwritten/for-users/README.fr.md) updated if user-facing behavior changed
  • No documentation change required — the exhaustion message text is not quoted in the docs, and the conceptual guidance already states that non-deterministic external state is "not fully replayable from the seed alone" (ArbitraryTestValues), which this change aligns the message with. No README behavior changed, so the French translation is unaffected.

Architecture decisions

  • No architectural decision in this pull request — honors and reinforces ADR-0013; no new decision, no public API change.
  • New decision recorded — ADR drafted as Proposed: ADR-____
  • Supersedes an existing ADR — successor proposed, status not flipped: ADR-____
  • ⚠️ Conflicts with an existing ADR — flagged for the maintainer: ADR-____

Related issues

Closes #212


Generated by Claude Code

claude and others added 2 commits July 21, 2026 19:52
A distinct collection whose element generator is foreign (carries no
IHasRandomSource) falls back to the ambient source for its count and
layout, but the foreign generator's own draws ignore that seed. The
exhaustion message nonetheless appended the faithful "reproduce this run
with Any.Reproducibly(seed, ...)" hint, so a user who replayed the seed
got different elements — and not even the same shortfall — the exact
trust failure the seed reporting exists to prevent.

Thread the failing generator into CollectionState.Exhausted and key the
hint on AnyDerivation.SourceOf(culprit): when it is null — a foreign
IAny, or an As/Combine derivation built over one — emit a qualified hint
that scopes the promise to the count and layout. The discriminator is
the null source, not an "is IHasRandomSource" test: DerivedAny carries a
null source over a foreign operand and must be qualified too.

Both exhaustion sites are covered — the element generator (FillDistinct)
and a ContainingAny(...) generator (DrawFresh) — keyed on that specific
generator's source. The qualified phrasing lives on RandomSource
(PartialReplayHint, a twin of ReplayHint) so it names Any.WithSeed(seed)
when the collection's own source is fixed, never the inapplicable
Any.Reproducibly, staying consistent with #211.

Library-sourced and As-over-library generators are unchanged: they stay
faithful and keep the full-replay hint. The dead null-guard the issue
also flagged was already removed by #211. Add four tests covering the
foreign, As-over-foreign, foreign-ContainingAny-over-fixed-source, and
unchanged-library cases.

Refs: #212
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018tME7DBWLTD7rSa5TWtodi

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: aea665b375

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Dummies/CollectionState.cs Outdated
Reefact and others added 2 commits July 21, 2026 22:19
A Combine derivation with at least one foreign operand keeps a sourced
operand's non-null source through the SourceOf(first) ?? ... collapse, so
the previous discriminator — a null source — classified it as faithful
and still promised a full Any.Reproducibly replay, even though the
composed value follows the foreign draw. This is the same over-promise
one level up, surfaced in review of #212.

Add AnyDerivation.IsReproducible: a generator is reproducible when it
draws only from its reported source — a library generator with a source,
or a derivation whose operands are all themselves reproducible. Record it
on DerivedAny (IReproducibilityHint) at construction from the operands,
computed in As, Combine (arities 2-8) and OrNull. A non-null source to
name and full reproducibility are now distinct signals.

Route both replay sites through the predicate: distinct-collection
exhaustion (CollectionState.Exhausted) and composer/factory failures
(AnyDerivation.Invoke). Generalize the qualified hint on RandomSource
(PartialReplayHint) so it phrases both the collection-element and the
composed-value case, per source (Any.Reproducibly or Any.WithSeed).

Add tests for the exhaustion and composer-failure paths over a Combine
that mixes a foreign operand with a library one.

Refs: #212
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018tME7DBWLTD7rSa5TWtodi
@Reefact
Reefact merged commit 7f01e5f into main Jul 21, 2026
15 checks passed
@Reefact
Reefact deleted the claude/issue-212-discussion-zm86xo branch July 21, 2026 20:32
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.

Dummies: distinct-collection exhaustion message over-promises replay for foreign element generators

2 participants