/** * Compiler app runner, runs `tenx @apps/compiler` (COMPILER flavor only) to * scan a local source folder and emit a symbol library (`.10x.json` units + * a linked `.10x.tar`). Docker-first (the compiler image log10x/compiler-10x), * with a local COMPILER-flavor `tenx` binary as an opt-in fallback. * * Flavor vocabulary: three flavors ship, on two axes, what the build can DO * (compile+run vs run only) and how it is BUILT (JVM vs native image): * * | JVM | native * compile + run | compiler | none (compiling needs dynamic class loading) * run only | runtime-jvm | runtime * * Exactly one of them carries the `generate` pipeline unit: `compiler`. Both * runtime flavors are refused here, `runtime-jvm` included, it runs on a JVM, * but it is packaged from the same runtime pipeline factory as the native * binary, so being a JVM build buys it no `generate`. Engines built before the * rename report the compiler as `cloud` and the runtime as `edge`/`native`, and * installed binaries keep printing the old tokens until their owner upgrades, * so every spelling is read here permanently, not as a transition shim. * See `COMPILER_FLAVORS` / `RUNTIME_FLAVORS`. * * Why a dedicated runner (not dev-cli's runners): the streaming apps * (@apps/mcp / @apps/mcp-file) are stdin-in / templates-out over a * `/mcp/{config,input,output}` contract. The compiler is shaped * differently, it scans SOURCE folders and writes SYMBOL libraries to * disk, configured by the bundled `@apps/compiler` config. dev-cli's * mode/install/binary resolution is reused so that logic stays * single-sourced, but the compile invocation, mounts, and output handling * live here. * Extensibility: * The `CompileConfig` descriptor + the two per-mode appliers * (`runDockerCompile` / `runLocalCompile`) are the seam for source axes. * Each axis, GitHub pull (implemented), Helm / Docker-image pull, GitHub * PUSH, scan/link tuning, adds an optional field on `CompileConfig` plus * a small renderer that emits one of four injection primitives: * 1. env vars (e.g. TENX_OUTPUT_SYMBOL_*, GH_TOKEN), * 2. file replacements (shadow configs: the inputPaths overlay local- * side, the pull//config.yaml overlays), * 3. @overlay launch args(the engine's native config layering), * 4. mounts (docker only). * Mode selection, the compiler-flavor gate, process exec, and output * scanning are written once and don't change as axes are added. * * GitHub pull: the engine's github scanner uses the GitHub REST API (no git * binary involved), configured by `pull/github/config.yaml`. That file is * replaced wholesale: bind-mounted over in docker mode, shadowed via * TENX_INCLUDE_PATHS in local mode, listing the requested repos/branch/ * folders. The token stays an `$=TenXEnv.get("GH_TOKEN")` reference in the * rendered YAML (never written to disk); the value travels as process env. * The engine hard-refuses an empty token ("empty GitHub API token"), even * for public repos, so callers must gate on a token being present. * * Docker-image pull: the engine materializes an image's filesystem by * shelling out to `docker manifest inspect` → `docker create` → `docker * export` (no `docker pull`, no registry HTTP client), configured by * `pull/docker/config.yaml`, replaced the same way as github. The * compiler-10x image bundles podman symlinked as /usr/local/bin/docker, so * the pull is DAEMONLESS, no host docker socket, but podman needs * CAP_SYS_ADMIN (user-namespace clone) + vfs storage, so docker mode adds * `--cap-add SYS_ADMIN -e STORAGE_DRIVER=vfs` ONLY when a dockerImage input * is present; the other sources stay unprivileged. Registry creds are * optional (public images pull anonymously); when given they travel as * DOCKER_USERNAME / DOCKER_TOKEN process env, same pattern as GH_TOKEN. * Local mode renders the overlay without a `command` override (the engine's * platform default applies) and needs a docker/podman CLI on the host. * * The compiler-flavor gate: the compiler app is absent from BOTH runtime * flavors, its scanners (ANTLR, bytecode, archive, executable) and * the link stage need the full JRE-packaged compiler distribution. Docker * mode uses the compiler image by contract; local mode probes the binary's * version banner (`10x engine v…, flavor: 'compiler'`, or `'cloud'` on an * engine built before the rename) and refuses anything else — including a * banner it cannot read at all, which is not evidence of the compiler * flavor. See `assertCompilerFlavor`. */ /** A local source folder on disk to scan. */ export interface CompileLocalInput { kind: 'local'; /** Absolute host path to the folder of source code / binaries. */ path: string; } /** GitHub repositories to pull (REST API) and scan. */ export interface CompileGithubInput { kind: 'github'; /** Repositories as `owner/repo` (e.g. `apache/commons-cli`). */ repos: string[]; /** Branch to pull for ALL repos; omit for each repo's default branch. */ branch?: string; /** Folders within each repo to pull; omit for the entire repo. */ folders?: string[]; } /** Docker/OCI images to pull (daemonless via podman in-image) and scan. */ export interface CompileDockerImageInput { kind: 'dockerImage'; /** Fully-qualified image refs (e.g. `docker.io/grafana/grafana:11.1.0`). */ images: string[]; } /** A `helm repo add` target, needed to resolve a bare `repo/chart` name. */ export interface HelmRepo { name: string; url: string; } /** * Helm charts to render (`helm template` + `helm show chart`) and scan. A * meta-source: the engine extracts the docker images and GitHub source repos * the chart references and (optionally) pulls THOSE too. */ export interface CompileHelmInput { kind: 'helm'; /** * Chart refs. OCI (`oci://...`) and full URLs resolve standalone; a bare * `repo/chart` needs a matching entry in `repos`. */ charts: string[]; /** `helm repo add` targets, so bare `repo/chart` names resolve. */ repos?: HelmRepo[]; /** Pull + scan docker images the charts reference (needs CAP_SYS_ADMIN). */ pullImages: boolean; /** Pull + scan GitHub source repos the charts reference (needs a token). */ pullRepos: boolean; } /** Artifacts to pull from a remote Artifactory instance (REST API) and scan. */ export interface CompileArtifactoryInput { kind: 'artifactory'; /** Artifactory base URL, e.g. `https://demo.jfrog.io/artifactory`. */ instance: string; /** Target repository key, e.g. `libs-release-local`. */ repo: string; /** Specific files within the repo to pull; omit to rely on folders. */ files?: string[]; /** Folder paths within the repo to pull; omit to rely on files. */ folders?: string[]; /** Pull folders recursively (sub-folders too). */ recursive: boolean; } /** * Where the compiler reads sources from. Local folder, GitHub pull, docker- * image pull, Helm pull, and Artifactory pull are implemented; further kinds * slot in here as union members, the appliers branch on `kind` and emit the * matching pull-config overlay. gomod pull is deliberately NOT exposed: it * recurses the full transitive dependency graph and floods the library with * third-party symbols. */ export type CompileInput = CompileLocalInput | CompileGithubInput | CompileDockerImageInput | CompileHelmInput | CompileArtifactoryInput; export interface CompileConfig { /** Inputs to scan, any mix of local folders, GitHub pulls, and docker-image pulls. */ inputs: CompileInput[]; /** Output artifact locations (host paths). */ output: { /** Folder for `.10x.json` symbol unit files (TENX_OUTPUT_SYMBOL_FOLDER). */ folder: string; /** Path of the linked `.10x.tar` library (TENX_OUTPUT_SYMBOL_LIBRARY_FILE). */ libraryFile: string; /** Compile runtimeName (TENX_RUNTIME_NAME); also the default tar stem. */ runtimeName: string; }; /** * Link the `.10x.json` symbol units ALREADY on disk under `output.folder` that * this run did not itself scan, the engine's `mergeExistingUnits` option. A * link-only run (no source `inputs`, output folder pointed at a pre-compiled * units tree) scans 0 files, so without this the merge sees an empty * scan-state and writes an EMPTY library. The bundled compiler config never * sets the option (it defaults `$?mergeExistingUnits=false`), so it is * passed as a literal CLI option arg, see `compileAppArgs`. Leave * normal source compile (only this run's freshly-scanned units are merged). */ mergeExistingUnits?: boolean; /** TENX_LICENSE_KEY to pass through. Omit to use the image's built-in limited license. */ license?: string; /** * Credentials the active pull sources need. Values travel as process env * (docker: bare `-e` pass-through; local: child env), never argv, never * disk. githubToken is REQUIRED when a github input is present (the engine * refuses an empty token, even for public repos). */ credentials?: { /** GitHub access token, surfaced to the engine as GH_TOKEN. */ githubToken?: string; /** Registry login for docker-image pull, surfaced as DOCKER_USERNAME. */ dockerUsername?: string; /** Registry token/password for docker-image pull, surfaced as DOCKER_TOKEN. */ dockerToken?: string; /** Artifactory API token, surfaced to the engine as ARTIFACTORY_TOKEN. */ artifactoryToken?: string; }; /** Hard cap on compile wall time in ms. */ timeoutMs: number; } export type CompileMode = 'docker' | 'local'; export interface CompileRunResult { mode: CompileMode; /** Docker image used (docker mode only). */ image?: string; /** Detected flavor token from the local binary banner (local mode only). */ flavor?: string | null; /** True when the compiler flavor was positively confirmed before running. */ flavorVerified: boolean; exitCode: number; timedOut: boolean; wallTimeMs: number; stdout: string; stderr: string; output: { folder: string; /** Symbol units with actual content (zero-byte units are excluded). */ unitCount: number; /** Units the scanners emitted EMPTY, every symbol was filtered out. */ emptyUnitCount: number; libraries: Array<{ path: string; bytes: number; }>; }; runtimeName: string; } /** * Thrown when a local `tenx` is present but is NOT the compiler flavor. The * message doubles as the agent-facing remediation (mirrors * DevCliNotInstalledError's self-describing-message convention). * * The refusal names WHICH wrong build the user has, because the three cases * need different things said to them: * - the native runtime, no `generate`, and it is native, so it never could * - `runtime-jvm`, a JVM build that still has no `generate`. This one * has to be said explicitly: a user who installed a * JVM package on Windows has every reason to assume * the JVM part is what mattered. It is not. The * capability split is baked into the artifact by the * pipeline factory it was packaged from. * - `edge`, the pre-rename token, printed by both packagings. * * The macOS install command says `log10x-cloud` on purpose: the cask token is * the PACKAGE id, which is frozen (Homebrew and the engine's release job pin it * to the file name) and does not follow the flavor rename. The install-script * FLAG does follow it, so that one now reads `--flavor compiler`. */ export declare class NotCompilerFlavorError extends Error { readonly flavor: string; constructor(binary: string, flavor: string); } /** * Thrown when a local `tenx` is present but its flavor could NOT be determined. * * A flavor that cannot be read is not evidence of the right flavor, and the * runtime binary carries no `generate` pipeline-unit factory. Proceeding on an * unreadable banner buys a failure minutes later inside a detached job instead * of one here. */ export declare class FlavorUndetectedError extends Error { readonly outcome: 'unreadable' | 'unrunnable'; readonly raw: string; constructor(binary: string, probe: { outcome: 'unreadable' | 'unrunnable'; raw: string; }); } /** * Thrown when a `helm repo add` pre-step fails (bad name/url, unreachable repo, * or it ran past the shared deadline). The message is agent-facing; `detail` * has URL userinfo redacted so an embedded `user:pass@` can't leak. */ export declare class HelmRepoAddError extends Error { constructor(repoName: string, detail: string); } /** * Which image the docker compile path runs. * * Precedence: LOG10X_COMPILER_IMAGE → LOG10X_TENX_IMAGE → DEFAULT_IMAGE. * A runtime image here is refused. Docker mode deliberately skips the flavor * probe that local mode runs, and an unrefused runtime image fails ~4s into * the container with `could not find pipeline unit factory for: * discoverSources` and a Jackson mapping chain: exit code 1, zero units, no * library. The likely way to arrive there is setting the SHARED * LOG10X_TENX_IMAGE to a runtime image in order to change the run path, * which drags the compiler along with it; `LOG10X_RUNTIME_IMAGE` exists so * that is not necessary. */ export declare function resolveCompilerImage(env?: NodeJS.ProcessEnv): string; export declare function runCompile(cfg: CompileConfig, opts?: { modeOverride?: 'auto' | 'docker' | 'local'; }): Promise; /** What `spawnCompileDetached` hands back for the job layer to persist. */ export interface CompileSpawnHandle { mode: CompileMode; /** Docker image (docker mode). */ image?: string; /** Container name, the docker-mode liveness + exit-code + log key. */ containerName?: string; /** Spawned client (docker) / engine (local) pid. */ pid: number; /** Pull-config overlay dir written for this run (reaped on completion). */ overlayDir?: string; /** Shared helm-home populated for this run (reaped on completion). */ helmHomeDir?: string; } /** * Spawn a compile DETACHED and return immediately, the counterpart to * runCompile for the async `log10x_compile` / `compile_status` split. Unlike * runCompile it never awaits the engine; `compile_status` reads the outcome * later from the container/process + the streamed log. Overlays are written * under `workspaceDir` (a PERSISTED per-job dir, not a mkdtemp that gets * cleaned in a `finally`), so the bind-mounts outlive this call for the whole * run. The same precondition gates as runCompile apply (docker availability / * compiler-flavor) and throw the same errors before anything is spawned. */ export declare function spawnCompileDetached(cfg: CompileConfig, spawnOpts: { workspaceDir: string; logPath: string; containerName: string; }, opts?: { modeOverride?: 'auto' | 'docker' | 'local'; }): Promise; /** * True when the compile pulls a container image and therefore needs the * daemonless in-image podman: a direct dockerImage input, or a Helm chart * configured to pull its referenced images. Pure / testable. */ export declare function needsContainerEngine(cfg: CompileConfig): boolean; /** * Build the `docker run` argv. A local input is realized by bind-mounting * it at the image's DEFAULT sources path, so the bundled `inputPaths: * path("data/compile/sources")` picks it up with no CLI/overlay override, * sidestepping the `OverwrittenOptionException` that a CLI `inputPaths` * would trigger (the scan unit is `allowMultiple: false`). Pull sources are * realized as `configMounts`: rendered pull configs bind-mounted (read-only) * over their baked counterparts. Outputs are driven entirely by env vars the * bundled scan/link configs already read via `TenXEnv.get`, pointed at a * single mounted `/work/symbols`. * * Credential env vars (GH_TOKEN / DOCKER_USERNAME / DOCKER_TOKEN) and the * license are passed as BARE `-e VAR` (docker's env pass-through) so the * secrets ride the spawned client's environment, not the argv, argv is * visible in process listings. * * `needsContainerEngine` inputs (dockerImage, or Helm-with-images) add * `--cap-add SYS_ADMIN` + `STORAGE_DRIVER=vfs`: the in-image podman pulls * daemonlessly (no host socket) but needs the user-namespace clone * capability, and vfs avoids a /dev/fuse device requirement. Only those * inputs pay the privilege. `opts.helmHomeHostDir` mounts a pre-populated * helm home so the engine's `helm template /` resolves. * * Pure (no I/O) so it is unit-testable. */ export declare function buildDockerArgs(cfg: CompileConfig, image: string, opts?: { linuxUser?: string; configMounts?: Array<{ hostPath: string; containerPath: string; }>; containerName?: string; helmHomeHostDir?: string; keepContainer?: boolean; }): string[]; /** * Render the shadow `compile/scanners/config.yaml`. Because the shadow * REPLACES the shipped file (first match on the include path wins), it must * re-declare `outputSymbolFolder` too, keeping the shipped env-hook * expression verbatim so TENX_OUTPUT_SYMBOL_FOLDER still drives the output. * Source paths are single-quoted so Windows backslashes stay literal and the * engine doesn't treat them as `$=` expressions. * * Pure (no I/O) so it is unit-testable. */ export declare function renderScannersOverlay(sourcePaths: string[]): string; /** * Render the github pull config that replaces the baked * `compile/pull/github/config.yaml` wholesale. The token field stays an * `$=TenXEnv.get("GH_TOKEN")` env reference, the secret value travels as * process env, never onto disk. Repos/branch/folders are single-quoted so * they can't be parsed as `$=` expressions. * * Pure (no I/O) so it is unit-testable. */ export declare function renderGithubPullOverlay(input: CompileGithubInput): string; /** * Render the docker pull config that replaces the baked * `compile/pull/docker/config.yaml` wholesale. Credentials stay * `$=TenXEnv.get(...)` env references, blank means "pre-authenticated / * anonymous" and the engine skips `docker login` (public images pull with no * creds). `githubRepoToken` rides GH_TOKEN too: when present, the engine * also pulls + scans the source repo named by the image's * `org.opencontainers.image.source` annotation; when blank it skips that, * silently. `remove` stays false, in docker mode the pulled image lives in * the throwaway container's vfs store, and local-mode users keep their cache. * * `opts.command` pins the docker CLI path (docker mode pins the in-image * podman symlink); omitted, the engine's platform default applies. * * Pure (no I/O) so it is unit-testable. */ export declare function renderDockerPullOverlay(input: CompileDockerImageInput, opts?: { command?: string; }): string; /** * Render the helm pull config that replaces the baked * `compile/pull/helm/config.yaml` wholesale. The default `helmCommand` * (/usr/local/bin/helm) is already correct in compiler-10x, so the overlay * only carries chartNames + the pull toggles. `pull.dockerImages` and * `pull.github.repos` control whether the engine also pulls the images / * source repos a chart references; the GitHub token stays an env reference. * * Pure (no I/O) so it is unit-testable. */ export declare function renderHelmPullOverlay(input: CompileHelmInput): string; /** * Render the artifactory pull config that replaces the baked * `compile/pull/artifactory/config.yaml` wholesale. The token stays an * `$=TenXEnv.get("ARTIFACTORY_TOKEN")` env reference, the secret value travels * as process env, never onto disk. instance/repo and the files/folders lists * are single-quoted so they can't be parsed as `$=` expressions. `files` and * `folders` are always emitted (as `[]` when absent) since the engine reads * both keys. * * Pure (no I/O) so it is unit-testable. */ export declare function renderArtifactoryPullOverlay(input: CompileArtifactoryInput): string; /** * Build TENX_INCLUDE_PATHS for local mode, overlay dir FIRST so its * `compile/scanners/config.yaml` shadows the install's copy. Mirrors the * include-path spelling in dev-cli's local runner. Separator is `;` on all * OSes (see the tenx install-layout reference). * * Pure (no I/O) so it is unit-testable. */ export declare function buildLocalIncludePaths(installPaths: { config: string; modules: string; }, overlayDir: string): string; /** * How the flavor probe ended. `unrunnable` and `unreadable` both mean the * flavor is unknown, but they need different remediation, so they stay distinct rather than * collapsing into one null. */ export type FlavorProbe = /** A flavor token was read off the banner. */ { outcome: 'parsed'; flavor: string; raw: string; } /** Every probe invocation ran, none printed a `flavor: ''` banner. */ | { outcome: 'unreadable'; flavor: null; raw: string; } /** No probe invocation could be executed at all (spawn error every time). */ | { outcome: 'unrunnable'; flavor: null; raw: string; }; /** * Probe the binary's version banner for its flavor token. The engine prints * `10x engine v, flavor: ''` (PipelineLauncher.engineVersion), * where `` is the pipeline factory's own name: `compiler` (`cloud` before * the rename) or `runtime` (`edge`/`native` before it). Try `--version` first * (the dedicated version provider), then `--help`, and read either stream. * * Reports WHY it came back empty. The old signature returned a bare * `flavor: null` for "banner in an unknown format", "binary segfaulted" and * "probe timed out" alike, and the caller could not tell them apart — which is * how a null came to mean "carry on". */ export declare function detectFlavor(binary: string): Promise; /** Env var that turns the undetected-flavor refusal back into a warning-free pass. */ export declare const ALLOW_UNVERIFIED_FLAVOR_ENV = "LOG10X_ALLOW_UNVERIFIED_FLAVOR"; /** * Banner tokens that mean "this build carries the Compiler app". * * `compiler` is what CloudPipelineFactory.name() returns from the flavor rename * on. `cloud` is what every engine built before it returns, and what every * ALREADY-INSTALLED binary keeps returning until its owner upgrades. Both are * permanent readers here: an install that predates the rename is a working * compiler install, and refusing it would break the very users who have one. */ export declare const COMPILER_FLAVORS: ReadonlySet; /** * Banner tokens for the NATIVE runtime build (GraalVM image). `runtime` is the * current name, `native` is what older engines and older installers call it. */ export declare const NATIVE_RUNTIME_FLAVORS: ReadonlySet; /** * Banner tokens for the JVM-packaged runtime, same runtime capabilities as the * native binary, delivered as .deb/.rpm/.msi/.dmg. Not a separate build: those * artifacts ship in every release, and on Windows they are the ONLY runtime, * because no `tenx-*-windows-*-native` asset is produced. * * It is refused by the compile gate exactly like the native runtime. The JVM/ * native axis is not the axis that decides who can compile: `runtime-jvm` is * packaged from the runtime pipeline factory, so it carries no `generate` * pipeline unit no matter what it runs on. */ export declare const JVM_RUNTIME_FLAVORS: ReadonlySet; /** * Every banner token that means "this build cannot compile". `edge` is the * pre-rename token and sits in neither sub-set on purpose: an engine that old * printed it from BOTH the native binary and the jpackage package, so the token * alone does not say which packaging is on the machine. * * Not consulted by the gate, which refuses everything outside COMPILER_FLAVORS * regardless. It exists so the refusal can say WHICH build the user has instead * of quoting a raw token at them. */ export declare const RUNTIME_FLAVORS: ReadonlySet; /** True when a parsed banner token names a build that carries the Compiler app. */ export declare function isCompilerFlavor(flavor: string | null | undefined): boolean; /** * The Compiler app's flavor gate, for every local-binary path. * * Three outcomes, all of them explicit: * - flavor reads `compiler` or `cloud` -> proceed * - flavor reads anything else -> NotCompilerFlavorError * - flavor cannot be read at all -> FlavorUndetectedError * * Two spellings pass, permanently, and only two: `runtime-jvm` is refused * alongside the native runtime, because the JVM/native axis is not the axis * that decides who can compile. The engine renamed its flavors (`cloud` -> * `compiler`, `edge`/`native` -> `runtime`), but a banner is read off whatever * binary is on this machine, and installed binaries keep printing the old token * until their owner upgrades. Accepting only the new one would hard-refuse every * working compiler install in the field; accepting only the old one is the * defect this branch fixes. * * The third case used to fall through. The gate was * `if (flavor && flavor !== 'cloud') throw`, so a null — a segfaulting binary, a * probe that timed out, a banner in a format this parser does not know — skipped * the check entirely and the run proceeded as though the compiler flavor had been * confirmed. The stated reasoning was that @apps/compiler would fail loudly * downstream if it really were the runtime build. It does not fail usefully: the * runtime flavor has no `generate` pipeline-unit factory, so the failure arrives * minutes later, inside a detached job, as an engine error about a missing app * rather than as "your local tenx is the wrong flavor". An unverifiable flavor is * now a refusal at the same point a wrong one is. * * `LOG10X_ALLOW_UNVERIFIED_FLAVOR=1` restores the old behaviour for whoever * genuinely runs a build whose banner this parser cannot read. That is an * explicit, greppable opt-out rather than a silent default. * * Returns the probe so callers can report what was actually seen — with the * opt-out set, `flavor` comes back null and `flavorVerified` is false, which is * the honest record of a run that proceeded unverified. */ export declare function assertCompilerFlavor(binary: string): Promise; /** * Extract the flavor token from a `10x engine v…, flavor: 'compiler'` banner. * Returns the lowercased token, or null if absent. * * Pure so it is unit-testable. */ export declare function parseFlavor(output: string): string | null; /** Convenience predicate over a version-banner string. Pure / testable. */ export declare function isCompilerFlavorOutput(output: string): boolean; /** * The non-secret TENX_* output env the bundled compiler config reads via * `TenXEnv.get`. Shared by both appliers (docker maps these to value-bearing * `-e` flags; local spreads them into the child env). * `TENX_LOG_APPENDER=tenxConsoleAppender` routes the engine's progress log to * stdout so the tool can capture and tail it. The license is NOT here, it is * a secret and rides a bare `-e` (docker) / direct env assignment (local) so * its value never lands in argv. * * Pure so it is unit-testable. */ export declare function compileEnvVars(p: { outputFolder: string; libraryFile: string; runtimeName: string; }): Record; /** * The engine argv for a run: the Compiler app config path, plus the * `mergeExistingUnits true` option when `cfg.mergeExistingUnits` is set. The * engine takes options as positional `name value` pairs after the config path * (PipelineCommandLine), and the `link` unit declares `mergeExistingUnits` as a * boolean option that `units/scan/settings.yaml` reads via `$?mergeExistingUnits`. * The literal `true` is passed verbatim (NOT a `$=TenXEnv.get(...)` expression, * which encodes as `~true` and is flaky); since no bundled config assigns the * option, a CLI value can't collide (no OverwrittenOptionException), unlike * inputPaths/outputSymbolFolder which the bundled config sets and which * therefore ride env/overlay instead. Shared by all three invocation sites * (docker argv, async local spawn, sync local exec). * * Pure (no I/O) so it is unit-testable. */ export declare function compileAppArgs(cfg: CompileConfig): string[]; /** * The secret env (credentials + license) a run needs, keyed by the var names * the engine reads. Docker maps these onto the spawned client's environment so * a bare `-e VAR` pass-through carries the value (never argv); local spreads * them into the child env. Empty when no creds/license are set. * * Pure (no I/O) so it is unit-testable. */ export declare function credentialEnv(cfg: CompileConfig): Record; /** * Walk the output folder for the artifacts the compiler produced: `.10x.json` * symbol units and `.10x.tar` libraries (path + byte size). Tolerant of a * missing/empty dir (returns zeros), since a compile that produced nothing is * a valid `no_signal` outcome, not an error. * * Zero-byte units are counted separately (`emptyUnitCount`), NOT as units: * the scanners write an empty `.10x.json` when every symbol in a file was * filtered out (e.g. only method/package tokens, which the default * `symbol.types` drops), counting those as success is the "green but empty" * trap. */ export declare function scanSymbolOutputs(dir: string): Promise<{ unitCount: number; emptyUnitCount: number; libraries: Array<{ path: string; bytes: number; }>; }>;