Skip to content

0.4.0

Choose a tag to compare

@github-actions github-actions released this 07 Aug 20:06
· 78 commits to main since this release

Changed

  • Breaking — the processing error channel is now typed. ProcessingOutcome::errorMessage (a free
    string) is replaced by std::optional<Models::ProcessingError> error, and
    ProjectItem::applyProcessingResults() now returns std::vector<Models::ProcessingError>
    (previously void). Consumers read outcome.error->message instead of outcome.errorMessage, and
    should surface the vector returned by applyProcessingResults(). outcome.failed /
    outcome.cancelled are unchanged (failed == error.has_value()).
  • Core::InputResult gains errorCode / errorCategory — the per-input skip reason
    (SkippedError) now carries a stable machine tag alongside the existing detail string, so a
    consumer can group/localise skips without parsing English. The file and message are still
    inputPath / detail (no duplication).

Added

  • Models::ProcessingError — one typed error vocabulary (code + category + message + file
    • slice) shared wherever a failure is consumed as a result: ProcessingOutcome::error, the
      applyProcessingResults() return, and the InputResult tag. ProcessingErrorCategory
      (Load / ProfileMatch / Slice / Encode / Io) and ProcessingErrorCode cover the pipeline's
      fatal sites and the post-render hash failure. Deliberately no live onError callback: for a fatal
      error the run returns immediately (read outcome.error), and per-input skips already flow through
      onInput; onLog(Error, …) remains the human transcript.
  • FileStatus::Error — a new, sticky input status for a page that was rendered but whose content
    hash could not be computed afterwards.
  • WorkspaceEditor::duplicateProject(source, newName) — seeds a new project from an existing one,
    copying its input files and profile links (canvasProfileIds + outputProfileId) only. The
    output directory, the output slice list and all render state are deliberately dropped, so the copy
    starts with Pending inputs and renders into its own folder. Mints a fresh workspace-unique project
    uid (the source keeps its own) and fresh project-local input uids — no identifier collides. Enables
    the GUI's "New from this…" action for the multi-publisher workflow.
  • Complete third-party notices for the bundled DLL graph. The Windows packages now ship
    credits/THIRD-PARTY-NOTICES.txt, credits/licenses/ (18 canonical/upstream licence texts) and a
    credits/sbom.spdx.json covering all 32 components (the 3 direct deps + the ~29 libvips runtime /
    compiler-runtime DLLs — glib, libpng, libjpeg/mozjpeg, freetype, harfbuzz, cairo, pango, webp, …),
    instead of only libvips + nlohmann/json. Generated at configure time (cmake/gen_credits.cmake) from
    the web-build's authoritative versions.json + a curated cmake/third_party.json; a Third-party coverage CI workflow fails if a bundled DLL is unmapped. The committed sbom/ snapshot (GitHub
    dependency graph) was refreshed to the full graph. (Legal note: third_party.json SPDX ids are
    curated best-effort and pending a final review; libimagequant is disclosed as GPL-3.0-or-later.)
  • Safety net for unforeseen faults. ProcessingPipeline::run() now wraps its whole body so any
    exception that escapes the inline handling (a bug, out-of-memory, a non-std::exception throw) becomes
    a typed Unexpected / Internal failure on outcome.error instead of unwinding out of run() and
    terminating the caller's worker thread; the CLI gained an equivalent top-level guard that prints a
    reportable diagnostic. New ProcessingErrorCode::Unexpected + ProcessingErrorCategory::Internal.
    (This handles C++ exceptions only — a hardware fault such as a segfault or null dereference is an OS
    signal / SEH, not a C++ exception, and is out of scope; catching those needs a dedicated crash handler.)
    The CLI also installs std::set_terminate to print the in-flight exception on the terminate paths
    (uncaught exception / noexcept violation / pure-virtual call) instead of aborting silently.

Fixed

  • An unreadable-after-render input no longer loops forever, silently. When computeFileSha256()
    returned "" (indistinguishable for "absent" and "locked / denied / offline"),
    applyProcessingResults() left a successfully-rendered input at Pending; sanitize() re-confirmed
    Pending, so every subsequent render redid all the work and overwrote the output indefinitely with
    nothing reported. Such an input is now set to FileStatus::Error (sticky, non-forcing) and returned
    as a typed InputHashFailed failure; it recovers to Processed once the file can be read again.

CLI

  • project duplicate --workspace F --name SRC --new-name COPY [--output DIR] — seeds a new project
    from SRC (input files + profile links only; no outputs / output dir / render state), the CLI face of
    WorkspaceEditor::duplicateProject(). Refuses a missing source or an already-taken name; without
    --output it notes that the copy needs an output directory before rendering.
  • process gained structured, TTY-aware output — a per-input tally (with the typed skip reason),
    a strip-assembly marker, an in-place progress bar (plain lines when piped), timing, and dedicated
    error sections that render ProcessingError fields (category / slice / file) plus the post-render
    "unverified input(s)" list. --json is unchanged apart from a new unverifiedInputs array. Symbols
    only, no colour, so redirected output stays clean.

What's Changed

  • chore(deps): bump advanced-security/spdx-dependency-submission-action from 0.1.1 to 0.2.0 by @dependabot[bot] in #1
  • chore(deps): bump actions/checkout from 4 to 7 by @dependabot[bot] in #2
  • chore(deps): update pytest requirement from >=7.0 to >=9.1.1 in /tests/cli-tests by @dependabot[bot] in #3
  • chore(deps): bump softprops/action-gh-release from 2 to 3 by @dependabot[bot] in #8
  • chore(deps): bump actions/attest-build-provenance from 1 to 4 by @dependabot[bot] in #7
  • chore(deps): bump actions/upload-artifact from 4 to 7 by @dependabot[bot] in #6
  • chore(deps): bump actions/checkout from 4 to 7 by @dependabot[bot] in #5
  • chore(deps): bump actions/download-artifact from 4 to 8 by @dependabot[bot] in #4

New Contributors

Full Changelog: 0.3.1...0.4.0