Implements the v1 direction decided in the RFC as a set of `x` subcommands
plus a small, contained compiler change.
* URL-as-identity, no registry — a dependency is named by its git import
path and a `git tag vX.Y.Z` publishes a version.
* Minimum Version Selection — a `require` is a minimum; the resolver picks
the greatest required minimum per module, then the reachable closure at
those versions. Deterministic, no SAT solver (tools/x/pkg.ludic).
* Content-addressed global store + per-project links — packages live once in
~/.ludic/store keyed by a content hash; each project links them under
ludic_modules/. package.ludic (manifest) + package.lock.ludic (lock).
* Namespace registration for source packages via a module-root import
fallback in the compiler: do_import resolves a non-local, non-absolute
import under $LUDIC_MODULES (default ludic_modules/), so a fetched
package's Ludic compiles into the consumer the way the built-in stdlib
does. Collisions and missing prebuilt targets are hard errors.
Commands: x add / x get / x update / x verify / x vendor. New hermetic suite
`x test-pkg` (stands up throwaway git repos, offline) is gated inside `x test`.
Existing programs compile byte-for-byte identically (the import fallback only
fires when the local path is absent); the C-free bootstrap fixpoint holds and
the seed is regenerated. Full suite: 87 passed, package suite: 12 passed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1.2 KiB
bump: minor
type: feat
Package manager (#63) — x add / x get / x update / x verify / x vendor bring third-party packages to Ludic with no new infrastructure. Dependencies are named by their git import path (URL-as-identity, no registry — a git tag vX.Y.Z is publishing), resolved by Go-style Minimum Version Selection, fetched into a content-addressed global store (~/.ludic/store, keyed by a file-content hash) and linked into each project under ludic_modules/. A package.ludic manifest declares dependencies, the provided Foo.* namespace(s), the kind (source or prebuilt) and, for prebuilt libs, the shipped targets; package.lock.ludic pins the resolved versions and content hashes for reproducible, verifiable builds. A source package's Ludic compiles into the consumer via a new module-root import fallback in the compiler (import "git.workshopsoft.io/user/pkg/foo.ludic" resolves against $LUDIC_MODULES, default ludic_modules/), so a package registers a namespace the same way the built-in stdlib does. Namespace collisions and missing prebuilt targets are hard errors. Existing programs compile byte-for-byte identically; the C-free bootstrap fixpoint is untouched. See docs/PACKAGES.md.