Changelog¶
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]¶
Changed¶
- lxml is now type-checked through
types-lxmlstubs instead of being treated as untyped. The# ty: ignore[unresolved-import]comments and thestr()cast insitemap.pyare gone, and lxml no longer rides the mypyignore_missing_importsoverride. Internal only; no API or output change. - Tightened the type-check configuration. mypy and ty do the gating, and mypy
gains
warn_unreachable,extra_checks,strict_bytes,local_partial_types, anddisallow_any_unimported. basedpyright runs itsrecommendedprofile as an advisory check: its warnings flag under-typed spots but never fail the gate (pyright exits non-zero on warnings, so it logs and does not block).zensical(which shipspy.typed) comes off the mypy override; onlyfeedgenandfeedparser, which have no stubs, remain. Internal only. - Upgraded locked dependencies (
uv lock --upgrade).
[0.1.6] - 2026-06-23¶
Added¶
- A sitemap for the generated section. With
site_urlset, the build writesdocs/<base>/sitemap.xmllisting every generated page (the section index, each post, and the taxonomy and archive pages you enable), so the content is in a sitemap a crawler can read. zensical's own sitemap covers itsnavpages only. The newemit_sitemapconfig key (defaulttrue) toggles it, and the CLI warns when it is skipped for a missingsite_url, the same as the feed.build_sitemapis exported as part of the public API.
Changed¶
uv.lockis now the single source of truth for dependencies.requirements.txt/requirements-dev.txtare no longer committed; they are generated on demand.scripts/regen_requirements.pygained a--stdout(pipe one set) and--output-dir DIR(write both into a directory) mode, andscripts/audit.pynow exports into a temporary directory for pip-audit and SBOM rather than reading committed files. The release SBOM step exports prod-only requirements through the helper. A Dependabot bump no longer needs a committed-requirements regen to pass audit.-
Merge policy: only merge commits are allowed on this repo now.
.github/settings.ymlsetsallow_squash_mergeandallow_rebase_mergetofalseso history is preserved. -
Dropped
from __future__ import annotationsand theif TYPE_CHECKING:guards across the codebase, and retired the flake8-type-checking (TCH) ruff rule. The project targets Python 3.14+, where PEP 649 defers annotation evaluation, so the future import and the type-only-import guarding are no longer needed. Internal only; no API or output change.
Fixed¶
- Release pipeline: the
pypideployment environment now matches the release tag. Itsv*.*.*policy was typed as a branch, which never matches avX.Y.Ztag, so the publish was blocked. The policy is now tag-typed, and a required reviewer gates the PyPI publish.testpypigained a matching tag policy so pre-release tags can deploy. - Branch protection on
mainnow applies. Thesettings.ymlprotection block omitted therestrictionskey, and the Settings app skips the whole block unless every top-level protection key is present (set tonullwhen unused). Addedrestrictions: null, so the declared review and status-check rules take effect.
Removed¶
- Committed
requirements.txtandrequirements-dev.txt, and theregen-requirementspre-commit hook that kept them in sync. Generated on demand fromuv.lockinstead.
Security¶
- Bump
msgpackto 1.2.1 (GHSA-6v7p-g79w-8964). The 1.2.0 streamingUnpackercould crash with a SEGV when reused after an error, a DoS risk on untrusted input, though it is a dev-only transitive dependency (viacachecontrol) so the published package never shipped it. The pre-pushpip-auditgate flags it on every push.
[0.1.5] - 2026-06-18¶
Added¶
- RSS feed items now split the body: the post excerpt goes in
<description>and the full rendered HTML goes in<content:encoded>. A post with no excerpt keeps the full HTML in<description>. feedgen emits both elements natively, so no custom extension is needed. - Code-review bot configuration so automated reviewers honor the project's house
style and skip generated files:
.coderabbit.yaml(CodeRabbit),.gemini/(Gemini Code Assist),code_review.mdwith anAGENTS.mdpointer (Codex), and an expanded.github/copilot-instructions.md(Copilot). Each encodes the same review focus (URL base-path correctness, feed determinism, public-API discipline) and the intentional-choice list, and defers toAGENTS.md. - Tags and Categories index pages now render a frequency-ordered cloud (busiest
term first, with post counts). The main Updates index and each taxonomy/archive
index carry a
Browse:nav linking the enabled index pages.
Changed¶
- Repository merge policy in
.github/settings.yml: merge commits are the preferred merge method. Squash merging is disabled andrequired_linear_historyis off so merge commits are allowed onmain.
[0.1.4] - 2026-06-17¶
Removed¶
- Dropped support for Python 3.11, 3.12, and 3.13. The package now requires Python 3.14 or newer. This is a breaking change for consumers still on an older interpreter.
[0.1.3] - 2026-06-17¶
Added¶
- RSS 2.0 feed at
docs/<base>/feed.xml, generated whensite_urlis set. Each item carries the full post HTML, rendered by zensical so it matches the site, with links rewritten to fully-qualified URLs for off-site readers. Two config keys control it:emit_feed(default true) andfeed_limit(default 0, no cap).
[0.1.2] - 2026-06-17¶
Fixed¶
- Carry the site sub-path in every emitted link. On a project Pages site served
under a base path (e.g.
/eth-protocol-fellowship/), generated post, tag, category, and archive links dropped the prefix and 404'd. The generator now reads[project] site_urland prepends its path, so a link resolves to/eth-protocol-fellowship/updates/<slug>/. Root-served sites are unchanged (nosite_urlpath means no prefix and no extra slash). The on-disk output dir staysdocs/<base>/, so only the emitted URLs gain the prefix.
[0.1.1] - 2026-06-17¶
Fixed¶
- Drop the empty gitleaks allowlist that newer gitleaks (v8.30) rejects with "allowlists must contain at least one check", which failed the pre-commit CI job. The standalone gitleaks action tolerated it, which masked the bug.
Changed¶
- Source
__version__from the installed package metadata instead of a hard-coded string, so a release bumps onlypyproject.toml; the tests no longer pin the version number. - Bump tooling: hatchling >=1.30.1, mkdocs-typer2[zensical] >=0.4.0, and the uv-pre-commit hook to 0.11.21 (dependabot).
[0.1.0] - 2026-06-17¶
Added¶
- Initial project scaffold.
- Post discovery and the content model: YAML front-matter parsing (block-list aware), post loading (slug from file stem, date coercion, taxonomies, excerpt), newest-first discovery, and grouping by category, tag, and year.
- Markdown emitters for the index listing, archive landing and per-year pages, and tag/category pages and their indexes. Output is zensical-safe: every link is a site-absolute directory URL and there are no bare reference brackets.
- A
build/cleanCLI and azensical.tomlconfig loader (the[project.extra.zensical_updates]table).builddiscovers source posts, copies them intodocs/<base>/, and writes the generated pages;cleanremoves that output. An invalid post (e.g. missing date) fails the build. - An end-to-end integration test: generate a fixture site, run
zensical build --clean --strict, and assert every generated post, taxonomy, and archive link resolves to a rendered page. This guards the two silent failures (wrong post URLs and front-matter link reads). - Documentation: README and a usage guide covering how to write posts, configure the generator, and run the build.