Vespucci Linter: Multi-level Notebook Analysis
- Vespucci Linter is a linting framework that unifies multi-level analysis of Python code, notebook structure, and ML-specific operations.
- It leverages the Moose platform and Famix metamodel to merge notebook and code entities for precise, cross-cell reasoning.
- Its dual usage extends to visualization linting, where hybrid human-AI systems combine rule-based checks with sociotechnical critique.
Searching arXiv for Vespucci Linter and closely related linting papers. {"query":"Vespucci Linter notebooks Moose FamixPython visualization linter Community Notes arXiv", "max_results": 10} {"query":"(Mignard et al., 15 Sep 2025) Vespucci Linter (Crisan et al., 11 Feb 2025) linting is people (Chen et al., 2021) VizLinter", "max_results": 10} Vespucci Linter is a linting framework associated with two closely related research trajectories. In its implemented form, it is a static analysis tool for Python machine learning notebooks, built on Moose and designed to analyze general Python coding conventions, notebook organization, and ML-specific aspects such as reproducibility and correct API usage through a unified metamodel of notebooks and code entities (Mignard et al., 15 Sep 2025). In adjacent visualization research, the same name is used as a design target for a broader linting system that would combine rule-based checks, machine learning, and human computation to evaluate data visualizations, including socially negotiated questions of misleadingness and context (Crisan et al., 11 Feb 2025, Chen et al., 2021). The common thread across these usages is an expansion of linting from narrow syntax and style checking toward contextual, domain-aware analysis.
1. Conceptual scope
In the notebook-analysis literature, Vespucci Linter addresses a specific problem: machine learning code, particularly within notebooks, often exhibits lower quality compared to traditional software, and the relevant bad practices occur at three distinct levels. These levels are general Python coding conventions, the organizational structure of the notebook itself, and ML-specific issues such as reproducibility and correct API usage (Mignard et al., 15 Sep 2025). The tool’s stated contribution is a static analysis approach with multi-level capabilities that can capture these layers simultaneously rather than treating them as isolated concerns.
This multi-level framing is central to why Vespucci Linter is distinct from conventional linters. The underlying claim is not merely that notebooks contain Python code, but that notebook quality depends on cell structure, execution order, outputs, and workflow semantics that are lost when notebooks are flattened into scripts. This is why the system unifies notebook entities with code entities instead of analyzing either one in isolation (Mignard et al., 15 Sep 2025).
In visualization research, “Vespucci Linter” appears as a broader architectural proposal rather than a finished tool. There it denotes a hybrid human–AI sociotechnical system intended to combine procedural checks, ML-based triage, and structured crowd critique to improve visualization quality and mitigate misinformation at scale while respecting the social and cultural dimensions of data communication (Crisan et al., 11 Feb 2025). A related precursor is VizLinter, a framework for Vega-Lite specifications that combines a visualization linter with a visualization fixer and focuses on legality and compatibility of visual encodings (Chen et al., 2021). This suggests that the name has become a convenient label for linting systems that move beyond single-level static checks.
2. Motivation and problem setting
The notebook-oriented Vespucci Linter is motivated by an overview of prior work showing that ML code, especially in notebooks, tends to violate established software engineering conventions more than traditional software. The data block identifies several contributing factors. Many ML practitioners come from non-software backgrounds and do not consistently follow software engineering best practices. Notebooks optimize for exploration and rapid prototyping through literate computing, but this can discourage strict organization and enforcement of standards. The fragmented, interleaved notebook structure also makes conventional tools less effective at analyzing code context across cells (Mignard et al., 15 Sep 2025).
The paper organizes these quality problems into three categories. At the Python level, the issues include unused variables and imports, high function complexity, global state, non-idiomatic imports, and naming issues. At the notebook level, the issues include unclear names, missing documentation cells, very long notebooks or cells, scattered imports, empty cells, and evidence of non-linear execution. At the ML-specific level, the issues include lack of reproducibility through missing seeds, misuse of in-place versus copy APIs, implicit hyperparameters and data-loading defaults, and ambiguous DataFrame merges (Mignard et al., 15 Sep 2025). This tripartite taxonomy is the basis for the tool’s rule set.
The motivation also depends on the shortcomings of prior tooling. Python linters such as PyLint, PyFlakes, and Ruff are described as strong for general code issues but lacking notebook context and ML-aware semantics. Notebook analyzers such as Pynblint and NBLyzer capture some notebook-specific concerns, but do not integrate ML workflow semantics. Pandera and related data-validation approaches focus on data schemas and types. ML Lint addresses project smells but defers code-level analysis to existing Python linters and does not analyze notebooks or ML workflows across cells. SonarQube adds some ML-adjacent rules but remains focused on traditional software engineering analysis (Mignard et al., 15 Sep 2025). Vespucci Linter is therefore positioned as a response to the single-level focus of existing tools.
A broader motivation appears in the visualization literature. There, linting is explicitly extended beyond code into sociotechnical domains where correctness is negotiated by communities, not only by formal rules. Visualizations are described as expressive artifacts whose rightness and wrongness are both technical and social, which automated rule engines alone may not capture (Crisan et al., 11 Feb 2025). This broader framing helps explain why “Vespucci Linter” is also invoked as a blueprint for hybrid systems rather than only as a notebook linter.
3. Metamodel, architecture, and analysis pipeline
The implemented Vespucci Linter is built atop Moose, described as a software analysis platform based on the Famix metamodeling framework. Moose provides a modular, extensible meta-platform for defining custom metamodels, FamixPython entities for modeling Python code, a query language, and the Critics rule engine for expressing linting rules in concise Pharo/Smalltalk code (Mignard et al., 15 Sep 2025). The architectural decision to use Moose is important because the tool’s core novelty lies in model unification rather than in a standalone parser.
Its metamodel has two parts. The notebook model represents a Notebook as a collection of Cells partitioned into CodeCells and TextCells, while preserving metadata such as execution counter, id, type, and links to Outputs capturing textual or visual results. The Python model uses FamixPython to represent modules, classes, functions or behaviors, variables, imports, invocations, and accesses. Each CodeCell is then linked to the FamixPython entities defined or used in it, including variables, functions, classes, imports, and invocations (Mignard et al., 15 Sep 2025). This mapping preserves notebook context while enabling notebook-wide queries.
The paper describes a four-step static analysis pipeline. First, the tool parses the .ipynb JSON, extracts cells and metadata, and concatenates all code cells into a temporary Python file. Second, it parses that file into a FamixPython model, builds the custom Notebook model, merges the two models, and links code entities back to the cells they belong to. Third, it evaluates all linting rules via Moose Critics on the unified model, with each violation including severity, location, and a remediation suggestion. Fourth, it serializes violations to JSON for downstream analysis or manual inspection (Mignard et al., 15 Sep 2025).
This unified model enables cross-cell reasoning. The paper explicitly identifies imports not in the first cell, repeated imports, and invocation sequences spanning cells as examples of queries made possible by the merged representation. It also enables linking violations to precise notebook locations, such as a specific cell, function, or invocation (Mignard et al., 15 Sep 2025). The system is static and favors avoiding false positives, which means that issues depending on dynamic features, runtime state, or star imports may be underreported.
The visualization literature supplies a parallel but distinct architectural vocabulary. VizLinter translates Vega-Lite specifications into a fact base, applies a rule base via Answer Set Programming, and maps each violation to repair actions selected by Binary Integer Programming under a reward-minus-cost objective (Chen et al., 2021). The sociotechnical visualization blueprint associated with Vespucci Linter expands this into a rule engine, contextual critique module, AI triage layer, human computation layer, and feedback loops from human notes to rule updates (Crisan et al., 11 Feb 2025). These architectures are not identical to the notebook tool, but they show how the same name is used to denote increasingly contextual forms of linting.
4. Rule system and linting capabilities
The notebook implementation defines 22 rules grouped into three levels, with identifiers P for Python, N for notebook, and M for machine learning. Thresholds are drawn from the literature and are tunable (Mignard et al., 15 Sep 2025). The rule catalog is part of the tool’s main contribution because it operationalizes the claim that notebook quality problems are multi-level.
| Level | Rule range | Representative focus |
|---|---|---|
| General Python | P1–P9 | Unused variables/imports, reassignments, naming, globals, function complexity |
| Notebook-specific | N1–N8 | Naming, version reporting, imports at the top, long or empty cells, missing text cells, notebook length, non-linear execution |
| ML-specific | M1–M5 | Uncontrolled randomness, in-place API misuse, implicit hyperparameters, unspecified usecols or dtype, ambiguous merges |
The Python rules include unused variables, variable reassignments, variable naming with a minimum identifier length greater than 3 except for conventions such as X and y, functions with more than 5 parameters, “consider using from import,” unused imports, reimported modules, functions with more than 11 local variables, and global variables in functions (Mignard et al., 15 Sep 2025). These rules are conventional in spirit, but their implementation benefits from notebook-wide scope and explicit cell mappings.
The notebook rules capture organizational and execution concerns that standard linters typically ignore. They include notebook naming constraints, presence of environment or library version reporting via package.__version__ or watermark, imports appearing outside the first code cell, code cells exceeding 30 lines, empty code cells, absence of any markdown cells, notebooks with more than 50 code cells, and out-of-order execution based on execution counters (Mignard et al., 15 Sep 2025). The non-linear execution rule is particularly notebook-specific because it targets hidden state and stale variables created by out-of-order runs.
The ML-specific rules target reproducibility and data-pipeline semantics. They detect ML-related functions called without fixed random seed parameters, in-place API misuse such as df.dropna() without reassignment or inplace=True, model instantiation without explicit key hyperparameters, pd.read_csv calls without explicit usecols or dtype, and DataFrame merges without explicit on, how, or validate parameters (Mignard et al., 15 Sep 2025). The library coverage in these ML rules focuses on pandas 2.2 and scikit-learn 1.6.1.
The tool also makes explicit accommodations for notebook-native behavior. CodeCells link to Outputs so that notebook-typical patterns such as a bare expression at the end of a cell can be distinguished from style issues. The system therefore excludes “pointless-statement” style warnings that are often intentional in notebooks (Mignard et al., 15 Sep 2025). This indicates that the linter is not simply a repackaged script checker, but a model deliberately adapted to notebook execution practices.
5. Empirical evaluation on Kaggle notebooks
The principal empirical study applies Vespucci Linter to a random sample of 5,000 notebooks drawn from KGTorrent, a corpus of 248,761 Kaggle notebooks from 2015–2020 (Mignard et al., 15 Sep 2025). For each notebook, the authors aggregated the number of violations per rule, the number of affected notebooks, the percentage of analyzed notebooks affected, and the average number of violations per affected notebook.
The reported results show violations at all three levels. Among the most prominent findings, N3 “Imports at the top” produced 15,527 violations across 1,931 notebooks, corresponding to 38.6% of the sample and 8.04 violations per affected notebook. P2 “Variable reassignments” produced 14,767 violations across 2,874 notebooks, or 57.5% of the sample and 5.14 per affected notebook. N2 “Version control” was violated in 4,951 notebooks, equivalent to 99.0% of the sample. N6 “Missing text cells” was violated in 904 notebooks, or 18.1% (Mignard et al., 15 Sep 2025).
The ML-specific results underscore the paper’s emphasis on reproducibility and explicitness. For M4, missing usecols in read_csv produced 6,275 violations and missing dtype produced 6,226 violations, with both issues present in over 65% of notebooks. M1 “Uncontrolled randomness” produced 3,343 violations in 20% of notebooks, and M3 “Implicit hyperparameters” appeared in 20.3% of notebooks (Mignard et al., 15 Sep 2025). By contrast, P4, P5, and P8 each appeared in fewer than 3% of notebooks, and N1 “Notebook naming” produced almost no violations because filenames had been normalized in KGTorrent.
The paper’s interpretation of these results is qualitative but direct. Some practices, once used, repeat throughout notebooks, especially scattered imports and variable reassignments. Documentation gaps suggest that a significant fraction of notebooks are personal or prototypical rather than communicative artifacts. ML-specific reproducibility and data-loading explicitness emerge as common pain points (Mignard et al., 15 Sep 2025). These observations support the argument that notebook linting cannot be reduced to generic Python style checking.
Manual validation covered 15 notebooks. The authors report that most rules were correctly triggered, but systematic false positives were found for P1 “Unused variables” due to current parsing limitations. The tool also intentionally prioritizes avoiding false positives, which means the results may underestimate true violations through false negatives (Mignard et al., 15 Sep 2025). This trade-off is central to the system’s current validity profile.
6. Broader interpretations: visualization linting and sociotechnical extensions
Outside notebook analysis, the name “Vespucci Linter” is used in the data block as a blueprint for visualization linting. One direct precursor is VizLinter, which defines a visualization linter as a static analysis tool that inspects an already-built visualization to detect violations of codified design principles and grammar-level constraints, and pairs it with a visualization fixer that automatically corrects detected violations according to the linter (Chen et al., 2021). VizLinter focuses on Vega-Lite specifications and targets within-encoding incompatibilities, cross-encoding conflicts, mark-channel incompatibilities, and typo or syntax issues.
A more expansive proposal appears in the sociotechnical linting paper on Community Notes. That work argues that visualizations are expressive artifacts whose rightness and wrongness are both technical and social, and proposes human computation—specifically Community Notes on social platforms—as a sociotechnical linter that can surface misleading visualizations and add contextual critique that algorithmic linters miss (Crisan et al., 11 Feb 2025). It organizes linting across “puritanical,” “neutral,” and “rebellious” dimensions, corresponding respectively to strict codified rules and static analysis, broader computational evaluation, and human judgment centered on “whatever” inputs and “by whatever” evaluation.
The same paper sketches a concrete “Vespucci Linter” architecture for visualizations. Its components include a visualization rule linter, a contextual critique module, an AI triage layer, a human computation layer, and feedback loops. The proposed rule engine would perform procedural checks such as zero-baseline for bar charts, log scale labeling, proper choropleth normalization, and error bars for uncertainty. The AI layer would score “misleadingness” risk from features such as truncated axes, suspicious smoothing, log-linear mismatches, extreme annotation framing, and selective time-windowing. The human layer would present the visualization, extracted context, and triage findings to reviewers using structured prompts and evidence checklists, then aggregate ratings with diversity-aware consensus and reliability metrics such as Cohen’s or Fleiss’ (Crisan et al., 11 Feb 2025).
This broader use of the term makes Vespucci Linter less a single software artifact than a family resemblance across linting systems. In the notebook paper, contextuality is achieved by unifying cells and code entities. In VizLinter, it is achieved by combining rule-based diagnosis and automated fixing over formal specifications. In the Community Notes paper, it is achieved by adding human computation to account for omitted context, domain conventions, and normative judgments (Mignard et al., 15 Sep 2025, Chen et al., 2021, Crisan et al., 11 Feb 2025). A plausible implication is that the name now denotes a general ambition: linting systems that preserve local structure while reasoning about broader workflow or communication context.
The data block also links Vespucci Linter to positive feedback through “code perfumes.” In that literature, code perfumes are the counterpart to code smells and indicate correct application of programming practices considered to be good. The guidance explicitly recommends making perfumes first-class citizens in Vespucci Linter output and pairing them with smells contextually (Obermüller et al., 2021). This is not part of the implemented notebook tool, but it defines a possible extension in which linting reports strengths as well as deficits.
7. Limitations, governance, and future directions
The notebook tool’s present limitations are those of static analysis over a dynamic language and interactive environment. Static analysis cannot fully resolve dynamic Python behaviors or runtime-dependent state, and star imports are exempt from some checks. Current ML rule coverage focuses on pandas and scikit-learn, with broader library support planned. The authors also note false positives for unused variables and a design choice that favors false negatives in order to reduce noise (Mignard et al., 15 Sep 2025). These constraints bound the interpretability of the reported violation counts.
The paper’s future directions are concrete. They include integrations with notebook environments such as JupyterLab and VS Code for inline, real-time feedback; richer ML semantics such as pipeline structure validation, data leakage detection, sequencing of fit/transform/predict, and evaluation metric checks; larger empirical studies; an extended rule catalog; CI integration and configuration; and environment-level indicators such as requirements.txt and Git for version-control awareness while preserving simplicity (Mignard et al., 15 Sep 2025). The practical effect of these directions would be to move the tool from batch analysis toward continuous development support.
The visualization-oriented Vespucci blueprint raises a different class of limitations and governance concerns. The Community Notes study is explicitly a provocation rather than a controlled empirical trial, and its evidence is qualitative. It also emphasizes that visualization quality is contested, guidelines are debated, and some lints are inherently irreconcilable. Consensus algorithms may hide legitimate disagreements, so diversity and dissent should be presented where appropriate (Crisan et al., 11 Feb 2025). These observations matter because a sociotechnical linter intervenes not only in artifacts but in public interpretation.
The same work identifies risks including the implied truth effect, automation bias, bias and fairness problems, adversarial misuse, transparency and accountability requirements, and privacy constraints. Its mitigations include documentation and audits of rules and models, calibration and training, uncertainty communication, moderation policies and escalation pathways, and privacy safeguards with data minimization (Crisan et al., 11 Feb 2025). These governance requirements are largely absent from the notebook paper because the notebook tool is a local static analyzer; they become central once linting is extended to public communication systems.
Taken together, these strands indicate that Vespucci Linter is best understood not as a single frozen product, but as a research program in contextual linting. Its most concrete instantiation is the Moose-based multi-level analyzer for Python ML notebooks (Mignard et al., 15 Sep 2025). Its broader significance lies in showing how linting can be generalized: from code style to notebook workflow, from formal specification legality to automated repair, and from algorithmic checks to sociotechnical evaluation of visual communication (Chen et al., 2021, Crisan et al., 11 Feb 2025).