Skip to content

codecaliper v0.1.1

Choose a tag to compare

@github-actions github-actions released this 14 Jul 04:37
  • package 0.1.1 · spec 1.1.0 · grammars: tree-sitter-python 0.25.0,
    tree-sitter-java 0.23.5 (binding tree-sitter 0.26.0)
  • 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.jsnp100.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.py before regenerating them; see [0.1.0]).