fix(backend): a repository's furniture is not part of its architecture - #451
Closed
parthrohit22 wants to merge 3 commits into
Closed
parthrohit22 wants to merge 3 commits into
parthrohit22 wants to merge 3 commits into
Conversation
…fine The engine was already right and the view threw it away. On pallets/click, a 177-file library with 1,963 observed symbols, the Architecture view rendered one node -- "Click", "Owns utility concerns", "derived from repository intelligence at /src/click" -- which is a directory listing with extra steps, not an explanation of the system behind the code. Three things changed, none of them an inference: A file that defines symbols is now a module in its own right. The old grouping collapsed everything under `src/<package>/` into one box, so a single-package repository was reduced to a single node. Files that define nothing (documentation, tests, config) keep their existing role grouping. Descriptions state what the snapshot observed instead of restating the path: how many symbols the module defines and which ones a reader would recognise it by. Responsibilities report the classified role where there was one, and say nothing where there was not -- "Owns unknown concerns" was a statement about the classifier, dressed up as a statement about the code. Symbols reach the analyzer through a key-only query. The documented bound on architecture_facts deliberately excludes symbol rows because they dominate a large snapshot; stable keys are short strings and already carry the file and the qualified name, which is all the module inventory reads. Only top-level definitions count. A method is defined by its class, not by the module, and counting every one turns "what does this module define" into a line-count proxy -- the kind of synthesized measure #217 rules out. Names that would collide take on as much of their parent path as they need (FastAPI has four modules called `utils`); unique names are left short. On click: core 38 symbols, exceptions 22 including Abort and BadArgumentUsage, decorators 18 including command and group, parser 17. On fastapi: 3,139 files, 358 nodes, `applications` reads "Defines 1 symbol: FastAPI." Closes #445
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
`.first()` picked whichever node the graph happened to order first, so the assertion silently re-pointed at the README module as soon as module ids changed -- it was asserting on position while claiming to assert on a name. The fixture's three modules still carry long names (`customer-subscription-entitlement-orchestration/component`), so the case under test is unchanged; the test now locates that node by its accessible name and additionally checks the on-screen label really is overflowing, which is the half of "truncated visually and recoverable accessibly" that was never actually verified.
On pallets/click the Architecture view reported 16 modules, 7 of which were not code: .devcontainer, .editorconfig, .github, .gitignore, .pre-commit-config.yaml, .readthedocs.yaml, changes.md, license.txt and uv.lock -- each typed shared-library and placed in the Shared layer, so a reader scanning the list saw the linter config given the same weight as the library. #396 excluded manifests and lockfiles by filename, which was right but narrower than the defect: none of those files is a manifest or a lockfile, so no filename list was ever going to catch them. A file is now a module only when the extraction observed something about it -- symbols it defines, a relationship it takes part in, or a role the snapshot classified it into. Nothing is judged unimportant; a file that produced no facts simply gave nothing to describe, and inventing a module from a path is how .gitignore ended up beside the library itself. uv.lock is a second, separate failure: it reached no extractor at all, so a uv-managed repository looked exactly like one that pins nothing. Adding it to the supported set would have been a false capability claim -- nothing reads it. It is instead registered as an unsupported format and claimed by the lockfile extractor solely to disclose itself as RI-EXT-UNSUPPORTED, with a benchmark fixture holding that expectation. Also: a parent directory that repeats the module's own name no longer qualifies it. examples/termui/termui.py read as "termui/termui"; it now reads as "examples/termui", beside "click/termui". click: 16 modules -> 34, none of them furniture, and the top of the list is core, types, decorators, exceptions. fastapi: 345 modules, no furniture, four utils resolved to dependencies/utils, openapi/utils, security/utils and fastapi/utils. Closes #444
parthrohit22
force-pushed
the
fix/444-non-code-files-are-not-modules
branch
from
September 11, 2026 17:31
c9a5c24 to
0ea82b9
Compare
This was referenced Sep 11, 2026
parthrohit22
added this pull request to stack #455
September 11, 2026 18:22
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.
Closes #444. Stacked on #450 — base is
feat/445-architecture-shows-real-modules, so review that first; this PR's own diff is the last commit. I'll retarget it todevonce #450 merges.The defect
On
pallets/click, 7 of the 16 reported modules were not code:Each typed
shared-library, in theSharedlayer. A reader scanning the module list saw the linter config given the same weight as the library.Why the previous fix missed it
#396 excluded manifests and lockfiles by filename. Correct, but none of the files above is a manifest or a lockfile — no filename list was ever going to catch
.gitignore.The rule
A file is a module when the extraction observed something about it: symbols it defines, a relationship it takes part in, or a role the snapshot classified it into. Nothing here judges a file unimportant — a file that produced no facts gave nothing to describe, and inventing a module from a path is exactly how
.gitignoreended up beside the library.The relationship clause matters: a package initialiser that only re-exports defines nothing of its own but is genuinely part of the structure, and the sealed edges say so.
uv.lockA second, separate failure — it reached no extractor at all, so a uv-managed repository looked identical to one that pins nothing.
The issue asks for it in
SUPPORTED_LOCKFILE_FILENAMES. I did not do that: that set is derived from capabilities markedSUPPORTED, and nothing readsuv.lock. Putting it there would claim extraction support the product does not have, in the registry that generates the public capability doc.Instead it follows the pattern already there for
package-lock.jsonv1 — registered asSupportStatus.UNSUPPORTED, claimed by the extractor solely so it can disclose itself:That is the outcome the issue wanted (recognised, not silently dropped) without the false claim.
supported_lockfile_filenames()is unchanged and a test now pins that distinction. Benchmark fixtureadv-src-lockfile-uvholds the expected graph; the poetry capability's limitation text, which used to lumpuv.lockin withPipfile.lockandpdm.lock, now points at the new entry.Also
A parent directory that repeats the module's own name no longer qualifies it.
examples/termui/termui.pyread astermui/termui; it now readsexamples/termui, besideclick/termui.Verified live
pallets/click: 16 modules → 34, no furniture, headed bycore(21),types(27),decorators(14),exceptions(14).fastapi: 345 modules, no furniture, and the fourutilsresolve todependencies/utils,openapi/utils,security/utils,fastapi/utils.Tests
New
test_repository_furniture_does_not_become_an_architecture_module— a fixture repo of dotfiles, a licence, a changelog, a CI workflow anduv.lockalongside one real source file; confirmed failing without the rule. Newtest_a_recognised_but_unread_lockfile_is_disclosed_rather_than_skipped. Full backend suite green;ruff checkandruff format --checkclean.