Skip to content

design(v2.10): freeze a stable downstream consumer facade and separate library errors from CLI/process exits #723

Description

@dmidlo

Parent handoff milestone: #721
Related: #513 #526 #612 #632#641 #722

Audit finding

The current public package still carries legacy API/process coupling that is acceptable for backwards compatibility but unsafe as the implicit contract for the forthcoming private ML consumer.

Concrete live-code examples on main:

  • src/histdatacom/api.py documents and raises SystemExit from library helper _import_file_to_polars after catching ValueError;
  • src/histdatacom/__init__.py mutates sys.modules[__name__].__class__ to make the package module callable through APICaller;
  • the repository already has a structured HistDataOperationError/ErrorCategory taxonomy, but legacy library paths do not consistently use it.

A clean downstream consumer must not unexpectedly terminate its process because an imported library operation encountered invalid data, and it must not depend on module-class mutation or CLI-only side effects to access scientific products.

Outcome

Freeze one explicit, typed, versioned consumer facade for dataset/handoff discovery, verification, projection and bounded replay. The facade is the supported Python-library boundary for #721 and is independently usable from the CLI.

Legacy callable-module and convenience APIs may remain during a deprecation window, but the handoff consumer must not require them.

Library/CLI separation

Library functions must:

  • return typed values/receipts or raise documented typed exceptions;
  • never call sys.exit, raise SystemExit, or terminate the interpreter for recoverable input/data/runtime failures;
  • distinguish scientific refusal/unsupported state from configuration, dependency, network, filesystem, parse, validation, cancellation and unknown programming/runtime failures;
  • preserve original exception chaining and stable machine-readable reason codes;
  • avoid printing/progress/UI side effects unless explicitly supplied an observer/progress sink.

CLI adapters may map typed exceptions/receipts to exit codes, human-readable messages and progress output at the outermost process boundary.

Consumer facade scope

At minimum expose supported operations for:

  • package/schema/handoff compatibility inspection;
  • HandoffBundleV1 discovery/read/verify;
  • dataset/view/feature-registry discovery;
  • deterministic feature projection;
  • canonical split/evidence-unit/weight retrieval;
  • origin/uncertainty/missingness/availability inspection;
  • lineage ancestry queries;
  • bounded golden-sample replay/verification;
  • explicit refusal for unsupported origin/information/right/schema modes.

No operation may require repository-relative files or an argparse namespace.

Exception contract

Create or extend a stable exception/result taxonomy covering at least:

  • invalid consumer request;
  • incompatible schema/package/handoff;
  • missing required artifact;
  • artifact integrity failure;
  • unsupported information/origin mode;
  • rights/policy refusal;
  • causal/lineage verification failure;
  • resource/preflight refusal;
  • dependency/runtime failure;
  • unexpected internal error.

Scientific unsupported/refused is not interchangeable with operational/runtime failure. A broad catch may translate an exception only at a documented boundary and must retain the original class/cause in diagnostic evidence.

Legacy compatibility

Inventory public legacy entry points including callable-module behavior, Api, CLI-oriented helpers and import-time compatibility shims. Classify each as:

  • supported consumer API;
  • compatibility-only/deprecated;
  • CLI-only;
  • internal/private.

Do not remove legacy behavior merely to satisfy this issue unless SemVer/deprecation policy permits it. The requirement is that new consumers have a conventional supported alternative and that legacy quirks cannot leak into the handoff contract.

Tests

A clean external test package must prove:

  • importing histdatacom has no destructive/process-exit side effect;
  • invalid library input raises a typed exception rather than SystemExit;
  • the same failure maps to a stable CLI exit code only in CLI execution;
  • consumer operations work without calling the module object;
  • monkeypatching/replacing sys.modules class is not required by the consumer;
  • structured scientific refusal remains distinct from unexpected exception;
  • exception serialization/redaction does not expose credentials/secrets;
  • public facade signatures and reason-code schemas are captured in compatibility fixtures.

Acceptance

#721's clean-room consumer uses only this supported facade plus published artifacts; no consumer path relies on package-call masquerading, argparse/process globals, SystemExit, repository-local state or undocumented side effects; CLI and Python-library semantics are independently testable; and #632 compatibility policy governs future facade evolution.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestmodern-toolingModern tooling, CI, release, coverage, and packaging hygienescientific-validationFalsifiability, calibration, leakage, reproducibility, and scientific acceptance gates

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions