You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
No emitted number changed in this cycle. The spec stays at 1.1.0.
The Buse-Weimer lane is now self-contained
Permission obtained. Westley Weimer, an author of the Buse-Weimer
dataset, granted redistribution of the raw snippets and annotator scores and
publication of derived data, by e-mail on 2026-07-11 (DKIM-verified). New PERMISSIONS.md records the message date, Message-ID, authentication result
and the sha256 of the retained original, states exactly what was asked and
answered, and is explicit that this is a permission, not a licence, and
that the accompanying citation request (cite both the TSE 2010 and the ISSTA
2008 paper) is a request, not a condition. This project honours it anyway.
The raw inputs are now tracked, under that grant, in validation/bw_faithfulness/derived/arbitration_inputs/: the 100 Java
snippets (snippets/1.jsnp … 100.jsnp), oracle.csv (the 121-row
per-annotator matrix) and scores.csv (the per-snippet means derived from
it). 102 files, 57,168 bytes.
The lane therefore reproduces offline.extract.py, train.py, report.py and arbitrate.py read the tracked pins as their primary source.
With no network and no cache/, they run to completion and regenerate the
seven artifacts they write, byte-for-byte. (features_fallback_off.csv is not
among them: it is a pinned input, the pre-BW-ALL-0007 extraction that the
arbitration compares against, and arbitrate.py fails if it is missing.) This
is what the 0.1.0 changelog claimed prematurely (see the correction under
[0.1.0] below); it is true now.
Two gates enforce the input contract (new pinned.py): a missing tracked
input is a hard error, exit 1, never a SKIP, so a lane that measured nothing
can no longer exit 0 and read as a successful run; and when cache/DatasetBW.zip is present, every pin is cross-checked byte-for-byte
against it, with any difference a hard error rather than a silent re-pin. pin_inputs.py records how the pins were produced and is not on the
reproduction path. Every SKIP-and-exit-0 path is gone from the lane.
The permission asymmetry between the three corpora has a canonical home: PERMISSIONS.md in prose, validation/bw_faithfulness/dataset.toml in
machine-readable form, which fetch.py enforces. Every other document that
touches the question states the consequence it needs, which is normally just
"this lane needs the network and that one does not", and links to those two.
The Buse-Weimer corpus remains the only dataset content in the tracked tree;
the Scalabrino et al. (2018) and Dorn (2012) corpora have no permission of any
kind, and not one byte of either is or will be tracked.
PMD is wired as the Java differential oracle
PMD 7.26.0 witnesses both cyclomatic and cognitive complexity, per method, for
Java. It is the first external witness Java cognitive complexity has had in this
project, and the second for Java cyclomatic (lizard was the only one). It is
independent of tree-sitter all the way down, its own Java grammar and its own
metric visitors, so agreement with it is not two wrappers around one parser
agreeing with themselves. Coverage: 16 Java inputs (9 reference-comparable corpus
cases plus 7 probes) x 2 metrics = 32 per-method comparisons, of which 28 agree.
Four new classified divergences (tests/differential/divergences.toml,
rendered to docs/spec/divergences.md):
java-contextual-001 / Point.quadrant and snippet:diff-java-switch-expr / SwExpr.grade, cognitive, ours 1, PMD 0 (COG-ALL-0001). One gap, hit twice:
PMD's CognitiveComplexity rule scores a switch expression zero. Measured on
all four forms: it counts arrow-form and colon-form switch statements,
agreeing with us, and zeroes both forms of switch expression, while its own
CyclomaticComplexity rule counts all four. The gap is
expression-versus-statement, and it is specific to PMD's cognitive rule.
snippet:diff-java-recursion / R.fact, cognitive, ours 1, PMD 2
(COG-ALL-0006). PMD takes the whitepaper's +1-per-recursive-call increment;
comparisons run in sonar-compat mode, which omits it. The Python oracle cognitive_complexity 1.3 takes the same side (py-recursion-001).
snippet:diff-java-lambda / L.make, cyclomatic, ours 2, PMD 1
(CORE-ALL-0003). PMD's CyclomaticComplexity rule neither descends into a lambda
body nor reports the lambda as a unit of its own, so the lambda's if is
counted nowhere. Two witnesses put PMD alone: lizard scores make 2, and PMD's
own CognitiveComplexity rule does descend into the lambda (cognitive 2). PMD's
two rules disagree with each other.
The residual gap, named. Recursion is the one axis on which the two cognitive
modes differ, and PMD takes the whitepaper side: on that row it witnesses the
whitepaper mode, which scores 2 and agrees with it exactly. Java's sonar-compat
recursion behaviour therefore still has no external witness, and rests on the
hand-computed corpus and the spec alone. The Java witnessing gap is narrowed, not
closed.
No measured value changed. PMD is a test-time oracle, never a runtime
dependency, and the spec stays at 1.1.0.
Running it. PMD is a JVM tool, so it is not in the oracles pip extra: it
needs java on PATH and python tools/fetch_pmd.py, which downloads about 73 MB
and sha256-verifies it against the pin in tests/differential/pmd.toml, into the
gitignored .oracles/. Sitting outside the pip closure that constraints/ci.txt
pins is precisely why PMD was cut at 0.1.0. Without PMD, or without a JVM, the
lane SKIPs with an actionable reason, exactly like the pip oracles. CI does not get
that option: the differential job in ci.yml installs a JVM (temurin 21), runs tools/fetch_pmd.py and hard-gates on pmd --version before pytest, because a
SKIP there would let the job pass while testing nothing.
Other
validation/breadth/: the cross-corpus parse-anatomy lane (parse rates over
the three corpora, plus a Python demo). It requires a network fetch and
always will, because two of its three corpora may not be redistributed.
validation/bw_faithfulness/dataset.toml now carries all three corpora with
their per-corpus permission status, as the machine-readable form of PERMISSIONS.md, and fetch.py enforces it.
ORCID recorded for the author in CITATION.cff
(0009-0009-9835-3800).
Root documentation overhauled: README.md, ARCHITECTURE.md and CLAUDE.md
had been restating each other. Each now declares what it is for and owns that
content alone (README: what the tool is and how to use it; ARCHITECTURE: the
requirements record, rationale and decision log; CLAUDE.md: agent operating
instructions). Two sections of ARCHITECTURE.md were describing code that
does not exist and have been rewritten against it. §8.3 still said the corpus
licence was "unstated", that the data was "never committed", and that a
missing archive produced an honest SKIP; all three had become false. §7.3
claimed bare Java snippets yield ERROR-dense trees and are always re-parsed
inside one class __CC__ { void __cc__() { … } } wrapper. In fact
tree-sitter-java's program rule accepts bare statement sequences and bare
method declarations (CORE-JAVA-0001), scaffolding is a fallback with two
candidate wrappers and a strict error-count minimizer that is adopted only
when it beats the bare parse, and 10 of the 100 dataset snippets actually take
it.
Three false claims in that documentation, all of them written rather than
checked, are corrected against the code:
"Adding a language touches zero core code" (ARCHITECTURE §5, repeated in CLAUDE.md) was wrong in both files. A third language must also edit languages/__init__.py (_BUILTIN, get_adapter()), syntax/grammars.py
(_GRAMMAR_MODULES, an unguarded dict lookup that raises a bare KeyError)
and cli.py (--lang choices, which rejects an unlisted language outright).
The "Adding a language" checklist in CONTRIBUTING.md now names all three
and says what each one's failure looks like.
ARCHITECTURE §11 and an earlier draft of this entry said the docs site has
deliberately no contributor page. It has had one since W7: mkdocs.yml's nav
lists it, and docs/contributing.md is a snippet transclusion of CONTRIBUTING.md, so the checklists are hosted on the site without existing
in two versions. The file that is linked rather than re-hosted is ARCHITECTURE.md.
ARCHITECTURE §3.4 introduced a divergences.toml stanza as a real record
while silently dropping a clause from its reason and adding four inline
comments the file does not contain. It is now quoted exactly, with the field
glosses moved to prose.
CONTRIBUTING.md gains "Superseding a ruling": which two fields go on the
retired stanza (status, superseded_by), what the successor needs
(since_spec, a corpus case citing it), and the fact that the spec level is
set by the drift gate rather than by the supersession (TOK-ALL-0004 →
TOK-ALL-0006 moved numbers and was a MAJOR; TOK-PY-0001 → TOK-PY-0002 did not
and was a MINOR).
mypy is listed as a hard CI gate in CONTRIBUTING.md's setup and README's
development section. It was in ci.yml and in CLAUDE.md, so the agent was
told and the human was not.
README pointed at arbitration_report.md for its tab-width correlations. That
file carries the verdict, not the numbers: they are in arbitration_report.json and, for the adopted setting, bw_faithfulness_report.md's per-feature table. README also now states the
annotator count as the tracked oracle.csv has it (121 rows, against the
paper's 120, reported and not reconciled).
RELEASING.md documents the release-order constraint the derived reports
impose (finalise _version.pybefore regenerating them; see [0.1.0]).