Skip to content

V0.9.0

Latest

Choose a tag to compare

@Mmodarre Mmodarre released this 10 Jun 14:02
· 5 commits to main since this release
6a60c56

Whats changed

Architecture refactor release. The internals were reorganized into a layered,
boundary-enforced architecture — a versioned public lhp.api facade, focused
core/ sub-packages, and an event-stream CLI — without changing the YAML
configuration contract. Existing projects generate the same pipeline code.

Added

  • Rich-based CLI rendering. lhp generate, lhp validate, and
    lhp show now run inside a Rich Live panel that opens with a
    Discovering flowgroups… spinner, switches to per-phase duration
    markers (✓ / ✗) and an in-flight progress spinner as work proceeds,
    and prints a per-pipeline summary table on exit. Coloring honors
    NO_COLOR and falls back to plain text when stdout is not a TTY.
    Shared rendering primitives live in src/lhp/cli/live_panel.py,
    with command-specific summary tables in generate_summary.py and
    validate_summary.py.
  • --show-all / -a flag on lhp generate and lhp validate.
    The post-run summary table defaults to failed pipelines only; pass
    --show-all to render the full table including passing rows. On a
    full-success run with no failures, the table is suppressed entirely
    and a single-line footer is printed (with a (use -a to list) hint
    when more than one pipeline ran). This keeps quiet runs short
    without losing the table for users who want it.
  • rich-click for CLI help rendering. click is imported as
    rich_click as click; existing decorators are unchanged but
    --help output now renders as a styled Rich panel.
  • LHPError.__rich__ + LHPError.from_unexpected_exception. Errors
    are rendered to stderr as a category-coloured Rich Panel with
    Context / Suggestions / Example / docs-link sections; the plain-text
    __str__ rendering is preserved verbatim for log files and non-TTY
    output. Unexpected exceptions are now converted into a generic
    LHPError via from_unexpected_exception instead of being matched
    by sniffing for "Error [LHP-" substrings in the stringified message.
  • WarningCollector + pre-pool YAML scanner. A per-run
    WarningCollector (src/lhp/cli/warning_collector.py) deduplicates
    non-fatal warnings by (category, message) and renders them as a
    yellow Rich panel at end of run. The deprecated bare-{token}
    substitution warning is now detected by a main-thread scan of raw
    YAML (src/lhp/cli/yaml_scanner.py) before workers are spawned —
    this fixes a silent regression where worker-side logger.warning
    calls were swallowed by the workers' NullHandler-only logger.
  • EnhancedSubstitutionManager.has_deprecated_bare_tokens.
    Per-instance flag flipped on the first deprecated {token}
    substitution so the orchestrator can forward a single entry to the
    WarningCollector. Replaces the previous module-level
    _DEPRECATED_BARE_TOKEN_WARNED flag.
  • Snapshot tests via syrupy. Rich rendering for LHPError
    panels, the validate summary table, and show flowgroup output is
    pinned by .ambr snapshots under tests/__snapshots__/. An autouse
    _isolate_lhp_console fixture in tests/conftest.py swaps the
    lhp.cli.console singletons for a deterministic no-color Console at
    fixed width so snapshots are stable across terminals and CI.
  • Dependency analysis overhaul. More accurate internal-vs-external edge
    classification, a new optional depends_on action field as an explicit
    dependency escape hatch (validated as LHP-VAL-063), and a shared dependency
    graph contract reused by lhp deps and orchestration-job generation.
  • dag --format job now validates job_name consistency on the live path.
  • Write-target fields cluster_by_auto and refresh_policy for streaming
    tables and materialized views.
  • Deterministic per-pipeline wheel packaging — content-addressed wheels
    emitted alongside source-mode pipelines.
  • lhp inspect-wheel <selector> command to list the .py modules inside a
    built pipeline wheel, or extract them with --extract DIR (preserving the
    in-wheel structure). The selector is either a path to a .whl or a pipeline
    name; the pipeline form requires --env/-e. New error codes LHP-IO-022
    (wheel file not found), LHP-IO-023 (not a wheel file), and LHP-IO-024
    (corrupt wheel archive) cover the failure modes.
  • Provisional WheelFacade public API — reachable as facade.wheel with
    list_modules(...) / extract_modules(...), returning the new provisional
    DTOs WheelContentsView and WheelModuleView (api/views.py) and
    WheelExtractionResult (api/responses.py). All are :stability: provisional.
  • Public typed API. A versioned lhp.api surface with stability annotations
    on every public symbol, shipped with py.typed.
  • Opt-in --log-file flag to persist verbose logs without cluttering the
    console.
  • $ is now allowed in schema-transform source column names.

Changed

  • cli_error_boundary renders via Rich Console. Errors print
    through err_console.print(lhp_error) so the new __rich__ panel
    takes effect on TTYs; the stringified-LHPError sniffing safety net
    is replaced by LHPError.from_unexpected_exception.
  • error_formatter.py reshaped around a single template dict.
    Plain-text (_format_message) and Rich (__rich__) renderings now
    consume the same _template_data() dict so the two presentations
    cannot drift. Category labels and Rich border styles are centralized
    in _category_label / _border_style.
  • src/lhp/cli/main.py slimmed. Unused helpers
    (_ensure_project_root, _load_project_config,
    _get_include_patterns, _discover_yaml_files_with_include) and a
    stray warnings.filterwarnings call were removed — the Click
    subcommands own these concerns directly.
  • Tooling consolidated onto ruff as the single linter, formatter, and
    import-sorter (replaces black + isort + flake8).
  • CLI rebuilt as a pure presentation layer over a single generate/validate
    event-stream facade, with animated progress, lazy startup, and a readable
    run summary.
  • core/ reorganized into focused sub-packages (codegen, coordination,
    loaders, processing, discovery, jobs, registry, dependencies,
    packaging, validators); the orchestrator, loaders, models, and validators
    were decomposed and domain errors moved into a dedicated error-code registry.
  • Documentation rewritten (Sphinx RST) with condensed per-action-sub-type AI
    skill references.
  • Bundle wheel-locator deduplicated. bundle/manager._find_wheel_filename
    now delegates to the shared core/packaging/wheel_reader.locate_pipeline_wheel,
    removing the duplicate locate logic. The TARGET_ARCHITECTURE.md §5bis budget
    is amended accordingly (wheel_reader.py ≤130; core/packaging/ total raised
    ≤650 → ≤700).

Performance

  • lhp generate is substantially faster on large projects — generation
    hot-path optimization, read-once / parse-once discovery, a single shared
    preflight for validate and generate, and a consolidated parallel-execution
    engine.
  • Cross-platform determinism — transitive Python-file copying emits
    byte-identical output on every OS.

Fixed

  • Malformed-secret references are now rejected; referential-integrity tests
    enforce a column-count check; operational-metadata ordering is deterministic.
  • Blueprint instance-reference rejection, monitoring-cleanup marker hardening,
    and a bundle read-only error invariant.
  • job_name dependency propagation for orchestration jobs.

Removed

  • Module-level _DEPRECATED_BARE_TOKEN_WARNED global in
    lhp/utils/substitution.py (replaced by per-instance
    has_deprecated_bare_tokens + WarningCollector).
  • DOLLAR_TOKEN_SIMPLE_PATTERN in EnhancedSubstitutionManager
    was unused.

Dependencies

  • Add rich>=13.0.0 and rich-click>=1.9.0,<2.0 as runtime deps.
  • Add syrupy>=4.6.0 as a dev dep for snapshot testing.