id: eofm_embed
name: Foundation Model Embedding
description: >
  Generate embeddings from an EO foundation model encoder.
  Outputs a multi-band raster (one band per embedding dimension)
  or GeoParquet with embedding vectors per chip.

  Supports Prithvi-EO-2.0, OLMo Earth, Clay, and other models
  registered in registry/models/. Preprocessing (band selection,
  normalization, chipping) is driven by the model profile.
version: 1.0.0
category: inference
type: raster-to-raster
default_implementation: native

inputs:
  - name: imagery
    type: raster
    format: [cog, tif]
    description: Input satellite imagery (must contain bands expected by model)
    required: true

# Parametric on `params.model:` — the actual band requirement is declared by
# the model record in registry/models/<model>.yaml (Prithvi expects
# [blue, green, red, nir, swir1, swir2]; Clay has its own list). Resolver
# must read the model record at plan time, not the op YAML.
requires: {}

outputs:
  - name: embeddings
    type: raster
    format: cog
    dtype: float32
    # No concept slug — `embedding` is not in registry/concepts/. Embeddings
    # are an abstract feature space, not a named geophysical phenomenon.
    # Follow-up: decide whether to mint an `embedding` concept (see ticket
    # recipe-library-operations-page/02-op-yaml-migration.md open questions).
    description: Multi-band raster (D bands, one per embedding dimension)

params:
  model:
    type: string
    default: prithvi-eo-2.0-300m
    description: Foundation model name from registry/models/
  device:
    type: select
    options: [auto, cpu, cuda]
    default: auto
    description: Compute device (auto selects CUDA if available)
  batch_size:
    type: integer
    default: 16
    description: Number of chips to process per inference batch
  overlap:
    type: integer
    default: 32
    description: Overlap in pixels between adjacent chips
  output_format:
    type: select
    options: [auto, cog, geoparquet, zarr]
    default: auto
    description: >
      Output format for embeddings. "auto" selects GeoParquet for
      chip-level embeddings (CLS token) and COG for pixel-level
      (dense spatial). Per Cloud Native Geo best practices.
  quantize:
    type: select
    options: [none, int8]
    default: none
    description: >
      Quantize embeddings to reduce storage. int8 gives 4x reduction
      with no downstream performance loss (per AlphaEarth findings).

execution:
  realtime_max_km2: 10
  cost_per_km2: 0.05
  time_per_km2_sec: 30
  memory_profile: high

cache_policy:
  ttl_days: 365
  invalidate_on: [model_update, source_update]

# backends: audited 2026-08-14 (defect 50). A key means a runtime that DISPATCHES this op —
# folia-engine `dispatch_op` (products/sdk/folia-engine/src/lib.rs), a `registerOp`/OP_TABLE
# entry in packages/compute, `_BUILTIN_OP_MAP` in folia/compute.py, or a backend manifest
# (folia/backends/*/backend.yaml).
backends:
  js:
    function: eofm_embed
    dispatch: packages/compute/src/ops/eofm-embed.ts
  python:
    function: ml.eofm.embed
    dispatch: folia/compute.py _BUILTIN_OP_MAP
