commit 2ae1c051cf
Author: Jarvis <jarvis@brendoncarroll.net>
Date: Wed Sep 2 20:47:02 2026 +0000
sys: carry stdio file handles on the Port type, interned via add_port
Remove the stdio_in/stdio_out/stdio_err singleton fields (and setStdio)
from System. They let the mvm executor read/write the host's real fds
through a wire that bypassed the port-token capability system. stdin/
stdout/stderr are now variant payloads of Port, so the file they name is
interned with the token via add_port and resolved back through get_port,
like every other host resource.
assembleCtx, execTerminal, and the stdio tests now intern the ports with
the real (or, in tests, temp-file) handles. Fixes a pre-existing test bug
that interned the stdout port with the stdin tag.
commit 0fb7771995
Author: Jarvis <jarvis@brendoncarroll.net>
Date: Wed Sep 2 17:17:33 2026 +0000
spore/mvm: rename valueof/LOAD_ANY to unwrapAnyValue/ANYVALUE_UNWRAP
Rename the LOAD_ANY opcode to ANYVALUE_UNWRAP and the #valueof spore
primitive to #unwrapAnyValue. The primitive now takes a compile-time type
T in addition to the AnyValue: ANYVALUE_UNWRAP(av, ty) checks that the
descriptor the AnyValue carries matches T and panics on mismatch,
otherwise yields the value typed by T. This makes the context-port deref
type-checked instead of blindly assuming a Port.
build.spawn/ctxPort and linux.stdinAttach/stdinConnect/stdoutPort/
stderrPort now pass (Port Empty Empty) as the unwrap target.
commit f41b8f3045
Author: Jarvis <jarvis@brendoncarroll.net>
Date: Wed Sep 2 16:52:24 2026 +0000
wire build-context stdin/stdout/stderr ports into spawned container stdio
Port deref. A build-context namespace entry is an AnyValue wrapping a
myc.Port(void,void) token (assembleCtx does AnyValue.init(Port, ...)). The
spore expression that recovers the raw 256-bit token is a new `valueof`
primitive: it lowers to a new mycelium LOAD_ANY opcode that loads the
AnyValue cell's ref, typed by the descriptor the AnyValue carries, yielding a
concrete (Port Empty Empty). valueof works both as interact's port argument
and as an Input/Output sum-case payload. Focused spore tests prove the token
round-trips through interact and through a Sum literal.
mvm stdio. interactFn now dispatches the stdin/stdout/stderr ports instead of
error.UnsupportedPort: stdout/stderr write the interact value's bytes to the
host's fds 1/2 (returning Unit), and stdin reads a chunk from fd 0 and returns
it as a String. A System.setStdio override lets the executor's stdio ports be
redirected to files so the round-trip is tested without touching the host
terminal. build.spawn uses valueof to deref the sys port, and stdinAttach/
stdinConnect/stdoutPort/stderrPort build an Input/Output triple from the
context's ports, so a build CSpec can wire a container's stdio to the host.
bash.sp. Rewrites build/bash.sp (the `want run build/bash.sp` target) against
the current linux.CSpec API: it pulls a pinned Debian image, unpacks its
rootfs via umoci, and runs /usr/bin/bash with the rootfs mounted at /, stdin
attached and stdout/stderr ported to the context. It type-checks against the
embedded stdlib (tested), and the linux executor's existing cspawn .attach/
.port lowering then maps those ports to host fds 0/1/2.
Fixes surfaced by running `want run`. FSStore.get asserted on zero-length read
buffers (empty descriptor blobs like Bit's), panicking any mvm.apply against
the on-disk store; it now returns 0 for an empty request. 3+-argument calls to
imported procs (docker.imageURL, build.fileAt, build.spawn) previously left
the concat-built input nested so the callee's flat FIELD bindings faulted; the
compiler now crafts the flat product from the compiled argument types when the
callee's parameter table is not in this file. String concat (`(concat "a" "b")`)
now lowers to a real LIST_CONCAT of the two list cells instead of a nested
Product, so imageURL builds a flat "path:tag@digest" at runtime.
Files: src/mycelium/isa.zig, src/mvm/{vm,checks}.zig, src/spore/{preamble,
compiler,mvm_run_test}.zig, src/exec/mvm/mvm.zig, src/sys/{fsstore,sys}.zig,
src/want/test.zig, stdlib/{build,linux}/*.sp, build/bash.sp.
commit 1c3c573a7b
Author: Jarvis <jarvis@brendoncarroll.net>
Date: Wed Sep 2 15:53:53 2026 +0000
download.file: keep hash and algo separate; hash is a Ref(Opaque)
Revert the digest-string FileTask in favor of separate fields: hash is
now myc.Ref(anyopaque) (an opaque reference / content address) and algo
remains a separate hash-algorithm string. A spore program expresses the
hash as a 64-hex CID literal (e.g. @abcd...), which coerces to
Ref(Opaque).
Expose Opaque as a spore type symbol so (Ref Opaque) resolves, and pin
docker.umoci's binary with a CID literal instead of a "sha256:<hex>"
string.
commit 7fb1d9fe46
Author: Jarvis <jarvis@brendoncarroll.net>
Date: Wed Sep 2 15:41:51 2026 +0000
spore: add CID literals and Ref(T) type coercion
Rename the AST node for a bare @<64-hex> content address from Ref to
CID: a CID is a raw 256-bit hash, not a reference. Add Ref as a type
constructor, so (Ref T) is a typed reference, and make a CID literal
coerce to Ref(T) in a (Ref T) position (the same 256 bits tagged with T);
a bare CID otherwise has the opaque reference type Ref(Opaque).
This lets a spore program express a pinned content address (e.g. a
download.file hash) as a CID literal while keeping the hash algorithm a
separate field.
commit 76212abaa4
Author: Jarvis <jarvis@brendoncarroll.net>
Date: Wed Sep 2 14:24:42 2026 +0000
docker: add umoci download and umoci-in-container rootfs unpack
docker.umoci downloads the pinned umoci release binary through
download.file, and docker.rootfs unpacks a pulled image's OCI layout by
spawning umoci in a fresh container (linux.run with init=umoci): the image
is snapshot-mounted at /image, unpacked --rootless into the writable /out
mount, and the captured output tree is returned as the rootfs.
linux.mount is a helper that pins a MountSrc onto a container path.
commit 890b5242b8
Author: Jarvis <jarvis@brendoncarroll.net>
Date: Wed Sep 2 14:24:37 2026 +0000
spore: compile list elements softly; support zero-argument proc calls
compileListLiteral's .list branch compiled each element with the strict
element type, so a proc-call element (whose result is dynamic) tripped
compileApply's non-any expected-type rejection. Compile elements with the
preferred type (compileArgSoft) instead, matching compileProductVals.
compileApply rejected any call with fewer than one argument, so a
zero-parameter proc could not be applied at all. Allow a bare call and
build the empty (0-bit) input node for the no-argument case.
commit d6156928ec
Author: Jarvis <jarvis@brendoncarroll.net>
Date: Wed Sep 2 13:02:32 2026 +0000
linux: order type deps first; tag pulled image indexes :latest
Define MountSrc/Mount/Input/Output before CSpec so its type alias
resolves at def time and can be exported cross-package (a type alias
whose referenced types are defined after it is not exported as a
resolvable AnyType).
Annotate the OCI index.json manifest descriptor with
org.opencontainers.image.ref.name=latest so umoci can unpack the pulled
image by reference (/image:latest). Update the layoutIndex test.
commit 65f5f923a1
Author: Jarvis <jarvis@brendoncarroll.net>
Date: Wed Sep 2 11:35:06 2026 +0000
linux: add MountSrc/Input/Output constructor helpers
Add spore helpers to build MountSrc/Input/Output values: snapshot,
output, emptyDir, procfs, sysfs, cgroup2fs, devpts mounts and
stdinClosed/outputClosed/outputLog stdio. Each constructs a bare Sum
case via (#typed ... {index: ...}).
Also spell the Port case as (Port Empty Empty): a bare Port symbol does
not resolve in a type position (only the (Port M S) SExpr form does via
resolveTypeSExpr). This matches myc.Port(void, void), the CSpawnTask
port type.
commit c49832d7cf
Author: Jarvis <jarvis@brendoncarroll.net>
Date: Tue Sep 1 21:19:45 2026 +0000
spore: lay out bare Sum cases by their packed size, not static width
compileSumLiteral rejected a Sum case with a runtime-sized payload
(String, Port, a nested product like FS), because unionCaseBits only
knew bit/bit-array/empty-product widths. Compute each case's width via
HeapType.sizeOf instead, so a MountSrc/Input/Output Sum (snapshot: FS,
port: Port) can be laid out.
This is groundwork: constructing such a value still needs the referenced
type (e.g. build.FS) to resolve across packages, which is tracked
separately.
commit d2339731a3
Author: Jarvis <jarvis@brendoncarroll.net>
Date: Tue Sep 1 21:14:44 2026 +0000
stdlib: drop local-import aliases now that lambda-body imports resolve
The compiler now resolves imported symbols as callees in lambda bodies
(landed upstream), so the workaround local aliases ((def ns_get ns.get),
(def spawn build.spawn)) are no longer needed. Call ns.get, build.spawn,
and build.fileAt directly from the build/docker/linux packages.
commit 4e680ad880
Author: Jarvis <jarvis@brendoncarroll.net>
Date: Tue Sep 1 20:10:05 2026 +0000
download.oci_image_ref: parse a canonical image reference
Add download.oci_image_ref, which takes a canonical
"path:tag@digest" reference (the string docker.imageURL builds) and
parses it server-side into an OciImageTask. Docker Hub official images
are expanded into the library/ namespace and loopback hosts use http, so
docker.pull can hand the reference straight to the op instead of
pre-parsing it in spore.
Wire docker.pull to the new op and add a parseImageRef test.
commit cdc753edcc
Author: Jarvis <jarvis@brendoncarroll.net>
Date: Tue Sep 1 20:07:10 2026 +0000
download.file: take a digest string instead of a raw CID
FileTask.hash was a marshalled stores.CID, which a spore program cannot
construct (it is a raw 256-bit value). Replace it with digest, an
"<algo>:<hex>" string parsed via oci.digestToCid in execFile, so
download.file is callable from spore to fetch a pinned binary such as
the umoci release.
commit 299c782963
Author: Jarvis <jarvis@brendoncarroll.net>
Date: Tue Sep 1 20:05:16 2026 +0000
linux: rewrite CSpec to match CSpawnTask and use linux.cspawn
Align the linux stdlib's CSpec with the host CSpawnTask: init (a
wantfs.Root binary), args/env/wd, mounts as {dst, src}, and
stdin/stderr/stdout unions. Rename the run op to linux.cspawn and return
CSpawnResult (exit_code + outputs). fileAtPath now delegates to
build.fileAt.
The mount/stdio constructor helpers are left out for now: building a
MountSrc/Input/Output Sum with a runtime-sized payload (snapshot: FS,
port: Port) is not yet supported by the compiler, so the bare type
definitions and run/fileAtPath are what compile today.
Extend the compile test to cover the linux package.
commit 36d3647c8f
Author: Jarvis <jarvis@brendoncarroll.net>
Date: Tue Sep 1 19:25:56 2026 +0000
stdlib: define full wantfs.Root FS type and wire build.pick
Give the build package a real FS type: the nested Product that mirrors
wantfs.Root's mycelium type (exploiting the List(u8) Extent form so no
opaque Ref leaks into the descriptor), so an FS produced by a host op
round-trips unchanged through spore.
Wire build.pick/build.fileAt to the wantfs.pick op, and fix build.spawn
to marshal sys.Task as {op_name, input} through the sys port. Imported
function calls are resolved via local aliases (the compiler does not
resolve imported symbols from lambda bodies), so try "ns" explicitly
and alias ns.get. Consolidate FS/pick into build.sp since cross-file
body references are not resolved; keep fs.sp as a package sibling.
Add a test compiling the docker package (and its build/fs/ns deps)
cleanly, proving the FS type, spawn, and pick all type-check.
commit 664bbf076f
Author: Jarvis <jarvis@brendoncarroll.net>
Date: Tue Sep 1 18:50:35 2026 +0000
wantfs: add wantfs.pick op that re-roots a selected path
Introduce a wantfs executor exposing a single wantfs.pick op. PickTask
carries a wantfs.Root plus a target path; execPick shifts every entry at
or below that path to the root of a fresh filesystem, reusing extents
unchanged and re-encoding only the paths. Picking a file yields a flat
single-file Root (the shape linux.cspawn's init expects), and picking a
directory yields its subtree.
Also redefine wantfs.Extent as myc.List(u8): it already holds a blob ref
plus byte length, and this makes its marshalled descriptor a plain
List(Byte), expressible from spore without exposing an opaque Ref.