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 shownow run inside a RichLivepanel 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_COLORand falls back to plain text when stdout is not a TTY.
Shared rendering primitives live insrc/lhp/cli/live_panel.py,
with command-specific summary tables ingenerate_summary.pyand
validate_summary.py. --show-all/-aflag onlhp generateandlhp validate.
The post-run summary table defaults to failed pipelines only; pass
--show-allto 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-clickfor CLI help rendering.clickis imported as
rich_click as click; existing decorators are unchanged but
--helpoutput now renders as a styled Rich panel.LHPError.__rich__+LHPError.from_unexpected_exception. Errors
are rendered to stderr as a category-coloured RichPanelwith
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
LHPErrorviafrom_unexpected_exceptioninstead 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-sidelogger.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_WARNEDflag.- Snapshot tests via
syrupy. Rich rendering forLHPError
panels, the validate summary table, andshowflowgroup output is
pinned by.ambrsnapshots undertests/__snapshots__/. An autouse
_isolate_lhp_consolefixture intests/conftest.pyswaps the
lhp.cli.consolesingletons 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 optionaldepends_onaction field as an explicit
dependency escape hatch (validated asLHP-VAL-063), and a shared dependency
graph contract reused bylhp depsand orchestration-job generation. dag --format jobnow validatesjob_nameconsistency on the live path.- Write-target fields
cluster_by_autoandrefresh_policyfor 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.pymodules inside a
built pipeline wheel, or extract them with--extract DIR(preserving the
in-wheel structure). The selector is either a path to a.whlor a pipeline
name; the pipeline form requires--env/-e. New error codesLHP-IO-022
(wheel file not found),LHP-IO-023(not a wheel file), andLHP-IO-024
(corrupt wheel archive) cover the failure modes.- Provisional
WheelFacadepublic API — reachable asfacade.wheelwith
list_modules(...)/extract_modules(...), returning the new provisional
DTOsWheelContentsViewandWheelModuleView(api/views.py) and
WheelExtractionResult(api/responses.py). All are:stability: provisional. - Public typed API. A versioned
lhp.apisurface with stability annotations
on every public symbol, shipped withpy.typed. - Opt-in
--log-fileflag to persist verbose logs without cluttering the
console. $is now allowed in schema-transform source column names.
Changed
cli_error_boundaryrenders via Rich Console. Errors print
througherr_console.print(lhp_error)so the new__rich__panel
takes effect on TTYs; the stringified-LHPError sniffing safety net
is replaced byLHPError.from_unexpected_exception.error_formatter.pyreshaped 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.pyslimmed. Unused helpers
(_ensure_project_root,_load_project_config,
_get_include_patterns,_discover_yaml_files_with_include) and a
straywarnings.filterwarningscall were removed — the Click
subcommands own these concerns directly.- Tooling consolidated onto
ruffas 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 sharedcore/packaging/wheel_reader.locate_pipeline_wheel,
removing the duplicate locate logic. TheTARGET_ARCHITECTURE.md§5bis budget
is amended accordingly (wheel_reader.py ≤130;core/packaging/total raised
≤650 → ≤700).
Performance
lhp generateis substantially faster on large projects — generation
hot-path optimization, read-once / parse-once discovery, a single shared
preflight forvalidateandgenerate, 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_namedependency propagation for orchestration jobs.
Removed
- Module-level
_DEPRECATED_BARE_TOKEN_WARNEDglobal in
lhp/utils/substitution.py(replaced by per-instance
has_deprecated_bare_tokens+WarningCollector). DOLLAR_TOKEN_SIMPLE_PATTERNinEnhancedSubstitutionManager—
was unused.
Dependencies
- Add
rich>=13.0.0andrich-click>=1.9.0,<2.0as runtime deps. - Add
syrupy>=4.6.0as a dev dep for snapshot testing.