oc_chat
Loading...
Searching...
No Matches
release_gates Namespace Reference

Classes

class  ViewSpec
class  GateConfigError
class  ParsedHeader
class  GateOutcome

Functions

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)

Variables

int EXIT_OK = 0
int EXIT_GATE_VIOLATION = 1
int EXIT_USAGE = 2
str PINNED_FALLBACK_SENTINEL = "0.0.0.dev0"
str _MIDDLE_DOT = "·"
 _REPO_ROOT = Path(__file__).resolve().parent.parent
str DEFAULT_MANIFEST = _REPO_ROOT / "oc_chat" / "roadmap" / "source" / "manifest.md"
tuple DEFAULT_PYPROJECTS
str _ROADMAP_DIR = "oc_chat/roadmap"
tuple VIEWS
 _HEADER_RE

Detailed Description

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)

Function Documentation

◆ _emit()

None release_gates._emit ( GateOutcome outcome)
protected

Definition at line 386 of file release_gates.py.

Here is the caller graph for this function:

◆ _installed_version()

str release_gates._installed_version ( )
protected
The installed package version resolve_version() consults first.

Definition at line 464 of file release_gates.py.

Here is the caller graph for this function:

◆ _is_clean_release()

bool release_gates._is_clean_release ( str version)
protected
True iff ``version`` is a final/post release (no dev / pre / local).

Definition at line 282 of file release_gates.py.

Here is the caller graph for this function:

◆ _read_frontmatter()

dict release_gates._read_frontmatter ( Path path)
protected
Return the YAML frontmatter of a markdown source record as a dict.

Definition at line 174 of file release_gates.py.

Here is the caller graph for this function:

◆ _release_core()

tuple[int, ...] release_gates._release_core ( str version)
protected

Definition at line 275 of file release_gates.py.

Here is the caller graph for this function:

◆ build_parser()

argparse.ArgumentParser release_gates.build_parser ( )

Definition at line 482 of file release_gates.py.

Here is the caller graph for this function:

◆ code_equality_gate()

GateOutcome release_gates.code_equality_gate ( * ,
str installed_version,
str resolved_version,
str manifest_version,
dict[str, ParsedHeader] headers,
set[str] configured_fallbacks,
bool exact )
Installed pkg == resolve_version() == manifest == headers.

``exact`` (release mode): full-string equality, no suffix tolerated, and the
live versions must not be a rejected fallback. Otherwise (dev-smoke): compare
release cores only, tolerating ``.devN+local`` on the live axis.

Definition at line 326 of file release_gates.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ consistency_gate()

GateOutcome release_gates.consistency_gate ( * ,
str release_tag,
str manifest_version,
dict[str, ParsedHeader] headers,
set[str] configured_fallbacks )
Release-tag value == manifest current_version == the four headers (exact).

Definition at line 291 of file release_gates.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_rejected_fallback()

bool release_gates.is_rejected_fallback ( str version,
set[str] configured_fallbacks )
Reject-on-EITHER: the pinned sentinel OR any configured fallback value.

Never a conjunction — an ``and`` implementation stays green on the pinned
untagged-archive state (where configured == sentinel and both fire together)
while silently dropping the value-independent belt (R05 both reviewers).

Definition at line 265 of file release_gates.py.

Here is the caller graph for this function:

◆ main()

int release_gates.main ( Optional[list[str]] argv = None)

Definition at line 499 of file release_gates.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_view_header()

ParsedHeader release_gates.parse_view_header ( str text,
ViewSpec view )
Parse the first ``**Version:**`` header of a view, per-view-STRICT.

Enforces the V13.3 per-view grammar: ``· Round N`` is REQUIRED on the
roadmap-changelog view and FORBIDDEN on the three bare views.

Definition at line 225 of file release_gates.py.

Here is the caller graph for this function:

◆ read_configured_fallbacks()

set[str] release_gates.read_configured_fallbacks ( tuple[Path, ...] pyproject_paths)
Read every ``[tool.setuptools_scm].fallback_version`` from the pyprojects.

Definition at line 207 of file release_gates.py.

Here is the caller graph for this function:

◆ read_manifest_version()

str release_gates.read_manifest_version ( Path manifest_path)
Return manifest ``extensions.current_version`` (direct source read).

Definition at line 195 of file release_gates.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ read_view_headers()

dict[str, ParsedHeader] release_gates.read_view_headers ( Path view_root)
Parse the four rendered view headers under ``view_root`` (the repo root).

Definition at line 247 of file release_gates.py.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ run_gates()

int release_gates.run_gates ( argparse.Namespace args)
Load inputs, run the mode's gates, return the process exit code.

Definition at line 395 of file release_gates.py.

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ _HEADER_RE

release_gates._HEADER_RE
protected
Initial value:
1= re.compile(
2 r"^\*\*Version:\*\*[ \t]+(?P<version>\S+)"
3 r"(?:[ \t]+" + re.escape(_MIDDLE_DOT) + r"[ \t]+Round[ \t]+(?P<round>\d+))?"
4 r"[ \t]*$",
5 re.MULTILINE,
6)

Definition at line 138 of file release_gates.py.

◆ _MIDDLE_DOT

str release_gates._MIDDLE_DOT = "·"
protected

Definition at line 109 of file release_gates.py.

◆ _REPO_ROOT

release_gates._REPO_ROOT = Path(__file__).resolve().parent.parent
protected

Definition at line 111 of file release_gates.py.

◆ _ROADMAP_DIR

str release_gates._ROADMAP_DIR = "oc_chat/roadmap"
protected

Definition at line 129 of file release_gates.py.

◆ DEFAULT_MANIFEST

str release_gates.DEFAULT_MANIFEST = _REPO_ROOT / "oc_chat" / "roadmap" / "source" / "manifest.md"

Definition at line 112 of file release_gates.py.

◆ DEFAULT_PYPROJECTS

tuple release_gates.DEFAULT_PYPROJECTS
Initial value:
1= (
2 _REPO_ROOT / "pyproject.toml",
3 _REPO_ROOT / "oc_chat" / "pyproject.toml",
4)

Definition at line 113 of file release_gates.py.

◆ EXIT_GATE_VIOLATION

int release_gates.EXIT_GATE_VIOLATION = 1

Definition at line 101 of file release_gates.py.

◆ EXIT_OK

int release_gates.EXIT_OK = 0

Definition at line 100 of file release_gates.py.

◆ EXIT_USAGE

int release_gates.EXIT_USAGE = 2

Definition at line 102 of file release_gates.py.

◆ PINNED_FALLBACK_SENTINEL

str release_gates.PINNED_FALLBACK_SENTINEL = "0.0.0.dev0"

Definition at line 106 of file release_gates.py.

◆ VIEWS

tuple release_gates.VIEWS
Initial value:
1= (
2 ViewSpec("roadmap", f"{_ROADMAP_DIR}/ROADMAP.md", False),
3 ViewSpec("roadmap_extended", f"{_ROADMAP_DIR}/ROADMAP-EXTENDED.md", False),
4 ViewSpec("roadmap_changelog", f"{_ROADMAP_DIR}/ROADMAP-CHANGELOG.md", True),
5 ViewSpec("product_changelog", "CHANGELOG.md", False),
6)

Definition at line 130 of file release_gates.py.