-
Notifications
You must be signed in to change notification settings - Fork 0
Description
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
- Expand Language Support: Add 22+ new programming languages to
runCodeaction - Maintain Backward Compatibility: Ensure existing
runCodetests continue working without modification - Unified Execution Interface: Provide consistent behavior across all supported languages
- Cross-Platform Reliability: Eliminate platform-specific language support gaps (e.g., Bash on Windows)
- Preserve Existing Features: Maintain all current
runCodecapabilities (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
runwill not be exposed - Automatic Language Detection: Users must explicitly specify the
languagefield for all code execution - Language-Specific Configuration: Advanced per-language flags or compiler options beyond what
runprovides by default - Custom Language Engines: Ability to add languages not supported by
run
Success Metrics
User Adoption
- Target: 30% of existing
runCodeusers adopt at least one new language within 90 days of release - Measurement: Telemetry tracking unique language values in
runCode.languagefield
Language Coverage
- Target: Support 25+ languages at launch (matching
runcapabilities) - Measurement: Count of distinct, tested languages in schema enum
Backward Compatibility
- Target: 100% of existing
runCodetests 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
runCodesteps 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
runCodetests pass without schema or behavior changes - Execution behavior for JavaScript, Python, and Bash remains identical
- No new required fields added to
runCodeschema
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
languagefield 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
runCodetest 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 mainandfunc 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,$$exitCodeexpressions 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
runCodeaction 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
languagefield 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
runbinary as npm/project dependency - Invoke
run --lang <language> --code <snippet>for each execution - Parse stdout/stderr/exit codes from
runprocess
Option B: Library Integration
- Investigate if
runexposes library API for embedding - Minimize process spawning overhead
- Direct access to language engines
Option C: Hybrid Approach
- Use
runbinary 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
runto project dependencies (npm or binary distribution) - Document version pinning strategy for
runto ensure reproducibility - Provide fallback mechanisms if
runinstallation fails
Dependencies and Assumptions
External Dependencies
- run tool: Requires
runbinary available in execution environment - Language Toolchains: Users must install language toolchains (e.g.,
go,rustc) separately - Platform Support:
runbinary must support target platforms (macOS, Linux, Windows)
Assumptions
- Users understand that language support depends on host environment toolchain availability
- CI/CD environments can install
runand required language toolchains runproject maintains backward compatibility and active maintenance- Performance overhead from
runis acceptable for testing use cases - Users will always explicitly specify the
languagefield in their test configurations
Migration and Rollout Plan
Phase 1: Alpha (Internal Testing)
- Implement
runintegration 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
runintegration - Fallback to previous JavaScript/Python/Bash implementation
- Clear versioning to support users pinned to older releases
Open Questions
-
Toolchain Installation: Should Doc Detective provide toolchain installation guidance or link to official language docs?
- Recommendation: Link to official sources; avoid maintaining installation instructions
-
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
-
REPL Support: Any future use cases for exposing
run's REPL functionality in tests?- Recommendation: Not for initial release; monitor user feedback
-
Custom Language Support: Should users be able to add languages not supported by
run?- Recommendation: Out of scope; encourages contribution to
runproject instead
- Recommendation: Out of scope; encourages contribution to
-
Compiled Language Caching: Should compilation artifacts be cached between test runs?
- Recommendation: Delegate to
run's default behavior; optimize if performance issues arise
- Recommendation: Delegate to
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 |
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 |
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 |