Repository navigation
feat(cli): compile source trees with relative URIs and a claimed language - #294
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
…uage Implement tasks 1.3, 2.1, 2.2, 2.4 and 2.5 of the OpenSpec change run-core-wasm-guests-from-any-language. - `--language` selects one of several claimed languages (SEL-3). Without it, several claimed languages give extension.input_invalid; an unclaimed language gives extension.capability_unavailable. The walk reads only the file extensions of the selected language. - Each document URI is the path relative to the source base: `--source-base`, else the current directory (SRC-1). An input outside the base is extension.input_invalid. A single file without `--source-base` keeps the earlier rule. - Each URI segment is percent-encoded as an RFC 3986 path segment, so names with `:`, `\` or a space are encoded, not refused (SRC-3). - Documents are sorted by the whole URI in byte order, a repeated URI is refused, and one file is bounded to 1 MiB. Limit messages name the limit and its value; link messages name the relative path; UTF-8 messages name the URI (SRC-2, FIT-1). - Tests prove byte-identical requests for the same tree and the same contextDigest for other trees. - Document the source base, the encoding, the order and the limits in apps/morphir/docs/extension.md. - Read the stop probe in the WASI entry, which clears an unused-field warning on wasm and wasm-gc. Checked with the released morphir-gleam 0.4.0 module (native and npm CLI).
Without --source-base, the document URIs of a directory compile are relative to that directory again, as before this change. The current directory default broke the published Elm 0.5.0-preview.2 and Python 0.4.2 extensions in the extension qualification suite: compile generated/src sent generated/src/Acme/Rules/Main.elm, and compile src named the Python module src.acme.rules. The Gleam 0.4.0 guest gives the same module names for compile src and compile . with this default. --source-base still overrides the base, and a single file keeps its earlier rule. Damian Reeves chose this option (B) on 2026-11-01. The spec, design (SRC-1), tasks, proposal, CLI help and documentation now describe it.
398e86a to
12163ba
Compare
|
Rebased onto Rebase. There were no git conflicts. But the extension qualification of #298 showed a behavior conflict with the first default source base (the current directory, option A). Checks on 0.10.18 (macOS arm64):
Under option A (before 12163ba), one native run had a failure in the known timing test |
Summary
This PR implements the source-tree slice of the OpenSpec change
run-core-wasm-guests-from-any-language(tasks 1.3, 2.1, 2.2, 2.4 and 2.5; beads
morphir-ukvn.5.64.37.1andmorphir-ukvn.5.64.37.2).--language(SEL-3). When the guest claims one language, the CLI uses it. When it claims several,--languagemust name one: without it the command exits 2 withextension.input_invalid, and the message namesthe claimed languages. An unclaimed language exits 2 with
extension.capability_unavailable. The walk reads onlythe file extensions of the selected language. Both refusals start no operation session.
--source-base, or,without it, to the directory that the user names (option B, decided by Damian Reeves on 2026-11-01). Thus
compile srcsendsapp/money.gleamfrom any current directory, as main does. With--source-base /work/shop,compile /work/shop/src/appsendssrc/app/money.gleam. An input outside the source base exits 2 withextension.input_invalid, and the message names the base. A single file without--source-basekeeps theearlier rule, so MoonBit requests do not change. The request has no
sources.root.%XX.my module.gleambecomesmy%20module.gleam. Names with:or\are now encoded, not refused.a-c.gleambeforea/b.gleam). A repeated URI is refused. A new 1 MiB bound applies to one file. Every limit message names thelimit and its value; a link or special file is named by its path relative to the base; a file that is not UTF-8
is named by its URI. All of these keep
extension.input_invalid, exit 2. The 4 MiB request check stays last.compileModelrequests; other treeswith the same package and options keep the same
contextDigest.apps/morphir/docs/extension.mdstep 4 and a new section "Source trees and document URIs";the ignore-file docs move to task 2.6, which waits for Ignore-file library and moonx tool: Git-compatible, custom ignore files, explain, layer and containment options moonrockz/moonx-tools#16.
apps/morphiron wasm and wasm-gc (unusedstop_requested).Without
--source-base, a directory compile sends the same URIs as main, so this PR has no breaking change fordirectory input. The first version made the current directory the default base (option A); the extension
qualification suite of #298 showed that it broke the published Elm
0.5.0-preview.2and Python0.4.2extensions,so Damian Reeves chose option B. A Cargo-style source root (from the project manifest and the extension's
workspace discovery) is a separate follow-up.
Out of scope: 2.6 (ignore files), the group 1 conversion tasks (1.6 to 1.13), groups 3 and 4.
Check with the released Gleam guest
Local pin (contract
0.2.0,wasm/morphir-bytes-v1, descriptor) overextension/gleam/v0.4.0(
morphir-gleam-0.4.0.wasmSHA-25612349dac…205e,release.jsonSHA-256be337f8f…93dc), on macOS arm64.Tree:
src/shared/numbers.gleam,src/app/money.gleam(importsshared/numbers.{type Amount}),src/app/orders.gleam(importsapp/money.{type Money}).extension compile srcfrom the project, no--model-formatapp/money,app/orders,shared/numbers, cross-module referenceacme/shop:shared/numbers#amountcompile .from the project, andcompile <abs>/srcfrom another directorymodel.jsonbyte-identical to the run above (option B, MoonBit 0.10.18)compile <abs>/src --source-base <abs>from another directorymodel.jsonbyte-identical to the run abovecompile src/sharedshared/numbers--source-base /tmp/elsewhereextension.input_invalidnaming the base--model-format ionextension.tuple_unavailableextension generate model/model-envelope.jsonapp/money.gleam,app/orders.gleam,shared/numbers.gleammodel.jsonbyte-identical to the native onesrc/app/my notes.gleamsrc/app/my%20notes.gleam; the guest decodes it once tomy notesand refuses it as a module name (INVALID_MODULE_URI)The last row is evidence for the open point "Percent-encoding (SRC-3)" of design.html: the guest decodes encoded
segments. Gleam 0.4.0 itself does not resolve imported or qualified values (
GLEAM_UNSUPPORTED_VALUE), so thetree imports types only; that is a guest limit, not a host one.
Test plan
moon testinapps/morphiron native, js, wasm and wasm-gcmoon checkinapps/morphiron all four targets: no warnings in the modulemise run lint,mise run lint:moonbit,mise run validateopenspec validate run-core-wasm-guests-from-any-language --strictmorphir-gleam0.4.0 module through the native and npm CLI (table above)mise run test:wasm-workers -- --target native: 3791 of 3792. The failure is the timing testa launch waits while another process briefly holds the copy open for writing(
pkgs/morphir-host/worker/process/native/unix_wbtest.mbt:124), a package that this PR does not change; itpasses 3 of 3 when run alone
bun run --cwd apps/morphir test native: the process-worker acceptance and the Extism acceptance (Python0.4.2 compiles
src) pass. Each of two runs stopped on a native SIGSEGV in anothercommand (
extension describein run 1,morphir generateintest-generation.tsin run 2), which matches theopen bead
morphir-fr6z(flaky native SIGSEGV); the samedescribepasses 3 of 3 when run by hand