Skip to content

Offline media task commands

openmed multimodal process-document, openmed multimodal transcribe and openmed multimodal draft adapt a trusted injected local session service. They do not install a provider. There is no default model, download, microphone capture, cloud fallback, automatic clinical finalization or record submission. This Python CLI slice owns command adapters; it does not replace the Python or OpenMedKit ambient session policy, preflight, ASR or note-evidence implementations.

Explicit invocation

openmed multimodal process-document ./document.pdf \
  --model-artifact ./installed-model \
  --session-factory my_application.media:create_service \
  --confirm-review --output-directory ./private-results --json

openmed multimodal transcribe ./audio.wav \
  --model-artifact ./installed-asr \
  --session-factory my_application.media:create_service \
  --consent-evidence ./consent-receipt.json \
  --confirm-review --output-directory ./private-transcript --json

openmed multimodal draft ./finalized-transcript.json \
  --model-artifact ./installed-note-model \
  --session-factory my_application.media:create_service \
  --consent-evidence ./consent-receipt.json \
  --confirm-review --output-directory ./private-draft --json

Media, consent and model artifacts must already exist locally. Source/consent files must be nonempty regular files, not symlinks or devices. A model artifact may be a file or directory, not a symlink. Input reads are bounded to 64 MiB; consent to 64 KiB; protected provider JSON to 8 MiB. The provider validates actual media, installed model contents and the semantic validity/currentness of consent. Presence of a receipt is not proof of valid consent. Transcribe and draft refuse a missing receipt before opening a service; a document service can also require consent. The service must refuse invalid, withdrawn or stale consent.

--confirm-review explicitly authorizes production of a protected draft. Both outputs retain a non-diagnostic notice and requires_clinical_review: true. Confirmation does not declare a clinical record finalized or submit it anywhere.

Injection and library boundary

openmed.cli.multimodal_inference exposes the narrow, command-owned LocalSessionService, LocalSession, LocalSessionRequest and LocalSessionResult protocols/data carriers. A factory is an installed module:function returning a service. Embedding applications can instead pass service= to handle_multimodal_inference.

The service declares local_only=True and supported LocalTask values. It opens one request with bounded media bytes, the selected artifact, opaque consent bytes and reviewer confirmation. run() returns a complete protected JSON object and an existing ProviderResultEnvelope, or a controlled SessionRefusal. The CLI revalidates the envelope and checks its input and output SHA-256 bindings. It never fills in citations, confidence, provider evidence or inferred statements. Source offsets/citations in protected results remain exactly service-owned.

The application adapter is responsible for using its library's PHI policy, media validation, finalized evidence, consent, provenance and retention rules. It must not capture, download, contact a network, write a clinical record or log source values. cancel() invalidates pending work; close() verifies cleanup and destroys service-owned retained data. Both are idempotent. If opening fails, the service must clean its own allocations because no session was returned. A successful close() is required before output creation. Python buffers are released normally; this CLI does not claim secure memory erasure, swap/crash-dump protection or clinical/provider qualification.

Factories execute trusted installed code. Python stdout/stderr from their calls are discarded defensively; native writes, preconfigured logging handlers and hostile plugins are not sandboxed. Factories must meet the no-raw-PHI logging contract themselves. Diagnostics never reflect exception messages or private paths. No inference or capture contract is duplicated by this adapter.

Output permissions and completion

On macOS and Linux/POSIX, the command exclusively creates a new user-selected output directory with mode 0700. Inside it, result.json, evidence.json and COMPLETE are exclusively created with mode 0600 (subject to a stricter umask). Use a trusted local parent directory; filesystem ACLs, backups and disk encryption remain host responsibilities. Existing directories, destination symlinks and existing files are never overwritten. There are no plaintext temporary files, caches or implicit retained artifacts outside the selected destination.

result.json contains protected service results, bound notices and review flags. evidence.json contains the value-free provider envelope, task/review flags and the SHA-256 digest of the exact protected file. JSON stdout contains that evidence only; plain stdout contains the non-diagnostic notice. It never prints source media, transcripts, drafts, filenames, consent values or credential text.

COMPLETE is written only after both output files have been flushed/fsynced and service cleanup has succeeded. Consumers must require successful exit and the marker, and verify result_file_digest; files alone do not prove completion. Writes to two files are not an atomic transaction. On errors, Ctrl-C/SIGINT or SIGTERM, owned outputs are removed and no pair is finalized. A cleanup failure is a refusal, never success. SIGKILL, power loss, filesystem removal failures and hostile in-process code cannot guarantee cleanup: an incomplete directory may remain in the explicitly selected protected destination and needs manual removal. The command never resumes such a directory. Embedded worker threads use service cancellation; signal handling is installed/restored only in the main thread.

Windows refuses with unsupported_permissions before any service is opened or output created: POSIX modes do not enforce Windows ACL privacy. Windows output support requires a separate reviewed ACL implementation; it is not simulated here. Tests exercise native POSIX permissions and a controlled Windows refusal.

Error codes

Failures use the standard CLI error envelope with controlled messages.

Code Exit Meaning
invalid_arguments 2 Invalid command syntax, without echoing argument values
provider_unavailable 1 No factory, unsupported task or unavailable provider
offline_required 1 Service does not declare local-only execution
consent_required 2 Missing or rejected consent evidence
review_required 2 Explicit reviewer confirmation missing
malformed_media 2 Empty input or provider-declared malformed media
resource_limit 2 Bounded read or provider limit exceeded
invalid_artifact 2 Missing/unreadable/symlink/special-file local input
invalid_result 1 Incomplete, malformed or unbound provider result
session_refused 1 Other provider abstention/validation failure
session_failed 1 Unexpected service failure or unrecognized refusal
output_failed 1 Destination exists or output cannot be created/written
cleanup_failed 1 Service destruction or owned-output removal failed
unsupported_permissions 1 Protected output permissions unavailable
cancelled 130 SIGINT/SIGTERM or service cancellation

Synthetic offline example

From a repository checkout, create explicit synthetic inputs (not model weights):

mkdir -m 700 synthetic-cli
printf 'synthetic media\n' > synthetic-cli/media.txt
printf 'synthetic consent\n' > synthetic-cli/consent.txt
printf 'synthetic placeholder\n' > synthetic-cli/artifact.txt
.venv/bin/python -c 'from openmed.cli import main; raise SystemExit(main())' \
  multimodal draft synthetic-cli/media.txt \
  --model-artifact synthetic-cli/artifact.txt \
  --consent-evidence synthetic-cli/consent.txt \
  --session-factory examples.multimodal.offline_cli:create_service \
  --confirm-review --output-directory synthetic-cli/results --json

The fake factory accepts only the exact synthetic bytes above and returns Synthetic draft only with synthetic offsets in the protected file. It runs no model or media decoder and makes no clinical-validation or benchmark claim. Unit and subprocess integration tests cover all three commands, success, unavailability, missing/rejected consent, malformed media, refusals, digest mismatch, permission modes, cancellation and cleanup failures.