Ecosystem metrics
- New Repos
- 7
- New
- Commits
- 1,015
- up 26.4%
- Releases
- 11
- up 10.0%
- Contributors
- 53
- down 1.9%
- Merges
- 24
- up 71.4%
Activity Overview
Commits and releases over time
- Commits
- Releases
- Authors
Repository Explorer
No repositories match that filter.
10388 commits in all time
May 18, 2026 21:15 – Aug 16, 2026 21:15 UTC
Merge ee6e17aaf7b37a675090627ae8a4941106202599 into c1e451f3864d614d28a54c6e5beacd19cdb71592
de323ec4
pull/31/merge
8/494 ++ 15 --
Also verify the typed client, the artifact the tests actually run against
There are TWO arrows out of the committed artifact, not one, and neither was
checked:
contracts/out/TrelyanInscription.*
| algod compile | algokit generate client
v v
bytecode ==? chain contracts/trelyan_client.py
The client branch matters more than it looks. contracts/trelyan_client.py is an
89 KB generated file stamped "DO NOT MODIFY IT BY HAND", and the LocalNet suite
deploys the committed TEAL and drives it THROUGH that client. CI only ever
consumes it; nothing regenerated it and compared. A contract whose ABI moved
without the client being regenerated would be exercised by a suite talking to
the old interface -- and the suite would pass.
CHECKED WITHOUT RUNNING THE GENERATOR, DELIBERATELY
`algokit generate client` needs algokitgen-py, which would pin this check to a
generator version whose formatting churn is not a finding. It is also, on the
machine this was written on, blocked outright by a Windows Application Control
policy (os error 4551) -- the same policy that currently blocks cargo-deny.
No generator is needed: the client EMBEDS the full spec it was generated from,
in _APP_SPEC_JSON. Comparing that to the committed arc56.json needs nothing but
the two committed files, runs anywhere, and is stable across generator versions.
The comparison is on PARSED JSON rather than bytes, because the client embeds
the spec minified while arc56.json is pretty-printed -- a byte comparison would
fail always and therefore mean nothing.
Failure reporting distinguishes an ABI-method change (names differ; the suite is
testing a different interface) from a signature/struct/metadata change (names
agree), because those read very differently to a reviewer.
VERIFIED
- clean tree: all five artifacts plus the client in step, exit 0
- rename a method inside the client's embedded spec: CLIENT DRIFT, exit 1,
naming both method lists
- a missing _APP_SPEC_JSON block is reported as "repair the check", not
silently passed -- if the generator's output shape changes, this check stops
reading what it thinks it reads, and that is a finding about the check
ee6e17aa
ci/verify-teal-matches-source
1/87 ++ 4 --
Put inscription.py inside the verified chain; it was never in it
verify_deployment.py documents a derivation chain in which nothing is stored
and everything is recomputed:
contracts/inscription.py
| puya <-- THIS ARROW
v
contracts/out/TrelyanInscription.* [committed artifacts]
| algod /v2/teal/compile
v
expected bytecode --sha512_256--> fingerprint ==? deployed program
CI only ever ran the part BELOW the committed artifact. The --recompile flag
covering the top arrow exists, and no workflow ever passed it: grep across
.github/workflows/ returns zero occurrences of "recompile".
So inscription.py -- the ONLY human-readable artifact in the chain, the file a
reviewer reads and an auditor is handed -- was not verified to correspond to
anything. An edit that changed behaviour, committed without regenerating
contracts/out/, passed every gate green: the committed TEAL still assembles to
the bytecode still on chain, and nothing compared the source to the artifact.
The reviewer reads one program, the network runs another, all checks pass.
That is the exact failure verify_deployment.py warns about in its own output --
"before treating any review of this source as a review of the live
application" -- arriving through the door nobody was watching.
WHAT THIS ADDS
contracts/verify_teal_matches_source.py recompiles from source with the pinned
toolchain and compares ALL FIVE committed artifacts as text, separating two
failure modes that need different responses:
BEHAVIOURAL instruction streams differ -- the artifact does not implement the
source. A correctness finding.
STALE instructions identical, only comments and '// inscription.py:NNN'
references differ. Bytecode unaffected, but an auditor tracing
TEAL back to source lands on the wrong line.
Running verify_deployment.py --recompile in CI would close most of this, and is
still worth doing. It would not close all of it: after its repair it compares
ASSEMBLED BYTECODE, deliberately, so comment churn cannot raise a false alarm --
which also means stale source references pass, since the assembler discards
comments. It also covers only the two .teal files, not the maps or the ARC-56
client contract.
REPRODUCIBILITY IS INVOCATION-SENSITIVE, AND NO DOCUMENTED COMMAND REPRODUCED
puya records the source path AS TYPED, in two forms in two places:
- .teal comments carry the path as given. Compiling from the repo root emits
'// contracts/inscription.py:156' where the committed artifact carries
'// inscription.py:156' -- 124 differing lines, every one cosmetic.
- .puya.map 'sources' is the path RELATIVE TO THE OUT-DIR. The committed map
says '../inscription.py', which only reproduces when the out-dir is a
SIBLING of inscription.py's parent, as contracts/out/ is.
Three build commands were documented -- README.md, CONTRIBUTING.md and
contracts/requirements.txt -- and NONE reproduced the committed artifacts. Two
ran from the repository root; the third referenced crypto/contracts/, a
directory that does not exist in this repository. THREAT_MODEL_AND_TRACEABILITY
carried the same non-existent path through its entire reproduction recipe --
an audit-facing document whose every step failed on file-not-found. All are
corrected to the invocation that actually reproduces:
cd contracts && puyapy inscription.py --out-dir out --target-avm-version 12
Verified: all five artifacts then reproduce BYTE-FOR-BYTE.
THE PIN IS NOW INSTALLABLE
puyapy==5.8.1 / algorand-python==3.5.0 existed only as a COMMENT describing a
venv on one developer's machine at %USERPROFILE%\trelyan-build. A commented pin
cannot be installed, so CI could not reproduce the build even in principle and
nothing would detect the toolchain moving. Now contracts/requirements-compile.txt,
with exact == pins: byte-comparison against a committed artifact is only
meaningful against a fixed compiler.
VERIFIED, NOT ASSUMED
- unmodified tree: all five artifacts identical, exit 0
- comment-only edit to inscription.py: reported STALE, exit 1
- behavioural edit (UInt64(0) -> UInt64(1)): reported BEHAVIOURAL DRIFT on
approval.teal (intcblock 0 1 8 32 -> 1 0 8 32) AND stale on the two
position-bearing files, in one report, exit 1
- the newly documented command run verbatim: git diff empty
Line endings are normalised before comparison. The committed blobs contain
CRLF while puya writes LF, so without that the job would fail on every Linux
run -- a verdict that depended on the operating system would not be a check.
58b61ff4
ci/verify-teal-matches-source
8/411 ++ 15 --
Merge 8b3c0bfb7b6a57c000adad8fe755556ca450a25b into c1e451f3864d614d28a54c6e5beacd19cdb71592
656eb2f4
pull/27/merge
5/185 ++ 8 --
Stop the version test from aborting the whole 3.10 suite
My own test broke CI, and the way it broke is worth more than the fix.
It imported `tomllib` at module scope. That is stdlib only from 3.11, and this
package supports 3.10 -- requires-python = ">=3.10", and the wire-format matrix
tests it. So on the 3.10 leg the import raised, and pytest reported:
collecting ... collected 69 items / 1 error
ERROR tests/test_version_is_single_sourced.py
E ModuleNotFoundError: No module named 'tomllib'
!!!!!!!! Interrupted: 1 error during collection !!!!!!!!
A collection error is not one failing test -- it aborts the ENTIRE session. All
69 wire-format tests stopped running on 3.10, and the job surfaced as a single
red check, indistinguishable from one ordinary failure. A green-looking matrix
with one red leg hid "68 tests never ran".
Fix: import the parser inside the function that uses it, with a 3.10 branch to
the `tomli` backport. Local scope means a parser problem fails THIS test and
leaves the rest of the suite running.
Verified against a real CPython 3.10.20, not assumed:
- before: Interrupted, 0 tests run
- after: 53 passed, 19 skipped -- and all three version tests RUN, not skip
- mutation (break the in-function import deliberately): 2 failed, 51 passed,
no Interrupt -- which is the property the change is actually for
- 3.12 unchanged: 53 passed, 19 skipped
Also declares `tomli>=2 ; python_version < "3.11"` in the dev extra. Stated
precisely: this is NOT what fixes the failure. pytest already depends on tomli
on <3.11 (it parses pyproject.toml config with it), so it was installed the
whole time -- removing it stops pytest from starting at all, before collection.
The declaration is so the suite names its own dependency instead of resting on
a transitive dependency of the test runner.
8b3c0bfb
fix/version-drift-and-missing-audit-docs
2/22 ++ 2 --
Merge 9e2bbebff833474cc4ef2f5ab64d9270955e0c79 into 337211c9b279ae7ee811998064b3de3f0ced7f73
35206bbf
pull/389/merge
15/250 ++ 224 --
note column added to voucher table
9e2bbebf
pull/389/head
5/8 ++ 2 --
Merge 075f375cfa60f1253481c466d36af16377020649 into 337211c9b279ae7ee811998064b3de3f0ced7f73
ac581750
pull/389/merge
14/244 ++ 224 --
Voucher database integrated for store voucher
075f375c
pull/389/head
11/171 ++ 44 --