vibe.review.template_functions

Template functions for VIBE Review.

Provides the req() function that templates use to reference requirements. This function serves two purposes:

  1. During probing: Registers the requirement as "applicable" for the current context
  2. During rendering: Returns a RequirementProxy with classification state

This enables the "template is truth" pattern where the template's conditional logic determines which requirements apply, rather than duplicating that logic in config.yml conditions.

Example template usage

{% if critical_service %} {% if not req('D5-1') %} Add audit rights clause: {{ req('D5-1').human_notes }} {% endif %}

When probed with critical_service=True, D5-1 will be registered as applicable. When probed with critical_service=False, the block is skipped and D5-1 is not registered.

RequirementProxy

Proxy object for requirement access in review templates.

Provides boolean semantics (truthy when compliant) and property access to classification details. Used by the req() template function.

Boolean behavior
  • True only when result == ClassificationResult.YES
  • False for NO, PARTIAL, NOT_APPLICABLE, PENDING
String behavior
  • Returns formatted string using requirement_string_template
  • Default: "{label}: {result}" (localized)
Example template usage

{% if req('D2-1') %}Requirement satisfied{% endif %} {% if not req('D2-1') %}...add amendment clause...{% endif %} {% if req('D2-1').result == PARTIAL %} {{ req('D2-1').human_notes }}

from_requirement_and_review

from_requirement_and_review(requirement: Requirement, review: RequirementReviewModel | None, string_template: str = DEFAULT_REQUIREMENT_STRING_TEMPLATE, result_localizer: Callable[[ClassificationResult], str] | None = None) -> RequirementProxy

Create proxy from a Requirement definition and optional review result.

Parameters:
  • requirement (Requirement) –

    The requirement definition from config

  • review (RequirementReviewModel | None) –

    The classification result from database (None if not yet classified)

  • string_template (str, default: DEFAULT_REQUIREMENT_STRING_TEMPLATE ) –

    Template for str formatting

  • result_localizer (Callable[[ClassificationResult], str] | None, default: None ) –

    Function to localize ClassificationResult values

Returns:
  • RequirementProxy

    RequirementProxy with combined requirement and classification data

pending

pending(requirement_id: str, label: str | None = None, string_template: str = DEFAULT_REQUIREMENT_STRING_TEMPLATE) -> RequirementProxy

Create a pending proxy for probing mode.

During template probing, we don't have classification results yet. This creates a falsy proxy that registers the requirement as applicable.

Parameters:
  • requirement_id (str) –

    The requirement ID

  • label (str | None, default: None ) –

    Optional label (defaults to ID)

  • string_template (str, default: DEFAULT_REQUIREMENT_STRING_TEMPLATE ) –

    Template for str formatting

Returns:

RequirementGroupProxy

Proxy object for group-level requirement access in review templates.

Provides boolean semantics (truthy when all requirements compliant) and methods for querying group compliance status.

Boolean behavior
  • True only when ALL requirements in the group have result == YES
  • False if any requirement is not compliant
Example template usage

{% if group('service_levels') %}All SLA requirements met{% endif %} {% if group('audit').incompliant_count > 0 %} {{ group('audit').incompliant_count }} audit issues found {% endif %} {% for r in group('audit').filter(PARTIAL) %} - {{ r.label }}: {{ r.human_notes }}

all_compliant

all_compliant: bool

Check if all requirements in the group are compliant (YES).

none_compliant

none_compliant: bool

Check if no requirements in the group are compliant.

compliant_count

compliant_count: int

Count of requirements with YES result.

incompliant_count

incompliant_count: int

Count of requirements that are not compliant (not YES).

filter

Filter requirements by classification result.

Parameters:
Returns:

empty

empty(group_id: str, title: str | None = None) -> RequirementGroupProxy

Create an empty group proxy for probing mode.

During template probing, we don't have classification results yet. This creates a falsy proxy (no requirements = not all compliant).

Parameters:
  • group_id (str) –

    The group ID

  • title (str | None, default: None ) –

    Optional title (defaults to ID)

Returns:

RequirementRegistry

Context manager for requirement discovery during template probing.

Usage

with RequirementRegistry() as registry: # Probe or render template here discovered = registry.get_requirements()

get_requirements

get_requirements() -> set[str]

Get the requirements discovered during this context.

RenderContext

Context manager for requirement rendering mode.

During rendering, provides lookup functions that return RequirementProxy and RequirementGroupProxy with actual classification data.

Usage

def req_lookup(req_id: str) -> RequirementProxy: # Return proxy with real classification data ...

def group_lookup(group_id: str) -> RequirementGroupProxy: # Return group proxy with requirements ...

with RenderContext(req_lookup, group_lookup, string_template="{label}: {result}"): # req() and group() calls will use lookups to get real data result = template.render(context)

get_discovered_requirements

get_discovered_requirements() -> set[str]

Get a copy of the discovered requirements set.

req

req(requirement_id: str) -> RequirementProxy

Look up a requirement in a review template.

This function serves two purposes: 1. During probing: Registers the requirement as applicable, returns pending proxy 2. During rendering: Returns RequirementProxy with actual classification data

The returned proxy: - Is truthy only when result == YES (fully compliant) - Stringifies using the configured requirement_string_template - Exposes properties: .result, .confidence, .human_notes, etc.

Parameters:
  • requirement_id (str) –

    The requirement ID (e.g., 'D5-1')

Returns:
Example

{% if req('D5-1') %}Requirement met{% endif %} {% if not req('D5-1') %}...add clause...{% endif %} {{ req('D5-1').human_notes }}

group

group(group_id: str) -> RequirementGroupProxy

Look up a requirement group in a review template.

This function serves two purposes: 1. During probing: Returns an empty group proxy (falsy due to no requirements) 2. During rendering: Returns RequirementGroupProxy with actual requirements

The returned proxy: - Is truthy only when ALL requirements in the group have result == YES - Stringifies to the group title - Provides methods: all_compliant(), incompliant_count(), filter(), etc.

Parameters:
  • group_id (str) –

    The group ID (e.g., 'service_levels', 'audit')

Returns:
Example

{% if group('service_levels') %}All SLA requirements met{% endif %} {% if group('audit').incompliant_count > 0 %} {{ group('audit').incompliant_count }} audit issues found {% endif %} {% for r in group('audit').filter(PARTIAL) %} - {{ r.label }}: {{ r.human_notes }}

create_review_template_globals

create_review_template_globals() -> dict[str, Any]

Create the globals dict to add to Jinja environment for review templates.

Returns:
  • dict[str, Any]

    Dict with 'req', 'group' functions and classification constants

The classification constants allow template expressions like

{% if req('D2-1').result == PARTIAL %}

probe_template_for_requirements

probe_template_for_requirements(template_env: Environment, template_content: str, context: dict[str, Any]) -> set[str]

Probe a template to discover which requirements are applicable.

Renders the template with the given context, collecting all req() calls that are executed. This implements "template is truth" - the template's conditional logic determines which requirements apply.

Parameters:
  • template_env (Environment) –

    The Jinja2 environment (from template_data.template_env)

  • template_content (str) –

    The Jinja2 template source

  • context (dict[str, Any]) –

    Context dict (e.g., {"critical_service": True})

Returns:
  • set[str]

    Set of requirement IDs that were referenced during rendering