Documentation only: RFC 0001 marks the point as outdated; ADR 0007 records the fork as a decision with its license duties, not as a deviation from the RFC. See docs/prs/2026-10-02-PR#21-rfc-0001-fork-outdated.md. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: mhoennig <michael@hoennig.de> Reviewed-on: #21
784 lines
30 KiB
Markdown
784 lines
30 KiB
Markdown
# RFC 0001: CodeCharta Export for Mutation-CRAP Code Cities
|
|
|
|
- Status: proposed
|
|
- Date: 2026-10-02
|
|
- Author: Michael Hönnig
|
|
- Implementation: in several PRs, starting with PR#13 (see section 16)
|
|
|
|
This RFC is the feature request as written, taken over unchanged apart from this header.
|
|
Decisions taken while implementing it go into ADRs and the PR-docs; this text is not maintained afterwards.
|
|
A point the implementation has overtaken is marked as outdated where it stands, with a pointer to the decision.
|
|
|
|
## 1. Goal
|
|
|
|
Add an optional CodeCharta export to werkcrappit.
|
|
|
|
The export shall turn the existing Mutation-CRAP analysis into an interactive 3D code city that can be opened with the standard CodeCharta visualization.
|
|
|
|
Do not build a custom 3D viewer.
|
|
|
|
CodeCharta is the rendering and navigation engine.
|
|
|
|
The visualization shall make structural size, complexity, Mutation-CRAP hotspots, and direct dependencies visible at a glance.
|
|
|
|
The intended mapping is:
|
|
|
|
| Program structure / metric | CodeCharta representation |
|
|
| --- | --- |
|
|
| Gradle module or analysis context | top-level district where useful |
|
|
| Java/JVM package | district / folder |
|
|
| class | building / file node |
|
|
| class LOC | building area |
|
|
| class complexity | building height |
|
|
| class Mutation-CRAP | building color |
|
|
| direct class dependency | edge between buildings |
|
|
|
|
The result shall be a valid CodeCharta `cc.json` 2.x file.
|
|
|
|
The initial implementation must work for Java.
|
|
|
|
Kotlin/JVM compatibility is desirable but must not delay or weaken the Java implementation.
|
|
|
|
## 2. Motivation
|
|
|
|
Werkcrappit currently identifies JVM methods that combine structural complexity with weak mutation-test effectiveness.
|
|
|
|
The Markdown report is useful for ranking individual methods, but it does not reveal spatial or architectural patterns well.
|
|
|
|
A code-city representation adds a complementary view.
|
|
|
|
Large packages become visibly large districts.
|
|
|
|
Large classes occupy more ground area.
|
|
|
|
Complex classes become taller buildings.
|
|
|
|
Classes containing badly tested complex methods become visually prominent through color.
|
|
|
|
Dependencies make it possible to recognize whether a hotspot is isolated or architecturally central.
|
|
|
|
The visualization is exploratory and does not replace the existing report or build gate.
|
|
|
|
## 3. Existing werkcrappit constraints
|
|
|
|
Read `AGENTS.md` and the existing specification before designing or changing production code.
|
|
|
|
Preserve all existing hard invariants.
|
|
|
|
In particular:
|
|
|
|
- Mutation results continue to come from the PIT listener API.
|
|
- Complexity continues to come from JaCoCo Core analysing original, unmutated class files.
|
|
- The Mutation-CRAP formula is not changed.
|
|
- Exact score comparison for the existing gate is not changed.
|
|
- The Gradle plugin must not contain a second implementation of the Mutation-CRAP formula.
|
|
- The existing `mutation-crap.json` remains the authoritative machine-readable Mutation-CRAP report.
|
|
- The existing `mutation-crap.md` remains unchanged unless a separately justified documentation change is required.
|
|
- The CodeCharta artifact is a derived visualization artifact.
|
|
|
|
Production code remains Java 21 unless there is a documented reason to change that decision.
|
|
|
|
Use `var` or `final var` where it improves readability and fits the existing style.
|
|
|
|
Use JUnit Jupiter and AssertJ for tests.
|
|
|
|
Use Mockito only where a test double is preferable to a small real fixture.
|
|
|
|
## 4. Scope
|
|
|
|
### 4.1 Required for the first usable version
|
|
|
|
Implement all of the following:
|
|
|
|
1. Produce a CodeCharta-compatible JSON file from a finished werkcrappit analysis.
|
|
2. Represent packages as nested CodeCharta folders.
|
|
3. Represent analysed classes as CodeCharta file nodes so each class becomes one building.
|
|
4. Export class LOC as an absolute numeric metric named `loc`.
|
|
5. Export aggregated class complexity as an absolute numeric metric named `complexity`.
|
|
6. Export aggregated class Mutation-CRAP as an absolute numeric metric named `mutation_crap`.
|
|
7. Export direct dependencies between analysed classes as CodeCharta dependency edges.
|
|
8. Add human-readable metric descriptors.
|
|
9. Include the analysed Git commit in CodeCharta metadata when it is available.
|
|
10. Support an optional source link for a class node when enough source-link information is configured or available.
|
|
11. Validate the generated result against the CodeCharta 2.x format in automated tests.
|
|
12. Add functional coverage proving that a real Gradle fixture produces a file that CodeCharta accepts.
|
|
|
|
### 4.2 Explicitly out of scope for the first version
|
|
|
|
Do not implement any of the following as part of this feature unless a concrete blocker makes a small part necessary:
|
|
|
|
- a custom 3D renderer;
|
|
- a CodeCharta fork (outdated: a patched viewer is in use since PR#20, see ADR 0007);
|
|
- an embedded CodeCharta web application;
|
|
- an IDE plugin;
|
|
- a local HTTP service for opening files in IntelliJ IDEA;
|
|
- automatic browser launching;
|
|
- hosting or publishing the generated visualization;
|
|
- method-as-building visualization;
|
|
- a new quality score derived from the class-level aggregations;
|
|
- transitive dependency closure;
|
|
- dependency edges to external libraries that are not buildings in the exported city;
|
|
- a replacement for the existing Markdown report;
|
|
- a replacement for the existing build gate.
|
|
|
|
## 5. Architectural direction
|
|
|
|
Treat CodeCharta export as a post-analysis transformation.
|
|
|
|
Prefer consuming the stable internal/report model that already represents the completed werkcrappit analysis rather than coupling CodeCharta serialization directly to PIT callbacks.
|
|
|
|
The exporter must not depend on PIT listener lifecycle details.
|
|
|
|
A reasonable decomposition is:
|
|
|
|
| Component | Responsibility |
|
|
| --- | --- |
|
|
| existing metric/report model | authoritative method-level Mutation-CRAP data |
|
|
| class aggregation | convert method-level data into class-level visualization metrics |
|
|
| class metadata analyser | derive LOC, source metadata, and direct class dependencies from original production bytecode and available source/build metadata |
|
|
| CodeCharta model | small internal representation of the required CodeCharta 2.x structures |
|
|
| CodeCharta writer | deterministic JSON serialization and checksum generation |
|
|
| Gradle integration | configure and execute the export in the real project context |
|
|
|
|
Do not introduce a separate Gradle subproject unless it produces a clear dependency or packaging benefit.
|
|
|
|
A package inside `werkcrappit-pit` for format-independent export logic plus thin orchestration in `werkcrappit-gradle-plugin` is acceptable.
|
|
|
|
A different split is acceptable if it preserves the existing dependency direction and hard invariants.
|
|
|
|
Document a non-obvious architecture choice in an ADR.
|
|
|
|
## 6. CodeCharta format requirements
|
|
|
|
Target the CodeCharta `cc.json` 2.x wire format.
|
|
|
|
At the time of this feature request, the authoritative schema is available at:
|
|
|
|
`https://raw.githubusercontent.com/MaibornWolff/codecharta/main/dev_docs/cc-json-2.0.schema.json`
|
|
|
|
Do not copy an assumed schema from this document into production code without checking the actual CodeCharta version selected for compatibility testing.
|
|
|
|
The generated document shall use the top-level structure:
|
|
|
|
```text
|
|
meta
|
|
files
|
|
lenses
|
|
```
|
|
|
|
The `files` array contains exactly one root folder in CodeCharta 2.x.
|
|
|
|
The class buildings are represented as `File` nodes.
|
|
|
|
Package and optional module/context containers are represented as `Folder` nodes.
|
|
|
|
The `metrics` lens contains the class metrics.
|
|
|
|
The `dependency` lens contains class dependency edges.
|
|
|
|
The 3D CodeCharta map reads physical dependency edges from `lenses.dependency.edges`.
|
|
|
|
Do not rely on `leafEdges` for the visible 3D class edges in this feature.
|
|
|
|
### 6.1 Compatibility rule for dependency edges
|
|
|
|
Keep physical edges deliberately minimal.
|
|
|
|
Each edge shall contain:
|
|
|
|
- `fromId`;
|
|
- `toId`;
|
|
- `attributes`, with at least a numeric `dependencies` value.
|
|
|
|
Do not emit optional edge properties merely because they exist on CodeCharta `main`.
|
|
|
|
In particular, do not emit `isCyclic` or `isPointingUpwards` in the first implementation.
|
|
|
|
A tested CodeCharta viewer rejected `isCyclic` as an additional property although the newer schema on CodeCharta `main` already allowed it.
|
|
|
|
This demonstrates that viewer and schema versions can differ.
|
|
|
|
Prefer the smallest format accepted by the compatibility target.
|
|
|
|
Cycles remain representable naturally as opposing directed edges.
|
|
|
|
### 6.2 Stable node IDs
|
|
|
|
Generate deterministic node IDs.
|
|
|
|
Follow the CodeCharta convention for file-tree identities where practical: the first 16 hexadecimal characters of SHA-256 over the canonical tree path.
|
|
|
|
A repeated export of the same logical tree shall produce the same node IDs independent of iteration order.
|
|
|
|
### 6.3 Checksum
|
|
|
|
Generate the CodeCharta metadata checksum exactly as required by the selected CodeCharta 2.x format.
|
|
|
|
Do not hard-code a constant or placeholder checksum.
|
|
|
|
Add a test that changes a metric or edge and proves that the checksum changes accordingly.
|
|
|
|
## 7. Logical city structure
|
|
|
|
### 7.1 Packages are districts
|
|
|
|
Translate the Java/JVM package hierarchy into nested CodeCharta folders.
|
|
|
|
Example:
|
|
|
|
```text
|
|
root
|
|
└── com
|
|
└── example
|
|
├── order
|
|
│ ├── Order
|
|
│ └── OrderService
|
|
└── billing
|
|
├── Invoice
|
|
└── BillingService
|
|
```
|
|
|
|
Do not flatten packages into a single folder name such as `com.example.order` if the CodeCharta layout can preserve the hierarchy cleanly.
|
|
|
|
The exporter may omit empty intermediate nodes only if that does not alter the intended district hierarchy.
|
|
|
|
### 7.2 Gradle multi-project builds
|
|
|
|
The existing werkcrappit analysis context already distinguishes modules/analyses.
|
|
|
|
Do not merge identically named classes from different Gradle subprojects.
|
|
|
|
For a per-analysis export, the analysis root can be the CodeCharta root.
|
|
|
|
If a combined multi-project export is implemented later, Gradle project paths shall form a hierarchy above the package hierarchy.
|
|
|
|
A combined multi-project city is not required for the first implementation.
|
|
|
|
## 8. Class-level metrics
|
|
|
|
The existing Mutation-CRAP metric is method-level.
|
|
|
|
CodeCharta buildings are class-level in this feature.
|
|
|
|
Aggregation must therefore be explicit and documented.
|
|
|
|
Do not silently call an aggregation an established CRAP metric.
|
|
|
|
### 8.1 Area: LOC
|
|
|
|
Export `loc` as the building area metric.
|
|
|
|
For the first version, define class LOC as the number of distinct source line numbers attributed to executable methods of that class by the same JaCoCo analysis of the original class file.
|
|
|
|
This definition deliberately avoids introducing a Java source parser merely to count physical lines.
|
|
|
|
Document that this value is executable/source-associated LOC derived from bytecode line information rather than a count of all non-empty source-file lines.
|
|
|
|
If JaCoCo provides no usable line information for a class, omit `loc` for that node rather than inventing zero.
|
|
|
|
If an alternative existing metric source in werkcrappit already provides a more precise and equally language-neutral class LOC without another test run, use it and document the decision.
|
|
|
|
Do not run tests again to obtain LOC.
|
|
|
|
### 8.2 Height: class complexity
|
|
|
|
Export `complexity` as the building height metric.
|
|
|
|
For the first version, class complexity is the sum of JaCoCo cyclomatic complexity values of the analysed, non-excluded methods belonging to that class.
|
|
|
|
Do not use the maximum method complexity as the class height.
|
|
|
|
Do not calculate a separate source-level complexity implementation.
|
|
|
|
The exported value must be derived from the same JaCoCo complexity data already used by werkcrappit.
|
|
|
|
### 8.3 Color: class Mutation-CRAP
|
|
|
|
Export `mutation_crap` as the building color metric.
|
|
|
|
For the first version, the class Mutation-CRAP visualization value is the maximum numeric Mutation-CRAP value among `SCORED` methods of the class.
|
|
|
|
The reason is intentionally conservative: one severe method shall not be hidden by averaging it with many trivial methods.
|
|
|
|
This maximum is a visualization aggregation only.
|
|
|
|
It is not a new class-level quality formula and must not be used by the existing gate unless separately specified in the future.
|
|
|
|
If a class has no `SCORED` method, omit `mutation_crap` for that class.
|
|
|
|
Never substitute `0` for unavailable, inconclusive, excluded, or unscored data.
|
|
|
|
### 8.4 Additional useful metrics
|
|
|
|
The exporter may add the following absolute metrics if they are cheap and unambiguous:
|
|
|
|
- `method_count`;
|
|
- `scored_method_count`;
|
|
- `inconclusive_method_count`;
|
|
- `max_method_complexity`;
|
|
- `mutant_count`.
|
|
|
|
These are optional.
|
|
|
|
Do not let optional metrics delay the required three visual dimensions.
|
|
|
|
## 9. Dependency edges
|
|
|
|
### 9.1 Meaning
|
|
|
|
An edge represents a direct static dependency from one analysed production class to another analysed production class.
|
|
|
|
The direction is caller/user -> referenced class.
|
|
|
|
Only dependencies whose source and target both have buildings in the exported city are required.
|
|
|
|
Do not create buildings for JDK classes or third-party libraries merely to satisfy an edge.
|
|
|
|
### 9.2 Extraction
|
|
|
|
Prefer extracting dependencies from the original production bytecode that werkcrappit already locates for JaCoCo analysis.
|
|
|
|
Do not depend on compiled test classes.
|
|
|
|
Do not load application classes through reflection to discover dependencies.
|
|
|
|
A direct ASM-based visitor is acceptable.
|
|
|
|
Declare a direct ASM dependency if the implementation uses ASM APIs; do not rely accidentally on a transitive dependency layout that another library happens to provide.
|
|
|
|
At minimum detect class references from:
|
|
|
|
- superclass and implemented interfaces;
|
|
- field types;
|
|
- method parameter and return types;
|
|
- bytecode field access owners;
|
|
- bytecode method invocation owners;
|
|
- object/array creation and type instructions.
|
|
|
|
Handle arrays and descriptors correctly.
|
|
|
|
Ignore primitive types.
|
|
|
|
Ignore self-edges by default.
|
|
|
|
Lambda/invokedynamic, annotations, generic signatures, bootstrap handles, and constants should be handled when straightforward, but they must not turn the first implementation into a general JVM dependency-analysis project.
|
|
|
|
Document any intentionally unsupported bytecode reference categories.
|
|
|
|
### 9.3 Edge aggregation
|
|
|
|
Collapse multiple individual references from class A to class B into one directed CodeCharta edge.
|
|
|
|
Set `attributes.dependencies` to the number of observed direct reference sites or dependency occurrences according to one documented counting rule.
|
|
|
|
Use the same counting rule deterministically across runs.
|
|
|
|
Do not emit duplicate A -> B edge records.
|
|
|
|
If A depends on B and B depends on A, emit two directed edges.
|
|
|
|
This naturally represents a cycle without requiring `isCyclic`.
|
|
|
|
## 10. Source metadata and links
|
|
|
|
### 10.1 Git commit
|
|
|
|
Populate `meta.commitHash` when the analysed commit is available reliably.
|
|
|
|
Prefer the exact analysed commit over a moving branch name such as `main`.
|
|
|
|
Do not guess a commit when the working tree state cannot be associated reliably with one.
|
|
|
|
### 10.2 Class source links
|
|
|
|
CodeCharta file nodes support a `link` field.
|
|
|
|
Use it when a stable class source URL can be constructed.
|
|
|
|
The first version shall not hard-code Gitea, GitHub, GitLab, or IntelliJ-specific URL rules into the exporter core.
|
|
|
|
Prefer a configurable source-link template.
|
|
|
|
A template may support placeholders such as:
|
|
|
|
```text
|
|
{commit}
|
|
{path}
|
|
{line}
|
|
{class}
|
|
{package}
|
|
```
|
|
|
|
Example for a Gitea installation:
|
|
|
|
```text
|
|
https://git.example.org/acme/project/src/commit/{commit}/{path}#L{line}
|
|
```
|
|
|
|
If the required values for the configured template are unavailable, fail configuration clearly or omit the link according to the documented option semantics.
|
|
|
|
Do not silently generate a broken URL.
|
|
|
|
### 10.3 Future local IDE navigation
|
|
|
|
Keep source path and first source line available internally so a later feature can generate a local IDE link or a localhost bridge URL.
|
|
|
|
Do not implement that bridge as part of this feature.
|
|
|
|
## 11. Gradle user experience
|
|
|
|
The export shall be opt-in initially.
|
|
|
|
Do not add noticeable work to users who only want the existing reports and gate.
|
|
|
|
A recommended shape is a task named:
|
|
|
|
```text
|
|
mutationCrapCodeCharta
|
|
```
|
|
|
|
The task consumes a completed werkcrappit analysis and writes a CodeCharta file.
|
|
|
|
Running the task may depend on the PIT/werkcrappit analysis task if the report is missing or stale, consistent with the existing `mutationCrapCheck` approach.
|
|
|
|
Do not add the CodeCharta task to Gradle `check` by default.
|
|
|
|
A possible extension DSL is:
|
|
|
|
```kotlin
|
|
werkcrappit {
|
|
codeCharta {
|
|
enabled = true
|
|
sourceLinkTemplate = "https://git.example.org/acme/project/src/commit/{commit}/{path}#L{line}"
|
|
}
|
|
}
|
|
```
|
|
|
|
The exact DSL may be adapted to the existing plugin architecture.
|
|
|
|
Avoid configuration that duplicates values already known from Gradle or the existing werkcrappit analysis.
|
|
|
|
A default output filename of `mutation-crap.cc.json` next to the existing werkcrappit reports is preferred.
|
|
|
|
If CodeCharta or current project conventions require a different suffix, document the reason.
|
|
|
|
## 12. Determinism
|
|
|
|
Two exports from identical inputs shall be byte-for-byte identical except for fields that are explicitly specified as variable.
|
|
|
|
Prefer no volatile timestamp at all.
|
|
|
|
Sort package children, class nodes, metric descriptor maps, and edges deterministically before serialization where map/list order can affect output or checksum.
|
|
|
|
The export must not depend on callback order from PIT, filesystem traversal order, hash-map iteration order, or Gradle worker scheduling.
|
|
|
|
## 13. Error handling
|
|
|
|
Treat the CodeCharta export as a visualization step, not as part of the Mutation-CRAP score calculation.
|
|
|
|
A requested CodeCharta task must fail with a clear diagnostic when its required authoritative input report is missing, unreadable, or incompatible.
|
|
|
|
A malformed generated CodeCharta document is a build error for the export task.
|
|
|
|
A missing optional source link is not a reason to invalidate otherwise valid metric data unless the user explicitly configured a template that cannot be satisfied.
|
|
|
|
A class without numeric Mutation-CRAP may still appear as a building with LOC and complexity.
|
|
|
|
A class without dependencies must still appear normally.
|
|
|
|
Unknown external dependency targets are ignored for physical edges in the first version.
|
|
|
|
Do not replace unavailable data with misleading zeros.
|
|
|
|
## 14. Validation
|
|
|
|
### 14.1 Unit tests
|
|
|
|
Cover at least:
|
|
|
|
- deterministic package-tree construction;
|
|
- deterministic CodeCharta node IDs;
|
|
- class LOC aggregation;
|
|
- class complexity aggregation;
|
|
- maximum Mutation-CRAP aggregation;
|
|
- omission of Mutation-CRAP when no method is scored;
|
|
- dependency extraction for representative Java bytecode constructs;
|
|
- dependency aggregation without duplicate edges;
|
|
- opposing edges for a cycle;
|
|
- source-link template expansion;
|
|
- JSON serialization;
|
|
- checksum generation;
|
|
- deterministic output independent of input iteration order.
|
|
|
|
### 14.2 Schema validation
|
|
|
|
Keep a compatibility test against the selected CodeCharta schema/version.
|
|
|
|
Do not fetch a mutable schema from the internet during normal tests.
|
|
|
|
Pin a tested schema artifact, a released CodeCharta validation tool, or a small verified local contract fixture in a reproducible way.
|
|
|
|
Document the selected CodeCharta compatibility version in `docs/compatibility.md` or a dedicated CodeCharta compatibility section.
|
|
|
|
### 14.3 Functional test
|
|
|
|
Add a Gradle TestKit fixture containing at least seven production classes in multiple packages and at least ten direct class dependencies.
|
|
|
|
The fixture shall include:
|
|
|
|
- at least three packages;
|
|
- at least one large/high-complexity class relative to the others;
|
|
- multiple different Mutation-CRAP values;
|
|
- at least one bidirectional dependency pair;
|
|
- at least one class with no outgoing dependency;
|
|
- at least one class with no numeric Mutation-CRAP if this can be created without distorting the fixture.
|
|
|
|
Run real PIT and werkcrappit analysis as the existing functional-test architecture requires.
|
|
|
|
Run the CodeCharta export task.
|
|
|
|
Assert that the generated `mutation-crap.cc.json` contains seven class buildings and the expected ten directed edges for the fixture.
|
|
|
|
Validate the generated document against the pinned CodeCharta compatibility contract.
|
|
|
|
Where practical, add a manually verified compatibility probe that loads the generated artifact into the CodeCharta viewer.
|
|
|
|
Record that probe in the compatibility documentation; do not pretend browser rendering is covered by a headless JSON unit test.
|
|
|
|
## 15. Acceptance scenarios
|
|
|
|
Keep canonical Gherkin feature files under `docs/features/` in German according to the repository convention.
|
|
|
|
Use new stable scenario IDs, for example `@MC-CC-...`.
|
|
|
|
The following scenarios define the intended behavior.
|
|
|
|
```gherkin
|
|
# language: de
|
|
|
|
Funktionalität: CodeCharta-Export der Mutation-CRAP-Analyse
|
|
|
|
Grundlage:
|
|
Angenommen ein erfolgreicher werkcrappit-Lauf hat einen vollständigen Mutation-CRAP-Report erzeugt
|
|
|
|
@MC-CC-001
|
|
Szenario: Packages werden zu Stadtteilen und Klassen zu Gebäuden
|
|
Angenommen die Analyse enthält Klassen in mehreren verschachtelten Packages
|
|
Wenn der CodeCharta-Export ausgeführt wird
|
|
Dann enthält der Dateibaum für die Package-Hierarchie verschachtelte Folder-Knoten
|
|
Und jede analysierte Klasse wird durch genau einen File-Knoten dargestellt
|
|
|
|
@MC-CC-002
|
|
Szenario: Gebäudegrundfläche basiert auf Lines of Code
|
|
Angenommen eine Klasse besitzt ausführbaren Code auf mehreren unterschiedlichen Quelltextzeilen
|
|
Wenn der CodeCharta-Export ausgeführt wird
|
|
Dann enthält ihr Gebäude die absolute Metrik "loc"
|
|
Und der Wert entspricht der dokumentierten Anzahl unterschiedlicher zugeordneter Quelltextzeilen
|
|
|
|
@MC-CC-003
|
|
Szenario: Gebäudehöhe basiert auf der aggregierten Komplexität
|
|
Angenommen eine Klasse besitzt mehrere analysierte Methoden mit JaCoCo-Komplexitätswerten
|
|
Wenn der CodeCharta-Export ausgeführt wird
|
|
Dann enthält ihr Gebäude die absolute Metrik "complexity"
|
|
Und der Wert ist die Summe der berücksichtigten Methodenkomplexitäten
|
|
|
|
@MC-CC-004
|
|
Szenario: Gebäudefarbe zeigt den schlechtesten Mutation-CRAP-Wert der Klasse
|
|
Angenommen eine Klasse besitzt mehrere mit Mutation-CRAP bewertete Methoden
|
|
Wenn der CodeCharta-Export ausgeführt wird
|
|
Dann enthält ihr Gebäude die Metrik "mutation_crap"
|
|
Und der Wert entspricht dem höchsten numerischen Mutation-CRAP-Wert dieser Methoden
|
|
|
|
@MC-CC-005
|
|
Szenario: Nicht bewertbare Methoden erzeugen keinen erfundenen guten Klassenwert
|
|
Angenommen keine Methode einer Klasse besitzt einen numerischen Mutation-CRAP-Wert
|
|
Wenn der CodeCharta-Export ausgeführt wird
|
|
Dann besitzt das Gebäude dieser Klasse keine Metrik "mutation_crap"
|
|
Und der Export setzt dafür nicht den Wert 0
|
|
|
|
@MC-CC-006
|
|
Szenario: Direkte Klassenabhängigkeiten werden als gerichtete Edges exportiert
|
|
Angenommen Klasse A referenziert Klasse B direkt im Produktionsbytecode
|
|
Und beide Klassen gehören zum exportierten Analyseumfang
|
|
Wenn der CodeCharta-Export ausgeführt wird
|
|
Dann enthält der Dependency-Lens genau eine gerichtete physische Edge von A nach B
|
|
Und diese Edge besitzt ein numerisches Attribut "dependencies"
|
|
|
|
@MC-CC-007
|
|
Szenario: Mehrere Referenzen derselben Klassen werden zu einer Edge zusammengefasst
|
|
Angenommen Klasse A referenziert Klasse B an mehreren Stellen
|
|
Wenn der CodeCharta-Export ausgeführt wird
|
|
Dann enthält der Dependency-Lens nur eine gerichtete Edge von A nach B
|
|
Und das Attribut "dependencies" entspricht der dokumentierten Anzahl der Referenzen
|
|
|
|
@MC-CC-008
|
|
Szenario: Ein Zyklus wird durch zwei gerichtete Edges dargestellt
|
|
Angenommen Klasse A hängt direkt von Klasse B ab
|
|
Und Klasse B hängt direkt von Klasse A ab
|
|
Wenn der CodeCharta-Export ausgeführt wird
|
|
Dann enthält der Dependency-Lens eine Edge von A nach B
|
|
Und eine Edge von B nach A
|
|
Aber keine der beiden Edges benötigt ein zusätzliches Feld "isCyclic"
|
|
|
|
@MC-CC-009
|
|
Szenario: Externe Bibliotheken erzeugen keine zusätzlichen Gebäude
|
|
Angenommen eine analysierte Klasse referenziert eine Klasse aus einer externen Bibliothek
|
|
Wenn der CodeCharta-Export ausgeführt wird
|
|
Dann wird für die externe Klasse kein Gebäude erzeugt
|
|
Und es wird keine physische Edge zu einem nicht vorhandenen Zielknoten erzeugt
|
|
|
|
@MC-CC-010
|
|
Szenario: Der analysierte Git-Commit wird als Metadatum exportiert
|
|
Angenommen der analysierte Git-Commit ist eindeutig bekannt
|
|
Wenn der CodeCharta-Export ausgeführt wird
|
|
Dann enthält "meta.commitHash" diesen Commit
|
|
|
|
@MC-CC-011
|
|
Szenario: Ein konfigurierter Source-Link zeigt auf den analysierten Commit
|
|
Angenommen ein Source-Link-Template ist konfiguriert
|
|
Und Commit, Source-Pfad und Startzeile einer Klasse sind bekannt
|
|
Wenn der CodeCharta-Export ausgeführt wird
|
|
Dann enthält der File-Knoten dieser Klasse einen expandierten Link
|
|
Und der Link verwendet den analysierten Commit statt eines beweglichen Branch-Namens
|
|
|
|
@MC-CC-012
|
|
Szenario: Der Export ist deterministisch
|
|
Angenommen dieselben Analyse- und Bytecode-Daten werden zweimal in unterschiedlicher Eingabereihenfolge bereitgestellt
|
|
Wenn beide CodeCharta-Exporte ausgeführt werden
|
|
Dann sind die erzeugten Dateien byteweise identisch
|
|
|
|
@MC-CC-013
|
|
Szenario: Der erzeugte Datensatz ist mit der unterstützten CodeCharta-Version kompatibel
|
|
Angenommen eine reale Gradle-Testfixture enthält sieben Klassen und zehn direkte Abhängigkeiten
|
|
Wenn PIT, werkcrappit und anschließend der CodeCharta-Export ausgeführt werden
|
|
Dann ist die erzeugte Datei gegen den gepinnten CodeCharta-Kompatibilitätsvertrag gültig
|
|
Und sie enthält sieben Klassengebäude
|
|
Und sie enthält zehn gerichtete Dependency-Edges
|
|
```
|
|
|
|
## 16. Suggested implementation sequence
|
|
|
|
Implement the feature in small reviewable vertical steps.
|
|
|
|
A suggested sequence is:
|
|
|
|
### Step 1: Minimal valid CodeCharta export
|
|
|
|
- Add the smallest internal CodeCharta model required for `meta`, `files`, and `lenses.metrics`.
|
|
- Export package folders and class buildings.
|
|
- Export `loc`, `complexity`, and `mutation_crap`.
|
|
- Add deterministic IDs and checksum handling.
|
|
- Prove schema compatibility in a functional fixture.
|
|
|
|
### Step 2: Dependency edges
|
|
|
|
- Add bytecode dependency extraction.
|
|
- Collapse duplicate class pairs.
|
|
- Export `lenses.dependency.edges` with minimal compatible properties.
|
|
- Extend the functional fixture to seven buildings and ten edges.
|
|
|
|
### Step 3: Gradle UX and source links
|
|
|
|
- Add the opt-in task/configuration.
|
|
- Add commit metadata.
|
|
- Add configurable source-link templates.
|
|
- Document usage.
|
|
|
|
If the existing architecture makes a different PR split substantially smaller or safer, adjust the split but keep each PR vertically usable and green.
|
|
|
|
## 17. Documentation changes
|
|
|
|
Update at least:
|
|
|
|
- `README.md` with a short CodeCharta section and example task invocation;
|
|
- `docs/compatibility.md` with the tested CodeCharta compatibility target;
|
|
- `docs/features/` with the accepted Gherkin scenarios;
|
|
- `docs/acceptance-test-map.md` with mappings from `@MC-CC-...` scenarios to automated tests;
|
|
- a PR document under `docs/prs/` for each implementation PR according to repository practice.
|
|
|
|
If a new architectural decision is required, add an ADR under `docs/adr/`.
|
|
|
|
Documentation must make clear that `mutation_crap` on a class is the maximum method score for visualization and not a new metric definition.
|
|
|
|
## 18. Example expected visualization
|
|
|
|
For a project containing:
|
|
|
|
```text
|
|
com.example.domain
|
|
Order
|
|
Customer
|
|
Invoice
|
|
|
|
com.example.service
|
|
OrderService
|
|
BillingService
|
|
|
|
com.example.persistence
|
|
OrderRepository
|
|
InvoiceRepository
|
|
```
|
|
|
|
CodeCharta should render three package districts containing seven buildings.
|
|
|
|
Building area shall reflect class LOC.
|
|
|
|
Building height shall reflect summed JaCoCo complexity.
|
|
|
|
Building color shall reflect the maximum scored method Mutation-CRAP value.
|
|
|
|
Ten direct class dependencies in the fixture shall be selectable as CodeCharta edges.
|
|
|
|
The user can then configure the CodeCharta viewer approximately as:
|
|
|
|
```text
|
|
Area = loc
|
|
Height = complexity
|
|
Color = mutation_crap
|
|
Edge = dependencies
|
|
```
|
|
|
|
The visual result is the acceptance target; the exact CodeCharta camera, layout, color scale, and rendering style are not part of werkcrappit's responsibility.
|
|
|
|
## 19. Definition of done
|
|
|
|
The feature is done when all of the following are true:
|
|
|
|
- A real Gradle project can produce `mutation-crap.cc.json` through the werkcrappit Gradle integration.
|
|
- The file is valid for the documented CodeCharta compatibility target.
|
|
- Packages appear as districts and classes as buildings.
|
|
- `loc`, `complexity`, and `mutation_crap` are selectable CodeCharta metrics.
|
|
- Direct dependencies are available as the `dependencies` edge metric.
|
|
- A seven-class fixture produces the expected ten directed edges.
|
|
- No optional incompatible edge fields such as `isCyclic` are required.
|
|
- Existing Mutation-CRAP JSON, Markdown, score calculation, and gate behavior remain unchanged.
|
|
- Unit and functional tests are green with `./gradlew build`.
|
|
- The new Gherkin scenarios are mapped to automated tests.
|
|
- Documentation explains how to open the generated file in CodeCharta and which metric to map to area, height, color, and edges.
|
|
|
|
## 20. Non-goals and future ideas
|
|
|
|
Keep these ideas visible but do not implement them in the first feature unless separately requested:
|
|
|
|
- toggle between analysed-commit Git links and local IDE links;
|
|
- local `localhost` bridge that opens IntelliJ IDEA at a source line;
|
|
- method drill-down from a class building;
|
|
- method-level logical `leafEdges`;
|
|
- combined city across all Gradle subprojects;
|
|
- comparison of two commits or releases;
|
|
- filtering edges by dependency type;
|
|
- cycle-specific edge styling;
|
|
- source-level dependency classification such as inheritance, instantiation, argument, and return-value usage;
|
|
- alternative scaling such as square-root or logarithmic visual transforms;
|
|
- custom CodeCharta presets for the werkcrappit metric mapping.
|
|
|
|
These can be built later without changing the primary Mutation-CRAP metric contract.
|
|
|
|
## 21. References
|
|
|
|
- werkcrappit repository: https://git.javagil.de/mi/werkcrappit
|
|
- werkcrappit agent instructions: https://git.javagil.de/mi/werkcrappit/src/branch/main/AGENTS.md
|
|
- CodeCharta: https://codecharta.com/
|
|
- CodeCharta cc.json 2.x schema: https://raw.githubusercontent.com/MaibornWolff/codecharta/main/dev_docs/cc-json-2.0.schema.json
|
|
|