Skip to content

A5 — implement fishwrap-build, fishwrap-version, fishwrap-validate-config CLIs #4

@maxspevack

Description

@maxspevack

Goal

Implement the three documented CLI entrypoints — fishwrap-build, fishwrap-version, fishwrap-validate-config — as stable, scriptable subcommands of the image. These are the consumer contract.

Context

The ADR (issue A1) commits to a CLI surface that downstream consumers depend on, not a Python ABI. The reason: CLI contracts are easy to keep stable across years; ABI contracts require care every refactor.

Today there is no fishwrap-version CLI. DC's publish_about.py:10 does import fishwrap to read __version__. Today there is no fishwrap-validate-config; a typo in config.py causes a runtime crash four minutes into a fetch (after feeds are pulled). Today there is no fishwrap-build; the four python -m fishwrap.X invocations are stitched together by Makefiles.

This issue creates the stable CLI surface that lets DC stop importing fishwrap as a Python module and lets a stranger validate their config in five seconds instead of five minutes.

Deliverable

In the fishwrap repo:

  1. fishwrap-build — wraps the existing fetcher → editor → enhancer → printer pipeline into a single command. Accepts --config <path>. Sets FISHWRAP_CONFIG and runs the four phases sequentially. Exit code: 0 on success, non-zero on any phase failure with a clear error
  2. fishwrap-version — prints __version__ from fishwrap/__init__.py to stdout, then exits 0. Adds nothing else (no banner, no whitespace surprises). Stable contract: stdout always parseable as a semver string
  3. fishwrap-validate-config — accepts a config file path. Loads the config (the same way fishwrap/_config.py loads it). Validates against a schema covering the keys the engine actually uses: FEEDS, SECTIONS, KEYWORDS, EDITORIAL_POLICIES, SCORING_PROFILES, SOURCE_SECTIONS, EDITION_SIZE, MIN_SECTION_SCORES, BOOST_UNIT_VALUE, FUZZY_BOOST_MULTIPLIER, EXPIRATION_HOURS, TIMEZONE, etc. Reports missing required fields, wrong types, and unknown top-level keys. Exit code: 0 on valid, non-zero on invalid with human-readable errors
  4. The schema documentation produced as part of issue D2 (docs/CONFIG_SCHEMA.md) is the user-facing reference; this issue is the implementation

These can be entry-point scripts via pyproject.toml/setup.cfg console_scripts, or shell wrappers in bin/ — implementer's choice as long as the image's entrypoint dispatch (issue A2) routes correctly.

Acceptance Criteria

  • fishwrap-version prints a single semver line and exits 0; tested against fixed expected output
  • fishwrap-build --config <path> runs the full pipeline; equivalent output to the old python -m fishwrap.{fetcher,editor,enhancer,printer} chain
  • fishwrap-validate-config <path> accepts a known-good config and exits 0
  • fishwrap-validate-config <path> rejects: missing required key, wrong type for known key, malformed EDITORIAL_POLICIES entry — each with a clear error pointing at the offending key
  • Validator runs in under 1 second on a typical config (no feed fetching, no DB)
  • Unit tests for the validator covering the rejection cases above

Out of Scope

  • Writing docs/CONFIG_SCHEMA.md — that is part of D2 (docs rewrite). This issue produces the validator; D2 produces the human-readable reference
  • Migrating consumers to use fishwrap-version — that's C5 (DC) and any other consumers later

Dependencies

  • Blocked by: A2 (entrypoint dispatch must exist)
  • Blocks: C5 (DC's publish_about.py decoupling depends on fishwrap-version existing)

References

  • ADR: docs/ADR/0001-release-artifact.md (issue A1)
  • Current config loader: fishwrap/_config.py:53-77
  • Current pipeline modules: fishwrap/{fetcher,editor,enhancer,printer}.py
  • Current version source: fishwrap/__init__.py
  • Manifesto: rule 1 (complexity is the enemy — small, stable CLI surface), rule 5 (root cause only — validate before fetching, don't crash mid-pipeline)

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:imageContainer / artifact contractphase:reliabilityM1 / v1.4 Pipeline Reliability workpriority:p0Blocking M1 ship

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions