`internal/app` owns top-level use cases for `run`, `validate`, and `inspect`. It wires configuration, storage backends, transforms, publish planning, execution, structured run reports, summaries, coordination, and notification handoff.
`Run` accepts a context, optional config path, dry-run flag, force flag, stdout writer, output format, and optional notifier. It loads YAML config, discovers source bundles for each configured pipeline, plans each destination independently, optionally executes publish plans, builds a `RunReport`, projects that report to text or JSON when stdout is supplied, and returns an aggregated error if any destination fails.
`RunPipeline` accepts a context, config path, pipeline ID, dry-run flag, force flag, and optional notifier. It runs exactly one configured pipeline and returns the same `RunReport` model without writing command output. Unknown pipeline IDs return `PipelineNotFoundError`, detectable with `IsPipelineNotFound`.
`PipelineRunCoordinator` wraps `RunPipeline` with in-memory admission control. It returns `PipelineRunRecord` values containing run ID, pipeline ID, status, timestamps, report, and error text. Duplicate in-flight runs for the same pipeline ID return `DuplicatePipelineRunError`, detectable with `IsDuplicatePipelineRun`.
`Validate` and `Inspect` accept either a local path or one configured pipeline source. `Validate` discovers and validates bundles. `Inspect` writes bundle metadata and manifest file entries to stdout when provided.
Destination failures are collected while later destinations continue to run. Source open and source discovery failures stop the run because there are no valid bundles to fan out.
`RunPipeline` uses the same config loading, secret loading, backend factory, transform registry, warning generation, destination planning, publish execution, notification behavior, and failure aggregation as `Run`, but first narrows the loaded config to the requested pipeline.
`run.go` contains the public `Run` and `RunPipeline` entrypoints and the main configuration orchestration paths. Package-local run helpers are grouped by responsibility:
These helpers remain in `internal/app` because command output, warning collection, destination failure aggregation, notifier handoff, and backend construction are app-owned orchestration concerns.
`PipelineRunCoordinator` keeps active run state in memory only. It allows different pipeline IDs to run concurrently and rejects a second active run for the same pipeline ID. Active state is cleared after success, destination-scoped failure, source/config failure, unknown pipeline ID, or context cancellation.
The admission context is checked before a run is admitted. Once admitted, execution uses the coordinator lifetime context so future transport request cancellation can stop waiting for admission without owning the actual run lifetime.
The app-level backend factory registers local, SSH, and S3 backends for execution. Source and destination backend config is converted through a shared app-local open spec before adapter construction. S3 explicit credential references are resolved through the config environment resolver.
The app-level transform registry registers Markdown-to-HTML using `internal/transform/markdown`. Lower-level publish code receives a resolver and does not import concrete transform implementations.
`Run` returns immediately for config loading errors, context cancellation before work starts, source open errors, and source discovery errors. `RunPipeline` also returns immediately with `PipelineNotFoundError` when the requested pipeline ID is not configured. Per-destination backend, planning, execution, and notification errors are aggregated into one run error after remaining destinations have been attempted.
Run diagnostics include pipeline id, destination id, destination backend, and bundle path for destination-scoped failures. Source open and discovery failures include the source backend.
`internal/app` coordinates packages but does not own manifest validation rules, destination state comparison, storage path rules, output planning, transform rendering, or backend-specific filesystem behavior.
`PipelineRunCoordinator` is an app-layer concurrency boundary only. It does not persist run records, expose HTTP routes, or define transport status endpoints.