summarize-v1) into actual prompt content your harness can use. It works through four levels in strict priority order — the first level to find a match wins.
The ResolverChain class
The resolution chain is implemented in promptops/resolver/chain.py:
override for a prompt ID, it goes straight to LocalResolver. Otherwise it tries WorkspaceResolver first (no manifest entry needed), then falls back to GitRefResolver or PackagedResolver based on the pin format.
Level 1 — Local override
LocalResolver reads a prompt from a local file path. This is the highest-priority level and is always checked first when an override is present in the consumption manifest.
When to use: local development against a separate prompt repo without publishing.
Configure in consumption.yaml:
.yaml, .yml, and .json files. It caches results by mtime to avoid re-reading unchanged files.
If the override path does not exist, LocalResolver raises FileNotFoundError. This prevents silent fallthrough to a stale pinned version when the override file is missing.
Level 2 — Workspace
WorkspaceResolver finds prompts in the local promptops/ directory — no manifest entry needed. This is how same-repo prompts work without any publishing step.
Paths tried (in order):
WorkspaceResolver also checks the shorter prompts/ and evals/ paths (without the promptops/ prefix). This is auto-detected by counting files matching promptops/prompts/*.yaml and similar globs.
Quick eval resolution: when the resolver finds a file in evals/, it checks for a prompt field. If present, it returns a synthetic prompt spec:
WorkspaceResolver.resolve() returns None, the chain continues to level 3 or 4.
Level 3 — Git ref
GitRefResolver retrieves prompt content from a specific git commit, tag, or semver range. This is the default pinning mechanism for separate prompt repos — zero publishing overhead.
Paths tried inside the git tree (in order):
Pin formats for git ref
Configure in
consumption.yaml:
GitRefResolver runs git tag --list (or git ls-remote --tags for remote repos) and finds all tags that satisfy the semver range using its own match_semver() implementation. It selects the highest matching stable version. Prerelease versions (e.g., v1.2.3-rc1) are excluded unless the range explicitly selects them.
Fallback for git archive: if the remote server disables git archive, the resolver falls back to a full git clone + git checkout in a temporary directory and reads the file from there.
All results are cached in memory by (prompt_id, pin) key.
Level 4 — Packaged artifact
PackagedResolver retrieves prompts from published artifacts — GitHub Releases, OCI registries, npm packages, or PyPI wheels. This level is triggered when the pin starts with a packaged-artifact prefix.
Pin formats for packaged artifacts
Configure in
consumption.yaml:
- If the pin is a
sha256:digest,PackagedResolverfetches the artifact, validates it againstprompt-package.schema.json, and finds the prompt spec with the matchingidinside the package’sspecsarray. - For all other URL/registry formats, the resolver fetches the artifact, validates it against
provider-artifact.schema.json, verifies the optional signature, then reads thepackage_digestfield and callsresolve()recursively with that digest (treating it as a level-4 sha256 lookup).
~/.promptops/cache/ using a URL-safe filename derived from the ref. If a network fetch fails but a cached copy exists, the resolver uses the cache. If no cache is available, it raises RuntimeError.
How the consumption manifest drives resolution
The consumption manifest (promptops/manifests/consumption.yaml) is the single config file that controls how the resolver behaves for your app.
ResolverChain.resolve(prompt_id, manifest) call:
- Validates the manifest against
consumption-manifest.schema.json. - Looks up the resolution rules for
prompt_id(override,pin,idmapping). - Applies the four-level chain based on those rules.
Pin format decision guide
- Development
- Same-repo
- Pinned to commit
- Pinned to tag
- Semver range
- Governed release
Use a local override when you are iterating on a prompt in a checked-out repo and don’t want to publish or commit.