Skip to content

Expand runCode language support #56

@hawkeyexl

Description

@hawkeyexl

This PRD defines requirements for extending the runCode action to support 25+ programming languages by integrating the run universal multi-language runner as a dependency. The enhancement will maintain backward compatibility with the existing JavaScript, Python, and Bash implementation while significantly expanding language coverage to include Rust, Go, TypeScript, C/C++, Ruby, and 20+ additional languages.


Problem Statement

Current State

The runCode action currently supports three languages:

  • JavaScript (via Node.js)
  • Python
  • Bash (not supported on Windows)

Problem

Technical writers documenting polyglot systems, developer tools, or multi-language platforms face significant limitations:

  • Limited Language Coverage: Only 3 languages supported, excluding widely-used languages like TypeScript, Go, Rust, Java, Ruby, PHP, and others
  • Platform Inconsistencies: Bash support excluded on Windows creates cross-platform testing gaps
  • Maintenance Burden: Adding each new language requires custom interpreter detection, execution logic, and platform-specific handling

User Impact

  • Technical writers cannot validate code examples in languages like Go, Rust, or TypeScript
  • Documentation teams for developer tools (CLIs, SDKs, APIs) cannot test multi-language samples
  • Cross-platform documentation requires maintaining separate test suites for different operating systems
  • Teams spend engineering resources building custom language execution wrappers

Goals and Non-Goals

Goals

  1. Expand Language Support: Add 22+ new programming languages to runCode action
  2. Maintain Backward Compatibility: Ensure existing runCode tests continue working without modification
  3. Unified Execution Interface: Provide consistent behavior across all supported languages
  4. Cross-Platform Reliability: Eliminate platform-specific language support gaps (e.g., Bash on Windows)
  5. Preserve Existing Features: Maintain all current runCode capabilities (timeout, exit codes, output validation, variable capture)

Non-Goals

  • Breaking Changes: No modifications to existing test schema or API surface
  • REPL Integration: Interactive REPL functionality from run will not be exposed
  • Automatic Language Detection: Users must explicitly specify the language field for all code execution
  • Language-Specific Configuration: Advanced per-language flags or compiler options beyond what run provides by default
  • Custom Language Engines: Ability to add languages not supported by run

Success Metrics

User Adoption

  • Target: 30% of existing runCode users adopt at least one new language within 90 days of release
  • Measurement: Telemetry tracking unique language values in runCode.language field

Language Coverage

  • Target: Support 25+ languages at launch (matching run capabilities)
  • Measurement: Count of distinct, tested languages in schema enum

Backward Compatibility

  • Target: 100% of existing runCode tests pass without modification
  • Measurement: Regression test suite pass rate

Performance

  • Target: Language execution overhead <200ms compared to current implementation
  • Measurement: Benchmark suite comparing execution time for JavaScript, Python, Bash

User Stories

Story 1: Multi-Language SDK Documentation

As a technical writer documenting a polyglot SDK,
I want to validate code examples in Go, Rust, Python, and JavaScript within a single test suite,
So that users can trust that examples work across all supported language bindings.

Acceptance Criteria:

  • Single test spec can contain runCode steps for Go, Rust, Python, and JavaScript
  • Output validation works identically across all four languages
  • Exit code assertions function consistently for compiled and interpreted languages

Story 2: Cross-Platform CLI Documentation

As a documentation engineer for a developer CLI tool,
I want to test installation scripts in Bash, PowerShell, and batch across macOS, Linux, and Windows,
So that onboarding docs remain accurate for all user platforms.

Acceptance Criteria:

  • Bash scripts execute on Windows via run's cross-platform support
  • Same test file runs on macOS, Linux, and Windows CI environments
  • Shell-specific syntax differences handled by run's language execution

Story 3: Backward Compatible Migration

As a user with existing runCode tests in JavaScript and Python,
I want new language support added without breaking my current tests,
So that I can upgrade Doc Detective versions safely.

Acceptance Criteria:

  • All existing runCode tests pass without schema or behavior changes
  • Execution behavior for JavaScript, Python, and Bash remains identical
  • No new required fields added to runCode schema

Detailed Requirements

Functional Requirements

FR1: Language Support Expansion

Priority: P0
Description: Extend the runCode.language field to support 25+ programming languages. The language field remains required for all runCode steps.

Supported Languages (Alphabetical):

  • Bash / Shell scripting
  • C
  • C++
  • C# / .NET
  • Crystal
  • Dart
  • Elixir
  • Go
  • Haskell
  • Java
  • JavaScript / Node.js (existing)
  • Julia
  • Kotlin
  • Lua
  • Nim
  • Perl
  • PHP
  • Python (existing)
  • R
  • Ruby
  • Rust
  • Swift
  • TypeScript
  • Zig

Acceptance Criteria:

  • Schema validation accepts all 25+ language values
  • Each language executes code correctly when toolchain is available on host machine
  • Language aliases (e.g., js, javascript, node) map to correct language
  • Error messaging clearly indicates when a language's toolchain is unavailable
  • language field remains required; omission results in validation error

