You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
core: __str__ and __repr__ both map to ToString — a __str__-only class repr()s as its str (python: <__main__.C object at …>) #2057
Cell: (program shape transcribed from the plan's measurement; re-run before fixing) __str__ and __repr__ both map to ToString (Shared/DunderNameMapping.cs:19-20; declaring both is SPY0522). So a user class that declares only __str__reprs as its str:
classC:
def__str__(self) ->str:
return"s"print(repr(C())) # Sharpy: s python: <__main__.C object at 0x…>
plan-0ca7b7 adds a Core IRepr channel for Core/Stdlib types (Optional, Template, datetime, string enums). Widening the user __repr__ dunder onto IRepr (so __str__/__repr__ are distinct members) is the feature; recorded as a deviation until then.
Found while planning plan-0ca7b7 (chores + P22 + P11e + P11f + P14b + P14c); measured @ acd1d40 with the built sharpyc. Filed as a sibling, NOT folded into that plan.
changed the title [-]core: str() of a CLR IFormattable (System.DateTime) is current-culture text while f"{dt}" becomes invariant after #2031 — pick one[/-][+]core: __str__ and __repr__ both map to ToString — a __str__-only class repr()s as its str (python: <__main__.C object at …>)[/+]on Sep 25, 2026
Ruling R-CP (owner, 2026-09-30): user __repr__ synthesizes IRepr and __str__ stays ToString — distinct members; a __str__-only class reprs as <mod.C object> (R-CF); the str-only-class-repr-is-str ledger row retires with the fix. Rejected: keep as a deviation. Output change for repr of __str__-only classes — the plan counts fixture hits. Contract (as P11f): every runtime spelling of a value or type — str, repr, type(x).__name__, __name__ on a reference, every message naming a type — comes from the ONE python-name/repr authority (PyFormat.PyTypeName/PyQualifiedName, IRepr, [SharpyName]). Generator FIRST: the reflective #1995 str/repr sweep becomes a python3 DIFFERENTIAL over every public Core/Stdlib type × site, allowlist ratchet; hand rows only for the user-class/dataclass/exception/function cells reflection cannot instantiate. Lands alone (printed output and, under R-DG, .expected.cs move). Lane / reach: silent-wrong · program. Class tracker:#2104 (Stdlib repr family); this issue is the user-__repr__ tracker. No seam hypothesis — the plan measures the seam.
Cell (2026-10-15, found by P63's iterator lane repair, #2288; lane silent-wrong, reach program).print(c) / str(c) on a user class that defines __iter__/__next__ but no __str__ formats the object by enumerating it. The formatting side effect consumes the iterator, so the program's later behaviour changes.
The repr TEXT is a deviation-by-default surface (python-fidelity-scope: message/repr text beyond the type name). The side effect is not: after print(c) the loop sees 0 items instead of 2, and with a __next__ that never stops, print(c) hangs. Contract: formatting an object is side-effect free and never iterates it. I'm posting it here as the nearest repr-channel tracker (__str__/__repr__ → ToString). It may be its own class (the default formatting of a user IEnumerable walks it) — for /batch-issues to place.
Batching 2026-10-20 @ a473af6 — charter .claude/plans/remediation-round-2026-09-20-batching.md §3.0 (and §3.17), chore in the current band (one commit, no plan); this issue stays the user-__repr__ tracker under P11g (order 17). Ruling R-HO (owner, 2026-10-20): D1 a — a Core chore in the current band: a Sharpy-compiled type is never a "plain CLR sequence" in Str and Repr.
Measured @ a473af6 (built CLI) — the 2026-10-15 cell plus its sibling cells:
dunders on the class
str
repr
f-string hole
list element
loop afterwards
__iter__/__next__ only
['item', 'item']
[]
[]
[[]]
0
+ __str__
Counter!
Counter!
Counter!
[Counter!]
2
+ __repr__
Counter()
Counter()
Counter()
[Counter()]
2
none (plain class)
<__main__.Plain object>
same
same
[<…>]
—
__len__ + __getitem__
<__main__.Seq object>
same
same
[<…>]
—
python3: <__main__.Counter object at …> on every site of row 1, loop 2. Row 2's repr is the R-CP cell already on this tracker. Rows 4–5 are the positive controls. The surface is COMPARED already (python-fidelity-scope row "user classes without __str__", R-CF) — no promotion needed; the side effect (iterator consumed; an endless __next__ hangs print) is the class.
Internals (read @ a473af6): the emitter makes the class IEnumerator<string>, IEnumerable<string>; Repr.cs runs TryFormatPlainClrSequence before PyFormat.TryFormatInstanceFallback, and Str carries the same arm in the same order (#1453). Cure: the Sharpy-instance test precedes the plain-sequence arm in BOTH (one predicate, two callers — a parallel-site shape, so the matrix covers both); the table above as a Core.Tests theory + one run fixture asserting the loop count; mutation (swap the arms back → the row-1 cells red); direction record (['item', 'item'] / 0 → <__main__.Counter object> / 2); fixture-hit count FIRST — the chore rides P21e's gate if no .expected moves, its own gate otherwise. Lane / reach: silent-wrong · program.
Rejected: (b) a P11g cell (order 17, lands alone with the R-DG snapshot churn; the consumption and the hang persist ~15 groups); (c) a new class issue (one arm; this tracker exists). (a) stacks under R-CP — the IRepr channel for user __repr__ lands on top of it; printed output changes once, from a value R-CF already rules wrong, so no new door.
Landed (chores band 2026-10-22) on dev @ 4d22212, PR #2346 to mainline. Whole-solution gate 81669/0/7 @ 4d22212 (measured), against 81093/0/7 @ be4664e.
R-HO chore, commit 2f2c38f.Str and Repr run TryFormatSharpyInstance, keyed on PyFormat.IsSharpyStamped, before TryFormatPlainClrSequence. A Sharpy-compiled iterator is never formatted by enumerating it.
Direction:print(c) on an __iter__/__next__ class was ['item', 'item'] with the later loop counting 0. It is now <__main__.Counter object> and the loop counts 2. The new fixture is builtins/iterable_instance_str_2057.
Gate fallout: the new fixture shifted two sweep samples.
The code-action shape pins moved +1, re-pinned in 4d22212 from a full run.
Batching 2026-10-22 @ 4d22212 — charter .claude/plans/remediation-round-2026-09-20-batching.md §3.0, chores — call-28 band: generator-formatting cell (order 0, one commit, no plan; rides P21e's gate if no fixture .expected moves). Ruling R-IF (owner, 2026-10-22): D6 a — split: the formatting half is a cell here under R-HO; the multi-pass half is RECORDED.
Cell (R-HO's contract: formatting a Sharpy-compiled object never iterates it):def gen() -> int: print("body ran"); yield 1; yield 2 then g = gen(); print(g) → observed body ran then [1, 2] @ be4664e (repr(g), the f-string hole and [g] likewise); expected <generator object gen at 0x…> with the body NOT run (python3 3.12). Lane silent-wrong, reach program. Found by the chores-band agent. Internals (read @ 4d22212): the R-HO arm is keyed on PyFormat.IsSharpyStamped and a compiler-synthesized iterator class carries no stamp.
R-IF (a): a synthesized generator's str/repr is <generator object gen> (the P11g python-name channel owns the final spelling, R-CP/R-DG; the at 0x… address is deviation, R-CI) and formatting never enumerates it; Core.Tests theory site {str, repr, print, f-string hole, list element} × producer {generator function, generator method, synthesized generator expression} + one run fixture asserting the body did NOT run; mutation (unstamp → the generator row red); direction record body ran + [1, 2] → <generator object gen>; fixture .expected hit count FIRST. The multi-pass half — two loops over one g print body ran twice and count 4 where python counts 2, because the spec maps a generator to IEnumerable<T> (generators.md:61,72) — is RECORDED under R-CM: ledger row generator-multi-pass (audience python, severity info, executed example) + one generators.md sentence, in the same commit. Rejected: (b) promote multi-pass — a single-pass wrapper per call (changes the runtime behaviour of every re-iterating program, one-way; an allocation per call; the IEnumerable<T> return C# consumers see would have to change); (c) both halves as ledger rows, formatting kept (leaves a side effect, and a hang on an endless generator, that R-HO already ruled a bug). The ledger row is relaxable to (b) later; (a) stacks under (b). This issue stays P11g's user-__repr__ tracker (§3.17).
Landed: generator-formatting cell (R-IF under R-HO) @ 963b345; ledger row generator-multi-pass @ 97db52f (dev 0fb7b23, mainline b99221c). #2057 stays open as P11g's tracker.
Cure:
Lowering records each generator function's python __qualname__ (IrCompilation.GeneratorQualifiedNames).
The emitter prints it as [global::Sharpy.SharpyGenerator("K.items")] on the iterator method.
Core reaches the stamp from the state machine through C#'s IteratorStateMachineAttribute.
TryFormatSharpyInstance, the one arm Str and Repr share, prints <generator object {qualname}> and never runs the body. The at 0x… address is omitted (R-CI).
A generator expression already printed <iterator object> without enumerating; its spelling is P11g's.
Direction record (run):
Expression
Before
After
print(g)
body ran + [1, 2]
<generator object gen>
K().items()
[3]
<generator object K.items>
K.Inner.walk
(same shape)
<generator object K.Inner.walk>
local generator in main
(same shape)
<generator object main.<locals>.inner>
Every line equals python3 3.12's minus the address.
Guards:
Core.Tests: producer {module function, method, generic, local function} × site {str, repr, print, f-string hole, list element}.
Compiler.Tests GeneratorObjectFormattingTests, a programmatic run test, so no corpus pins move.
Mutation records:
Emitter stamp removed: red, with the pre-fix output.
Core arm skipped: 14/46 red.
Roster: the __qualname__ scope switch in LoweringPass.LowerStatement is a documented-by-design dispatch-site row @ 0fb7b23. The gate flagged it as unrostered. Mutation: the contract marker removed turns DesignCitations_ResolveToContractComments red.
Fixture-hit count: 0 .expected files moved. Two C# snapshots gained the attribute line. Spy stdlib regenerated: Itertools.cs and Os.cs, attribute lines only.
Ledger row generator-multi-pass (R-IF): two loops over one generator count 4 here and 2 in python. generators.md gains the sentence.
tagged_unions.md has no str/repr section and there is no Python oracle, so this is a ruling, not a bug. Proposed, extending Optional's constructor-spelling ruling (#2005): str and repr of a union value are both the constructor spelling with payload reprs — Shape.Circle(3), LoadState.Loaded('users.csv'), unit cases as Shape.Empty() (parenthesized, matching None()); Result's Ok(…)/Err(…) follow the same rule. Mojo 1.2 adopted the same default for its EnumLike types (Shape.circle(3) / repr → Shape.circle(Int(3)), unit cases without parentheses).
Rung: the union lowering emits one class per case, so emit ToString() plus the IRepr channel on each; sequence after this issue's __str__/__repr__ split so a user-declared __str__ on a union keeps winning. Found reviewing the Mojo 1.2.0 release notes (docs/design/mojo-release-reviews/v1.2.0.md).
Batching 2026-10-23 @ 6c95019 — charter .claude/plans/remediation-round-2026-09-20-batching.md §3.17, P11g — python-name/repr channel residue (order 17, this issue's channel). Ruling R-IM (owner, 2026-10-23): (a) PROMOTE — str and repr of a user-declared union value are both the constructor spelling with payload reprs — Shape.Circle(3), LoadState.Loaded('users.csv') — with unit cases PARENTHESIZED, Shape.Empty() (the spec's construction spelling, tagged_unions.md:107, and None()'s shape from #2005); Result follows the same rule (Ok(1) / Err('e'), with #2137); a user __str__/__repr__ on the union wins.
Measured by the filer @ 0c90a73: print(Shape.Circle(3)), repr(...) and a list of union values all print <__main__.Shape.Circle object>. The surface was unlisted (R-CM, deviation until promoted); it is now a COMPARED row beside Optional/Template in python-fidelity-scope.md (R-IM). Rung: the union lowering emits one class per case, so ToString() plus the IRepr channel on each case class (P11g's mechanism, after this issue's __str__/__repr__ split so the user dunder keeps winning); a tagged_unions.mdstr/repr section with executed examples. Matrix: case shape {unit, one payload, several payloads, str payload, nested union payload} × site {str, repr, print, f-string hole, list element}; fixture-hit count first (no fixture asserts today's text — grep at the plan). Rejected: (b) RECORD the user-class default <module.Shape.Circle object> as a ledger row; (c) repr module-qualified (__main__.Shape.Circle(3)) — two spellings to pin for one value where Optional has one; the bare-unit variant (Shape.Empty, the pattern spelling) was offered and not taken. Printed output is one-way once a fixture pins it. Lane silent-wrong, reach program; the cell stays on this tracker.
Activity
[-]core: str() of a CLR IFormattable (System.DateTime) is current-culture text while f"{dt}" becomes invariant after #2031 — pick one[/-][+]core: __str__ and __repr__ both map to ToString — a __str__-only class repr()s as its str (python: <__main__.C object at …>)[/+]feat(core,codegen): one python-name authority — PyTypeName (messages)…
antonsynd commentedon Sep 30, 2026
Batching 2026-09-30 @ db8e05b — charter
.claude/plans/remediation-round-2026-09-20-batching.md§3.13, P11g — python-name/repr channel residue (order N5; lands alone; generator FIRST).Ruling R-CP (owner, 2026-09-30): user
__repr__synthesizesIReprand__str__staysToString— distinct members; a__str__-only class reprs as<mod.C object>(R-CF); thestr-only-class-repr-is-strledger row retires with the fix. Rejected: keep as a deviation. Output change forreprof__str__-only classes — the plan counts fixture hits. Contract (as P11f): every runtime spelling of a value or type —str,repr,type(x).__name__,__name__on a reference, every message naming a type — comes from the ONE python-name/repr authority (PyFormat.PyTypeName/PyQualifiedName,IRepr,[SharpyName]). Generator FIRST: the reflective #1995 str/repr sweep becomes a python3 DIFFERENTIAL over every public Core/Stdlib type × site, allowlist ratchet; hand rows only for the user-class/dataclass/exception/function cells reflection cannot instantiate. Lands alone (printed output and, under R-DG,.expected.csmove). Lane / reach: silent-wrong · program. Class tracker: #2104 (Stdlib repr family); this issue is the user-__repr__tracker. No seam hypothesis — the plan measures the seam.antonsynd commentedon Oct 16, 2026
Cell (2026-10-15, found by P63's iterator lane repair, #2288; lane
silent-wrong, reachprogram).print(c)/str(c)on a user class that defines__iter__/__next__but no__str__formats the object by enumerating it. The formatting side effect consumes the iterator, so the program's later behaviour changes.sharpyc run(built CLI @ f8c37f9)['item', 'item']/[]/0<__main__.Counter object at …>×2 /2The repr TEXT is a deviation-by-default surface (python-fidelity-scope: message/repr text beyond the type name). The side effect is not: after
print(c)the loop sees 0 items instead of 2, and with a__next__that never stops,print(c)hangs. Contract: formatting an object is side-effect free and never iterates it. I'm posting it here as the nearest repr-channel tracker (__str__/__repr__→ToString). It may be its own class (the default formatting of a userIEnumerablewalks it) — for/batch-issuesto place.antonsynd commentedon Oct 21, 2026
Batching 2026-10-20 @ a473af6 — charter
.claude/plans/remediation-round-2026-09-20-batching.md§3.0 (and §3.17), chore in the current band (one commit, no plan); this issue stays the user-__repr__tracker under P11g (order 17). Ruling R-HO (owner, 2026-10-20): D1 a — a Core chore in the current band: a Sharpy-compiled type is never a "plain CLR sequence" inStrandRepr.Measured @ a473af6 (built CLI) — the 2026-10-15 cell plus its sibling cells:
strrepr__iter__/__next__only['item', 'item'][][][[]]__str__Counter!Counter!Counter![Counter!]__repr__Counter()Counter()Counter()[Counter()]<__main__.Plain object>[<…>]__len__+__getitem__<__main__.Seq object>[<…>]python3:
<__main__.Counter object at …>on every site of row 1, loop 2. Row 2'srepris the R-CP cell already on this tracker. Rows 4–5 are the positive controls. The surface is COMPARED already (python-fidelity-scope row "user classes without__str__", R-CF) — no promotion needed; the side effect (iterator consumed; an endless__next__hangsprint) is the class.Internals (read @ a473af6): the emitter makes the class
IEnumerator<string>, IEnumerable<string>;Repr.csrunsTryFormatPlainClrSequencebeforePyFormat.TryFormatInstanceFallback, andStrcarries the same arm in the same order (#1453). Cure: the Sharpy-instance test precedes the plain-sequence arm in BOTH (one predicate, two callers — a parallel-site shape, so the matrix covers both); the table above as a Core.Tests theory + one run fixture asserting the loop count; mutation (swap the arms back → the row-1 cells red); direction record (['item', 'item']/ 0 →<__main__.Counter object>/ 2); fixture-hit count FIRST — the chore rides P21e's gate if no.expectedmoves, its own gate otherwise. Lane / reach: silent-wrong · program.Rejected: (b) a P11g cell (order 17, lands alone with the R-DG snapshot churn; the consumption and the hang persist ~15 groups); (c) a new class issue (one arm; this tracker exists). (a) stacks under R-CP — the
IReprchannel for user__repr__lands on top of it; printed output changes once, from a value R-CF already rules wrong, so no new door.fix(core): a Sharpy class instance is never a plain CLR sequence — st…
test(conformance): SharpyInstanceFormattingTests joins the ConsoleCap…
test(lsp): the code-action shape sweep's extract-method and wrap-try …
antonsynd commentedon Oct 22, 2026
Landed (chores band 2026-10-22) on
dev@ 4d22212, PR #2346 to mainline. Whole-solution gate 81669/0/7 @ 4d22212 (measured), against 81093/0/7 @ be4664e.R-HO chore, commit 2f2c38f.
StrandReprrunTryFormatSharpyInstance, keyed onPyFormat.IsSharpyStamped, beforeTryFormatPlainClrSequence. A Sharpy-compiled iterator is never formatted by enumerating it.Direction:
print(c)on an__iter__/__next__class was['item', 'item']with the later loop counting 0. It is now<__main__.Counter object>and the loop counts 2. The new fixture isbuiltins/iterable_instance_str_2057.Gate fallout: the new fixture shifted two sweep samples.
Stays open as the user-
__repr__tracker under P11g (R-CP).Merge pull request #2346 from antonsynd/dev
antonsynd commentedon Oct 22, 2026
Batching 2026-10-22 @ 4d22212 — charter
.claude/plans/remediation-round-2026-09-20-batching.md§3.0, chores — call-28 band: generator-formatting cell (order 0, one commit, no plan; rides P21e's gate if no fixture.expectedmoves). Ruling R-IF (owner, 2026-10-22): D6 a — split: the formatting half is a cell here under R-HO; the multi-pass half is RECORDED.Cell (R-HO's contract: formatting a Sharpy-compiled object never iterates it):
def gen() -> int: print("body ran"); yield 1; yield 2theng = gen(); print(g)→ observedbody ranthen[1, 2]@ be4664e (repr(g), the f-string hole and[g]likewise); expected<generator object gen at 0x…>with the body NOT run (python3 3.12). Lane silent-wrong, reach program. Found by the chores-band agent. Internals (read @ 4d22212): the R-HO arm is keyed onPyFormat.IsSharpyStampedand a compiler-synthesized iterator class carries no stamp.R-IF (a): a synthesized generator's
str/repris<generator object gen>(the P11g python-name channel owns the final spelling, R-CP/R-DG; theat 0x…address is deviation, R-CI) and formatting never enumerates it; Core.Tests theory site {str, repr, print, f-string hole, list element} × producer {generator function, generator method, synthesized generator expression} + one run fixture asserting the body did NOT run; mutation (unstamp → the generator row red); direction recordbody ran+[1, 2]→<generator object gen>; fixture.expectedhit count FIRST. The multi-pass half — two loops over onegprintbody rantwice and count 4 where python counts 2, because the spec maps a generator toIEnumerable<T>(generators.md:61,72) — is RECORDED under R-CM: ledger rowgenerator-multi-pass(audience python, severity info, executed example) + onegenerators.mdsentence, in the same commit. Rejected: (b) promote multi-pass — a single-pass wrapper per call (changes the runtime behaviour of every re-iterating program, one-way; an allocation per call; theIEnumerable<T>return C# consumers see would have to change); (c) both halves as ledger rows, formatting kept (leaves a side effect, and a hang on an endless generator, that R-HO already ruled a bug). The ledger row is relaxable to (b) later; (a) stacks under (b). This issue stays P11g's user-__repr__tracker (§3.17).fix(core): a generator object prints python's `<generator object qual…
docs(deviations): subclassing a Core collection and a generator's mul…
Merge dev into mainline: call-28 band slice 2 (refs #2057 #2143 #2342 #…
test(compiler): the __qualname__ scope switch in LoweringPass.LowerSt…
antonsynd commentedon Oct 22, 2026
Landed: generator-formatting cell (R-IF under R-HO) @ 963b345; ledger row
generator-multi-pass@ 97db52f (dev 0fb7b23, mainline b99221c). #2057 stays open as P11g's tracker.Cure:
__qualname__(IrCompilation.GeneratorQualifiedNames).[global::Sharpy.SharpyGenerator("K.items")]on the iterator method.IteratorStateMachineAttribute.TryFormatSharpyInstance, the one armStrandReprshare, prints<generator object {qualname}>and never runs the body. Theat 0x…address is omitted (R-CI).<iterator object>without enumerating; its spelling is P11g's.Direction record (
run):print(g)body ran+[1, 2]<generator object gen>K().items()[3]<generator object K.items>K.Inner.walk<generator object K.Inner.walk>main<generator object main.<locals>.inner>Every line equals python3 3.12's minus the address.
Guards:
GeneratorObjectFormattingTests, a programmatic run test, so no corpus pins move.Mutation records:
Roster: the
__qualname__scope switch inLoweringPass.LowerStatementis adocumented-by-designdispatch-site row @ 0fb7b23. The gate flagged it as unrostered. Mutation: the contract marker removed turnsDesignCitations_ResolveToContractCommentsred.Fixture-hit count: 0
.expectedfiles moved. Two C# snapshots gained the attribute line. Spy stdlib regenerated:Itertools.csandOs.cs, attribute lines only.Ledger row
generator-multi-pass(R-IF): two loops over one generator count 4 here and 2 in python.generators.mdgains the sentence.antonsynd commentedon Oct 22, 2026
Cell (same channel, needs a ruling — D5, deviation by default): a user-declared
unionvalue has nostr/reprtoday. Measured @ 0c90a73:tagged_unions.mdhas nostr/reprsection and there is no Python oracle, so this is a ruling, not a bug. Proposed, extending Optional's constructor-spelling ruling (#2005):strandreprof a union value are both the constructor spelling with payload reprs —Shape.Circle(3),LoadState.Loaded('users.csv'), unit cases asShape.Empty()(parenthesized, matchingNone());Result'sOk(…)/Err(…)follow the same rule. Mojo 1.2 adopted the same default for itsEnumLiketypes (Shape.circle(3)/repr→Shape.circle(Int(3)), unit cases without parentheses).Rung: the union lowering emits one class per case, so emit
ToString()plus theIReprchannel on each; sequence after this issue's__str__/__repr__split so a user-declared__str__on a union keeps winning. Found reviewing the Mojo 1.2.0 release notes (docs/design/mojo-release-reviews/v1.2.0.md).Generated by Claude Code
antonsynd commentedon Oct 23, 2026
Batching 2026-10-23 @ 6c95019 — charter
.claude/plans/remediation-round-2026-09-20-batching.md§3.17, P11g — python-name/repr channel residue (order 17, this issue's channel). Ruling R-IM (owner, 2026-10-23): (a) PROMOTE —strandreprof a user-declaredunionvalue are both the constructor spelling with payload reprs —Shape.Circle(3),LoadState.Loaded('users.csv')— with unit cases PARENTHESIZED,Shape.Empty()(the spec's construction spelling,tagged_unions.md:107, andNone()'s shape from #2005);Resultfollows the same rule (Ok(1)/Err('e'), with #2137); a user__str__/__repr__on the union wins.Measured by the filer @ 0c90a73:
print(Shape.Circle(3)),repr(...)and a list of union values all print<__main__.Shape.Circle object>. The surface was unlisted (R-CM, deviation until promoted); it is now a COMPARED row beside Optional/Templateinpython-fidelity-scope.md(R-IM). Rung: the union lowering emits one class per case, soToString()plus theIReprchannel on each case class (P11g's mechanism, after this issue's__str__/__repr__split so the user dunder keeps winning); atagged_unions.mdstr/reprsection with executed examples. Matrix: case shape {unit, one payload, several payloads,strpayload, nested union payload} × site {str, repr, print, f-string hole, list element}; fixture-hit count first (no fixture asserts today's text — grep at the plan). Rejected: (b) RECORD the user-class default<module.Shape.Circle object>as a ledger row; (c)reprmodule-qualified (__main__.Shape.Circle(3)) — two spellings to pin for one value where Optional has one; the bare-unit variant (Shape.Empty, the pattern spelling) was offered and not taken. Printed output is one-way once a fixture pins it. Lane silent-wrong, reach program; the cell stays on this tracker.docs(design): the fidelity-scope table records the call-29 rulings — …