The git-native dependency model: use statements name explicit host/owner/repo/path (first segment must contain a dot), with std/ expanding to github.com/openprose/prose/packages/std/ and co/ to the co/ sibling, bare owner/repo reserved for the future p.prose.md registry, and .prose.md extension inference plus as aliasing. It specifies the runtime disk-only resolution algorithm against deps/{host}/{owner}/{repo}/, the prose install multi-pass scan of use, Services, and pattern references with transitive closure, cycle errors, and newer-SHA conflict auto-resolution with warnings, the prose install --update bump flow, the plaintext prose.lock format (host/owner/repo plus SHA, committed), the gitignored deps/ cache layout with host in the path, private-repo credential reuse, and the no-network no-auto-install runtime behavior with Forme and VM interaction tables. Authors and tooling engineers read this when adding use references or pattern refs, running prose install, or debugging missing-dependency errors.
role: dependency-resolution
summary: |
How OpenProse resolves git-native dependencies from use statements,
service references, and pattern references. Defines the resolution
algorithm, the prose install command, the lockfile format, and the <openprose-root>/deps/
directory structure.
see-also:
- prose.md: VM execution semantics (loads resolved deps at runtime)
- forme.md: Wiring semantics (resolves services and systems from
/deps/) - SKILL.md: Command routing for
prose install
Dependency Resolution
OpenProse uses a git-native dependency model. use statements, dependency-like
service names, and pattern: references can point at any explicit git host.
Dependencies are cloned into <openprose-root>/deps/, pinned in <openprose-root>/prose.lock, and resolved from
disk at runtime.
use Statement Parsing
A use statement names an explicit git host, owner, repo, and path. The
canonical form is host/owner/repo/path:
use "github.com/openprose/prose/packages/std/evals/inspector"
Parsed as:
| Field | Value |
|---|---|
| Host | github.com |
| Owner | openprose |
| Repo | prose |
| Path | packages/std/evals/inspector |
| Clone URL | host-specific URL for github.com/openprose/prose |
| Local clone | <openprose-root>/deps/github.com/openprose/prose/ |
| Resolved file | <openprose-root>/deps/github.com/openprose/prose/packages/std/evals/inspector.prose.md |
The first path segment is the host (must contain a dot — github.com,
gitlab.com, codeberg.org, git.company.com). The next two segments are
always owner/repo. Everything after is a path within the cloned
repository.
Any git host works. Nothing in the resolver privileges GitHub — it's the common case, not a default.
std/ and co/ Shorthands
The OpenProse monorepo hosts two packages. Both get shorthands:
std/→github.com/openprose/prose/packages/std/co/→github.com/openprose/prose/packages/co/
use "std/evals/inspector"
# equivalent to:
use "github.com/openprose/prose/packages/std/evals/inspector"
use "co/systems/company-repo-checker"
# equivalent to:
use "github.com/openprose/prose/packages/co/systems/company-repo-checker"
Both shorthands resolve into the same clone of openprose/prose under
<openprose-root>/deps/github.com/openprose/prose/; packages/std/ and packages/co/ are
sibling subdirectories inside that clone.
Bare owner/repo Form
Identifiers without a host prefix (e.g. use "alice/research") are reserved
for the OpenProse registry — eventually hosted at p.prose.md. That
registry isn't open for publication yet, so the bare form doesn't resolve
today. Write the host explicitly (github.com/alice/research) or use the
std/ shorthand. When the registry opens, the bare form gains a defined
resolution without breaking systems that wrote explicit hosts.
File Extension Resolution
If the use path includes an explicit .prose.md extension, use it. If no extension, prefer .prose.md:
use "github.com/alice/tools/formatter"
# resolves to: <openprose-root>/deps/github.com/alice/tools/formatter.prose.md
Aliasing
use statements support as aliases in execution blocks:
use "github.com/alice/research-pipeline" as research
let result = call research
topic: "quantum computing"
In ### Services, use the full path — aliases are for execution blocks only.
Resolution Algorithm (Runtime)
When the VM or Forme encounters a use path at runtime:
- Expand
std/andco/shorthands togithub.com/openprose/prose/packages/{std|co}/if applicable - Parse
{host}/{owner}/{repo}from the first three segments - Check
<openprose-root>/deps/{host}/{owner}/{repo}/exists on disk - If not found, error immediately (see Error Handling below)
- Resolve the remaining path segments within the cloned repo
- Return the absolute file path
No network calls during resolution. All dependencies must be pre-installed via prose install. The VM reads from <openprose-root>/deps/ on disk only.
prose install
Scans the project for dependency references and clones missing dependencies.
Algorithm
- Scan all
*.prose.mdfiles under<openprose-root>/src/for:use "host/owner/repo/path"statements- service names in
### Servicesthat start withstd/,co/, orhost/owner/repo/ pattern:references that start withstd/,co/, orhost/owner/repo/
- Expand
std/andco/shorthands togithub.com/openprose/prose/packages/{std|co}/ - Parse each expanded dependency path to extract
{host, owner, repo}triples (the first segment is the host if it contains a dot) - For each unique
{host, owner, repo}: a. If<openprose-root>/deps/{host}/{owner}/{repo}/does not exist, clone the repository using the host's normal git URL into<openprose-root>/deps/{host}/{owner}/{repo}/b. If<openprose-root>/prose.lockhas a pinned SHA for this repo, checkout:git checkout {sha}c. If no pinned SHA exists (new dependency), use HEAD and record the SHA - Scan transitive dependencies — scan all
*.prose.mdfiles within newly cloned repos in<openprose-root>/deps/for their ownusestatements - Cycle detection — if a newly discovered dependency is already in the resolved set, skip it. If scanning reveals a cycle (A requires B requires A), error:
[Error] Circular dependency detected: A → B → A - Repeat from step 2 with any newly discovered dependencies until no new deps are found
- Write
<openprose-root>/prose.lockwith all resolved{host, owner, repo, sha}entries (direct and transitive, flat list)
Transitive Resolution (Multi-Pass)
Dependencies can themselves have dependencies. prose install resolves transitively:
Pass 1: Scan project files → find direct deps → clone them
Pass 2: Scan <openprose-root>/deps/ for new use statements → find transitive deps → clone them
Pass 3: Scan newly cloned transitive deps → find more → clone
...repeat until stable (no new deps discovered)
If a cycle is detected at any pass, prose install errors immediately and lists the cycle path. Cycles indicate a design problem in the dependency graph — they cannot be auto-resolved.
All dependencies — direct and transitive — are pinned in the flat <openprose-root>/prose.lock.
Version Conflict Resolution
If two dependencies require the same repo at different commits, prose install auto-resolves to the newer SHA (by commit date) and emits a warning:
This is a convenience policy, not proof that the newer dependency fits every
caller. Treat the warning as review-required: inspect the affected dependency,
run relevant tests, and commit the resulting <openprose-root>/prose.lock only when the newer
version is acceptable.
[Warning] Version conflict for alice/utils:
Required by: your-project (a1b2c3d)
Required by: bob/toolkit (f6e5d4c)
Resolved to: f6e5d4c (newer, 2026-04-01)
Override: manually edit <openprose-root>/prose.lock if needed
This is not an error. The user can override by editing <openprose-root>/prose.lock directly.
Private Repositories
prose install uses the user's existing git credential helpers transparently. SSH keys, gh auth, .netrc — whatever git is configured to use for github.com works for prose install.
prose install --update
Bumps all pinned SHAs to the latest HEAD of their default branch.
Algorithm
- For each
host/owner/repoin<openprose-root>/prose.lock: a. Rungit fetchin<openprose-root>/deps/{host}/{owner}/{repo}/b. Get the latest HEAD SHA c. Rungit checkout {new-sha} - Re-scan for transitive dependencies (new versions may add or remove
usestatements) - Rewrite
<openprose-root>/prose.lockwith updated SHAs
<openprose-root>/prose.lock Format
Plaintext. One line per dependency. Format: host/owner/repo sha.
# <openprose-root>/prose.lock — pinned dependency versions
# Do not edit unless you know what you're doing
github.com/openprose/prose a1b2c3d4e5f6
github.com/alice/research f6e5d4c3b2a1
gitlab.com/bob/utils 9c8d7e6f5a4b
Rules:
- One dependency per line
- Format:
{host}/{owner}/{repo} {sha}(space-separated) - Comments start with
# - Direct and transitive dependencies listed flat — no nesting, no hierarchy markers
- Host is explicit — no default is assumed, so any git provider works uniformly
- Order does not matter (but
prose installwrites them sorted alphabetically)
<openprose-root>/prose.lock is committed to git. It ensures reproducible builds — anyone cloning the project gets the same dependency versions.
<openprose-root>/deps/ Directory Structure
<openprose-root>/deps/
├── github.com/
│ ├── openprose/
│ │ └── prose/ # Full clone of github.com/openprose/prose
│ │ ├── packages/
│ │ │ ├── std/ # Standard library (resolved by `std/` shorthand)
│ │ │ │ ├── evals/
│ │ │ │ │ ├── inspector.prose.md
│ │ │ │ │ ├── contract-grader.prose.md
│ │ │ │ │ └── regression-tracker.prose.md
│ │ │ │ └── memory/
│ │ │ │ ├── user-memory.prose.md
│ │ │ │ └── project-memory.prose.md
│ │ │ └── co/ # Company-as-prose (resolved by `co/` shorthand)
│ │ │ └── systems/
│ │ │ └── company-repo-checker/
│ │ │ └── index.prose.md
│ │ └── ...
│ ├── alice/
│ │ └── research-pipeline/ # Full clone of github.com/alice/research-pipeline
│ │ └── ...
│ └── bob/
│ └── toolkit/ # Transitive dep, also a full clone
│ └── ...
└── gitlab.com/
└── team/
└── repo/ # Any git host works; host is part of the path
<openprose-root>/deps/ MUST be in .gitignore. It is a cache, fully reproducible from <openprose-root>/prose.lock via prose install.
Each entry under <openprose-root>/deps/ is a full git clone (or shallow clone) of the
corresponding repository, checked out to the SHA pinned in <openprose-root>/prose.lock. The
host is part of the cache key so repos with the same owner/repo name on
different hosts do not collide.
Runtime Behavior
At execution time, the VM and Forme resolve use paths by reading from <openprose-root>/deps/ on disk.
- No git operations during execution
- No network calls during execution
- No auto-install —
prose rundoes not runprose installimplicitly
If a dependency is missing or <openprose-root>/deps/ does not exist:
[Error] Dependency not found: github.com/openprose/prose
Run `prose install` to install dependencies.
If <openprose-root>/prose.lock exists but <openprose-root>/deps/ is missing or incomplete, the same error applies. The user must run prose install.
Interaction with Forme
When Forme resolves a service listed in ### Services, it checks <openprose-root>/deps/ as part of its resolution order (see forme.md, Step 2):
- Same directory as the system file:
./researcher.prose.md - A subdirectory matching the name:
./researcher/index.prose.md <openprose-root>/deps/directory: first<openprose-root>/deps/{host}/{owner}/{repo}/{path}.prose.md, then<openprose-root>/deps/{host}/{owner}/{repo}/{path}/index.prose.md- Bare
owner/repoidentifiers: reserved for the OpenProse registry (future home atp.prose.md); inert today
A service or system reference like std/evals/inspector in ### Services resolves to <openprose-root>/deps/github.com/openprose/prose/packages/std/evals/inspector.prose.md after std/ shorthand expansion.
A directory-root system reference like co/systems/company-repo-checker resolves to <openprose-root>/deps/github.com/openprose/prose/packages/co/systems/company-repo-checker/index.prose.md.
Interaction with the VM
When the VM encounters a use statement during execution:
- Expand shorthand (
std/→github.com/openprose/prose/packages/std/;co/→github.com/openprose/prose/packages/co/) - Parse
{host}/{owner}/{repo}and remaining path - Read the service or system from
<openprose-root>/deps/{host}/{owner}/{repo}/{path}.prose.md, or from<openprose-root>/deps/{host}/{owner}/{repo}/{path}/index.prose.mdwhen the dependency is a directory-root system - Parse the imported service or system contract (
### Requires/### Ensures) - Register the import (with alias if
aswas used)
Runtime resolution is disk-only. If a use path is missing from <openprose-root>/deps/, the
VM errors and tells the caller to run prose install.
Interaction with p.prose.md
p.prose.md is reserved as the future home of the OpenProse registry.
Publication there isn't open yet — no identifier actually resolves via
p.prose.md today. When it opens, the bare owner/repo form gains a
defined resolution and p.prose.md takes on a discovery role (search,
docs, install counts, eval scores, and supported runtimes).
| Use case | Resolution |
|---|---|
use "github.com/owner/repo/path" in a system |
<openprose-root>/deps/github.com/owner/repo/; error if missing |
use "std/..." or use "co/..." in a system |
Expands to github.com/openprose/prose/packages/{std|co}/... then resolves as above |
prose run github.com/owner/repo/path at the CLI |
Same algorithm as use |
prose run github.com/owner/repo/path@{version} |
That specific pinned version in <openprose-root>/deps/; error if missing |
prose run ... --offline |
<openprose-root>/deps/ only; error on miss |
use "alice/research" / prose run alice/research |
Reserved for the OpenProse registry; inert today |
| Browsing/searching for systems | Not yet available; p.prose.md will host this |
use and prose run share one resolution algorithm. prose install is the
explicit "get me every declared dependency at its pinned SHA" command. Neither
use nor prose run auto-fetches a missing dependency during execution.
Summary
| Concept | Detail |
|---|---|
| Package identity | Any git host, named explicitly (github.com/..., gitlab.com/...); bare owner/repo reserved for future p.prose.md |
| Install command | prose install (explicit, not auto) |
| Update command | prose install --update |
| Lockfile | <openprose-root>/prose.lock (plaintext, committed) |
| Cache directory | <openprose-root>/deps/{host}/{owner}/{repo}/ (gitignored) |
| Shorthands | std/ → github.com/openprose/prose/packages/std/; co/ → github.com/openprose/prose/packages/co/ |
| Clone strategy | Full clone (supports SHA checkout without refetch) |
| Transitive deps | Multi-pass scan until stable (errors on cycles) |
| Version conflicts | Auto-resolve to newer SHA with warning |
| Runtime resolution | Disk only, no network |
| Private repos | Uses existing git credentials |