Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ Repo `codegen-compare-tool`, local folder `code-review`, package
`compare_tool`. Where this file and `~/.claude/CLAUDE.md` disagree, this one
wins.

`docs/architecture.md` explains how the pieces fit and why — layering, the two
diff passes, the shared seams, the result-dict contract. Read it before a change
that crosses module boundaries; this file is the rules, that one is the map.

## 1. Fail-safe is not negotiable

**If it cannot be *proven* to be noise, it is a real change.** A rule that is
Expand Down Expand Up @@ -74,7 +78,7 @@ any dev script take whatever they need; no need to ask first.

The exception is **what ships in `compare_tool.pyz`**: the scan, the rules, the
diff, the report, the review store and `gitsource` import stdlib only. That
zipapp is 78 KB, needs nothing installed, and is the documented fallback for
zipapp is ~110 KB, needs nothing installed, and is the documented fallback for
the machines where antivirus blocks the `.exe` — one third-party import in
`scanner.py` and it stops running there, which is a shipped promise broken by
an import nobody reviewed.
Expand Down Expand Up @@ -102,8 +106,12 @@ Two more promises the same machines depend on:

Tests pass on layouts that look broken. Every UI change gets looked at:

```bash
QT_QPA_PLATFORM=offscreen python smoke.py # widget.grab().save(png), then read the png
Write a throwaway script under `%TEMP%` that builds the widget, grabs it and
saves a png — then read the png:

```powershell
$env:QT_QPA_PLATFORM = 'offscreen'
python $env:TEMP\smoke.py # widget.grab().save(png)
```

and, for anything about colour or legibility, a real window on the desktop.
Expand Down Expand Up @@ -180,6 +188,7 @@ decision; the frozen entry point asks it rather than re-deriving it.
```bash
python -m compare_tool <old_gen> <new_gen> --report out.html
python -m unittest discover -s tests # unittest, NOT pytest
.\build.ps1 # dist/compare_tool.pyz
.\build.ps1 -Exe # plus the .exe (needs pyinstaller)
.\build.ps1 # dist\compare-tool.exe (needs pyinstaller + PySide6)
.\build.ps1 -Pyz # plus dist\compare_tool.pyz
.\build.ps1 -PyzOnly # zipapp only, no build dependencies
```
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ scan did find is still printed.
| `--exclude PATTERN` | Skip files matching a glob (relative path or bare file name), repeatable. Example: `--exclude compare_report.html` |
| `--exit-zero` | Always exit 0 even when real changes exist (report-only mode for pipelines). Compare errors still exit 2 |
| `--arxml-only` | Scan only `.arxml`/`.xml`/`.a2l` and write a compact per-type report (default `arxml_update.html`) — always written, even when nothing changed |
| `--review FILE` | Render notes and sign-offs from a review file (`codegen-review.json`, written by the viewer) next to the changes they belong to, with a `Reviewed` badge. Must be named explicitly; no effect with `--arxml-only` |
| `--review FILE` | Render notes and sign-offs from a review file (`codegen-review.json`, written by the viewer) next to the changes they belong to, plus a `Reviewed` badge that hides the changes already signed off. Must be named explicitly — a report must not pick up someone else's sign-off by accident; no effect with `--arxml-only` |
| `--qt`, `--viewer` | Open the side-by-side viewer on folders named on the command line, instead of comparing them in the terminal. Needs the `viewer` extra (see below) |

Omitting `old_dir`/`new_dir` opens the viewer. `--gui` (the tkinter panel) was removed in 1.1.0.
Expand Down Expand Up @@ -114,6 +114,8 @@ Reading a scan:

`Review mode` adds the note box and a `Review` column in the tree — green when every change in a row is signed off, amber part way, grey when none is. Sign off one change (`Ctrl+R`) or a whole file (`Ctrl+Shift+R`); the notes travel into the exported report.

`Export report…` (`Ctrl+E`) writes the same self-contained HTML report the CLI writes, with the review notes folded in. It is always built from the **complete scan**, never from what is on screen — a category you collapsed in the tree still appears in the file with its real verdict.

Full walkthrough is built into the app — `Help` → `User guide` (`F1`), which works offline. Standalone `.exe` (no Python needed): see [Single-file build](#single-file-build).

## What counts as noise
Expand Down Expand Up @@ -166,7 +168,6 @@ A file whose XML fails to parse is skipped from this summary (its text diff stil

Files are grouped by **Simulink model** using the Embedded Coder AUTOSAR naming convention (`X.c`, `X.h`, `X.arxml`, `Rte_X.h`, the modular ARXML set, …). Files that match no model land in a final **Shared / other** group.


## HTML report

Self-contained file, one per compare: badge toggles, folder tree, filter box, collapsible diffs per file. Opens `Unimportant` hidden and `Modified` expanded, so it opens on what matters.
Expand All @@ -189,7 +190,7 @@ See [azure-pipelines.yml](azure-pipelines.yml) for a working example (OLD checke

```powershell
.\build.ps1 # dist\compare-tool.exe - one file, nothing to install on the target
.\build.ps1 -Pyz # also dist\compare_tool.pyz (~80 KB) for machines that have Python 3.8+
.\build.ps1 -Pyz # also dist\compare_tool.pyz (~110 KB) for machines that have Python 3.8+
.\build.ps1 -PyzOnly # zipapp only (building it needs no PyInstaller / PySide6)
```

Expand All @@ -203,7 +204,7 @@ See [azure-pipelines.yml](azure-pipelines.yml) for a working example (OLD checke

Built as a **console** application so terminal runs keep their exit code (`1` = real changes, `2` = compare incomplete) for the CI gate. The viewer hides the console window at runtime — you'll see a brief flash on double-click. A crash un-hides the console so the error is visible.

- **`.pyz` (zipapp, stdlib)**: `python compare_tool.pyz <old> <new> [flags]`. Prefer it when Python is available — ~80 KB, no build dependencies, not flagged by antivirus. The CLI works anywhere; the viewer additionally needs PySide6 on that machine (without it, the tool says so instead of opening).
- **`.pyz` (zipapp, stdlib)**: `python compare_tool.pyz <old> <new> [flags]`. Prefer it when Python is available — ~110 KB, no build dependencies, not flagged by antivirus. The CLI works anywhere; the viewer additionally needs PySide6 on that machine (without it, the tool says so instead of opening).
- **`.exe` (PyInstaller onefile, ~47 MB)**: no Python needed on the target. Building needs `pyinstaller` and `PySide6` on the dev machine (`build.ps1` installs them), and the binary only runs on the OS it was built on. PyInstaller executables are sometimes blocked by antivirus or AppLocker — fall back to the `.pyz` there.

Every CLI flag behaves identically in the packaged builds. `build/` and `dist/` are already in `.gitignore`.
Expand All @@ -226,10 +227,16 @@ compare_tool/
├── c_rules.py # C/H rules: strip comments, tokenize, detect renames, extract RTE access points
├── arxml_rules.py # ARXML rules: UUID, ADMIN-DATA, DATE, comments + extract port interfaces, SWCs (ports/runnables/events)
├── a2l_rules.py # A2L rules: strip C-style comments + extract CHARACTERISTIC/MEASUREMENT
├── view_model.py # renderer-agnostic view model (paint mode, intra-line span, row alignment) shared by the report and the viewer
├── syntax.py # line-at-a-time C / XML token spans, Qt-free so it ships in the .pyz
├── review.py # reviewer notes and sign-offs, keyed by change content so they survive a rescan
├── gitsource.py # read-only `git archive` of a commit into a temp folder, so a commit can be the OLD side
└── report.py # self-contained HTML report (badge toggles, model overview, grouping, filter, collapsible diffs)
```

