Skip to content

fix(backend): a repository's furniture is not part of its architecture - #457

Merged
parthrohit22 merged 1 commit into
devfrom
fix/444-non-code-files-are-not-modules
Sep 11, 2026
Merged

parthrohit22 merged 1 commit into
devfrom
fix/444-non-code-files-are-not-modules

Conversation

@parthrohit22

Copy link
Copy Markdown
Collaborator

Closes #444.

The defect

On pallets/click, 7 of the 16 reported modules were not code:

.devcontainer  .editorconfig  .github  .gitignore
.pre-commit-config.yaml  .readthedocs.yaml  changes.md  license.txt  uv.lock

Each typed shared-library, in the Shared layer. 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 .gitignore ended 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.lock

A 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 marked SUPPORTED, and nothing reads uv.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.json v1 — registered as SupportStatus.UNSUPPORTED, claimed by the extractor solely so it can disclose itself:

RI-EXT-UNSUPPORTED  info  uv.lock is recognised but not read, and no resolutions are claimed

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 fixture adv-src-lockfile-uv holds the expected graph; the poetry capability's limitation text, which used to lump uv.lock in with Pipfile.lock and pdm.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.py read as termui/termui; it now reads examples/termui, beside click/termui.

Verified live

pallets/click: 16 modules → 34, no furniture, headed by core (21), types (27), decorators (14), exceptions (14).

fastapi: 345 modules, no furniture, and the four utils resolve to dependencies/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 and uv.lock alongside one real source file; confirmed failing without the rule. New test_a_recognised_but_unread_lockfile_is_disclosed_rather_than_skipped. Full backend suite green; ruff check and ruff format --check clean.


Supersedes #451 — same branch, rebased onto dev now that #445 has merged. GitHub had marked the original as part of a stack, which blocked both merging and retargeting it.

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.

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
@vercel

vercel Bot commented Sep 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
partha-frontend Ready Ready Preview Sep 11, 2026 6:39pm UTC

@parthrohit22
parthrohit22 merged commit 78e9b09 into dev Sep 11, 2026
12 checks passed
@parthrohit22
parthrohit22 deleted the fix/444-non-code-files-are-not-modules branch September 11, 2026 18:39
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.

fix(backend): non-code top-level files still become Architecture modules

1 participant