|
| dict | _read_frontmatter (Path path) |
| str | read_manifest_version (Path manifest_path) |
| set[str] | read_configured_fallbacks (tuple[Path,...] pyproject_paths) |
| ParsedHeader | parse_view_header (str text, ViewSpec view) |
| dict[str, ParsedHeader] | read_view_headers (Path view_root) |
| bool | is_rejected_fallback (str version, set[str] configured_fallbacks) |
| tuple[int,...] | _release_core (str version) |
| bool | _is_clean_release (str version) |
| GateOutcome | consistency_gate (*, str release_tag, str manifest_version, dict[str, ParsedHeader] headers, set[str] configured_fallbacks) |
| GateOutcome | code_equality_gate (*, str installed_version, str resolved_version, str manifest_version, dict[str, ParsedHeader] headers, set[str] configured_fallbacks, bool exact) |
| None | _emit (GateOutcome outcome) |
| int | run_gates (argparse.Namespace args) |
| str | _installed_version () |
| argparse.ArgumentParser | build_parser () |
| int | main (Optional[list[str]] argv=None) |
Release-time version gates for the OC Chat single-version system.
Purpose
-------
Two mechanical, re-runnable gates (Plan 143g-code S5; addendum §"Acceptance
tests" — orchestrator release-time gates). They run at the ``v0.8.0`` cut (and
every later release), NOT in the branch worktree suite — no ``v0.8.0`` tag
exists pre-release, so the *release-mode* run only ever goes green on the exact
annotated release commit. This module ships the tooling + its unit tests; the
real invocation is the orchestrator's, per the addendum's bundle transaction.
Responsibilities
----------------
- :func:`consistency_gate` / :func:`code_equality_gate` — the two pure gate
predicates over already-parsed inputs (fixture-testable).
- :func:`read_manifest_version` / :func:`read_view_headers` /
:func:`read_configured_fallbacks` — isolated I/O: direct source/render reads.
- :func:`parse_view_header` — the per-view-STRICT header grammar.
- :func:`is_rejected_fallback` — the reject-on-EITHER fallback predicate.
- :func:`run_gates` / :func:`main` — mode dispatch + typed process exits.
The two gates
-------------
- **Consistency gate** (committed axis): the Release-tag helper value ==
manifest ``extensions.current_version`` == the four rendered ``**Version:**``
headers. Needs the annotated tag, so it runs in ``--mode release`` only.
- **Code-equality gate** (live axis vs committed): installed package release
core == :func:`resolve_version` == manifest ``current_version`` == the
headers.
Modes
-----
- ``--mode release`` — ONE invocation runs BOTH gates, EXACT equality (no
``.devN`` / local suffix tolerated), required on the exact annotated
``v0.8.0`` release commit. Any consulted live version equal to EITHER a
configured ``fallback_version`` (read from the two pyprojects) OR the pinned
sentinel ``0.0.0.dev0`` is rejected — reject-on-EITHER, never a conjunction.
- ``--mode dev-smoke`` — tolerates ``.devN+ghash`` on the live axis (compares
release cores); runs the code-equality + header-consistency checks but NOT
the tag-consistency check (no release tag exists in dogfood). Its report
STATES it is NOT a release authorization.
The gate never imports ``registry/render/**``: the manifest read is a DIRECT
source read of ``oc_chat/roadmap/source/manifest.md`` frontmatter, and the view
headers are parsed straight from the rendered files.
Header grammar (per-view STRICT — addendum §"The header fix" V13.3 table):
``**Version:** {version}`` on all four views; ``· Round {N}`` REQUIRED and
value-checked on ``ROADMAP-CHANGELOG.md`` only, FORBIDDEN on the three bare
views (``ROADMAP.md`` / ``ROADMAP-EXTENDED.md`` / product ``CHANGELOG.md``).
Exit codes
----------
- 0 — all requested gates passed.
- 1 — a gate violation (drift / inequality / rejected fallback).
- 2 — usage or configuration error (bad args, missing/malformed inputs).
Diagnostics
-----------
Domain: OC_CHAT.MAIN
Levels:
L2 — lifecycle events (gate pass/fail)
L3 — semantic details (per-axis values)
L4 — deep tracing
Contracts
---------
- Gate functions are pure over their parsed inputs (fixture-testable); I/O is
isolated in the ``read_*`` / ``load_*`` helpers.
- Fail-closed with diagnostics NAMING the disagreeing axis.
Dependencies
------------
- packaging (packaging.version.Version — declared in both pyprojects, S1b)
- oc_diagnostics (structured debug logging via _dbg)
- oc_chat.core.release_tag (lazy; resolve_release_tag and release_tag_core - the annotated release tag and its prefix-aware version core)
- oc_chat.core._version (lazy; resolve_version - the live version for the code-equality gate)
- yaml (lazy; PyYAML safe_load of the roadmap manifest frontmatter)