FR2: Backward Compatibility

Priority: P0
Description: Maintain 100% compatibility with existing runCode behavior for JavaScript, Python, and Bash.

Acceptance Criteria:

  • Existing test files execute without modification
  • Execution behavior (output, exit codes, timing) remains identical for existing languages
  • Schema remains valid for all existing runCode test steps
  • No performance degradation for existing languages (within 5% tolerance)

FR3: Main Function Flexibility

Priority: P1
Description: For compiled languages, support both complete programs with main functions and code snippets without main functions.

Acceptance Criteria:

  • Go code executes with or without package main and func main()
  • Rust code executes with or without fn main()
  • C/C++ code executes with or without int main()
  • Java code executes with or without class/main method boilerplate
  • Wrapper injection documented for each language

Example:

{
  "runCode": {
    "language": "go",
    "code": "fmt.Println(\"Hello!\")"
  }
}

Executes successfully despite missing package main declaration.


FR4: Cross-Platform Consistency

Priority: P0
Description: Eliminate platform-specific language support gaps.

Acceptance Criteria:

  • Bash executes on Windows via run's cross-platform shell support
  • All 25+ languages execute identically on macOS, Linux, and Windows (when toolchain available)
  • Platform-specific limitations documented clearly (e.g., Swift on Linux)
  • Error messages indicate platform vs. toolchain availability issues

FR5: Output Validation Compatibility

Priority: P0
Description: Maintain existing stdio validation behavior across all languages.

Acceptance Criteria:

  • String matching works identically for all languages
  • Regex validation (e.g., /^hello-world.*/) functions consistently
  • Combined stdout/stderr validation remains unchanged
  • Multi-line output handling works for compiled and interpreted languages

FR6: Variable Capture

Priority: P0
Description: Support variable capture from stdout, stderr, and exit codes for all languages.

Acceptance Criteria:

  • $$stdio.stdout, $$stdio.stderr, $$exitCode expressions work for all languages
  • Output encoding handled correctly (UTF-8 assumed)
  • Binary output from compiled languages handled gracefully
  • Variable capture documented with examples for compiled vs. interpreted languages

FR7: Toolchain Detection and Error Messaging

Priority: P1
Description: Provide clear feedback when required language toolchains are unavailable.

Acceptance Criteria:

  • Error message indicates which language toolchain is missing
  • Suggested installation command provided when possible (e.g., "Install Go from https://golang.org")
  • Documentation includes toolchain requirements table for all languages
  • CI/CD environment setup examples provided

Non-Functional Requirements

NFR1: Performance

Priority: P1
Description: Language execution overhead must remain minimal.

Acceptance Criteria:

  • Execution overhead <200ms for interpreted languages vs. direct interpreter invocation
  • Compilation caching enabled for compiled languages to reduce repeat execution time
  • Timeout behavior unchanged from current implementation
  • Performance benchmarks documented for each language category (compiled vs. interpreted)

NFR2: Documentation

Priority: P0
Description: Comprehensive documentation for new language support.

Deliverables:

  • Updated runCode action reference with all 25+ languages
  • Language-specific examples for popular use cases (API testing, CLI validation, etc.)
  • Toolchain installation guide per language
  • Migration guide for users adding new language tests
  • Troubleshooting section for common language-specific issues
  • Clear documentation that language field is always required

NFR3: Testing Coverage

Priority: P0
Description: Comprehensive test coverage for all supported languages.

Acceptance Criteria:

  • Automated tests for each language's basic execution
  • Edge case tests: exit codes, output validation, timeouts, variable capture
  • Cross-platform test suite (macOS, Linux, Windows)
  • Backward compatibility regression tests for JavaScript, Python, Bash
  • Performance benchmarks for each language

Technical Design Considerations

Integration Architecture

The runCode action will integrate run as a dependency via one of these approaches (implementation team to decide):

Option A: Direct Binary Execution

  • Install run binary as npm/project dependency
  • Invoke run --lang <language> --code <snippet> for each execution
  • Parse stdout/stderr/exit codes from run process

Option B: Library Integration

  • Investigate if run exposes library API for embedding
  • Minimize process spawning overhead
  • Direct access to language engines

Option C: Hybrid Approach

  • Use run binary for unsupported languages
  • Maintain existing JavaScript/Python/Bash implementations for performance
  • Gradual migration path

Schema Changes

The language enum in runCode_v2.schema.json will expand from:

"enum": ["python", "bash", "javascript"]

To include all supported languages:

"enum": [
  "bash", "c", "cpp", "crystal", "csharp", "dart", "elixir", "go", 
  "haskell", "java", "javascript", "julia", "kotlin", "lua", "nim", 
  "perl", "php", "python", "r", "ruby", "rust", "swift", "typescript", "zig"
]

Language aliases will be normalized to primary language names internally. The language field remains required.

