CLI Contracts ============= OneCite exposes stable command-line envelopes for automation and CI workflows. Human-readable output is still available, but automation should prefer the JSON or NDJSON modes below. Process JSON ------------ ``onecite process INPUT --json`` writes one JSON object to stdout unless ``--output`` is used. The envelope contains: - ``schema_version``: currently ``"1.0"``. - ``tool`` and ``command``: ``"onecite"`` and ``"process"``. - ``status``: ``"passed"`` when all entries resolved, otherwise ``"failed"``. - ``summary``: total, succeeded, failed, and success rate. - ``options``: the effective CLI options that affect processing. - ``failed_entries``: unresolved entries with their error payloads. - ``results``: formatted BibTeX strings. The current top-level contract is exactly ``schema_version``, ``tool``, ``command``, ``status``, ``summary``, ``options``, ``failed_entries``, and ``results``. Additive fields should be treated as a contract change and covered by tests. Use ``--fail-on-unresolved`` when unresolved entries should make the process exit with code ``2``. If a hard processing error happens before per-entry results can be built, ``--json`` still writes the same top-level envelope with ``status: "failed"``, a single ``failed_entries`` error payload, and exit code ``1``. Process NDJSON -------------- ``onecite process INPUT --ndjson`` emits newline-delimited JSON events: - ``summary``: one event containing status, summary, and options. - ``result``: one event per formatted BibTeX result. - ``failure``: one event per unresolved entry. This mode is intended for streaming automation workflows that want partial results without parsing human text. Hard processing errors in ``--ndjson`` mode emit a ``summary`` event with ``status: "failed"`` followed by one ``failure`` event, then exit with code ``1``. Benchmark JSON -------------- ``onecite benchmark --json`` emits a deterministic regression report for the configured benchmark suite: - ``schema_version``: currently ``"1.0"``. - ``suite`` and ``suite_version``. - ``source_mode``: ``"offline"`` by default, ``"live"`` with ``--live``. - ``status`` and ``summary``. - ``cases`` with per-case status, failures, and observed counts. The default offline mode uses bundled fixtures and patches OneCite's HTTP source calls, so the deterministic benchmark does not require network access. Passing ``--live`` removes that isolation and should be reserved for explicit upstream-source spot checks. The default command exits ``0`` only when every bundled case passes. Custom suites can lower the gate with ``--min-success-rate``. Reports should include the suite name, suite version, source mode, total case count, and pass counts so the result is not mistaken for a general citation-accuracy score. Passing the bundled suite means the covered cases passed. The displayed ``success_rate`` is rounded to four decimals for readability; the exit gate uses the unrounded ``passed / total_cases`` ratio, so a displayed ``0.6667`` does not satisfy ``--min-success-rate 0.6667`` when the actual ratio is ``2/3``. Doctor JSON ----------- ``onecite doctor --json`` emits an installation-health report: - ``schema_version``: currently ``"1.0"``. - ``tool`` and ``command``: ``"onecite"`` and ``"doctor"``. - ``status``: ``"passed"`` only when every check passed. - ``environment``: Python executable, Python version, platform, and package version. - ``summary``: total, passed, and failed check counts. - ``checks``: package version, templates, benchmark resources, skill package, and offline benchmark gate. The current doctor top-level contract is exactly ``schema_version``, ``tool``, ``command``, ``status``, ``environment``, ``summary``, and ``checks``. Each check contains ``name``, ``status``, ``message``, and ``details``. Exit Codes ---------- - ``0``: command completed and its quality gate passed. - ``1``: command failed, benchmark/doctor gate failed, or processing raised an error. - ``2``: ``onecite process --fail-on-unresolved`` found unresolved entries. Stdout and Stderr ----------------- Machine-readable JSON and NDJSON are written to stdout. Interactive prompts and saved-file status messages are routed to stderr in those modes so stdout stays parseable.