Repository navigation
test: the build family's probes run one check per obligation - #54
Merged
Merged
Conversation
C11, C17, C18 and C19 ran as one check named `claim`, so no listed obligation earned credit and every per-obligation seed was reported missed (PR #49). Each now runs one Row.Check per obligation its row's axes select, against the baseline its source names: - C17: a cast, a default and RequireParameterlessConstructor's argument each judged on the places of their own enum, reported at or around the value; where the reports sit is reported-where-written's. A valid value names no obligation, so the claim gains a-member-is-silent, quoted from the README's example beside the reported default, with a seed. - C18: the consumer's report and generation judged per obligation; the equality twin check reads base-member alone, since the row's shape is not what it runs. - C19: every argument is also used at a written and an inferred call; the attribute's obligation is judged at the calls, methods-the-compiler-calls at the row's site against each argument's inferred call, so a misjudged kind and an unchecked site fail apart. - C11: a parse shape's obligation against the CHANGELOG's sentence; the ordinary shape, which no obligation selected, gains parsing-where-it-can-be-parsed, quoted from the 2.0.0 entry, with a seed. Its exemption of ISpanParsable cited nothing and is gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The first seeds of a-member-is-silent and parsing-where-it-can-be-parsed failed the seeded build: CMTK0014 reading member names reported the shipping code's own constants, and an enum without parsing broke code that parses one. The seeds now make CMTK0014 judge an explicit cast by its form, and attach the generated [TypeConverter] to a top-level value object only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ordinary shape's check failed on ISpanParsable for a value object over string, Uri, an enum and NodaTime.Instant once its uncited exemption was gone. #52 gave the string one ISpanParsable and narrowed the Generators README: "A `Uri`, an enum and a NodaTime type have neither." C11 quotes that as the not-promised entry no-span-parsing-without-the-underlying-types, for those wrapped types and text.entry ISpanParsable, and parsing-where-it-can-be-parsed declares it inapplicable there (#50), so Row.Check records those rows inapplicable with the citation. string keeps no exemption. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…vers the rest again
The four pairs of Uri, an enum, a [Flags] enum and NodaTime.Instant with text.entry ISpanParsable
are not promised ("A `Uri`, an enum and a NodaTime type have neither."), and still counted as
wanted, by the parse-shape obligations, which never read shape.wrapped. They are excluded with
that reason (decision 102). The rows are regenerated (`prober rows --probe`), so the seven pairs
the four now-inapplicable rows carried are covered again, and C11Shapes.g.cs with them (decls.cs).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cable four carried Regenerated whole (`prober rows --probe`, 4d01780), C11's 157 rows covered 888 of its 1044 pairs: the covering array puts a shape.wrapped value on a parse-shape row, which never reads it, and counts the row's wrapped pairs covered; where an axis has no unblocked value it places an excluded pair anyway. So C11 keeps its 241 rows of da2c291 and adds the arrays `prober rows --claim` printed over the pairs those left uncovered (`--seed 4`, five rows, then `--seed 1`, one), each an ordinary row, staged with them and published. C11Shapes.g.cs is generated again from the 247 rows (decls.cs). C11 covers 1044 of 1044 pairs, the four excluded ones left out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
C11, C17, C18 and C19 ran as one check named
claim. So no listed obligation of theirs earned credit, and PR #49 reported every per-obligation seed of C17 and C19 missed (C18's and C11's were the same). Each probe now runs oneRow.Checkper obligation its row's axes select, named by the claim's obligation id and with its baseline, following C22 (#47).(FaultKind)9:a-cast-naming-no-member,reported-where-written, plusconstructor-accessibility-tooatsite=attribute-argument.default:default-and-zero,reported-where-written.valid:a-member-is-silent(new, below)Docs(src/CodoMetis.TypeKit.Analyzers/README.md#cmtk0014)names-each-base-member,a-warning-and-generated,generated-equality-never-calls-the-base, on every rowDocs(Generators README#equality),Docs(…#build-errors),Twin(the wrapped ints' own equality)interface-and-unsealed,value-object-and-closed-set,flags-enum-and-read-only-struct,a-pair-once-at-the-later-argument), plusmethods-the-compiler-callswhere the site is notcallDocs(docs/type-constraints.md#the-kind-of-a-type-argument)or#two-parameters-apart;#constrain-a-type-parameterfor the methodsimplicit-result,ref-text,abstract-string-constructor), orparsing-where-it-can-be-parsed(new, below) forordinaryDocs(CHANGELOG.md#2.1.0-fixed);Twin(the catalogue's top-level value object of the same kind and wrapped type)How each check is kept to its own obligation:
FaultKindplaces (a-cast…,default-and-zero);RequireParameterlessConstructor's argument (constructor-accessibility-too; underdefault-and-zero,defaultthere isPublicand must stay silent).Rz.Reported). Where the report sits isreported-where-written's question alone (Rz.WhereWritten: at the value's own span, and nothing outside every place).base-memberalone and is credited with no shape pairs it never ran. The row is read from the rows file's copy, asDecls.Keydoes.siteonly where the site iscall, so in aforeachrow it is not credited withsite=foreach.methods-the-compiler-callsjudges each use at the row's site against the same argument's inferred call in the same compilation.BuildRoslyn.csgainsAgreeover a subset of marks,At,Around,Outside,ReportedandWhereWritten. The oldAgreedelegates to the new one.Obligation decisions
a-member-is-silent.public static readonly ImportFault Duplicate = new(FaultKind.Conflict);, the member written beside the reportednew(default). Axesvalue=[valid].a-cast-naming-no-member: a valid value's silence is evidence for neither the cast obligation nor the default one. A rule that reports every value, members included, would pass both. No seed had ever shown the 86 valid rows could fail.(FaultKind)2is reported.ordinary: the new obligationparsing-where-it-can-be-parsed.parse-shape=ordinary, which none of the three obligations selects. Leaving them asclaimwould have kept half the probe unconverted. Making them inapplicable would have uncovered everyordinarypair.`IParsable`/`ISpanParsable`/`IUtf8SpanParsable`, formatting in the invariant culture. Axesparse-shape=[ordinary].[TypeConverter]is attached to a top-level value object only.parsing-where-it-can-be-parsed:shape.wrapped∈ {Uri,enum,flags-enum,NodaTime.Instant} andtext.entry=ISpanParsable, citednot-promised:no-span-parsing-without-the-underlying-types(the Finding, below).Row.Checkapplies it, and it stays out of code because it depends on the axes alone. No other converted check decides inapplicability, so nothing else moved into the claims.Outcome note keys and uncited excuses
BuildConsumer,BuildDecls,BuildSource,BuildRoslyn) called an inapplicable, expected-refusal or inconclusive key. None was converted, and noNoteKeysmember was touched. Pass keys stayc.Note(NoteKeys.Compared, …).no-span-parsing-without-the-underlying-types, fromsrc/CodoMetis.TypeKit.Generators/README.md#what-is-generated: "AUri, an enum and a NodaTime type have neither." Its axes are the four wrapped types andtext.entry=ISpanParsable. The sentence comes from fix: a value object over string implements ISpanParsable, as string does #52's narrowed README.ISpanParsable(entry is not "ISpanParsable"), citing nothing.IParsable,ISpanParsableandIUtf8SpanParsable"when the underlying type can be parsed". No record or fact narrows that.Finding: value objects over a parseable type lack
ISpanParsable(C11)The rows. Probe
C11ParseShapesBuildProbe, checkparsing-where-it-can-be-parsed(Baseline.Twin), categoryviolation. All five haveparse-shape=ordinaryandtext.entry=ISpanParsable:The failure, for #205:
violation:ISpanParsable: the value object over string, which parses, has no ISpanParsable. The other four read the same, with their wrapped type. Each row fails 3 of 3 times at HEAD (prober try --rows 174,180,183,189,205).Why now. The ordinary check's presence test exempted
ISpanParsable(entry is not "ISpanParsable") and cited nothing. Rule 2 makes that an uncited excuse: it is gone, and the check runs. The comparison with the catalogue still agrees, since both sides lack it; only the presence test fails.Triage (
.claude/skills/probe-triage):TextOps.Implements(ISpanParsable<>, Vo)). The catalogue's top-level value object over the same type lacks it too, so it is no artefact of the row's shape.docs-query find ISpanParsable --kind factfinds nothing, and this is TypeKit's own generation, not a framework's.IParsable,ISpanParsable,IUtf8SpanParsable| when the underlying type can be parsed".design/aspects.mdexplains only the enum strategy, and no record narrows it.ValueObjectParsableAspect.ResolveStrategygivesISpanParsableonly to itsSpanParsablestrategy.stringreturns its ownStringstrategy first, althoughstringisISpanParsable<string>. That breaks even the aspect's doc comment ("where the wrapped type has them").Uri, the enums andNodaTime.Instanttake theUri,EnumandTypeConverterstrategies, which generateIParsablealone.Skipwas written.The two sides, as the row's value object / the catalogue's / the wrapped type:
stringISpanParsableISpanParsableISpanParsable<string>Uri, enum, flags-enum,NodaTime.InstantISpanParsableISpanParsableISpanParsableEvery one of them gets
IParsable.The fix landed as #52 (decision (a), a
fix:withFound-By: PR), merged into release/2.2.0 at 0805ac5 and into this branch at f9ee5b2:stringimplementsISpanParsable;ISpanParsableandIUtf8SpanParsableare generated "where the underlying type has them", and the note says "AUri, an enum and a NodaTime type have neither.";SpanParsingTests).How C11 cites it (da2c291):
no-span-parsing-without-the-underlying-types, quoting that sentence verbatim fromsrc/CodoMetis.TypeKit.Generators/README.md#what-is-generated. Its axes areshape.wrapped∈ {Uri,enum,flags-enum,NodaTime.Instant} andtext.entry=ISpanParsable.universe(Axes.Build) accepts the quote.parsing-where-it-can-be-parseddeclares itself inapplicable there (build: declared applicability: an obligation says where it does not apply, read by the universe, the covering generator, the gate and Row.Check #50'sinapplicable, with the same axes andcite: not-promised:no-span-parsing-without-the-underlying-types), soRow.Checkrecords those rows inapplicable before the body runs.text.entry, so the same types'Parse,TryParse,IParsableand type converter checks still run.stringis not in it: its row now passes on the fix, not on an excuse.Rows #174, #180, #183 and #189 are inapplicable, and #205 passes. The recorded reason, for #174:
inapplicable:not-promised:no-span-parsing-without-the-underlying-types(declared shape.wrapped=Uri text.entry=ISpanParsable). C11 ended at inapplicable 4, pass 237, no violation, inprober tryand inreplay --family textat da2c291.The exclusion and the rows (4d01780, 6e6beaa):
text.entry=ISpanParsable. They still counted as wanted, because C11's three parse-shape obligations want every pair they do not declare, though they never readshape.wrapped.claims.json(decision 102's form). The reason: "AUri, an enum and a NodaTime type have neither (Generators README, What is generated: no ISpanParsable or IUtf8SpanParsable where the underlying type has none, not-promised no-span-parsing-without-the-underlying-types), so parsing-where-it-can-be-parsed is inapplicable there and no check that reads shape.wrapped can credit them." The universe goes from 1048 to 1044 pairs (242179 to 242175 in all).prober rows --proberegenerated C11's rows whole as 157 rows (4d01780), which covered only 888 of 1044. The covering array puts ashape.wrappedvalue on a parse-shape row, which never reads it, and counts that row's wrapped pairs as covered. Where an axis has no unblocked value, it places an excluded pair anyway.prober rows --claimprinted over the pairs those left:--seed 4, fiveordinaryrows over the 7, then--seed 1, one more. Row 243 of the first array was arecord-structwithbase-depth-3, which C11's declarations substitute, so it missed (base-depth-3,Uri).C11Shapes.g.cswas generated again withdecls.cs(GeneratedHarnessTestspasses).axesnarrowing the pairs it wants, and a covering array that never places an excluded pair) is for WS2's closing record, not this branch.Before and after
replay --family buildand--family textof release/2.2.0 at cfc9a2a, from an empty state, in an untouched worktree.abstract-string-constructorpass 22;implicit-resultpass 28;parsing-where-it-can-be-parsedinapplicable 4, pass 171;ref-textpass 22a-cast-naming-no-memberpass 75;a-member-is-silentpass 86;constructor-accessibility-toopass 32;default-and-zeropass 122;reported-where-writtenpass 197a-warning-and-generatedpass 280;generated-equality-never-calls-the-basepass 280;names-each-base-memberpass 280a-pair-once-at-the-later-argumentpass 80;flags-enum-and-read-only-structpass 72;interface-and-unsealedpass 66;methods-the-compiler-callspass 226;value-object-and-closed-setpass 64abstractpass 20;closed-set-named-as-generated-memberpass 4;equality-operatorpass 20;every-error-links-the-tablepass 144;generic-wrappedpass 24;named-as-generated-memberpass 22;no-type-half-generatedpass 144;over-objectpass 6;over-system-enumpass 7;over-value-objectpass 20;unsealed-record-classpass 21claimpass 101claimpass 261claimpass 309claimpass 46claimexpected-refusal 5, inapplicable 13, pass 568claimexpected-refusal 78, inapplicable 127, pass 381prober status(afteruniverse; 44 claims, 242179 pairs before, 242175 after C11's exclusion):C19 keeps every pair, although its attribute checks no longer read a non-call
site, because its methods' checks earn those pairs.Seeds
prober seeds --probe Pfor the four probes and C22 as the control, one at a time, after the merge. 28 of 28 are caught, each by the check of its own obligation, named in the detail:methods-the-compiler-calls.Verdicts
Through
build-verdict, at 6e6beaa:test --project test/CodoMetis.TypeKit.Prober.Tests: TESTS OK: 245 passed, 0 skipped.test --project test/CodoMetis.TypeKit.Conventions.Tests: TESTS OK: 1475 passed, 0 skipped,ProbeCiteTestsandProbeNoteKeyTestsamong them.prober registerandpublishranSourceLinton each seed's registration.Noticed on the way, not changed here
watchedpaths for the same reason; C22 has none.Commits
test: the build family's probes run one check per obligationtest: the two new obligations' seeds buildtest: C11 does not promise span parsing over a type that has nonetest: C11 excludes the span-parsing pairs no check can credit, and covers the rest again(its whole regeneration is replaced by the next)test: C11 keeps its rows and adds the six that cover what the inapplicable four carried🤖 Generated with Claude Code