v0.14.2 — source_hash LLM laundering fix
Released 2026-05-27 · PyPI
Fixed
-
Source-hash LLM laundering: features stay stale after a
successful regen (#48).
The polish LLM was given the rendered template (with
frontmatter) as input context and asked to improve the body.
Empirically, the LLM also echoed the frontmatter in its
output — sometimes with single-character transcription errors
in deterministic fields likesource_hash. That broke
staleness detection: the frontmattersource_hashwritten
into the polished file didn't match whatcompute_source_hash
recomputed on the same source, leaving the feature permanently
"stale" after a successful regen.Concrete evidence from attune-ai's spec-engine feature
(2026-05-27):frontmatter: f8ced22b02899aa25ff409636e659830c6ba856d70de6ddd1a9bf1cbe37a1337 computed: f8ced22b02899aa25ff709636e659830c6ba856d70de6ddd1a9bf1cbe37a1337 ^ position 19: LLM wrote f4 instead of f7Fix: field-level frontmatter merge in
generator.apply_polish_results. The canonical value for
every DETERMINISTIC field (type,name,feature,depth,
generated_at,source_hash,status) is re-injected from
the rendered template after polish, overriding whatever the
LLM emitted. NON-deterministic fields (polish: skipped
marker from the lenient-mode fallback path, any future
polish-layer metadata) are preserved unchanged.Unblocks attune-gui Phase 2 (
living-docs-regen-automation)
which neededattune-author status --dry-runto reach a fixed
point after regen. Once attune-gui pins this release, its CI
fail-if-stalegate can be turned on. attune-ai's dashboard
stale count also stops mis-flagging features that have just
been regenerated.End-to-end verified: regenerating
spec-engineon attune-ai
with the fix in place produces 11 templates whose frontmatter
source_hashall matchcompute_source_hash's recomputed
value (vs. 0/11 pre-fix).
Changed
publish.ymltrigger swapped fromrelease: [published]to
push: tags: 'v*.*.*'. Aligns with thepublish-pypi.yml
pattern in attune-ai (synced 2026-05-25; original swap in
attune-ai PR #459). Releases created byGITHUB_TOKEN(i.e.
by another workflow) do NOT fire therelease:[published]
event — a documented GitHub Actions limitation that bit
attune-ai's v7.1.0 ship. Tag-push fires unconditionally, so
the publish workflow runs whether the release object was
created bygh release create(human flow we use today), a
release-automation workflow (future), or justgit push origin <tag>without any release object at all.workflow_dispatch
retained as fallback. No public API or package surface
affected — this is CI hygiene.