chore: add a justfile and AGENTS.md - #29
Merged
Merged
Conversation
grep -rP descends into compiled caches, whose .pyc bytes are not ASCII. A clean CI checkout has none, so the step passed; anyone running the same grep locally after a test run gets a failure on output nobody wrote.
Every recipe in check and test is a command ci.yml runs, with CI's arguments: ruff format --check and ruff check over gerberdiff/ and tests/, the non-ASCII grep, mypy, and pytest with --cov-fail-under=90. CONTRIBUTING.md's four hand-typed commands were missing the format --check, the coverage gate and the ASCII step, so passing them locally did not mean passing CI. AGENTS.md names the org contract as the floor and records what is specific here: the exit-code contract settled in 0685cde, that only geomdiff can return 2, that import gerberdiff stays Cairo-free, the ASCII rule, the coverage gate, and that planning/ is gitignored scratch rather than a plan.
The lazy render import was credited with the Windows CI leg running. It is not the mechanism: the raster tests skip through HAS_CAIRO in tests/cairo_support.py, which exists because cairocffi raises OSError rather than ImportError when the shared library is missing.
"Every sibling has one" is false: orlab has no docs/DECISIONS.md either. The point stands without the comparison, so it is stated without one.
The exit table said `different` is exit 1. It is exit 1 only with --fail-on-diff; without the flag a run with 28928 changes across 14 of 15 layers exits 0. Both existing records of this -- the EXIT_DIFFERENT docstring and the 0.30.0 changelog entry -- carry the qualifier, and this file was the copy that dropped it, which is exactly the gate it tells a reader to write: `[ $? -eq 1 ]` never fires. Also note that 2 is unreachable once a change is found, since `different` outranks `indeterminate`, and point a caller at `summary.unrepresented` instead. The ASCII rule claimed every tracked text file is enforced. The argv is `gerberdiff/ tests/ *.md *.toml` with root-level globs, so 26 of 131 tracked files are outside it -- all of docs/, all of .github/, and the justfile carrying the rule. Scoped the sentence to what the check reads. Name the test matrix as the largest deliberate gap between `just test` and CI, and attribute kicad-happy to aklofas rather than implying it is a sibling.
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #28 (the first two boxes; the
CONTRIBUTING.mdbox is left open deliberately -- see below).The justfile
Every recipe inside
checkandtestis a command.github/workflows/ci.ymlruns, with CI's arguments rather than tidier ones. Derivation, job by job:uv sync --dev(all three jobs)setupuv run ruff check gerberdiff/ tests/lintuv run ruff format --check gerberdiff/ tests/fmt-checkgrep -rP '[^\x00-\x7F]' gerberdiff/ tests/ *.md *.tomlasciiuv run mypy gerberdiff/ tests/typecheckpytest tests/ --cov=gerberdiff --cov-fail-under=90 -qtestpytest tests/ -qtest-nocovcheckisfmt-check lint ascii typecheck-- the lint and typecheck jobs in full. The paths aregerberdiff/ tests/and not.because that is what CI passes; a recipe over.would check a different set of files and still be called the CI gate.Deliberately not recipes:
--cov-report=xml. CI passes it on one leg only, to upload the report as an artifact. Locally it writes a file nobody reads.pre-commit. Nothing inci.ymlruns it, so it isjust hooks, outsidecheck. A greenchecksays nothing about the hooks -- the same gap netspec#30 and slicelab#24 record for their repos.uv sync --locked. CI runs plainuv sync --dev, sosetupdoes too. Making the local recipe stricter than CI would be a different claim than the one this file makes.The ci.yml change
grep -rPdescends into__pycache__, and.pycfiles are full of non-ASCII bytes. CI never noticed because a fresh checkout has no caches; running the identical command locally afterjust testdoes:--exclude-dir=__pycache__is added to both the workflow step and the recipe, so they stay one command. It is a no-op on CI's checkout and changes nothing about which tracked files are checked --git ls-files gerberdiff testslists no binary file (py.typedandtests/__init__.pyare empty).Still red-capable after the change, checked by planting the character it exists to catch:
The gate, run
(
asciiis a shebang recipe, sojustdoes not echo it; it ran betweenlintandtypecheckand exited 0.)AGENTS.md
Names the org contract as the floor and carries only what is substantiated in this repo's code or docs:
0685cde(A3):0identical,1different,2indeterminate,4environment fault,64usage -- with2spelled as a third diff outcome rather than a verdict,differentoutrankingindeterminate, and2returned regardless of--fail-on-diff. Each traced to the code that implements it (DiffOutcomeandGeometryDiffResult.outcomeingeometry/types.py, thegeomdiffexit path incli.py).geomdiffcan return2. The rasterdiffverb exits0,1,4or64and has no third outcome, because it keeps no record of what it failed to model wherelayer_geometry.pycounts anUNREPRESENTED_REASONSkey. Recorded as the current state of the code, not as a design claim, and flagged as something not to add by inference.import gerberdiffis Cairo-free -- render imports are lazy, which is why the Windows CI leg runs at all. Stated with the one-line command that checks it ('cairocffi' in sys.modulesmust beFalse, verified).cli.pycoverage omission, theokaggregator's explicitresult != 'success'form and why the tolerant form is wrong for a workflow with no path filtering.docs/DECISIONS.mdhere, unlike every sibling. Said plainly, with where the reasoning actually lives instead.planning/,artifacts/andoutputs/are gitignored local scratch (.gitignore221-223;git ls-files planningreturns nothing), andplanning/README.mdrecords its own contents as historical. Flagged so nobody plans against it.No Status claim is made that was not run. The verb list came from
gerberdiff --help, the version fromgerberdiff.__version__, and the Cairo-free claim from importing the package and readingsys.modules.Left for #28
CONTRIBUTING.mdstill lists the four hand-typed commands that drift from CI. Pointing it at the recipes is a docs change with its own reviewable content and is kept out of this one.