Skip to content

Cut 0.17.0 — the question one application cannot answer - #51

Merged
peopleworks merged 1 commit into
mainfrom
release/0.17.0
Aug 25, 2026
Merged

Cut 0.17.0 — the question one application cannot answer#51
peopleworks merged 1 commit into
mainfrom
release/0.17.0

Conversation

@peopleworks

Copy link
Copy Markdown
Owner

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 corpus map

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, TallerSolution and FerreteriaSolution disagree the way client work disagrees:

  • each carries its own copy of the same AuditedEntity base — which is how a shared layer really travels between clients
  • all three model Cliente and Factura, with different property sets
  • Factura.Total is a decimal in two of them and a double in the third
  • Activo is a bool in one and a string in another
  • two declare the same Aprobar action

They 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

  • Class labels overprinted in the middle of the map — which is exactly where the interesting classes are. Names are now anchored radially away from their own cluster, the way the application names are pushed off the ring. Asserted by measuring text bounding boxes on the dense six-project case: zero collisions.
  • The overlap grid's rotated column names cost a band of empty page taller than the grid it labelled. Columns are numbered now; the row headings carry the names once.

The same correction, turned on the tool itself

Four generators carried a version number as a default. HtmlExplainerGenerator said 0.10.1 — six releases after 0.10.1 shipped. AgentContextGenerator, which writes AGENTS.md, said 0.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

  • 514 tests pass (16 new on the graph layout and the end-to-end corpus)
  • The placement rules are asserted, not eyeballed: a class every application models lands within half a pixel of the centre; a class two of four share sits equidistant from those two and off centre
  • Interaction verified in the DOM on the six-project case: hover isolates with zero leakage, the pair filter reports 29 matches in PWPresupuesto + pwControlVisita with zero leakage, and clicking a class on the map lands on its comparison card without touching the search box

Version bumped in all six places. [Unreleased] is empty.

🤖 Generated with Claude Code

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",
});
}
}
@peopleworks
peopleworks merged commit 4a25038 into main Aug 25, 2026
6 checks passed
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.

2 participants