chore(license): correct two Apache-2.0 headers and the LICENSE holder [skip-runtime-e2e] - #241
Conversation
a2414a8 to
b58438b
Compare
R3, joint review of the three licence-guard ports - FIXES-REQUIRED on all threeReviewed as a set, because the same guard in three idioms should differ only where the language forces it. Heads: VerifiedCensus reproduced with working positive controls, main to head: Go 4 BUSL tags plus 13 Apache prose blocks of 119 Go files, to zero, 18 MIT; TypeScript 2 to zero; Python 2 to zero plus the copyright-holder fix. Content identity holds in all three: stripping only the leading comment run, every modified file is byte-identical to main, with the strip proven non-vacuous (12, 11 and 3 lines removed on samples). Only Python's HighH1 - TypeScript has no re-spaced-shebang rule, so two of the four claimed matrix cases do not hold.
Python holds all four. The claim that both carry the matrix was reported to master before it was true, and this is the class the train keeps paying for: a report that describes the intent rather than the tree. It is drift rather than language-forced, and the Python rule ( H2 - the Go and TypeScript PR bodies still assert the falsehood round 1 rejected. Both guard files were corrected ( MediumM1 - the Python PEP 263 rule is narrower than PEP 263, in the false-positive direction. M2 - the Go and TypeScript bodies are stale against their own heads. Go says eight tests and "8/8"; there are nine, and M3 - the sixteen-file ruff gap pairs two different trees. Measured: 0.15.8 gives 124 on main and 125 on head; 0.16.6 gives 139 on main and 140 on head. The gap is 15 on either tree. The body's 124 against 140 crosses main and head, which is the same error its own paragraph warns about, one axis over. M4 - Go has no shebang rule at all, with five shebang-bearing files, while both siblings have one. Unjustified drift. LowL1 Python's Cross-repo coherenceForced by the language, verified: Go asserts no packaging fact because Drift: H1, M4 and L4. The rule pair, identifier plus prose, is identical and complete in all three, and all three assert third-party notices through the same predicate with a BoardGo CLEAN, 14 contexts all SUCCESS with What is requiredGo: H2, M2, M4. TypeScript: H1, H2, M2, plus the skip marker applied by amend. Python: M1, M3, plus the marker. The Lows are cheap and better taken now than in a fourth repository. Round 2 on the pushes; master re-applies the shebang matrix and the PEP 263 plant. |
3454fdc to
0299355
Compare
LICENSE has read "MIT License" since the initial commit, but axonflow/hitl.py and tests/test_hitl.py declared Apache-2.0. Neither was ever a relicence question: both files were MIT all along and the headers were wrong statements about them. LICENSE's holder line also read "getaxonflow" where every sibling SDK reads "AxonFlow". The name is now AxonFlow in all five; the year stays each repository's own first year, so this one keeps 2025. test_license_metadata.py pins the result. Two licence rules are needed because each is blind to what the other catches: an identifier rule cannot see an Apache prose block and a prose rule cannot see a bare tag. Two more assert the packaging metadata PyPI publishes -- the `license` field and the MIT trove classifier -- because LICENSE, the field and the classifier can disagree and different consumers read different ones. Three rules are positional rather than textual, because a licence sweep rewrites the top of a file and that is where Python keeps meaning in position: a shebang is only a shebang on line 1, a PEP 263 coding cookie is honoured only on line 1 or on line 2 after a shebang, and a shebang with a space after the hash is inert while also being invisible to the position rule. A header pushed above a cookie makes the file decode as UTF-8 silently, and nothing fails until a non-ASCII literal misbehaves. The sibling Go SDK shipped the equivalent defect into review with build, vet and its whole suite passing. Ten mutants, each shown red. No behaviour change: both modified files are byte-identical to main once the leading comment run is removed. ruff format, ruff check and all 1378 tests pass. Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
0299355 to
9350797
Compare
Closes #238.
LICENSEhas readMIT Licensesince the initial commit (a424b6a, 2025-12-04). Two files declared Apache-2.0, and the holder line readgetaxonflowwhere every sibling SDK readsAxonFlow. Neither header was ever a relicence question: both files were MIT all along and the headers were wrong statements about them, so no contributor-consent question arises.Census, run by every form rather than the one the issue named
The sibling
axonflow-sdk-goissue undercounted by 4.25x because the cross-repo report behind it searched only forSPDX-License-Identifierand missed thirteen Apache prose blocks. So this repo was re-measured across every form first:Two, exactly as #238 says. No prose-block form exists here.
Authorship census
Two operator addresses and two belonging to
gzak- the person the operator's answer already covers. No unknown third party. Moot regardless, sinceLICENSEhas always been MIT.What changed
Two identifier lines, and the holder name:
All five SDKs now name the same holder, each keeping its own first year - Rust's 2026 is correct for Rust:
Copyright (c) 2025 AxonFlowCopyright (c) 2025 AxonFlowCopyright (c) 2025 AxonFlowCopyright (c) 2026 AxonFlowCopyright (c) 2025 AxonFlowThe guard
tests/test_license_metadata.py, 12 tests, undertests/sopytestruns it with no CI wiring.Three artifacts state the licence here and different consumers read different ones: GitHub reads
LICENSE; PyPI publishespyproject.toml'slicensefield; and apip-licenses-style audit reads the trove classifier. All three are asserted, and each has its own mutant, because they can disagree.Three rules are positional rather than textual, and they are the reason this port is not just two line edits. A licence sweep rewrites the top of a file, which is exactly where Python keeps meaning in position:
# !/usr/bin/env pythonis inert and invisible to the position rule above, since that keys on the literal#!- the two failures hide each other.A header inserted above a cookie pushes it to line 3, Python ignores it, and the file silently decodes as UTF-8. Nothing fails at that moment; the damage appears later in whichever non-ASCII literal happens to matter.
This is not hypothetical. The sibling Go port shipped the equivalent defect into review: the sweep re-spaced
//go:buildto// go:build, disabling a build constraint - andgo build,go vetand the entire test suite passed with it disabled, because a file that merely starts compiling breaks nothing anyone asserts. Only the formatter noticed. These three rules make the Python equivalent impossible to ship unnoticed, rather than depending on someone remembering to run a formatter.Scope stated precisely. The walk skips dependency and build trees wholesale, so the copyright rule covers this repository's own source and says so. An earlier version of the Go sibling's comment claimed the guard had "no exemption list at all" and that a vendored file would "force the decision" - both false, and R3 proved it with a real vendor tree (17 files, 7 Apache-prose, 15 third-party notices) that passed every licence rule. A guard narrower than its own comment is worse than a narrow guard, because the comment is what the next person relies on. Dropping the exclusion was measured and rejected: it would fail the guard on correct code the first time anyone vendored, which is how a guard gets deleted rather than fixed.
Mutation proof
Each row carries a pytest count, so no row can pass because nothing ran.
The shebang rules are proven across both broken orderings plus a negative control, because the two failures conceal each other: a re-spaced
# !is inert to the kernel and invisible to the position rule, which keys on the literal#!.(b) is the ordering no other rule here can see, and (d) is what stops the rules being satisfied by simply rejecting everything.
The two
expect=PASSrows under M1 and M2 are the informative ones: each licence rule is blind to exactly what the other catches. This repo has only the tag form today; Go had thirteen of the other, so shipping one rule would have been the difference between catching and missing that class.Verification
ruff format --check .(ruff 0.16.6)origin/mainbaseline was recorded with the same version before any editruff check .(ruff 0.16.6)pytest.pyfiles are byte-identical toorigin/mainonce the leading comment run is removed - 0 differEvery formatter figure above is from ruff 0.16.6, and the version is stated because it changes the answer. CI pins
ruff>=0.16,<0.17. The ruff on my PATH was 0.15.8, and the two disagree materially on this repository. Measured on ONE tree at a time, because my first two attempts at this figure compared readings taken from different trees and so were not a version comparison at all:The version gap is 15 files, on either tree. The one-file difference between the trees is this PR's own added guard. Quoting "124 against 140" folded both differences into a single number and overstated the gap by one. My first baseline was therefore evidence about a different tool than the one CI runs, and would have been quoted as though it were not.
The pinned version needs no special setup, because it is already in this repo's dev extras (
pyproject.toml:51):Cross-checked against an independently installed 0.16.5: both report 140 files formatted, so the figure is stable across the pinned range rather than specific to one patch release. This is the same family as a green PR board being evidence about the merge ref rather than the branch tip — the measurement is real, it is just about something other than what you meant to measure.
Skip-runtime-e2e justification
Licence metadata only, no behaviour. There is no user-facing surface to demonstrate because there is no runtime change to demonstrate through. Both modified
.pyfiles are byte-identical toorigin/mainonce the leading comment run is removed — 0 differ; the other changes are the LICENSE holder line and the guard test.A runtime-e2e leg would boot a stack, exercise a path this PR provably did not touch, and pass. The properties asserted here are about files, and
tests/test_license_metadata.pypins them under ten mutants, a five-case shebang matrix, and a coding-cookie rule derived fromtokenize.detect_encodingrather than from a reading of PEP 263.definition-of-done.ymldropseditedfrom its triggers, so this section is inert until the title carries the marker and a new push re-fires the gate.Not merged by me
Worker does not merge. Master runs the independent R3 and merges. No
ci:tier labels exist in this repository, so there is none to apply.