Problem
Running attune-author regenerate <feature> writes a new source_hash to the template's YAML frontmatter, but attune-author status <feature> (or regenerate --dry-run <feature>) immediately afterwards still reports the feature as stale. The loop never reaches a fixed point.
Surfaced by attune-gui's Phase 2 of living-docs-regen-automation (Smart-AI-Memory/attune-gui#62), which is parked until this is fixed.
Hypothesis
Asymmetric inputs to the same hash function:
- The status/staleness path (
compute_source_hash / compute_semantic_hash in src/attune_author/staleness.py) hashes the full set of source files matched by the feature glob.
- The regen-write path appears to hash a budget-truncated view — evidenced by
ground_truth.budget: dropped X to fit budget log lines during regen. Whatever the budget step produces ends up as the written source_hash, which can never match the full-set hash the status check recomputes.
To reproduce
On any corpus with a feature whose source set exceeds the ground-truth budget:
attune-author regenerate <feature>
attune-author status <feature> # expected: fresh. actual: stale.
Code pointers
compute_source_hash definition: src/attune_author/staleness.py:211
- Regen call site that hashes:
src/attune_author/generator.py:355
- Frontmatter write of
source_hash:: src/attune_author/generator.py:1452
Suggested fix direction
Always write the full-set hash to frontmatter (so the artifact's fingerprint matches what the staleness check recomputes), regardless of what slice of the source was sent to the LLM. Trace which code path overwrites source_hash with the budget-truncated value and gate it.
Full design doc: docs/specs/regen-staleness-hash-mismatch/decisions.md (added in #41).
Blocks
Problem
Running
attune-author regenerate <feature>writes a newsource_hashto the template's YAML frontmatter, butattune-author status <feature>(orregenerate --dry-run <feature>) immediately afterwards still reports the feature as stale. The loop never reaches a fixed point.Surfaced by attune-gui's Phase 2 of
living-docs-regen-automation(Smart-AI-Memory/attune-gui#62), which is parked until this is fixed.Hypothesis
Asymmetric inputs to the same hash function:
compute_source_hash/compute_semantic_hashinsrc/attune_author/staleness.py) hashes the full set of source files matched by the feature glob.ground_truth.budget: dropped X to fit budgetlog lines during regen. Whatever the budget step produces ends up as the writtensource_hash, which can never match the full-set hash the status check recomputes.To reproduce
On any corpus with a feature whose source set exceeds the ground-truth budget:
Code pointers
compute_source_hashdefinition:src/attune_author/staleness.py:211src/attune_author/generator.py:355source_hash::src/attune_author/generator.py:1452Suggested fix direction
Always write the full-set hash to frontmatter (so the artifact's fingerprint matches what the staleness check recomputes), regardless of what slice of the source was sent to the LLM. Trace which code path overwrites
source_hashwith the budget-truncated value and gate it.Full design doc:
docs/specs/regen-staleness-hash-mismatch/decisions.md(added in #41).Blocks