Cut 0.17.0 — the question one application cannot answer - #51
Merged
Conversation
The wiki shipped as tables. Tables are what you read second; a corpus needs something you read first, and this release gives it three pictures that are arithmetic rather than decoration. The map places every shared class between the applications that model it: at the average direction of those applications, at a distance set by how much they agree. So a class every application has belongs to no one direction and falls to the centre, and the picture reads before the caption does — the middle is your common ground, the rim is the work that belongs to one client. Beside it, two things only a corpus can draw: which two of your projects are most alike, as a grid you click to hold the page to just those two, and the DevExpress releases your estate is spread across, with the release your framework catalog actually describes marked on it. A diagram is believed faster than a sentence and checked less, so the placement rules are asserted rather than eyeballed, and the same corpus draws the same picture every run — a diagram that moves between two runs cannot be used to compare them. Three sample client modules come with it. Fixtures for one application can only ever exercise half of a corpus, so these three disagree the way client work disagrees: each carries its own copy of the same audit base, all three model Cliente and Factura, and Factura.Total is a decimal in two of them and a double in the third. They run extraction, analysis and rendering end to end, and the map in the README is drawn from them — nothing in the documentation is a mock-up. Two defects came from opening the page rather than reading the diff: labels overprinting in the middle of the map, where the interesting classes are, and an overlap grid whose rotated column names cost a band of empty page taller than the grid it labelled. The release closes with the same correction turned on the tool itself. Four generators carried a version number as a default — the explainer stamped 0.10.1 six releases after 0.10.1 shipped, and the writer of AGENTS.md stamped 0.9.0 eight releases on. Nothing failed, because a default every caller overrides is a default nobody rereads. They now say `of unknown version`, which cannot go stale, and a test refuses any generator default shaped like a version. 514 tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W45tzJFX3NoSrk7svtQeKT
Comment on lines
+184
to
+225
| foreach (var group in groups) | ||
| { | ||
| var members = group.ToList(); | ||
|
|
||
| if (members.Count == 1) | ||
| { | ||
| var only = members[0]; | ||
|
|
||
| separated.Add(only with | ||
| { | ||
| LabelX = only.X, | ||
| LabelY = only.Y - only.Radius - 5, | ||
| LabelAnchor = "middle", | ||
| }); | ||
|
|
||
| continue; | ||
| } | ||
|
|
||
| // Wide enough that the names clear each other, not just the circles. A cluster is | ||
| // where the interesting classes are, so it is the one place the drawing must not | ||
| // become a smudge. | ||
| var spread = 26 + (5.5 * members.Count); | ||
|
|
||
| for (var index = 0; index < members.Count; index++) | ||
| { | ||
| var angle = 2 * Math.PI * index / members.Count; | ||
| var member = members[index]; | ||
| var x = member.X + (Math.Cos(angle) * spread); | ||
| var y = member.Y + (Math.Sin(angle) * spread); | ||
|
|
||
| // Each name is pushed away from the middle of its own cluster, the same way the | ||
| // application names are pushed off the ring, so two neighbours lean apart. | ||
| separated.Add(member with | ||
| { | ||
| X = x, | ||
| Y = y, | ||
| LabelX = x + (Math.Cos(angle) * (member.Radius + 6)), | ||
| LabelY = y + (Math.Sin(angle) * (member.Radius + 6)) + (Math.Sin(angle) < -0.4 ? -3 : 9), | ||
| LabelAnchor = Math.Cos(angle) < -0.25 ? "end" : Math.Cos(angle) > 0.25 ? "start" : "middle", | ||
| }); | ||
| } | ||
| } |
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.
The wiki shipped as tables. Tables are what you read second. This release gives the corpus three pictures that are arithmetic rather than decoration, plus the demo corpus that lets any of it be shown publicly.
The three pictures
The map. Every shared class is placed between the applications that model it — at the average direction of those applications, at a distance set by how much they agree. A class every application has belongs to no one direction, so it falls to the centre. The picture reads before the caption does: the middle is your common ground, the rim is the work that belongs to one client. Hover an application to isolate what it shares, hover a class to see who has it, click a class to land on its comparison.
The overlap grid. How many class names each pair of applications both model. The diagonal is held out of the colour scale, so one large project cannot wash out every real overlap. Click a cell to hold the whole page to just those two applications — the filter takes a pair, not only a single project.
The version strip. The DevExpress releases the estate is spread across, spaced ordinally — nine years between two releases drawn to scale is one dot and a gap — with the release your framework catalog actually describes marked on it.
Layout is deterministic. The same corpus draws the same picture every run, because a diagram that moves between two runs cannot be used to compare them.
The demo corpus
Fixtures for one application can only ever exercise half of a corpus.
ClinicaSolution,TallerSolutionandFerreteriaSolutiondisagree the way client work disagrees:AuditedEntitybase — which is how a shared layer really travels between clientsClienteandFactura, with different property setsFactura.Totalis adecimalin two of them and adoublein the thirdActivois aboolin one and astringin anotherAprobaractionThey run extraction → analysis → rendering end to end, and the map above is drawn from them — nothing in the documentation is a mock-up.
Two defects from opening the page, not reading the diff
The same correction, turned on the tool itself
Four generators carried a version number as a default.
HtmlExplainerGeneratorsaid0.10.1— six releases after 0.10.1 shipped.AgentContextGenerator, which writesAGENTS.md, said0.9.0— eight releases on. Nothing failed, because a default every caller overrides is a default nobody rereads, and the one page it would ever stamp is a page whose footer then names a release that did not generate it.They now say
of unknown version, which cannot go stale, and a test refuses any generator default shaped like a version. That test is what found the second and third offenders.Verification
29 matches in PWPresupuesto + pwControlVisitawith zero leakage, and clicking a class on the map lands on its comparison card without touching the search boxVersion bumped in all six places.
[Unreleased]is empty.🤖 Generated with Claude Code