Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,28 @@ and this project adheres to
Work in progress for the next release. Add entries here as
changes land, not at tag time.

## [0.7.0] - 2026-05-08

### Changed

- **`attune_author.manifest` / `attune_author.staleness` /
`attune_author.freshness` are now the source of truth.** These
modules previously re-exported from `attune-help`; with PR #14
they ship natively in attune-author. Existing imports from
`attune_author.*` continue to work; downstream code using
`attune_help.*` now goes through deprecation shims (see
`attune-help` 0.11.0 CHANGELOG).

### Removed (dependency)

- **`attune-help>=0.10.0` runtime dependency dropped.** It was a
leftover from when `manifest`/`staleness`/`freshness` lived in
attune-help and this package re-exported them. After PR #14
inverted the direction, no `from attune_help` imports remain in
`src/attune_author/`. Removing the dep also breaks the circular
package-metadata edge that would otherwise form once
`attune-help` 0.11.0 declares `attune-author>=0.7.0`.

## [0.5.1] - 2026-04-30

### Changed
Expand Down
3 changes: 1 addition & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "attune-author"
version = "0.6.2"
version = "0.7.0"
description = "Documentation authoring and maintenance for the attune ecosystem — generate, maintain, and validate help content with AI assistance."
readme = {file = "README.md", content-type = "text/markdown"}
requires-python = ">=3.10"
Expand Down Expand Up @@ -41,7 +41,6 @@ dependencies = [
"jinja2>=3.1.0",
"python-frontmatter>=1.0.0",
"pyyaml>=6.0",
"attune-help>=0.10.0", # manifest + staleness now live in attune-help; attune-author re-exports them as shims.
]

[project.optional-dependencies]
Expand Down
2 changes: 1 addition & 1 deletion src/attune_author/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
attune-help (reader) and attune-ai (full dev workflows).
"""

__version__ = "0.6.2"
__version__ = "0.7.0"

from attune_author.manifest import Feature, Manifest, load_manifest
from attune_author.staleness import StalenessReport, check_staleness, compute_source_hash
Expand Down
15 changes: 5 additions & 10 deletions src/attune_author/staleness.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,19 +194,13 @@ def compute_semantic_hash(
if abs_path.suffix == ".py":
try:
for record in extractor.extract(abs_path):
hash_parts.append(
f"{rel_path}::{record.qualname}::{record.signature_hash}"
)
hash_parts.append(f"{rel_path}::{record.qualname}::{record.signature_hash}")
except SyntaxError:
content = abs_path.read_bytes()
hash_parts.append(
f"{rel_path}::{hashlib.sha256(content).hexdigest()}"
)
hash_parts.append(f"{rel_path}::{hashlib.sha256(content).hexdigest()}")
else:
content = abs_path.read_bytes()
hash_parts.append(
f"{rel_path}::{hashlib.sha256(content).hexdigest()}"
)
hash_parts.append(f"{rel_path}::{hashlib.sha256(content).hexdigest()}")
except OSError as e:
logger.warning("Cannot read %s: %s", rel_path, e)

Expand Down Expand Up @@ -311,7 +305,8 @@ def parse_doc_footer(text: str) -> dict[str, str]:

The footer format is::

<!-- attune-generated: source_hash=abc123 feature=foo kind=how-to generated_at=2026-04-23 -->
<!-- attune-generated: source_hash=abc123 feature=foo
kind=how-to generated_at=2026-04-23 -->

The comment may appear anywhere in the file but is conventionally
the last line.
Expand Down
1 change: 1 addition & 0 deletions tests/test_manifest_relocated.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from pathlib import Path

import pytest

from attune_author.manifest import (
Feature,
FeatureManifest,
Expand Down
16 changes: 6 additions & 10 deletions tests/test_staleness_relocated.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,7 @@ def test_compute_source_hash_deterministic(tmp_path: Path):


def test_compute_source_hash_changes_on_edit(tmp_path: Path):
f = _write_src(
tmp_path, "src/auth/login.py", "def login(name: str) -> str:\n return name\n"
)
f = _write_src(tmp_path, "src/auth/login.py", "def login(name: str) -> str:\n return name\n")
feat = Feature(name="auth", description="", files=["src/auth/**"])
h1, _ = compute_source_hash(feat, tmp_path)
f.write_text(
Expand All @@ -160,7 +158,9 @@ def test_compute_source_hash_stable_across_docstring_edit(tmp_path: Path):
feat = Feature(name="auth", description="", files=["src/auth/**"])
h1, _ = compute_source_hash(feat, tmp_path)
f.write_text(
'def login(name: str) -> str:\n """Very detailed login documentation.\"\"\"\n return name\n',
"def login(name: str) -> str:\n"
' """Very detailed login documentation."""\n'
" return name\n",
encoding="utf-8",
)
h2, _ = compute_source_hash(feat, tmp_path)
Expand All @@ -169,14 +169,10 @@ def test_compute_source_hash_stable_across_docstring_edit(tmp_path: Path):

def test_compute_source_hash_changes_on_signature_edit(tmp_path: Path):
"""Semantic hashing: adding a parameter changes the hash."""
f = _write_src(
tmp_path, "src/auth/login.py", "def login(name: str) -> str:\n return name\n"
)
f = _write_src(tmp_path, "src/auth/login.py", "def login(name: str) -> str:\n return name\n")
feat = Feature(name="auth", description="", files=["src/auth/**"])
h1, _ = compute_source_hash(feat, tmp_path)
f.write_text(
"def login(name: str, password: str) -> str:\n return name\n", encoding="utf-8"
)
f.write_text("def login(name: str, password: str) -> str:\n return name\n", encoding="utf-8")
h2, _ = compute_source_hash(feat, tmp_path)
assert h1 != h2

Expand Down
Loading