actrun

    MVP GitHub Actions-compatible push CI runner with bitflow lowering, native execution, and bit workspace materialization.

    github-actions
    workflow
    runner
    ci
    Download zip
    Author
    Version
    0.32.0
    License
    Apache-2.0
    Last updated
    12 days ago
    Downloads
    622

    #actrun

    A local GitHub Actions runner built with MoonBit. Run and debug GitHub Actions workflows locally with a gh-compatible CLI.

    actrun keeps its release contract as close as possible to existing GitHub Actions semantics. Workflow YAML and action metadata stay on a GitHub-compatible surface, while WASM support is treated as a self-hosted runner optimization. See docs/public-api.md for the contract boundary and ADR 0001 for the rationale.

    #Install

    # npx (no install required) npx @mizchi/actrun workflow run .github/workflows/ci.yml # curl (Linux / macOS) curl -fsSL https://raw.githubusercontent.com/mizchi/actrun/main/install.sh | sh # Docker docker run --rm -v "$PWD":/workspace -w /workspace ghcr.io/mizchi/actrun workflow run .github/workflows/ci.yml # npm global install npm install -g @mizchi/actrun # Nix (run without installing) nix run github:mizchi/actrun -- workflow run .github/workflows/ci.yml # Nix (install into profile) nix profile install github:mizchi/actrun # moon install moon install mizchi/actrun/cmd/actrun # Build from source git clone https://github.com/mizchi/actrun.git && cd actrun moon build src/cmd/actrun --target native

    #Nix

    #Run directly

    nix run github:mizchi/actrun -- workflow run .github/workflows/ci.yml

    #Build from source

    nix build github:mizchi/actrun ./result/bin/actrun workflow run .github/workflows/ci.yml

    #Development shell

    With direnv and nix-direnv:

    echo "use flake" > .envrc direnv allow

    Or without direnv:

    nix develop

    #Adding the overlay to your flake.nix

    { inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; actrun.url = "github:mizchi/actrun"; }; outputs = { nixpkgs, actrun, ... }: let system = "aarch64-darwin"; # or "x86_64-linux" pkgs = import nixpkgs { inherit system; overlays = [ actrun.overlays.default ]; }; in { packages.${system}.default = pkgs.actrun; devShells.${system}.default = pkgs.mkShell { packages = [ pkgs.actrun ]; }; }; }

    #Without flakes

    # default.nix provides a ready-to-use derivation let actrun = import (builtins.fetchTarball "https://github.com/mizchi/actrun/archive/main.tar.gz") { }; in actrun

    #Quick Start

    # Run a workflow locally actrun workflow run .github/workflows/ci.yml # Show execution plan without running actrun workflow run .github/workflows/ci.yml --dry-run # Emit flow cache plan JSON for an external orchestrator actrun workflow run .github/workflows/ci.yml \ --dry-run \ --json \ --flow-cache-store /tmp/flow-cache.json \ --flow-signature build=sig-build # Skip actions not needed locally (e.g. setup tools already installed) actrun workflow run .github/workflows/ci.yml \ --skip-action actions/checkout \ --skip-action extractions/setup-just # Run in isolated worktree actrun workflow run .github/workflows/ci.yml \ --workspace-mode worktree # Generate config file actrun init # View results actrun run view run-1 actrun run logs run-1 --task build/test

    #Configuration

    actrun init generates an actrun.toml in the current directory:

    # Workspace mode: local, worktree, tmp, docker workspace_mode = "local" # Skip actions not needed locally local_skip_actions = ["actions/checkout"] # Trust all third-party actions without prompt trust_actions = true # Nix integration: "auto" (force), "off" (disable), or empty (auto-detect) nix_mode = "" # Additional nix packages nix_packages = ["python312", "jq"] # Container runtime: docker, podman, container, lima, nerdctl container_runtime = "docker" # Include uncommitted changes in worktree/tmp workspace # include_dirty = true # Default local GitHub context when `--event` is omitted # [local_context] # repository = "owner/repo" # ref_name = "main" # before_rev = "HEAD^" # after_rev = "HEAD" # actor = "your-name" # Override actions with local commands # [override."actions/setup-node"] # run = "echo 'using local node' && node --version" # Affected file patterns per workflow # [affected."ci.yml"] # patterns = ["src/**", "package.json"]

    When --event is omitted, actrun auto-detects github.repository, github.ref_name, github.sha, and github.actor from the local git repository when possible. Use [local_context] only when you need to pin or override those values. See Local GitHub Context for precedence and examples.

    CLI flags always override actrun.toml settings. See Cheatsheet for quick reference and Advanced Workflow for details.

    #Flow Cache

    Use --flow-cache-store <path> together with one or more --flow-signature <job-or-task>=<fingerprint> flags to exchange task cache state with the embedded bitflow planner.

    --dry-run --json includes a flow_cache.plan payload with per-task hit/miss information. A normal run writes successful task fingerprints back to the same store and persists both the plan and writeback result under run.json as flow_cache.plan and flow_cache.writeback.

    #CLI Reference

    #Workflow Commands

    actrun workflow list # List workflows in .github/workflows/ actrun workflow run <workflow.yml> # Run a workflow locally

    #Run Commands

    actrun run list # List past runs actrun run view <run-id> # View run summary actrun run view <run-id> --json # View run as JSON actrun run watch <run-id> # Watch until completion actrun run logs <run-id> # View all logs actrun run logs <run-id> --task <id> # View specific task log actrun run download <run-id> # Download all artifacts

    #Analysis Commands

    # Lint: type check expressions and detect dead code actrun lint # Lint all .github/workflows/*.yml actrun lint .github/workflows/ci.yml # Lint a specific file actrun lint --ignore W001 # Suppress a rule (repeatable) # Visualize: render workflow job dependency graph actrun viz .github/workflows/ci.yml # ASCII art (terminal) actrun viz .github/workflows/ci.yml --mermaid # Mermaid text (for Markdown) actrun viz .github/workflows/ci.yml --detail # Mermaid with step subgraphs actrun viz .github/workflows/ci.yml --svg # SVG image actrun viz .github/workflows/ci.yml --svg --theme github-light

    #Lint Diagnostics

    RuleSeverityDescription
    undefined-contexterrorUndefined context (e.g. foobar.x)
    wrong-arityerrorWrong function arity (e.g. contains('one'))
    unknown-functionerrorUnknown function (e.g. myFunc())
    unknown-propertywarningUnknown property (e.g. github.nonexistent)
    type-mismatchwarningComparing incompatible types
    unreachable-stepwarningUnreachable step (if: false)
    future-step-referrorReference to future step
    undefined-step-referrorReference to undefined step
    undefined-needserrorUndefined needs job reference
    circular-needserrorCircular needs dependency
    unused-outputswarningUnused job outputs
    duplicate-step-iderrorDuplicate step IDs in same job
    missing-runs-onerrorMissing runs-on
    empty-joberrorEmpty job (no steps)
    uses-and-runerrorStep has both uses and run
    empty-matrixwarningMatrix with empty rows
    invalid-useserrorInvalid uses syntax
    invalid-globwarningInvalid glob pattern in trigger filter
    redundant-conditionwarningAlways-true/false condition
    script-injectionwarningScript injection risk (untrusted input in run:)
    permissive-permissionswarningOverly permissive permissions
    deprecated-commandwarningDeprecated workflow command (::set-output etc.)
    missing-prt-permissionswarningpull_request_target without explicit permissions
    if-alwayswarningBare always() — prefer success() \|\| failure()
    dangerous-checkout-in-prterrorCheckout PR head in pull_request_target
    secrets-to-third-partywarningSecrets passed via env to third-party action
    missing-timeoutwarningNo timeout-minutes (opt-in: --strict)
    mutable-action-refwarningTag ref instead of SHA pin (opt-in: --online)
    action-not-founderrorAction ref not found on GitHub (opt-in: --online)

    Configure lint behavior in actrun.toml:

    [lint] preset = "default" # default, strict, oss ignore_rules = ["unknown-property", "unused-outputs"]

    PresetIncludes
    defaultAll rules except missing-timeout and online checks
    strictdefault + missing-timeout
    ossstrict + mutable-action-ref / action-not-found (network)

    #Visualization Example

    $ actrun viz .github/workflows/release.yml ┌───────┐ ┌─────┐ ┌────────┐ │ build │ │ npm │ │ docker │ └───────┘ └─────┘ └────────┘ │ └────────────┐ │ ┌─────────┐ │ release │ └─────────┘

    #Artifact & Cache Commands

    actrun artifact list <run-id> # List artifacts actrun artifact download <run-id> --name <name> # Download artifact actrun cache list # List cache entries actrun cache prune --key <key> # Delete cache entry

    #Workflow Run Flags

    FlagDescription
    --dry-runShow execution plan without running
    --skip-action <pattern>Skip actions matching pattern (repeatable)
    --workspace-mode <mode>worktree (default), local, tmp, docker
    --repo <path>Run from a git repository
    --event <path>Push event JSON file
    --repository <owner/repo>GitHub repository name
    --ref <ref>Git ref name
    --run-root <path>Run record storage root
    --nixForce nix wrapping for run steps
    --no-nixDisable nix wrapping even if flake.nix/shell.nix exists
    --nix-packages <pkgs>Ad-hoc nix packages (space-separated)
    --container-runtime <name>Container runtime: docker, podman, container, lima, nerdctl
    --wasm-runner <kind>Wasm runner kind: wasmtime, deno, v8
    --affected [base]Only run if files matching patterns changed (see below)
    --retryRe-run only failed jobs from the latest run
    --include-dirtyInclude uncommitted changes in worktree/tmp workspace
    --jsonJSON output for read commands and --dry-run

    #Affected Runs

    Skip workflows when no relevant files have changed. Patterns are resolved in order:

    1. actrun.toml [affected."<workflow>"] patterns
    2. on:push:paths from the workflow file (automatic fallback)

    # Compare against last successful run (default) actrun ci.yml --affected # Compare against a specific rev actrun ci.yml --affected HEAD~3 actrun ci.yml --affected abc1234 # Preview what would happen (shows plan even if skipped) actrun ci.yml --affected HEAD~1 --dry-run

    Configure patterns in actrun.toml:

    [affected."ci.yml"] patterns = ["src/**", "package.json"] [affected.".github/workflows/lint.yml"] patterns = ["src/**", "*.config.*"]

    If actrun.toml has no patterns, on:push:paths from the workflow is used automatically:

    on: push: paths: ["src/**", "*.toml"] # actrun --affected uses these

    #Workspace Modes

    ModeDescription
    localRun in-place in the current directory
    worktreeCreate an isolated git worktree for execution (default)
    tmpClone to a temp directory via git clone
    dockerRun in a Docker container

    #Container Runtime

    actrun supports multiple container runtimes for job container:, services:, and docker:// actions.

    RuntimeBinaryNotes
    dockerdockerDefault
    podmanpodmanDocker-compatible CLI
    containercontainerApple container runtime (macOS)
    nerdctlnerdctlcontainerd CLI
    limalima nerdctlLima VM with nerdctl (wrapper script auto-generated)

    # CLI flag actrun workflow run ci.yml --container-runtime podman # actrun.toml container_runtime = "podman" # Environment variable (also works) ACTRUN_CONTAINER_RUNTIME=podman actrun workflow run ci.yml

    #Supported GitHub Actions

    #Builtin Actions (deterministic emulation)

    ActionSupported Inputs
    actions/checkout@*path, ref, fetch-depth, clean, sparse-checkout, submodules, lfs, fetch-tags, persist-credentials, set-safe-directory, show-progress
    actions/upload-artifact@*name, path, if-no-files-found, overwrite, include-hidden-files
    actions/download-artifact@*name, path, pattern, merge-multiple
    actions/cache@*key, path, restore-keys, lookup-only, fail-on-cache-miss
    actions/cache/save@*key, path
    actions/cache/restore@*key, path, restore-keys, lookup-only, fail-on-cache-miss
    actions/setup-node@*node-version, node-version-file, cache, registry-url, always-auth, scope

    #Remote Actions (fetch + execute)

    • GitHub repo node actions with pre/main/post lifecycle
    • GitHub repo docker actions with pre-entrypoint/entrypoint/post-entrypoint lifecycle
    • Composite actions (local and remote)
    • docker://image direct execution

    #Self-Hosted WASM Optimization

    • A self-hosted runner may prefer a sibling *.wasm file next to a standard node* action runs.main
    • The same action still runs on GitHub Actions through the normal JS fallback path
    • The runtime family is selected with --wasm-runner / ACTRUN_WASM_RUNNER

    Protocol extensions such as wasm://... and runs-on: wasi are experimental / internal and are not part of the release contract. See docs/public-api.md for details.

    #Local-Only Execution Flag

    actrun sets ACTRUN_LOCAL=true in the execution environment. Use this in if: conditions to skip steps locally or run steps only locally:

    steps: # Skipped when running locally (runs on GitHub Actions) - uses: actions/checkout@v5 if: ${{ !env.ACTRUN_LOCAL }} # Runs only locally (skipped on GitHub Actions) - run: echo "local debug info" if: ${{ env.ACTRUN_LOCAL }}

    On GitHub Actions, ACTRUN_LOCAL is not set, so !env.ACTRUN_LOCAL evaluates to true and all steps run normally.

    #Action Overrides

    Replace specific uses: action steps with custom run: commands via actrun.toml. This is useful when you have tools installed locally and want to skip the action's setup logic.

    [override."actions/setup-node"] run = "echo 'using local node' && node --version"

    When a workflow step matches uses: actions/setup-node@*, actrun replaces it with the specified run: command before execution.

    Combine with local_skip_actions for full control:

    local_skip_actions = ["actions/checkout"] [override."actions/setup-node"] run = "echo 'using local node'" [override."actions/setup-python"] run = "python3 --version"

    #Secrets & Variables

    # Provide secrets via environment variables ACTRUN_SECRET_MY_TOKEN=xxx actrun workflow run ci.yml # Provide variables ACTRUN_VAR_MY_VAR=value actrun workflow run ci.yml

    Secrets are automatically masked in stdout, stderr, logs, and run store. The ::add-mask:: workflow command is also supported.

    #Environment Variables

    VariableDescription
    ACTRUN_SECRET_<NAME>${{ secrets.<name> }}
    ACTRUN_VAR_<NAME>${{ vars.<name> }}
    ACTRUN_NODE_BINNode.js binary path
    ACTRUN_DOCKER_BINDocker binary path
    ACTRUN_WASM_RUNNERWasm runner kind: wasmtime, deno, v8
    ACTRUN_WASM_BINWasm runtime binary (default: wasmtime)
    ACTRUN_GIT_BINGit binary path
    ACTRUN_GITHUB_BASE_URLGitHub API base URL
    ACTRUN_ARTIFACT_ROOTArtifact storage root
    ACTRUN_CACHE_ROOTCache storage root
    ACTRUN_GITHUB_ACTION_CACHE_ROOTRemote action cache root
    ACTRUN_ACTION_REGISTRY_ROOTCustom registry root
    ACTRUN_NIXSet to false to disable nix wrapping

    ACTRUN_WASM_RUNNER を指定した場合、default bin は wasmtime / deno / ACTRUN_NODE_BIN (v8) に切り替わります。ACTRUN_WASM_BIN を併用すると、runner kind は固定したまま実行 binary だけ上書きできます。

    #Nix Integration

    actrun automatically detects flake.nix or shell.nix in the workspace root and wraps run: steps in the corresponding nix environment. This lets workflows written for ubuntu-latest run locally with nix-managed toolchains.

    #Auto-detection

    ConditionWrapping
    flake.nix existsnix develop --command <shell> <script>
    shell.nix existsnix-shell --run '<shell> <script>'
    Neither existsNo wrapping (host environment)

    Detection requires nix to be installed. If nix is not found, wrapping is silently skipped.

    #Examples

    # Auto-detect flake.nix / shell.nix actrun workflow run .github/workflows/ci.yml # Disable nix wrapping actrun workflow run .github/workflows/ci.yml --no-nix # Ad-hoc packages without flake.nix actrun workflow run .github/workflows/ci.yml --nix-packages "python312 jq" # Disable via environment variable ACTRUN_NIX=false actrun workflow run .github/workflows/ci.yml

    #Typical flake.nix for Rust

    { inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; outputs = { self, nixpkgs }: let systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]; forAllSystems = nixpkgs.lib.genAttrs systems; in { devShells = forAllSystems (system: let pkgs = nixpkgs.legacyPackages.${system}; in { default = pkgs.mkShell { packages = [ pkgs.rustc pkgs.cargo ]; }; }); }; }

    #Typical flake.nix for Python + uv

    { inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; outputs = { self, nixpkgs }: let systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]; forAllSystems = nixpkgs.lib.genAttrs systems; in { devShells = forAllSystems (system: let pkgs = nixpkgs.legacyPackages.${system}; in { default = pkgs.mkShell { packages = [ pkgs.python312 pkgs.uv ]; }; }); }; }

    #Notes

    • Only run: steps are wrapped. uses: action steps are not affected.
    • Job container: steps skip nix wrapping (container has its own environment).
    • nix develop / nix-shell is invoked per step, so the nix environment is consistent across steps.

    #Workflow Features

    • Push trigger filter (branches, paths)
    • strategy.matrix (axes, include, exclude, fail-fast, max-parallel)
    • Job/step if conditions (success(), always(), failure(), cancelled())
    • needs dependencies with output/result propagation
    • Reusable workflows (workflow_call) with inputs, outputs, secrets, secrets: inherit, nested expansion
    • Job container and services with Docker networking
    • Expression functions: contains, startsWith, endsWith, fromJSON, toJSON, hashFiles
    • File commands: GITHUB_ENV, GITHUB_PATH, GITHUB_OUTPUT, GITHUB_STEP_SUMMARY
    • Shell support: bash, sh, pwsh, custom templates ({0})
    • step.continue-on-error, steps.*.outcome / steps.*.conclusion

    #Performance

    Benchmark on Apple Silicon (M-series):

    ModeStartupCPU (Node.js)Write 1k files
    local~0.13s644ms52ms
    nix-packages~0.70s629ms47ms
    apple-container~0.93s502ms14ms

    • local — lowest overhead, best for fast iteration
    • nix-packages — +0.6s startup for nix develop; execution speed identical to local
    • apple-container — +0.9s startup; many-file I/O is 3-4x faster (ext4 vs APFS metadata)

    See docs/perf.md for full benchmark details.

    # Try it yourself nix run github:mizchi/actrun -- workflow run .github/workflows/ci.yml

    #Development

    just # check + test just fmt # format code just check # type check just test # run tests just e2e # run E2E scenarios just release-check # fmt + info + check + test + e2e just build-js # build the npm CLI bundle (dist/actrun.js) and library (lib/actrun.js)

    #Live Compatibility Testing

    # One-shot: dispatch, wait, download, compare just gha-compat-live compat-checkout-artifact.yml # Step by step just gha-compat-dispatch compat-checkout-artifact.yml just gha-compat-download <run-id> just gha-compat-compare compat-checkout-artifact.yml _build/gha-compat/<run-id>

    #Architecture

    FilePurpose
    src/lib.mbtContract types
    src/parser.mbtWorkflow YAML parser
    src/trigger.mbtPush trigger matcher
    src/lowering.mbtBitflow IR lowering, action/reusable workflow expansion
    src/executor.mbtNative host executor
    src/runtime.mbtGit workspace materialization
    src/lint/Expression parser, type checker, dead code detection, workflow visualization
    src/cmd/actrun/main.mbtCLI entry point
    testdata/Compatibility fixtures

    #Prior Art

    • actionlint — Static checker for GitHub Actions workflow files. actrun lint is inspired by its rule design and type system.

    #License

    Apache-2.0

    #actrun

    MVP の GitHub Actions 互換 push CI ランナー向けコア API。

    The release-contract principle is: keep GitHub Actions-compatible surface area stable, and keep runner optimizations or protocol extensions internal / experimental.

    この package は push workflow の subset を parse し、bitflow IR に lower し、native target では host shell 上で実行できます。

    • push trigger のフィルタ判定
    • workflow YAML subset parser
    • workflow/job/step 契約型
    • ActionRef / resolver
    • bitflow IR への lowering
    • bitflow task cache plan / writeback の CLI 連携 (--flow-cache-store, --flow-signature)
    • workflow list の最小 read-only CLI
    • workflow run の最小 subcommand
    • strategy.matrix の最小対応 (axes / include / exclude / mixed axes + include / fail-fast / max-parallel)
    • matrix job に対する needs fan-in と aggregated ${{ needs.<job>.result }} / ${{ needs.<job>.outputs.* }}
    • minimal job-level if: (success() default, always() / failure() / cancelled(), simple github.* / needs.* comparison)
    • minimal step-level if: (success() default, always() / failure() / cancelled())
    • minimal expression functions (contains, startsWith, endsWith, fromJSON, toJSON, hashFiles)
    • ${{ vars.* }} の最小対応 (ACTRUN_VAR_<NAME> から供給)
    • ${{ secrets.* }} の最小対応 (ACTRUN_SECRET_<NAME> から供給, if: 直接参照は未対応)
    • workflow_call trigger と inputs / outputs / secrets の parse / contract 対応
    • local / remote reusable workflow (jobs.<job_id>.uses) の最小実行 (with, workflow_call.inputs の required / implicit default / type validation, caller job の strategy.matrix, matrix caller 上の workflow_call.outputs 集約, workflow_call.outputs, secrets mapping, secrets: inherit, nested reusable workflow, remote reusable workflow 内 local action)
    • job container の string / mapping form の parse / contract 対応と、run step / GitHub repo node* action を docker adapter で実行する最小対応
    • job container 配下の GitHub repo / direct runs.using: docker action を sibling container として実行し、job container の volume mount を共有する最小対応
    • job container 配下で actions/checkout@* が host 側に materialize した workspace を後続 container run step から見える形で扱う最小対応
    • job container 配下で actions/upload-artifact@* / actions/download-artifact@* の roundtrip を後続 container run step から扱う最小対応
    • job services の mapping form の parse / contract 対応、service container の最小 lifecycle 実行、${{ job.services.<id>.ports[...] }} context、health check wait、job container との docker network 共有の最小対応
    • workflow/job permissions / concurrency の parse / contract 対応と lowering reject
    • step-level continue-on-error
    • ${{ steps.<id>.outcome }} / ${{ steps.<id>.conclusion }} の最小対応
    • native host executor
    • CLI run store の最小対応 (--run-root, _build/actrun/runs/<run-id>/run.json, jobs.json, artifacts.json, caches.json, tasks/*.stdout.log|stderr.log|summary.md, jobs/artifacts/caches index, timestamps, run list, run view, run watch, run logs, run download, artifact list, artifact download, cache list, cache prune)
    • local injection point の CLI flag 対応 (--artifact-root, --cache-root, --github-action-cache-root, --registry-root)
    • bit repo から push commit を materialize する runtime
    • uses: actions/checkout@* と uses: builtin://checkout の最小 builtin 対応
    • actions/checkout の path / sparse-checkout / sparse-checkout-cone-mode / fetch-depth / ref / clean / submodules の最小 builtin 対応
    • uses: actions/upload-artifact@* / uses: actions/download-artifact@* の最小 builtin 対応 (directory, wildcard path, if-no-files-found, overwrite, download-all directory mode, merge-multiple)
    • uses: actions/setup-node@* の最小 builtin 対応 (node-version, cache: npm, registry-url)
    • job container 配下で actions/setup-node@* が PATH shim と output を後続 run step に伝播する最小対応
    • uses: actions/cache@* / actions/cache/restore@* の restore-keys, lookup-only, fail-on-cache-miss 対応
    • job container 配下で actions/cache@* の miss -> deferred save -> next job restore を後続 container run step から扱う最小対応
    • native prefetch による owner/repo[/path]@ref GitHub repo action の remote fetch / cache fill
    • cache 済み owner/repo[/path]@ref GitHub repo composite action の workspace-aware 展開
    • cache 済み / prefetched owner/repo[/path]@ref GitHub repo node* action の最小実行
    • cache 済み / prefetched owner/repo[/path]@ref GitHub repo runs.using: docker action の最小実行
    • uses: ./path の local composite action 展開
    • local composite action 内の nested uses 展開
    • local composite action の with と ${{ inputs.* }} の最小対応
    • CI, GITHUB_ACTIONS, GITHUB_WORKSPACE, GITHUB_WORKFLOW, GITHUB_JOB の基本 env 注入
    • GITHUB_ACTION の最小対応
    • cached / prefetched GitHub action 向けの GITHUB_ACTION_REPOSITORY, GITHUB_ACTION_REF 注入
    • local composite action inner step への GITHUB_ACTION_PATH 注入
    • local composite action inner step 間に閉じた GITHUB_STATE の最小対応
    • cache 済み / prefetched GitHub repo node* action の pre / main / post lifecycle と GITHUB_STATE 共有
    • cache 済み / prefetched GitHub repo runs.using: docker action の pre-entrypoint / entrypoint / post-entrypoint lifecycle と GITHUB_STATE 共有
    • GITHUB_ENV, GITHUB_PATH, GITHUB_OUTPUT, GITHUB_STEP_SUMMARY の file command 対応
    • native run step における ${{ env.* }} の最小対応
    • direct dependency に対する ${{ needs.<job>.outputs.<name> }}, ${{ needs.<job>.result }} の最小対応
    • push workflow における ${{ github.ref }}, ${{ github.ref_name }}, ${{ github.sha }} と GITHUB_REF, GITHUB_REF_NAME, GITHUB_SHA の最小対応
    • push workflow における ${{ github.event_name }} と GITHUB_EVENT_NAME の最小対応
    • push workflow における ${{ github.repository }} と GITHUB_REPOSITORY の最小対応
    • push workflow における ${{ github.repository_owner }} と GITHUB_REPOSITORY_OWNER の最小対応
    • push workflow における ${{ github.actor }} と GITHUB_ACTOR の最小対応
    • native run step における ${{ github.workflow }}, ${{ github.job }}, ${{ github.workspace }} の最小対応
    • native run step における ${{ github.action }} の最小対応
    • cached / prefetched GitHub action 文脈での ${{ github.action_repository }}, ${{ github.action_ref }} の最小対応
    • local composite action inner step における ${{ github.action_path }} の最小対応
    • native run step における ${{ runner.os }}, ${{ runner.arch }}, ${{ runner.temp }}, ${{ runner.environment }} の最小対応
    • file-based な bash / sh / pwsh 実行と {0} 付き custom shell template の最小対応
    • job 内の後続 step に対する ${{ steps.<id>.outputs.<name> }} の最小対応
    • uses: docker://... の native docker 実行
    • MVP 範囲外機能の明示的 reject

    CLI では actrun workflow list --repo /path/to/repo で .github/workflows/*.yml|*.yaml を列挙できます。name が空なら file stem を fallback に使います。actrun workflow run .github/workflows/ci.yml は従来の actrun .github/workflows/ci.yml と同じ実行経路を subcommand で呼ぶ入口です。actrun .github/workflows/ci.yml --repo /path/to/repo --workspace /tmp/work --before <sha> の形で、repo 上の commit snapshot を materialize してから実行できます。--event /path/to/push-event.json を渡すと GitHub push webhook payload から PushEvent を組み立てます。--changed を省略した場合は changed paths を自動計算します。${{ github.repository }} / GITHUB_REPOSITORY は --repository で明示 override でき、未指定なら repo root の origin remote URL から自動推測します。--run-root を渡すと local run record の保存先を上書きでき、現時点では <run-root>/run-<n>/run.json, jobs.json, artifacts.json, caches.json と tasks/*.stdout.log|stderr.log|summary.md を保存し、run.json には started_at_ms / finished_at_ms, exit_code, job 状態、artifact/cache index も含みます。--flow-cache-store <path> を --flow-signature <job-or-task>=<fingerprint> と併用すると、dry-run 時は bitflow task cache の plan を計算し、--json 出力や run.json に flow_cache.plan を含めます。通常実行では successful な task を同じ store に writeback し、その結果を flow_cache.writeback として run record に残します。actrun run list は保存済み run を新しい順に列挙し、actrun run view <run-id> は run store を要約表示し、--json 付きなら run.json をそのまま返します。actrun run watch <run-id> は run store が終端状態になるまで poll し、完了時に run view と同じ要約、--json 付きなら run.json を返し、failed/cancelled 系 state では non-zero で終了します。actrun run logs <run-id> --task <task-id> は保存済み task log / summary を読み戻し、--json 付きなら task ごとの stdout / stderr / summary payload を返します。actrun run download <run-id> はその run の全 artifact を <dir>/<artifact-name>/... に展開し、--json 付きなら download 結果の summary を返します。actrun artifact list <run-id> はその run の artifact index を列挙し、actrun artifact download <run-id> --name <artifact> は保存済み artifact を指定 directory に展開し、--json 付きなら copied file の summary を返します。actrun cache list は cache root 配下の workspace ごとの cache key と file 一覧を列挙し、actrun cache prune --key <cache-key> は一致する cache entry を削除します。--artifact-root / --cache-root は builtin artifact/cache store の保存先を、--github-action-cache-root / --registry-root は remote action cache / custom registry root をそれぞれ上書きします。--workspace-mode は contract だけ先に入っていて、local workflow 実行では worktree、--repo 実行では tmp が default です。

    #例

    ///|
    test {
    let workflow = new_workflow(
    "ci",
    [
    new_job("build", [
    new_run_step("install", "pnpm install"),
    new_run_step("test", "pnpm test"),
    ]),
    new_job("lint", [new_run_step("lint", "pnpm lint")], needs=["build"]),
    ],
    trigger=new_push_trigger(branches=["main"], paths=["src/*"]),
    defaults=new_run_defaults(shell=Some("bash")),
    )

    let event = new_push_event("main", ["src/lib.mbt"])
    inspect(matches_push_trigger(workflow.trigger, event), content="true")

    let src =
    #|on: push
    #|jobs:
    #| build:
    #| runs-on: ubuntu-latest
    #| steps:
    #| - run: pnpm test
    let parsed = parse_workflow_yaml(src)
    let lowered = lower_push_workflow(parsed.workflow.unwrap())
    @debug.debug_inspect(lowered.errors, content="[]")
    @debug.debug_inspect(lowered.ir.tasks.length(), content="2")
    }

    #MVP 非対応

    • pwsh binary が存在しない環境での PowerShell workflow 実行
    • reusable workflow の広い互換対応
    • custom registry action の remote fetch / registry protocol 解決

    parse_action_ref distinguishes GitHub repo refs, local paths, docker://..., and custom registry refs. A custom registry action (bit://std/cache@v1) resolves its manifest from ACTRUN_ACTION_REGISTRY_ROOT/<scheme>/<name>/<version>. On the release-contract surface, the stable WASM-related API is GitHub-compatible workflow / action metadata plus runner-local configuration (ACTRUN_WASM_RUNNER, ACTRUN_WASM_BIN). The native executor may prefer a sibling *.wasm next to a standard node* action runs.main as a self-hosted runner optimization. ACTRUN_WASM_RUNNER accepts wasmtime, deno, or v8, and the default binary becomes wasmtime, deno, or ACTRUN_NODE_BIN (node) respectively. ./local-action reads action.yml / action.yaml from the workspace and expands to composite steps while wiring with into ${{ inputs.* }}. prefetch_workflow_github_actions_native clones owner/repo[/path]@ref into _build/actrun/github_actions or ACTRUN_GITHUB_ACTION_CACHE_ROOT; composite manifests are expanded, runs.using: node* executes runs.main and pre / post, and runs.using: docker executes runs.image / runs.args / runs.entrypoint / runs.pre-entrypoint / runs.post-entrypoint from the native executor. The prefetch path uses ACTRUN_GIT_BIN; the native executor uses ACTRUN_NODE_BIN / ACTRUN_DOCKER_BIN / ACTRUN_WASM_BIN; setup-node uses ACTRUN_SETUP_NODE_BIN; ${{ vars.* }} comes from ACTRUN_VAR_<NAME>; ${{ secrets.* }} comes from ACTRUN_SECRET_<NAME>; and the GitHub host can be overridden by ACTRUN_GITHUB_BASE_URL. wasm://... and runs-on: wasi may still exist inside the repo but are not part of the release contract and are treated as internal / experimental. ResolvedAction separates the backend string from the capability model (host / docker / wasm).

    ActionRef

    pub enum ActionRef {
    GitHubRepo(String, String, String, String?)
    LocalPath(String)
    DockerImage(String)
    Registry(String, String, String)
    }

    ActionRefParseResult

    pub struct ActionRefParseResult {
    action : ActionRef?
    errors : Array[String]
    }

    ActionResolutionResult

    pub struct ActionResolutionResult {
    action : ResolvedAction?
    errors : Array[String]
    }

    BackendCapabilities

    pub struct BackendCapabilities {
    host : Bool
    docker : Bool
    wasm : Bool
    }

    BitChangedPathsResult

    pub struct BitChangedPathsResult {
    paths : Array[String]
    base_sha : String
    head_sha : String
    errors : Array[String]
    }

    BitWorkspace

    pub struct BitWorkspace {
    repo_root : String
    git_dir : String
    workspace_root : String
    commit_sha : String
    refname : String
    remote_url : String
    }

    BitWorkspaceResult

    pub struct BitWorkspaceResult {
    workspace : BitWorkspace?
    errors : Array[String]
    }

    ConcurrencySpec

    pub struct ConcurrencySpec {
    group : String
    cancel_in_progress : String?
    }

    ExecutionPlan

    pub struct ExecutionPlan {
    tasks : Array[TaskPlan]
    job_outputs : Map[String, Map[String, String]]
    job_if_conditions : Map[String, String]
    job_needs : Map[String, Array[String]]
    job_need_targets : Map[String, Map[String, Array[String]]]
    job_virtual_targets : Map[String, Array[String]]
    job_virtual_output_targets : Map[String, Map[String, Array[String]]]
    job_matrix_groups : Map[String, String]
    job_matrix_fail_fast : Map[String, Bool]
    job_containers : Map[String, JobContainerSpec]
    job_services : Map[String, Map[String, JobContainerSpec]]
    composite_output_mappings : Map[String, Map[String, String]]
    }

    GitHubActionPrefetchResult

    pub struct GitHubActionPrefetchResult {
    fetched : Array[String]
    errors : Array[String]
    }

    JobContainerCredentialsSpec

    pub struct JobContainerCredentialsSpec {
    username : String
    password : String
    }

    JobContainerSpec

    pub struct JobContainerSpec {
    image : String
    credentials : JobContainerCredentialsSpec?
    env : Map[String, String]
    ports : Array[String]
    volumes : Array[String]
    options : String?
    }

    JobMatrixSpec

    pub struct JobMatrixSpec {
    rows : Array[Map[String, String]]
    fail_fast : Bool
    max_parallel : Int?
    }

    JobSpec

    pub struct JobSpec {
    id : String
    name : String
    if_condition : String
    needs : Array[String]
    outputs : Map[String, String]
    permissions : PermissionsSpec?
    concurrency : ConcurrencySpec?
    runs_on : Array[String]
    env : Map[String, String]
    defaults : RunDefaults
    steps : Array[StepSpec]
    matrix : JobMatrixSpec?
    reusable_workflow : String?
    reusable_workflow_with : Map[String, String]
    reusable_workflow_secrets : Map[String, String]
    reusable_workflow_inherit_secrets : Bool
    services : Map[String, JobContainerSpec]
    container : JobContainerSpec?
    container_image : String?
    timeout_minutes : Int
    environment : String
    }

    LocalActionParseResult

    pub struct LocalActionParseResult {
    action : LocalActionSpec?
    errors : Array[String]
    }

    LocalActionSpec

    pub struct LocalActionSpec {
    name : String
    inputs : Map[String, String]
    outputs : Map[String, String]
    steps : Array[StepSpec]
    }

    LoweringResult

    pub struct LoweringResult {
    ir :
    FlowIr

    plan : ExecutionPlan
    errors : Array[String]
    }

    PermissionsSpec

    pub struct PermissionsSpec {
    values : Map[String, String]
    }

    PlanJob

    pub struct PlanJob {
    id : String
    needs : Array[String]
    runs_on : Array[String]
    steps : Array[PlanStep]
    }

    PlanResult

    pub struct PlanResult {
    workflow_name : String
    errors : Array[String]
    jobs : Array[PlanJob]
    }

    PlanStep

    pub struct PlanStep {
    id : String
    kind : String
    name : String
    shell : String
    script : String
    uses : String
    backend : String
    if_condition : String
    env : Map[String, String]
    with_values : Map[String, String]
    }

    PushEvent

    pub struct PushEvent {
    ref_name : String
    before_sha : String
    after_sha : String
    changed_paths : Array[String]
    repository : String
    actor : String
    }

    PushEventJsonParseResult

    pub struct PushEventJsonParseResult {
    event : PushEvent?
    errors : Array[String]
    }

    PushTrigger

    pub struct PushTrigger {
    branches : Array[String]
    branches_ignore : Array[String]
    paths : Array[String]
    paths_ignore : Array[String]
    tags : Array[String]
    tags_ignore : Array[String]
    }

    ResolvedAction

    pub struct ResolvedAction {
    uses : String
    action_ref : ActionRef
    kind : String
    backend : String
    capabilities : BackendCapabilities
    action_path : String?
    entrypoint : String?
    image : String?
    args : Array[String]
    }

    RunDefaults

    pub struct RunDefaults {
    shell : String?
    working_directory : String?
    }

    ShellEnv

    pub struct ShellEnv {
    vars : Map[String, String]
    cwd : String
    stdout_buf : Array[String]
    stderr_buf : Array[String]
    exit_code : Int
    exit_called : Bool
    write_file : (String, String, Bool) -> Bool
    read_file : (String) -> String?
    file_exists : (String) -> Bool
    is_dir : (String) -> Bool
    mkdir : (String) -> Bool
    remove : (String) -> Bool
    }

    StepSpec

    pub struct StepSpec {
    id : String
    name : String
    run : String?
    uses : String?
    shell : String?
    working_directory : String?
    env : Map[String, String]
    with_values : Map[String, String]
    if_condition : String
    continue_on_error : String
    timeout_minutes : Int
    }

    StoreEnvEntry

    pub struct StoreEnvEntry {
    key : String
    value : String
    } derive(ToJson,
    Debug
    ,
    FromJson
    )

    Env update: maps to GITHUB_ENV (key=value or heredoc) HTTP: POST /runs/{run_id}/env body: {"key": "...", "value": "..."}

    StoreMode

    pub enum StoreMode {
    FileStore
    HttpStore(String)
    }

    StoreOutputEntry

    pub struct StoreOutputEntry {
    key : String
    value : String
    } derive(ToJson,
    Debug
    ,
    FromJson
    )

    Step output: maps to GITHUB_OUTPUT (key=value per line) HTTP: POST /steps/{step_id}/outputs body: {"key": "...", "value": "..."}

    StorePathEntry

    pub struct StorePathEntry {
    path : String
    } derive(ToJson,
    Debug
    ,
    FromJson
    )

    Path update: maps to GITHUB_PATH (one path per line) HTTP: POST /runs/{run_id}/path body: {"path": "..."}

    StoreStepResult

    pub struct StoreStepResult {
    outputs : Map[String, String]
    env_updates : Map[String, String]
    path_entries : Array[String]
    summary : String
    } derive(ToJson,
    Debug
    ,
    FromJson
    )

    Collected results for a step execution. In file mode: parsed from GITHUB_OUTPUT/GITHUB_ENV files. In HTTP mode: GET /steps/{step_id}/result

    StoreSummaryEntry

    pub struct StoreSummaryEntry {
    content : String
    } derive(ToJson,
    Debug
    ,
    FromJson
    )

    Step summary: maps to GITHUB_STEP_SUMMARY (markdown text) HTTP: POST /steps/{step_id}/summary body: {"content": "..."}

    TaskPlan

    pub struct TaskPlan {
    id : String
    kind : String
    job_id : String
    step_id : String
    name : String
    script : String
    shell : String
    working_directory : String
    if_condition : String
    runs_on : Array[String]
    env : Map[String, String]
    with_values : Map[String, String]
    action : ResolvedAction?
    action_scope : String?
    requires_action_started : Bool
    continue_on_error : String
    timeout_minutes : Int
    }

    TaskRunReport

    pub struct TaskRunReport {
    id : String
    kind : String
    status : String
    code : Int
    duration_ms : UInt64
    shell : String
    script : String
    cwd : String
    stdout : String
    stderr : String
    summary : String
    }

    WasmDceReport

    pub struct WasmDceReport {
    removable_functions : Int
    removable_bytes : Int
    ok : Bool
    error : String
    }

    WasmModuleInfo

    pub struct WasmModuleInfo {
    total_bytes : Int
    function_count : Int
    import_count : Int
    export_count : Int
    valid : Bool
    error : String
    }

    WasmOptimizeResult

    pub struct WasmOptimizeResult {
    original_size : Int
    optimized_size : Int
    optimized_bytes : Bytes
    ok : Bool
    error : String
    }

    WasmSandbox

    pub struct WasmSandbox {
    tempdir : String
    env_path : String
    output_path : String
    path_path : String
    summary_path : String
    state_path : String
    }

    WasmSandboxResult

    pub struct WasmSandboxResult {
    env_updates : Map[String, String]
    path_entries : Array[String]
    output_values : Map[String, String]
    state_updates : Map[String, String]
    summary : String
    }

    WorkflowCallInputSpec

    pub struct WorkflowCallInputSpec {
    description : String
    required : Bool
    default_value : String?
    input_type : String
    }

    WorkflowCallOutputSpec

    pub struct WorkflowCallOutputSpec {
    description : String
    value : String
    }

    WorkflowCallSecretSpec

    pub struct WorkflowCallSecretSpec {
    required : Bool
    }

    WorkflowCallSpec

    pub struct WorkflowCallSpec {
    inputs : Map[String, WorkflowCallInputSpec]
    outputs : Map[String, WorkflowCallOutputSpec]
    secrets : Map[String, WorkflowCallSecretSpec]
    }

    WorkflowParseResult

    pub struct WorkflowParseResult {
    workflow : WorkflowSpec?
    errors : Array[String]
    }

    WorkflowRunReport

    pub struct WorkflowRunReport {
    ok : Bool
    state : String
    order : Array[String]
    steps : Array[WorkflowStepReport]
    issues : Array[String]
    task_reports : Array[TaskRunReport]
    }

    WorkflowSpec

    pub struct WorkflowSpec {
    name : String
    run_name : String
    trigger : PushTrigger
    pull_request_trigger : PushTrigger?
    workflow_call : Bool
    workflow_call_spec : WorkflowCallSpec?
    permissions : PermissionsSpec?
    concurrency : ConcurrencySpec?
    env : Map[String, String]
    defaults : RunDefaults
    jobs : Array[JobSpec]
    }

    WorkflowStepReport

    pub struct WorkflowStepReport {
    id : String
    status : String
    required : Bool
    duration_ms : UInt64
    message : String
    }

    analyze_wasm_dead_code

    fn analyze_wasm_dead_code(bytes : Bytes) -> WasmDceReport

    backend_capabilities_for

    fn backend_capabilities_for(backend : String) -> BackendCapabilities

    build_sandboxed_wasmtime_args

    fn build_sandboxed_wasmtime_args(sandbox : WasmSandbox, env : Map[String, String], module_path : String) -> Array[String]

    Build wasmtime arguments for sandboxed execution. Only the tempdir is mounted — no access to host filesystem.

    cleanup_run_temp_files

    fn cleanup_run_temp_files(workspace_root : String) -> Unit

    cleanup_wasm_sandbox

    fn cleanup_wasm_sandbox(sandbox : WasmSandbox) -> Unit

    Clean up the sandbox tempdir after use.

    cli_args

    fn cli_args() -> Array[String]

    Command-line arguments with the program name at index 0 on every target. On the JS target process.argv starts with the Node.js executable, which is dropped so that callers see the same shape as on native.

    collect_secret_values

    fn collect_secret_values() -> Array[String]

    compute_bit_changed_paths

    fn compute_bit_changed_paths(rfs : &
    RepoFileSystem
    , repo_root : String, event : PushEvent) -> BitChangedPathsResult

    compute_bit_changed_paths_native

    fn compute_bit_changed_paths_native(repo_root : String, event : PushEvent) -> BitChangedPathsResult

    create_wasm_sandbox

    fn create_wasm_sandbox(step_id : String) -> WasmSandbox?

    dump_workflow_context_json

    async fn dump_workflow_context_json(workflow_name : String, plan : ExecutionPlan, workspace_root : String, push_event : PushEvent, dispatch_inputs? : Map[String, String], event_name? : String) -> String

    empty_step_result

    fn empty_step_result() -> StoreStepResult

    execute_lowered_native

    async fn execute_lowered_native(lowered : LoweringResult, workspace_root? : String, push_event? : PushEvent?, event_name? : String, dispatch_inputs? : Map[String, String], nix_mode? : String, nix_packages? : Array[String], sandbox_mode? : String, sandbox_writable? : Array[String], allow_destructive_checkout_clean? : Bool) -> WorkflowRunReport

    extract_add_mask_values

    fn extract_add_mask_values(report : WorkflowRunReport) -> Array[String]

    filter_workflow_jobs

    fn filter_workflow_jobs(workflow : WorkflowSpec, skip_job_ids : Array[String]) -> WorkflowSpec

    filter_workflow_steps

    fn filter_workflow_steps(workflow : WorkflowSpec, skip_patterns : Array[String]) -> WorkflowSpec

    find_task_plan

    fn find_task_plan(plan : ExecutionPlan, id : String) -> TaskPlan?

    find_task_run_report

    fn find_task_run_report(report : WorkflowRunReport, id : String) -> TaskRunReport?

    find_workflow_step_report

    fn find_workflow_step_report(report : WorkflowRunReport, id : String) -> WorkflowStepReport?

    inspect_wasm_module

    fn inspect_wasm_module(bytes : Bytes) -> WasmModuleInfo

    lower_push_workflow

    fn lower_push_workflow(workflow : WorkflowSpec) -> LoweringResult

    lower_push_workflow_in_workspace

    fn lower_push_workflow_in_workspace(workflow : WorkflowSpec, workspace_root : String) -> LoweringResult

    mask_report_secrets

    fn mask_report_secrets(report : WorkflowRunReport, secret_values : Array[String]) -> WorkflowRunReport

    mask_secrets

    fn mask_secrets(text : String, secret_values : Array[String]) -> String

    matches_push_trigger

    fn matches_push_trigger(trigger : PushTrigger, event : PushEvent) -> Bool

    materialize_bit_push_workspace

    fn materialize_bit_push_workspace(fs : &
    FileSystem
    , rfs : &
    RepoFileSystem
    , repo_root : String, event : PushEvent, workspace_root : String, remote_url? : String) -> BitWorkspaceResult

    materialize_bit_push_workspace_native

    fn materialize_bit_push_workspace_native(repo_root : String, event : PushEvent, workspace_root : String, remote_url? : String) -> BitWorkspaceResult

    new_backend_capabilities

    fn new_backend_capabilities(host? : Bool, docker? : Bool, wasm? : Bool) -> BackendCapabilities

    new_concurrency_spec

    fn new_concurrency_spec(group : String, cancel_in_progress? : String?) -> ConcurrencySpec

    new_job

    fn new_job(id : String, steps : Array[StepSpec], name? : String, if_condition? : String, needs? : Array[String], outputs? : Map[String, String], permissions? : PermissionsSpec?, concurrency? : ConcurrencySpec?, runs_on? : Array[String], env? : Map[String, String], defaults? : RunDefaults, matrix? : JobMatrixSpec?, reusable_workflow? : String?, reusable_workflow_with? : Map[String, String], reusable_workflow_secrets? : Map[String, String], reusable_workflow_inherit_secrets? : Bool, container? : JobContainerSpec?, container_image? : String?, services? : Map[String, JobContainerSpec], timeout_minutes? : Int, environment? : String) -> JobSpec

    new_job_container_credentials_spec

    fn new_job_container_credentials_spec(username : String, password : String) -> JobContainerCredentialsSpec

    new_job_container_spec

    fn new_job_container_spec(image : String, credentials? : JobContainerCredentialsSpec?, env? : Map[String, String], ports? : Array[String], volumes? : Array[String], options? : String?) -> JobContainerSpec

    new_job_matrix

    fn new_job_matrix(rows : Array[Map[String, String]], fail_fast? : Bool, max_parallel? : Int?) -> JobMatrixSpec

    new_local_action

    fn new_local_action(steps : Array[StepSpec], name? : String, inputs? : Map[String, String], outputs? : Map[String, String]) -> LocalActionSpec

    new_permissions_spec

    fn new_permissions_spec(values? : Map[String, String]) -> PermissionsSpec

    new_push_event

    fn new_push_event(ref_name : String, changed_paths : Array[String], before_sha? : String, after_sha? : String, repository? : String, actor? : String) -> PushEvent

    new_push_trigger

    fn new_push_trigger(branches? : Array[String], branches_ignore? : Array[String], paths? : Array[String], paths_ignore? : Array[String], tags? : Array[String], tags_ignore? : Array[String]) -> PushTrigger

    new_run_defaults

    fn new_run_defaults(shell? : String?, working_directory? : String?) -> RunDefaults

    new_run_step

    fn new_run_step(id : String, run : String, name? : String, shell? : String?, working_directory? : String?, env? : Map[String, String], if_condition? : String, with_values? : Map[String, String], continue_on_error? : String, timeout_minutes? : Int) -> StepSpec

    new_shell_env

    fn new_shell_env(vars : Map[String, String], cwd? : String, write_file? : (String, String, Bool) -> Bool, read_file? : (String) -> String?, file_exists? : (String) -> Bool, is_dir? : (String) -> Bool, mkdir? : (String) -> Bool, remove? : (String) -> Bool) -> ShellEnv

    new_task_plan

    fn new_task_plan(id : String, kind : String, job_id : String, step_id : String, name : String, script : String, shell : String, working_directory : String, if_condition : String, runs_on : Array[String], env : Map[String, String], with_values? : Map[String, String], action? : ResolvedAction?, action_scope? : String?, requires_action_started? : Bool, continue_on_error? : String, timeout_minutes? : Int) -> TaskPlan

    new_uses_step

    fn new_uses_step(id : String, uses : String, name? : String, env? : Map[String, String], if_condition? : String, with_values? : Map[String, String], continue_on_error? : String, timeout_minutes? : Int) -> StepSpec

    new_workflow

    fn new_workflow(name : String, jobs : Array[JobSpec], run_name? : String, trigger? : PushTrigger, pull_request_trigger? : PushTrigger?, workflow_call? : Bool, workflow_call_spec? : WorkflowCallSpec?, permissions? : PermissionsSpec?, concurrency? : ConcurrencySpec?, env? : Map[String, String], defaults? : RunDefaults) -> WorkflowSpec

    new_workflow_call_input_spec

    fn new_workflow_call_input_spec(description? : String, required? : Bool, default_value? : String?, input_type? : String) -> WorkflowCallInputSpec

    new_workflow_call_output_spec

    fn new_workflow_call_output_spec(description? : String, value? : String) -> WorkflowCallOutputSpec

    new_workflow_call_secret_spec

    fn new_workflow_call_secret_spec(required? : Bool) -> WorkflowCallSecretSpec

    new_workflow_call_spec

    fn new_workflow_call_spec(inputs? : Map[String, WorkflowCallInputSpec], outputs? : Map[String, WorkflowCallOutputSpec], secrets? : Map[String, WorkflowCallSecretSpec]) -> WorkflowCallSpec

    optimize_wasm_module

    fn optimize_wasm_module(bytes : Bytes, level? : String) -> WasmOptimizeResult

    override_workflow_steps

    fn override_workflow_steps(workflow : WorkflowSpec, overrides : Map[String, String]) -> WorkflowSpec

    parse_action_ref

    fn parse_action_ref(text : String) -> ActionRefParseResult

    parse_github_push_event_json

    fn parse_github_push_event_json(text : String) -> PushEventJsonParseResult

    parse_local_action_yaml

    fn parse_local_action_yaml(text : String) -> LocalActionParseResult

    parse_workflow_yaml

    fn parse_workflow_yaml(text : String) -> WorkflowParseResult

    plan_result_to_json

    fn plan_result_to_json(result : PlanResult) -> String

    plan_workflow

    fn plan_workflow(yaml_text : String, workspace_root? : String) -> PlanResult

    prefetch_workflow_github_actions_native

    async fn prefetch_workflow_github_actions_native(workflow : WorkflowSpec, workspace_root : String, git_bin? : String?, github_base_url? : String?) -> GitHubActionPrefetchResult

    read_sandbox_results

    fn read_sandbox_results(sandbox : WasmSandbox) -> WasmSandboxResult

    Read results from the sandbox after WASM execution.

    registry_module_path

    fn registry_module_path(name : String, version : String) -> String

    WASM module registry route. GET /modules/{name}/{version}/main.wasm → binary

    resolve_action_ref

    fn resolve_action_ref(action : ActionRef) -> ActionResolutionResult

    resolve_action_uses

    fn resolve_action_uses(text : String) -> ActionResolutionResult

    resolve_wasm_runner_command

    fn resolve_wasm_runner_command(wasm_bin : String, wasm_args : Array[String], workspace_root : String) -> (String, Array[String])

    Backward-compatible wrapper that infers runner kind from the configured binary.

    select_workflow_job

    fn select_workflow_job(workflow : WorkflowSpec, job_id : String) -> WorkflowSpec

    select_workflow_step

    fn select_workflow_step(workflow : WorkflowSpec, job_id : String, step_id : String) -> WorkflowSpec

    shell_exec

    fn shell_exec(env : ShellEnv, script : String) -> Int

    shell_stderr

    fn shell_stderr(env : ShellEnv) -> String

    shell_stdout

    fn shell_stdout(env : ShellEnv) -> String

    step_matches_skip_pattern

    fn step_matches_skip_pattern(step : StepSpec, patterns : Array[String]) -> Bool

    store_env_path

    fn store_env_path(run_id : String) -> String

    store_mode_from_env

    fn store_mode_from_env(env : Map[String, String]) -> StoreMode

    store_outputs_path

    fn store_outputs_path(run_id : String, step_id : String) -> String

    HTTP API route definitions. These are path templates — the dispatcher fills in {run_id} and {step_id}.

    store_path_path

    fn store_path_path(run_id : String) -> String

    store_step_result_path

    fn store_step_result_path(run_id : String, step_id : String) -> String

    store_summary_path

    fn store_summary_path(run_id : String, step_id : String) -> String

    strip_unsupported_workflow_fields

    fn strip_unsupported_workflow_fields(workflow : WorkflowSpec) -> WorkflowSpec