Error Handling

New error types to consider:

  • ToolchainNotFound: Language toolchain not installed on host
  • CompilationFailed: Compiled language failed during compilation phase
  • UnsupportedPlatform: Language not supported on current OS

Dependency Management

  • Add run to project dependencies (npm or binary distribution)
  • Document version pinning strategy for run to ensure reproducibility
  • Provide fallback mechanisms if run installation fails

Dependencies and Assumptions

External Dependencies

  • run tool: Requires run binary available in execution environment
  • Language Toolchains: Users must install language toolchains (e.g., go, rustc) separately
  • Platform Support: run binary must support target platforms (macOS, Linux, Windows)

Assumptions

  • Users understand that language support depends on host environment toolchain availability
  • CI/CD environments can install run and required language toolchains
  • run project maintains backward compatibility and active maintenance
  • Performance overhead from run is acceptable for testing use cases
  • Users will always explicitly specify the language field in their test configurations

Migration and Rollout Plan

Phase 1: Alpha (Internal Testing)

  • Implement run integration for 5 representative languages (Go, Rust, TypeScript, Ruby, Java)
  • Internal testing with Doc Detective maintainers
  • Performance benchmarking against current implementation
  • Backward compatibility validation

Phase 2: Beta (Early Adopters)

  • Expand to all 25+ languages
  • Beta release to select users via feature flag
  • Gather feedback on toolchain error messaging
  • Documentation review and iteration

Phase 3: General Availability

  • Default enable for all users
  • Full documentation published
  • Blog post / release notes highlighting new language support
  • Monitoring for regression reports

Rollback Plan

  • Feature flag allows disabling run integration
  • Fallback to previous JavaScript/Python/Bash implementation
  • Clear versioning to support users pinned to older releases

Open Questions

  1. Toolchain Installation: Should Doc Detective provide toolchain installation guidance or link to official language docs?

    • Recommendation: Link to official sources; avoid maintaining installation instructions
  2. Version Pinning: Should users be able to specify language toolchain versions (e.g., Python 3.9 vs 3.12)?

    • Recommendation: Initial release uses whatever toolchain is on PATH; defer version pinning to future iteration
  3. REPL Support: Any future use cases for exposing run's REPL functionality in tests?

    • Recommendation: Not for initial release; monitor user feedback
  4. Custom Language Support: Should users be able to add languages not supported by run?

    • Recommendation: Out of scope; encourages contribution to run project instead
  5. Compiled Language Caching: Should compilation artifacts be cached between test runs?

    • Recommendation: Delegate to run's default behavior; optimize if performance issues arise

Appendix

Language Support Matrix

Language Aliases Toolchain Required Windows Support Notes
Bash bash, sh, shell bash ✅ (via run) Cross-platform via run
C c, gcc gcc or clang Requires compiler
C++ cpp, c++, g++ g++ or clang++ Requires compiler
C# csharp, cs, dotnet .NET SDK -
Crystal crystal, cr crystal ⚠️ (Limited) Check platform support
Dart dart dart -
Elixir elixir, ex elixir -
Go go, golang go -
Haskell haskell, hs ghc -
Java java javac + JRE -
JavaScript javascript, js, node node Existing support
Julia julia, jl julia -
Kotlin kotlin, kt kotlinc + JRE -
Lua lua lua -
Nim nim nim -
Perl perl, pl perl -
PHP php php -
Python python, py python3 Existing support
R r, rscript R -
Ruby ruby, rb ruby -
Rust rust, rs rustc Compilation required
Swift swift swift ⚠️ (macOS/Linux) Limited Windows support
TypeScript typescript, ts node + ts-node or deno Transpilation required
Zig zig zig -

Example Test Case

Before (Current Limitation):

{
  "tests": [{
    "steps": [
      {
        "description": "Cannot test Go code example",
        "runCode": {
          "language": "go",
          "code": "fmt.Println(\"Hello from Go!\")"
        }
      }
    ]
  }]
}

Error: "go" is not a valid language value

After (With Enhancement):

{
  "tests": [{
    "steps": [
      {
        "description": "Test Go code example",
        "runCode": {
          "language": "go",
          "code": "fmt.Println(\"Hello from Go!\")",
          "stdio": "Hello from Go!"
        }
      },
      {
        "description": "Test Rust code example",
        "runCode": {
          "language": "rust",
          "code": "println!(\"Hello from Rust!\");",
          "stdio": "Hello from Rust!"
        }
      },
      {
        "description": "Test TypeScript code example",
        "runCode": {
          "language": "typescript",
          "code": "console.log('Hello from TypeScript!');",
          "stdio": "Hello from TypeScript!"
        }
      }
    ]
  }]
}

Success: All three language tests execute and validate output


Revision History

Version Date Author Changes
0.1 2025-10-05 Product Management Initial draft
0.2 2025-10-05 Product Management Removed automatic language detection requirement

Sub-issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions