# EX Script — Package Ecosystem

## Design goals

- Deterministic resolution: the same manifest installs the same code, forever.
- Fast install: only what changed, no `node_modules` archaeology.
- Simple publishing: one command, one artifact.
- Workspaces that actually work: monorepos without project references.
- Type information ships with the package — no `@types` parallel universe.

## The manifest: `project.xan`

```
name = "my-project"
version = "0.1.0"
entry = "src/main.xan"
deps = [
    "web-framework@0.5",
    "cli-parser@^2.1",
    "local:../shared-utils",          # local path dependency
]
workspaces = ["packages/*"]
```

- `deps` are `name@range` (semver ranges), local paths, or `git+https://...`.
- The package name is the import prefix: `from pkg:web-framework import router`.
- Workspaces list globs of local packages; workspace members may depend on each
  other by name and resolve locally without publishing.

## Resolution and the lockfile: `ex.lock`

```
[my-project]
deps = { web-framework = { version = "0.5.2", integrity = "sha256:..." } }
```

- `ex install` resolves the manifest against the registry index, records exact
  versions + content hashes in `ex.lock`, and installs to `deps/`.
- `ex install` with an existing lockfile reinstalls exactly the locked versions
  (no registry queries needed).
- Integrity hashes are verified on every install; a changed hash is an error
  with the fix ("update the lockfile: `ex install --update`").
- `ex audit` (planned) checks installed versions against a vulnerability index
  and the lockfile's advisory data.

## Install layout

```
project/
├── project.xan
├── ex.lock
├── deps/                  # installed packages (gitignored)
│   └── web-framework/     # source + compiled artifacts + type table
└── src/
```

`deps/` is a flat, content-addressed-adjacent tree keyed by resolved version:
`deps/web-framework@0.5.2/`. The compiler resolves `pkg:web-framework` to that
directory, reads the package's `type-table.json` for checking (fast, no
re-parse), and links its compiled JS for bundling.

## What a package publishes

The registry stores one artifact per version:

```
web-framework-0.5.2.xanpkg     # tar.gz:
├── src/                      # EX sources (for source links and debugging)
├── type-table.json           # checked public API (types, signatures, schemas)
├── dist/main.js              # compiled bundle (pre-checked)
└── project.xan                # manifest (name, version, deps)
```

- Consumers never parse the package's sources: the type table is authoritative
  and compact (a schema is a few hundred bytes, not megabytes of `.d.ts`).
- Integrity is the content hash of the artifact, recorded in the lockfile.

## Publishing

```
ex publish                   # tag + upload + record in registry index
```

- Version bumps are explicit (`ex bump major|minor|patch`), with the lockfile
  ensuring consumers see exactly what was tested.
- Pre-release tags (`0.5.2-rc.1`) are allowed; `ex add` defaults to stable
  releases.
- A package may be private (`private = true` in manifest): never publishable,
  installable only by path or workspace.

## The registry

The reference registry is a static index (a signed JSON file listing
name → versions → integrity + tarball URL). It is deliberately boring: no
accounts, no auth, no build scripts executed at install time (a security
feature — installed packages never run code during install).

The prototype in this repo implements: manifest parsing, semver range
resolution against a local index or git URLs, lockfile creation/verification,
local path deps, and workspace resolution. The public registry and `ex
publish` are planned for beta.

## Dependency audits

`ex audit` (planned) checks: integrity, known vulnerabilities (advisory index),
license metadata, and dependency count with a size report. `ex tree` prints the
dependency graph with versions and sizes.

## Version compatibility

Packages compile against the toolchain version recorded in their type table;
if a consumer's toolchain differs incompatibly, the error says exactly that,
with the fix (`ex upgrade` or pin). No more "Cannot find module or its
corresponding type declarations."