To add a rule: write the strip function in `c_rules.py` / `arxml_rules.py`, then register it in the shadow builder and `_build_variants` in `diff_engine.py`.
[docs/architecture.md](docs/architecture.md) covers how these fit together and why: the two diff passes, where a verdict is decided, the shared seams and the result-dict contract. Anything both renderers need lives in `view_model.py` — reimplementing a mapping inline lets the HTML report and the viewer drift apart about what changed.

To add a rule: write the strip function in `c_rules.py` / `arxml_rules.py` / `a2l_rules.py`, join it into that ruleset's shadow, register one labelled variant in `_build_variants` in `diff_engine.py`, and add both tests — the pattern alone is noise, and the same pattern *beside* a real change still reports the real change.

Issues and pull requests are welcome. Please keep the **compare core stdlib-only** — it has to run on locked-down build servers, so PySide6 stays confined to `compare_tool/qtviewer/` and is imported only when the viewer opens — and add a test under `tests/` for any new rule.

Expand Down
2 changes: 1 addition & 1 deletion build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# and the exit code; the viewer hides the console
# window at runtime (see packaging\entry.py).
#
# dist\compare_tool.pyz optional tiny zipapp (~80 KB) for machines that
# dist\compare_tool.pyz optional tiny zipapp (~110 KB) for machines that
# already have Python 3.8+. Stdlib only, so the CLI
# works anywhere; the viewer additionally needs
# PySide6 installed on that machine.
Expand Down
Loading
Loading