From 22fd201ee4cfa06bc40f5144294e540e9b87c572 Mon Sep 17 00:00:00 2001 From: SSobol77 Date: Sat, 11 Jul 2026 12:31:46 +0200 Subject: [PATCH] chore: prepare v0.2.4 release metadata --- CHANGELOG.md | 125 +++++++++ README.md | 26 +- docs/architecture/command-plan-service.md | 2 +- docs/install/windows.md | 2 +- docs/release/README-release.md | 1 + docs/release/v0.2.4.md | 251 ++++++++++++++++++ flake.nix | 2 +- packaging/arch/PKGBUILD | 2 +- packaging/nix/package.nix | 2 +- pyproject.toml | 2 +- tests/docs/test_v024_release_metadata.py | 155 +++++++++++ tests/packaging/test_release_metadata_v024.py | 124 +++++++++ 12 files changed, 682 insertions(+), 12 deletions(-) create mode 100644 docs/release/v0.2.4.md create mode 100644 tests/docs/test_v024_release_metadata.py create mode 100644 tests/packaging/test_release_metadata_v024.py diff --git a/CHANGELOG.md b/CHANGELOG.md index e1584ef..a711342 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,131 @@ See the LICENSE file in the project root for full license text. # Changelog +## 0.2.4 - Extensions, Diagnostics, and Release Gate Hardening + +ECLI v0.2.4 adds the Extensions Foundation, extension-backed syntax and theme +integration, F4 diagnostics/linter architecture, OS/artifact-aware provisioning +evidence, Linux official distro evidence audits, and release gate hardening. + +### Added + +- Added the curated Extensions Layer under `src/ecli/extensions/` with + data-only language, grammar, snippet, configuration, and theme assets. + +- Added extension manifest registry, package-data contract coverage, and + source-tree tests that reject raw VS Code runtime/source artifacts, + generated outputs, media/test assets, and misplaced extension roots. + +- Added extension-backed language detection, TextMate grammar catalog lookup, + syntax rendering, and multiline comment/string protection for editor text. + +- Added theme registry and theme bridge support for extension-backed themes, + including numbered theme migration coverage for the current configuration + model. + +- Added the F4 Diagnostics/Linter architecture with normalized diagnostics + models, provider registry, provider utilities, Ruff reference provider, + linter microservice metadata, parser coverage, and service/provider + selection tests. + +- Added OS/artifact-aware F4 linter provisioning contracts, provisioning + evidence generation/verification scripts, packaging hooks, and exact + 21-artifact evidence coverage. + +- Added Linux F4 provisioning policy manifests, distro provenance catalog, + distro mapping evidence, official Debian evidence promotion, and official + evidence drift audit gates. + +### Changed + +- Project package version is `0.2.4`. + +- README now presents v0.2.4 as the current release and describes the + Extensions Layer, F4 Diagnostics/Linter architecture, provisioning evidence + gates, and current safety boundaries. + +- Release validation is separated into source/structural Gate 2, explicit + fail-closed built-artifact validation, and exact final GitHub Release asset + verification. + +- PyPI and GitHub Release publication ordering now requires successful built + artifact validation before publication jobs may run. + +- Release documentation now preserves the exact 21 ECLI-owned uploaded asset + contract, treats GitHub-generated source archives as outside that contract, + and keeps checksum sidecars as non-uploaded verification evidence. + +### Fixed + +- Removed agent-workspace files from the tracked repository and release + contract surface. + +- Stabilized v0.2.3 runtime/UX edge cases before adding the F4 and extension + layers. + +- Simplified CLI preload document handling while preserving editor open/create + semantics. + +- Prevented logging rollover errors from corrupting the TUI. + +### Safety Boundaries + +- Imported extension assets are data only; ECLI does not execute VS Code + extension runtime code. + +- F4 provisioning evidence gates are packaging/release contracts and do not + redesign the F4 panel UI. + +- Clean-machine Debian 13 installer validation has not yet been completed. + Repository tests and CI evidence do not replace that physical installation + test. + +## 0.2.3 - Panel Console Stabilization + +ECLI v0.2.3 is a Panel Console Stabilization release on top of the Services +Foundation. It keeps the existing editor behavior intact, rejects full +PTY/VT terminal emulator scope for ECLI 0.2.x, and replaces the fragile F11 +terminal experiment with an ECLI-owned PySH Console Panel. + +### Added + +- Added the F11 PySH Console Panel as the supported command-console panel + surface. + +- Added F12 focus switching between the editor and right-side panels. + +- Added deterministic PySH backend diagnostics and console builtins for `cd`, + `pwd`, `clear`, and `exit`. + +- Added command cancellation coverage for the console backend path. + +### Changed + +- PySH is used as a subprocess argv backend only; command execution uses safe + argv construction rather than shell interpolation. + +- The release explicitly rejects full PTY terminal emulation, VT parsing, + xterm behavior, fullscreen terminal application scope, PySH source migration, + and PySH monorepo conversion. + +- The official GitHub Release asset contract is exactly 21 clean public asset + names. Numeric public prefixes were documented as a v0.2.3 staging mistake + and are rejected by the release asset verifier after repair. + +### Fixed + +- Stabilized F11 panel open/focus behavior and F12 editor/panel focus routing. + +- Preserved service-panel safety boundaries: System Doctor remains read-only, + Command Plan output remains draft/preview-only, and privileged remediation is + not enabled. + +### Safety Boundaries + +- No full PTY/VT terminal emulator is included. + +- No VMLab, QEMU, QMP, or privileged remediation runtime scope is included. + ## 0.2.2 - Packaged Runtime Startup Fixes ### Fixed diff --git a/README.md b/README.md index fc4440d..638dc76 100755 --- a/README.md +++ b/README.md @@ -51,9 +51,9 @@ See the LICENSE file in the project root for full license text. ## 🚀 About ECLI -**ECLI** (Editor CLI) is a terminal-first engineering operations workbench. It combines a curses-based editor with right-side workflow panels and a typed service foundation for configuration, project discovery, command-plan previews,policy checks, audit logging, privileged-action refusal paths, and read-only system diagnostics. +**ECLI** (Editor CLI) is a terminal-first engineering operations workbench. It combines a curses-based editor with right-side workflow panels and a typed service foundation for configuration, project discovery, command-plan previews, policy checks, audit logging, privileged-action refusal paths, and read-only system diagnostics. -The v0.2.3 release is a Panel Console Stabilization layer on top of the Services Foundation. It keeps the Services Foundation editor behavior intact, rejects full PTY terminal emulation for ECLI 0.2.x, and replaces the fragile F11 terminal experiment with an ECLI-owned PySH Console Panel. PySH is used as a command execution backend only; this release does not execute remediation, apply command plans, launch VMLab runtimes, add QEMU/QMP runtime scope, migrate PySH source, or perform real privileged operations. +The v0.2.4 release layers the Extensions Foundation, extension-backed TextMate rendering, the F4 Diagnostics/Linter architecture, and release gate hardening on top of the Services Foundation and v0.2.3 Panel Console Stabilization work. It keeps the existing editor and service-panel safety model intact while adding curated extension assets, deterministic syntax/theme adapters, F4 linter provisioning contracts, Linux official evidence drift checks, and separated release validation gates. ### ✨ Key Features @@ -491,7 +491,7 @@ Master ECLI with these essential keyboard shortcuts. Press `F1` anytime inside t | `Insert` | Toggle Insert / Overwrite mode | | `F12` | Switch focus between editor and panels | -The right side of the editor hosts workflow panels. The v0.2.3 panel-console stabilization keeps service panels read-only or preview-only: System Doctor does not mutate host state, Command Plan previews do not execute, the Services panel reports composition status, F11 opens or focuses the PySH Console Panel, and F12 switches focus between the editor and panels. +The right side of the editor hosts workflow panels. The v0.2.4 release keeps service panels read-only or preview-only: System Doctor does not mutate host state, Command Plan previews do not execute, the Services panel reports composition status, F4 opens the Diagnostics/Linter panel, F11 opens or focuses the PySH Console Panel, and F12 switches focus between the editor and panels. ### Minimal Service CLI @@ -572,12 +572,22 @@ Complete documentation is organized by audience: ## 🏗️ Architecture -ECLI v0.2.3 keeps the existing editor/TUI behavior and Services Foundation infrastructure, then adds Panel Console Stabilization for the ECLI-owned PySH Console Panel: +ECLI v0.2.4 keeps the existing editor/TUI behavior, Services Foundation infrastructure, and Panel Console Stabilization baseline, then adds the Extensions Foundation, TextMate-backed syntax rendering, and F4 Diagnostics/Linter architecture: * **Core Editor**: curses-based terminal editor with async task integration * **Right-Side Panels**: Help, Diagnostics/Lint, AI Code Assistant, System Doctor, Git, File Manager, Services, and Command Plan previews +* **Extensions Layer**: curated data-only language and theme assets under `src/ecli/extensions/`, consumed through deterministic ECLI adapter code + +* **Syntax Service**: extension-backed language detection, TextMate grammar catalog lookup, scope rendering, and multiline comment/string protection + +* **Theme Registry**: extension-backed theme registry and bridge with numbered theme selection and migration compatibility + +* **F4 Diagnostics/Linter**: normalized diagnostics service, provider registry, Ruff reference provider, and linter microservice metadata under `src/ecli/extensions/linters/` + +* **F4 Provisioning Contracts**: OS/artifact-aware linter provisioning evidence gates, Linux official distro evidence, and exact 21-artifact coverage for release readiness + * **PySH Console Panel**: F11 opens or focuses an ECLI-owned command console panel backed by PySH subprocess execution * **ConfigService**: typed layered configuration loading @@ -596,7 +606,7 @@ ECLI v0.2.3 keeps the existing editor/TUI behavior and Services Foundation infra * **ServiceRegistry**: explicit composition root without global service-locator state -**Safety boundaries for v0.2.3:** +**Safety boundaries for v0.2.4:** * SystemDoctor is read-only. @@ -606,11 +616,15 @@ ECLI v0.2.3 keeps the existing editor/TUI behavior and Services Foundation infra * Service panels are visible in the UI but do not execute remediation. +* Imported extension assets are data-only; ECLI does not execute VS Code extension runtime code. + +* F4 provisioning evidence gates are release/packaging contracts and do not change F4 panel UI behavior. + * Full PTY terminal emulation, VT parsing, xterm behavior, and raw interactive PySH inside curses are not included. * PySH is used as a command execution backend only; PySH source migration and monorepo conversion are not included. -* VMLab runtime behavior, QEMU runtime scope, and QMP runtime scope are not included in v0.2.3. +* VMLab runtime behavior, QEMU runtime scope, and QMP runtime scope are not included in v0.2.4. For detailed architecture information, see [Architecture Overview](https://github.com/SSobol77/ecli/blob/main/docs/architecture/current-architecture.md). diff --git a/docs/architecture/command-plan-service.md b/docs/architecture/command-plan-service.md index 6cadcde..b3e0890 100644 --- a/docs/architecture/command-plan-service.md +++ b/docs/architecture/command-plan-service.md @@ -906,7 +906,7 @@ Required schema: "source": "user", "details": {}, "metadata": { - "ecli_version": "0.2.3", + "ecli_version": "0.2.4", "schema_revision": "audit-v1" } } diff --git a/docs/install/windows.md b/docs/install/windows.md index 447ed07..66319c0 100644 --- a/docs/install/windows.md +++ b/docs/install/windows.md @@ -60,7 +60,7 @@ For source/development builds on Windows, install: PowerShell checksum verification should be performed before first execution: ```powershell -$version = "0.2.3" +$version = "0.2.4" $file = "ecli_${version}_win_x86_64_setup.exe" $expected = (Get-Content "$file.sha256" -Raw).Trim().Split()[0] $actual = (Get-FileHash -Algorithm SHA256 -LiteralPath $file).Hash.ToLowerInvariant() diff --git a/docs/release/README-release.md b/docs/release/README-release.md index 1a1fc08..3e7c10a 100644 --- a/docs/release/README-release.md +++ b/docs/release/README-release.md @@ -46,6 +46,7 @@ Authoritative files: - `release-process.md` - `release-checklist.md` - `artifact-verification.md` +- `v0.2.4.md` - `v0.2.3.md` - `v0.2.2.md` - `v0.2.1.md` diff --git a/docs/release/v0.2.4.md b/docs/release/v0.2.4.md new file mode 100644 index 0000000..95a1048 --- /dev/null +++ b/docs/release/v0.2.4.md @@ -0,0 +1,251 @@ + +# ECLI v0.2.4 Release Notes + +ECLI v0.2.4 is an Extensions, Diagnostics, and Release Gate Hardening +release. It builds on the v0.2.3 Panel Console Stabilization baseline with a +curated extensions asset layer, extension-backed TextMate syntax rendering, +the F4 Diagnostics/Linter architecture, OS/artifact-aware linter provisioning +contracts, Linux official distro evidence audits, and hardened release gates. + +## Highlights + +- Curated Extensions Layer for data-only language, grammar, snippet, + language-configuration, and theme assets. + +- Extension-backed language detection, TextMate grammar catalog lookup, + syntax rendering, and multiline comment/string protection. + +- Theme registry and theme bridge support for extension-backed themes with + numbered theme migration compatibility. + +- F4 Diagnostics/Linter architecture under `src/ecli/extensions/linters/` with + normalized diagnostics models, provider registry, Ruff reference provider, + linter manifests, package contracts, parser coverage, and provider-selection + tests. + +- OS/artifact-aware F4 linter provisioning contracts with deterministic dry-run + evidence generation, evidence verification, packaging hooks, and exact + 21-artifact coverage. + +- Linux official distro evidence and release-blocking drift audit for official + package-manager provenance records. + +- Release validation split into source/structural Gate 2, explicit fail-closed + built-artifact validation, and exact final GitHub Release asset-set + verification. + +- Publication ordering hardened so PyPI and GitHub Release publication jobs + require successful built-artifact validation. + +## Extensions and Editor Improvements + +- `src/ecli/extensions/` is now the single approved location for curated + extension runtime data. The tree is constrained to ECLI integration code, + language assets, theme assets, and third-party notices. + +- Imported VS Code/TextMate assets remain data-only. ECLI consumes manifests, + grammars, language configuration, snippets, and themes through deterministic + adapter code; it does not execute VS Code extension runtime code. + +- The extension manifest registry parses contribution metadata into ECLI-owned + internal models and is covered by package-data and tree-shape tests. + +- Language detection resolves file extensions, names, and first-line patterns + from extension metadata. + +- The TextMate grammar catalog and syntax service apply resolved grammars to + editor text and protect multiline comment/string regions. + +- The theme registry and bridge load extension-backed themes and map TextMate + scopes into ECLI rendering styles while preserving numbered theme selection + and migration compatibility. + +## F4 Diagnostics and Provisioning + +- F4 keeps the existing Diagnostics Panel interaction model. The work in this + release is backend architecture, provider normalization, and packaging + contract evidence; it is not an F4 UI redesign. + +- The linter layer lives under `src/ecli/extensions/linters/` with a common + diagnostics model, provider protocol, display helpers, service, registry, + provider utilities, and per-linter microservice directories. + +- Ruff remains the wired reference provider. Additional linters carry + manifests and package contracts for provisioning and release-readiness + reasoning. + +- Provisioning contracts map required linter/toolchain behavior to the existing + 21 release artifact entries. Evidence generation is safe by default and + suitable for dry-run/verify release gates. + +- Linux provisioning policy manifests validate expected tool mechanisms, + package names, release-blocking state, path containment, selected tool sets, + and per-tool evidence shape. + +- Debian official distro metadata evidence is recorded for approved tools and + protected by an official evidence drift audit. Drift is release-blocking. + +## Release and Packaging Hardening + +- The official GitHub Release asset contract remains exactly 21 ECLI-owned + uploaded assets. GitHub-generated `Source code (zip)` and + `Source code (tar.gz)` archives are outside the canonical 21 entries. + +- Checksum sidecars remain mandatory CI/release verification evidence under + `releases//.checksums/`; they are not uploaded as separate GitHub + Release assets. + +- `make validate-gate2` is source and structural validation. It checks version + consistency, runtime imports, Linux official evidence drift, and the PyPI + source contract dry-run without requiring built release artifacts. + +- `make validate-built-artifacts` is the explicit physical artifact gate. It + validates complete artifact/sidecar pairs and fails closed on partial built + artifact sets. + +- `make validate-release-assets` verifies the exact final GitHub Release asset + set after release assets are assembled. + +- Publication jobs in the release workflow now preserve their publication + policies while requiring successful built-artifact validation. + +- Agent-workspace files and folders were removed from the tracked repository + and from the release contract surface. + +## Fixed Issues + +- Stabilized F4 selected diagnostic line-highlight initialization for + lightweight test/runtime instances. + +- Removed local agent-workspace files from release contract consideration. + +- Simplified CLI preload document path handling while preserving the editor's + single preload implementation. + +- Prevented logging rollover errors from corrupting the TUI. + +- Hardened release checksum sidecar handling so partial built-artifact states + fail closed in the explicit built-artifact gate. + +- Aligned release documentation with the current three-gate validation model. + +## Safety Boundaries and Non-Goals + +- F4 provisioning evidence and policy validation do not redesign the F4 panel, + keybindings, or visual behavior. + +- Imported extension assets are not an extension host and do not execute + upstream extension code. + +- System Doctor remains read-only, Command Plan output remains draft/preview + only, and privileged remediation remains out of scope. + +- Full PTY terminal emulation, VT parsing, xterm behavior, VMLab runtime, + QEMU runtime, and QMP runtime remain out of scope. + +## Validation Commands + +Source and structural validation: + +```sh +uv sync --extra dev +uv run ruff check src tests scripts +uv run ruff format --check src tests scripts +uv run python scripts/check_runtime_imports.py +uv run pytest -q +make validate-version-consistency +make validate-gate2 +make help +uv run ecli --version +``` + +Final built-artifact validation, after artifacts are intentionally built and +sidecars are present: + +```sh +make validate-built-artifacts +``` + +Final GitHub Release asset-set validation, after `releases//` is +assembled: + +```sh +make validate-release-assets +``` + +## Exact 21 GitHub Release Asset Rule + +Every official ECLI release uploads exactly 21 ECLI-owned physical GitHub +Release assets, one per canonical matrix entry. The GitHub UI may display +**Assets 23** because it adds `Source code (zip)` and `Source code (tar.gz)` +automatically. Those generated source archives are not ECLI-owned uploaded +artifacts and are not part of the canonical 21 artifact contract entries. + +Mandatory GitHub Release assets for v0.2.4: + +```text +ecli_editor-0.2.4-py3-none-any.whl +ecli_editor-0.2.4.tar.gz +ecli_0.2.4_linux_x86_64.bin +ecli_0.2.4_linux_x86_64.tar.gz +ecli_0.2.4_linux_x86_64.deb +ecli_0.2.4_linux_x86_64.rpm +ecli_0.2.4_opensuse_x86_64.rpm +ecli_0.2.4_arch_x86_64.pkg.tar.zst +ecli_0.2.4_slackware_x86_64.txz +ecli_0.2.4_linux_x86_64.AppImage +ecli_0.2.4_freebsd_x86_64.pkg +ecli_0.2.4_freebsd_ports_chroot_evidence.tar.gz +ecli_0.2.4_macos_universal2_app_evidence.tar.gz +ecli_0.2.4_macos_universal2.dmg +ecli_0.2.4_win_x86_64.exe +ecli_0.2.4_win_x86_64_setup.exe +ecli_0.2.4_nix_flake_evidence.tar.gz +ecli_0.2.4_nixos_package_evidence.tar.gz +ecli_0.2.4_docker_deb_helper_evidence.tar.gz +ecli_0.2.4_docker_rpm_helper_evidence.tar.gz +ecli_0.2.4_workflow_contract_evidence.tar.gz +``` + +## Known Limitations + +- Physical artifact validation is separate from source/structural Gate 2 and + must be run only when built artifacts and checksum sidecars are intentionally + present. + +- PyPI wheel and source distribution entries are constrained Python packages; + complete F4 linter provisioning belongs to Full platform artifacts or + documented manual developer/minimal/repair flows. + +- Some linter microservices provide packaging/provisioning metadata before a + runtime provider/parser is wired. Missing executable handling remains a + defensive fallback for development, minimal, damaged, or unsupported + environments. + +- Clean-machine Debian 13 installer validation has not yet been completed. + Repository tests and CI evidence do not replace that physical installation + test. + +## Upgrade Notes + +- Configuration files using deprecated theme aliases remain covered by theme + numbering migration behavior. Prefer the documented 100/200/300 theme number + ranges for current light, dark, and high-contrast themes. + +- Release maintainers should use `make validate-gate2` for source and + structural contracts, then run `make validate-built-artifacts` and + `make validate-release-assets` only in the appropriate built-artifact and + final release contexts. diff --git a/flake.nix b/flake.nix index 7d252cc..f94b0eb 100644 --- a/flake.nix +++ b/flake.nix @@ -21,7 +21,7 @@ in pkgs.callPackage ./packaging/nix/package.nix { src = self; - version = "0.2.3"; + version = "0.2.4"; }; in { diff --git a/packaging/arch/PKGBUILD b/packaging/arch/PKGBUILD index c5e87c5..927000d 100644 --- a/packaging/arch/PKGBUILD +++ b/packaging/arch/PKGBUILD @@ -7,7 +7,7 @@ # PyPI: https://pypi.org/project/ecli-editor/0.0.1/ pkgname=ecli-editor -pkgver=0.2.3 +pkgver=0.2.4 pkgrel=1 pkgdesc="Terminal-first engineering operations workbench" arch=("x86_64" "aarch64") diff --git a/packaging/nix/package.nix b/packaging/nix/package.nix index 83eaf63..038db8c 100644 --- a/packaging/nix/package.nix +++ b/packaging/nix/package.nix @@ -9,7 +9,7 @@ { pkgs, src ? ../.., - version ? "0.2.3", + version ? "0.2.4", }: let diff --git a/pyproject.toml b/pyproject.toml index 5e3db9b..a2bdc5e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,7 @@ build-backend = "hatchling.build" [project] name = "ecli-editor" -version = "0.2.3" +version = "0.2.4" description = "ECLI — terminal-first engineering operations workbench" readme = "README.md" requires-python = ">=3.11" diff --git a/tests/docs/test_v024_release_metadata.py b/tests/docs/test_v024_release_metadata.py new file mode 100644 index 0000000..2cb9e51 --- /dev/null +++ b/tests/docs/test_v024_release_metadata.py @@ -0,0 +1,155 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Project: Ecli +# File: tests/docs/test_v024_release_metadata.py +# Website: https://www.ecli.io +# Repository: https://github.com/SSobol77/ecli +# PyPI: https://pypi.org/project/ecli-editor/0.0.1/ +# +# Copyright (c) 2026 Siergej Sobolewski +# +# Licensed under the GNU General Public License version 2 only. +# See the LICENSE file in the project root for full license text. + +"""v0.2.4 release documentation metadata contract.""" + +from __future__ import annotations + +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[2] +VERSION = "0.2.4" + + +def _read(relative_path: str) -> str: + return (ROOT / relative_path).read_text(encoding="utf-8") + + +def _one_line(text: str) -> str: + return " ".join(text.split()) + + +def test_readme_presents_v024_as_current_release() -> None: + readme = _read("README.md") + + assert "The v0.2.4 release layers the Extensions Foundation" in readme + assert "ECLI v0.2.4 keeps the existing editor/TUI behavior" in readme + assert "**Safety boundaries for v0.2.4:**" in readme + + +def test_changelog_contains_ordered_v024_v023_v022_sections() -> None: + changelog = _read("CHANGELOG.md") + normalized = _one_line(changelog) + v024 = changelog.index("## 0.2.4 - Extensions, Diagnostics") + v023 = changelog.index("## 0.2.3 - Panel Console Stabilization") + v022 = changelog.index("## 0.2.2 - Packaged Runtime Startup Fixes") + + assert v024 < v023 < v022 + assert "F11 PySH Console Panel" in changelog + assert "F12 focus switching" in changelog + assert "subprocess argv backend" in changelog + assert "exactly 21 clean public asset names" in normalized + + +def test_v024_release_notes_exist_and_are_indexed() -> None: + notes = _read("docs/release/v0.2.4.md") + normalized = _one_line(notes) + index = _read("docs/release/README-release.md") + + assert "# ECLI v0.2.4 Release Notes" in notes + assert "Extensions, Diagnostics, and Release Gate Hardening" in normalized + assert "exactly 21 ECLI-owned physical GitHub Release assets" in normalized + assert "ecli_0.2.4_workflow_contract_evidence.tar.gz" in notes + assert "- `v0.2.4.md`" in index + assert index.index("- `v0.2.4.md`") < index.index("- `v0.2.3.md`") + + +def test_historical_v023_release_notes_remain_v023_specific() -> None: + notes = _read("docs/release/v0.2.3.md") + + assert "# ECLI v0.2.3 Release Notes" in notes + assert "ecli_editor-0.2.3-py3-none-any.whl" in notes + assert "ecli_0.2.3_workflow_contract_evidence.tar.gz" in notes + assert "0.2.4" not in notes + assert "v0.2.4" not in notes + + +def test_no_completed_clean_machine_debian13_validation_claim_is_added() -> None: + current_docs = "\n".join( + _read(path) + for path in ( + "README.md", + "CHANGELOG.md", + "docs/release/README-release.md", + "docs/release/v0.2.4.md", + ) + ).lower() + + forbidden_claims = ( + "clean-machine debian 13 validation completed", + "validated on a second clean debian 13", + "physically validated on a second clean debian 13", + "debian 13 clean-machine installer validation passed", + ) + for claim in forbidden_claims: + assert claim not in current_docs + + assert ( + "clean-machine debian 13 installer validation has not yet been " + "completed" in current_docs + ) + + +def test_public_release_surfaces_omit_internal_maintainer_process_language() -> None: + surfaces = { + "README.md": _read("README.md"), + "CHANGELOG.md": _read("CHANGELOG.md"), + "docs/release/v0.2.4.md": _read("docs/release/v0.2.4.md"), + } + + forbidden_terms = ( + "this release metadata", + "release metadata update", + "for v0.2.4 release metadata", + "no tag, upload", + "created by this document", + "post-cut", + "pr #145", + "pr #146", + "pr #147", + "agent prompt", + "chore/prepare-v0.2.4", + ) + + for surface_name, text in surfaces.items(): + lowered = text.lower() + for term in forbidden_terms: + assert term not in lowered, ( + f"{surface_name} contains forbidden term: {term!r}" + ) + + +def test_debian_clean_machine_limitation_appears_exactly_once() -> None: + notes = _read("docs/release/v0.2.4.md") + marker = "Clean-machine Debian 13 installer validation has not yet been completed." + + assert notes.count(marker) == 1 + + +def test_canonical_release_identity_is_consistent_across_public_surfaces() -> None: + readme = _read("README.md") + changelog = _read("CHANGELOG.md") + notes = _one_line(_read("docs/release/v0.2.4.md")) + + identity = "Extensions, Diagnostics, and Release Gate Hardening" + + assert "## 0.2.4 - Extensions, Diagnostics, and Release Gate Hardening" in ( + changelog + ) + assert f"ECLI v0.2.4 is an {identity} release." in notes + assert "release gate hardening" in readme.lower() + + assert "release evidence" not in readme.lower() + assert "release evidence" not in changelog.lower() + assert "release evidence" not in notes.lower() diff --git a/tests/packaging/test_release_metadata_v024.py b/tests/packaging/test_release_metadata_v024.py new file mode 100644 index 0000000..b689597 --- /dev/null +++ b/tests/packaging/test_release_metadata_v024.py @@ -0,0 +1,124 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Project: Ecli +# File: tests/packaging/test_release_metadata_v024.py +# Website: https://www.ecli.io +# Repository: https://github.com/SSobol77/ecli +# PyPI: https://pypi.org/project/ecli-editor/0.0.1/ +# +# Copyright (c) 2026 Siergej Sobolewski +# +# Licensed under the GNU General Public License version 2 only. +# See the LICENSE file in the project root for full license text. + +"""v0.2.4 release metadata and version-source contract.""" + +from __future__ import annotations + +import os +import subprocess +import sys +import tomllib +from pathlib import Path +from types import ModuleType + +import pytest +from conftest import load_script_module + + +VERSION = "0.2.4" + + +def _read(path: Path) -> str: + return path.read_text(encoding="utf-8") + + +def _pyproject_version(repo_root: Path) -> str: + with (repo_root / "pyproject.toml").open("rb") as handle: + return tomllib.load(handle)["project"]["version"] + + +@pytest.fixture +def release_assets(repo_root: Path) -> ModuleType: + return load_script_module( + repo_root, "scripts/verify_release_assets.py", "verify_release_assets" + ) + + +def test_authoritative_version_sources_are_current(repo_root: Path) -> None: + assert _pyproject_version(repo_root) == VERSION + assert f'version = "{VERSION}"' in _read(repo_root / "flake.nix") + assert f'version ? "{VERSION}"' in _read(repo_root / "packaging/nix/package.nix") + assert f"pkgver={VERSION}" in _read(repo_root / "packaging/arch/PKGBUILD") + + +def test_make_validate_version_consistency_passes(repo_root: Path) -> None: + result = subprocess.run( + ["make", "validate-version-consistency"], + cwd=repo_root, + capture_output=True, + text=True, + timeout=30, + check=False, + ) + + assert result.returncode == 0, result.stdout + result.stderr + assert f"pyproject={VERSION} ecli.__version__={VERSION}" in result.stdout + + +def test_runtime_version_cli_reports_current_release(repo_root: Path) -> None: + env = os.environ.copy() + python_path = str(repo_root / "src") + existing_pythonpath = env.get("PYTHONPATH") + if existing_pythonpath: + python_path = os.pathsep.join((python_path, existing_pythonpath)) + env["PYTHONPATH"] = python_path + + result = subprocess.run( + [sys.executable, "-m", "ecli", "--version"], + cwd=repo_root, + env=env, + capture_output=True, + text=True, + timeout=20, + check=False, + ) + + assert result.returncode == 0, result.stderr + assert result.stdout.strip() == f"ecli {VERSION}" + + +def test_packaging_filenames_derive_current_version( + repo_root: Path, + release_assets: ModuleType, +) -> None: + project_version = _pyproject_version(repo_root) + names = release_assets.expected_asset_names(project_version) + + assert project_version == VERSION + assert len(names) == 21 + assert len(set(names)) == 21 + assert all(VERSION in name for name in names) + assert all("0.2.3" not in name for name in names) + assert "ecli_editor-0.2.4-py3-none-any.whl" in names + assert "ecli_0.2.4_linux_x86_64.deb" in names + assert "ecli_0.2.4_workflow_contract_evidence.tar.gz" in names + + +def test_exact_twenty_one_release_asset_semantics_remain_unchanged( + release_assets: ModuleType, +) -> None: + names = release_assets.expected_asset_names(VERSION) + + assert len(names) == 21 + assert "Source code (zip)" not in names + assert "Source code (tar.gz)" not in names + assert not any(name.endswith(".sha256") for name in names) + + +def test_release_workflow_has_no_hard_coded_v024_path(repo_root: Path) -> None: + release_workflow = _read(repo_root / ".github/workflows/release.yml") + + assert f"releases/{VERSION}" not in release_workflow + assert f"releases\\{VERSION}" not in release_workflow + assert f"v{VERSION}" not in release_workflow