package vibe:compiler-host;

// The vibe compiler's OWN host execution contract (#1143): every host
// function `cli_main` needs a runner to provide for the compiler to run at
// all, expressed the same way `vibe compile --wit` already expresses a
// COMPILED PROGRAM's effect surface (lib/@vibe/compiler/wit_gen.vibe,
// docs/effect-wit-mapping.md). That generator explicitly renders a
// host-capability effect (Fs, Env, Stdin, Stdout, ...) as a
// `// host capability effect '...' (provided by the vibe runtime; no WIT
// mapping yet)` comment rather than a real WIT import -- this file is a
// hand-authored answer to that gap for the compiler's own entry point,
// `export fn cli_main() -> Int with Exception + Fs + Env + Stdin + Stdout`
// (lib/@vibe/compiler/cli_adapter.vibe). `Exception` never crosses the host
// boundary (vibe-internal control flow; an escaping throw is a component
// trap, not a capability), matching the same rule the generator applies to
// user programs.
//
// Types follow wit_type_text's existing Int -> s64 / Bool -> bool /
// String -> string / Bytes -> list<u8> / Unit -> omitted-return-type
// mapping (lib/@vibe/compiler/wit_gen.vibe). Operation parameters are
// positional (arg0, arg1, ...): vibe effect operation declarations do not
// carry parameter names, exactly as documented for user-program WIT
// generation.
//
// IMPORTANT (Codex review, PR #1178 round 1): the `fs` interface below is
// NOT derived from `effect Fs { ReadFile, WriteFile, Exists, Mkdir }`
// (lib/@vibe/fs/fs_effect.vibe) -- that block is only a 4-op convenience
// subset for user-program `import Fs` usage. The actual boundary the
// checker enforces is a per-BUILTIN string tag (`Some("Fs")` on each entry
// in lib/@vibe/compiler/core/builtin_registry.vibe, plus
// `Fs::readdir` in checker/builtins_fs.vibe), and `cli_main`'s declared
// a `with` row containing `Fs` admits any builtin carrying that tag -- but
// admitting an op and cli_main actually CALLING it are different things
// (round 1 conflated them and included all 17 tagged ops). `env`/`stdin`/
// `stdout` were already tag-consistent with their builtin-table
// signatures (single op set each) and needed no correction.
// `Stderr::write_char`/`write_stream` exist as real builtins with the same
// tag mechanism but are confirmed NOT part of `cli_main`'s row (zero
// occurrences in cli_adapter.vibe; the checker would reject any reachable
// Stderr call without "Stderr" in the row) -- deliberately excluded.
//
// PER-OP REACHABILITY AUDIT (round 2, following up on round 1's own
// recorded open question; round 3 tightened it further, Codex review PR
// #1180): grepped every `Fs::<op>(` call site across lib/@vibe/compiler,
// excluding tests, the checker/codegen registration tables themselves, and
// the auto-generated `*_bundle.vibe`/`_cli_adapter_module_source.vibe`
// flatten artifacts (which just duplicate other files' text, not new call
// sites). Six ops have real, non-test call sites REACHABLE FROM
// `cli_main`'s own import graph (`read-file`/`write-file`/`write-bytes`
// directly in cli_adapter.vibe, which also directly imports the `runtime`
// and `loader` packages; `exists` in runtime/typecheck_fs.vibe and
// cache/persistent_cache.vibe, both under the imported `runtime` package;
// `stat-token` in loader/loader.vibe and core/module_graph_path.vibe,
// under the imported `loader` package; `readdir` in loader/loader.vibe and
// loader/header_cache.vibe, same package).
//
// `Fs::remove` was included through round 2 but removed in round 3: its
// only call site, entry/cli_cache/cli_cache.vibe's
// `clear_prepare_probe_caches`, is under a separate `entry/cli_cache/`
// directory that `cli_adapter.vibe` never imports and nothing else in the
// compiler calls into either -- an orphaned/alternate entry point, not
// part of `cli_main`'s reachable graph (Codex review, PR #1180).
//
// The remaining twelve ops from round 1's original 17 (`remove` plus ten
// others, and later `publish-immutable-text`) -- `read-bytes`, `is-dir`,
// `is-file`, `remove`, `mkdir`, `mkdir-p`, `chdir`, `getcwd`, `copy`,
// `append`, `rename`, `publish-immutable-text` -- either have ZERO real call
// sites anywhere in the compiler's own source, or (in `remove`'s case) a real
// call site that isn't reachable from `cli_main`. The new immutable publisher
// is deliberately registered but dormant until a future cache PR, preserving
// seed compatibility. They're recognized builtin names but `cli_main` never
// invokes any of them itself.
//
// This resolves round 1's open question about `runtime/viberun`, but NOT
// as cleanly as round 2 first claimed (Codex review, PR #1180 caught a
// second error here): of the eleven originally-unused ops, `runtime/viberun/src/main.rs`
// actually registers THREE of them anyway (`fs_is_dir`, `fs_is_file`,
// `fs_read_bytes`, confirmed at lines ~1791-1835) -- those three are
// present in BOTH runners, `cli_main` just doesn't happen to need them.
// Only the remaining eight (`Fs::remove` and `mkdir`/`mkdir-p`/`chdir`/
// `getcwd`/`copy`/`append`/`rename`) are genuinely absent from `viberun`
// while present in the Node runner. Either way the conclusion is the same
// -- `cli_main` reaches none of the now-twelve, so neither runner's exact
// coverage of them matters to this contract -- but the earlier "viberun is
// missing all of them" framing was wrong and is corrected here.
//
// This is the PORTABLE contract only: preopen-dir sandboxing, store/linker
// setup, fuel/memory limits, and other per-runner configuration are NOT
// part of it -- they're how a given runtime chooses to implement these
// imports, not what the imports are. `runtime/viberun`'s Rust
// `register_vibe_imports` implements exactly this six-op `fs` surface (plus
// three of the originally excluded eleven, which cli_main just doesn't call).
// `scripts/wasm_vibe_host_runner.js`'s Node `vibeModule` implements this
// surface plus all twelve excluded ops plus an entire http/json surface --
// none of which `cli_main` itself ever calls. That extended surface
// belongs to LIBRARY effects used by compiled USER programs (the full
// lib/@vibe/fs surface, lib/@vibe/http), generated per-program by the
// existing --wit path, not to this fixed compiler-host contract.
//
// The #906 worker-transport adapter modes (VIBE_MODULE_JOB_DIR,
// VIBE_LIST_DEPS, VIBE_PUBLISH_ENV_CACHE) need NO additional imports beyond
// this world -- they're plain Env::get-gated branches in cli_adapter.vibe
// that only ever call fs.read-file/fs.write-bytes, treating `input_path` as
// a directory rather than a single file in job-dir/env-cache mode.

world vibe-compiler-host {
  import fs: interface {
    read-file: func(arg0: string) -> string;
    write-file: func(arg0: string, arg1: string);
    write-bytes: func(arg0: string, arg1: list<u8>);
    exists: func(arg0: string) -> bool;
    stat-token: func(arg0: string) -> s64;
    readdir: func(arg0: string) -> list<string>;
  }

  import env: interface {
    get: func(arg0: string) -> string;
    args-get: func(arg0: s64) -> string;
    args-len: func() -> s64;
  }

  import stdin: interface {
    read-char: func() -> s64;
    read-stream: func(arg0: s64) -> string;
  }

  import stdout: interface {
    write-char: func(arg0: s64);
    write-stream: func(arg0: string);
  }

  export cli-main: func() -> s64;
}
