Packaging-only release. No changes to hunt logic, CLI commands, or LLM providers.
Read this before upgrading
athf.metrics was missing from every published wheel from 0.15.0 through 0.18.0.
pyproject.toml used an explicit [tool.setuptools] packages = [...] list that was never updated when the subpackage was added. Anyone who installed from PyPI got a distribution with no athf/metrics/ directory at all. pip install -e . and twine check both hid this: the editable install resolves against the source tree, and twine check validates metadata rather than archive contents.
What this did and did not affect — the two halves of the metrics system were packaged differently:
- The
athf metricsCLI kept working.athf/commands/metrics.pyandathf/core/metrics.pyshipped normally in every affected release; only theathf/metrics/recording facade was dropped. Soshow,summary, andextractwere never broken, which is part of why the gap went unnoticed. - Automatic recording was silently inert. The three instrumentation call sites import
athf.metricslazily inside atryand swallow the failure —athf/agents/base.pycatchesImportErrorand logs at debug level, whileathf/core/web_search.pyandathf/commands/similar.pyuse a bareexcept Exception: pass. No warning ever surfaced.
Installing 0.19.0 starts emitting LLM-call, web-search, and similarity-search metrics for the first time on any environment that installed from PyPI. That is a behavior change, not only a packaging repair. If you relied on the previous (accidental) absence of automatic metric emission, review athf/metrics/ before upgrading.
Fixed
-
Ship
athf.metrics.[tool.setuptools.packages.find]withinclude = ["athf*"]discovers subpackages instead of relying on a hand-maintained list, so a newly added subpackage can no longer be silently dropped from the artifact. (#54)Scope of the drift, measured against the real artifacts: the 0.18.0 wheel carried 9 subpackages and this one carries 10. The diff is exactly
athf.metrics— nothing else was missing, and nothing was lost.
Changed — release engineering
-
The published artifact is now verified, not just the reviewed one.
publish.ymlpreviously built its own artifact and gated it ontwine checkalone, so it had neither of the guards added totests.yml. Both workflows now callscripts/verify_packaging.py, which asserts every source subpackage is present in the wheel and the sdist, and that each one imports from the installed wheel — checked via__file__provenance from a working directory outside the checkout, because otherwisesys.path[0]lets the source tree satisfy the import and the check passes hollow. (#54) -
One implementation, not two copies. The guards live in a single script invoked by both workflows. A declaration in one place drifting out of step with reality in another is the exact failure mode that lost
athf.metricsfor four releases. (#54) -
The version has a single source.
pyproject.tomlnow declaresdynamic = ["version"]readingathf.__version__, so the second literal that could disagree with it is gone.tests/test_packaging.pylocks the declaration in place, andpublish.ymladditionally asserts the version baked into the built wheel'sMETADATAmatches the tag — somethingtwine checkdoes not do. (#54) -
The guard checks both directions. Subpackage comparison is now bidirectional, so an artifact that ships a package deleted from the source tree fails too — a stale
build/or*.egg-infois enough to produce one. The no-literal-version test also rejects single-quoted values, which are valid TOML and previously slipped through. (#55)
Upgrade
pip install --upgrade agentic-threat-hunting-framework==0.19.0
Full Changelog: v0.18.0...v0.19.0