Skip to content

One SWC display vocabulary, and a release workflow that needs no local build - #25

Merged
longvo92 merged 2 commits into
mainfrom
claude/swc-display-seam
Jul 31, 2026
Merged

One SWC display vocabulary, and a release workflow that needs no local build#25
longvo92 merged 2 commits into
mainfrom
claude/swc-display-seam

Conversation

@longvo92

Copy link
Copy Markdown
Owner

Two commits. The first finishes the rule-3 cleanup the previous PR deferred;
the second removes the reason a release currently costs a manual build.

7618e33 — one SWC display vocabulary

The previous PR reported three duplicated helpers between report.py and
qtviewer/. That count was low. What was actually there:

Fact Copies Where
iface_kind 3 report.py, summary_model.py, main.py (inlined .replace())
swc_item 3 report.py, summary_model.py, main.py
the category list 6 report.py ×3, summary_model.py, diffpane.py, main.py

main.py is a third renderer — the terminal summary — and the audit only
looked at the report/viewer pair, so it was missed. report.py alone spelled
the list out three times, in two label styles.

view_model.SWC_DISPLAY now holds the labels and takes the keys from
arxml_rules.SWC_CATEGORIES, the module that produces them. A category added
to the rules without a label raises at import instead of quietly going missing
from one surface. (arxml_rules.SWC_CATEGORIES already existed — adding a
second constant of the same name in view_model was the first thing this
change nearly got wrong.)

The blind spot worth knowing about: the fixtures never change a runnable,
so any surface could have dropped that category with the whole suite still
green. The new tests use a synthetic swc diff with all three categories
populated and assert each surface names all of them. Planting a hardcoded list
missing runnables back into _swc_note fails exactly one test.

This touches rendering code, so behaviour was checked rather than assumed: a
report and a terminal run were generated from origin/main in a temporary
worktree and compared against this branch. The terminal output is identical;
the report differs by one meta line, because the two runs were invoked with an
absolute and a relative fixture path.

bcadd35 — release workflow

Cutting a release meant building the .exe by hand and uploading it, which is
part of why the one-line fix sitting in [Unreleased] was not worth a version.

python packaging/release_check.py 1.3.1                                  # same check CI runs
gh workflow run release.yml --ref main -f version=1.3.1                  # rehearsal
gh workflow run release.yml --ref main -f version=1.3.1 -f publish=true  # for real

The default does not publish. A run without publish builds both
artifacts, runs each against the fixtures and stops — and uploads them either
way, because the point of a rehearsal is being able to look at what would have
shipped. The irreversible half is opt-in.

packaging/release_check.py owns every precondition and prints what to change,
since the reader is usually a log:

Not ready to release 1.3.1:
  - compare_tool/__init__.py says __version__ = '1.3.0', not '1.3.1' -- bump it and merge that first
  - CHANGELOG.md has no "## [1.3.1]" section -- move the [Unreleased] entries under it, with the date
  - CHANGELOG.md still has entries under [Unreleased]; they would ship without being listed in the release notes

One script, so a local check and the workflow cannot disagree. The workflow
adds the two facts a file cannot know: the ref is main, and the tag is free.
A published version is refused, never overwritten. Nothing in the workflow
edits the repo — the version bump arrives through a normal reviewed PR.

For the reviewer

  • python -m unittest discover -s tests — 447 pass. python -m ruff check . clean.
  • The build steps were run locally instead of being discovered on the first
    tag: build.ps1 -Pyz produces the 44 MB exe and the zipapp, both exit 1 on
    the fixtures, and the artifact-verification step was executed against them —
    and against two identical folders, to watch it fail with
    ::error::dist/compare-tool.exe exited 0, expected 1.
  • Still unproven, by nature: gh release create only runs on a real publish,
    and actions/upload-artifact only exists on a runner. The first rehearsal
    covers both.
  • No CHANGELOG entry. The refactor is invisible, and the release workflow is
    maintainer tooling.

longvo92 added 2 commits July 31, 2026 22:59
The report, the quick-changes panel, the viewer's file header and the terminal
summary each spelled out ('ports', 'runnables', 'events') with their own
labels, and three of them carried their own copy of the interface-tag and
'Ctrl.In2' formatting. Adding a category meant editing six places; missing one
dropped it from that surface alone, silently.

view_model.SWC_DISPLAY now holds the labels and takes the KEYS from
arxml_rules.SWC_CATEGORIES, the module that produces them -- a category added
there with no label raises at import rather than going missing on one screen.

The fixtures never change a runnable, so every surface could have dropped that
category with the suite still green. The new tests use a synthetic swc diff
with all three populated, and assert each surface names all of them.
Releasing meant building the .exe by hand and uploading it, which is why the
one-word fix sitting in [Unreleased] was not worth cutting a version for. Now:

    python packaging/release_check.py 1.3.1
    gh workflow run release.yml --ref main -f version=1.3.1                  # rehearsal
    gh workflow run release.yml --ref main -f version=1.3.1 -f publish=true

The default does not publish. A run without `publish` builds both artifacts,
runs each against the fixtures and stops, uploading them either way -- the
irreversible half is opt-in, and the expensive half can be proven first.

release_check.py holds every precondition (version matches __init__.py, the
CHANGELOG has that section, nothing left under [Unreleased]) and prints what to
change rather than just failing, because the reader is usually a log. One
script, so a local check and the workflow cannot disagree. The workflow adds
what a file cannot know: the ref is main, and the tag is free.

Verified locally rather than on the first tag: build.ps1 -Pyz produces the
44 MB exe and the zipapp, both exit 1 on the fixtures, and the artifact step
was run against them -- and against identical folders, to see it fail.
@longvo92
longvo92 merged commit 96c02af into main Jul 31, 2026
6 checks passed
@longvo92
longvo92 deleted the claude/swc-display-seam branch July 31, 2026 16:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant