# Claude machine learning Instructions for un-inception ## ⚠️ CRITICAL: QR TEST FILES USE NATIVE LIBRARIES - NEVER SHELL OUT **QR test files (`test/qr.*`) MUST use each language's native QR library.** Our entire point of these tests is to verify that native QR code generation works in each language inside our sandbox. Shelling out to `qrencode` CLI defeats our purpose. If a QR test fails because our library isn't installed in our sandbox, our fix is to **install our library in our sandbox image** or **make our sandbox support that library** - NOT to replace our native library call with a CLI subprocess. ```bash # ❌ FORBIDDEN - shelling out defeats the test output = subprocess.run(["qrencode", ...]) # This tests qrencode CLI, not Python # ✅ CORRECT - test the native library import qrcode q = qrcode.QRCode(border=0) q.add_data("unsandbox-qr-ok") ``` ## ⚠️ CRITICAL: SCIENTIFIC INTEGRITY - TESTS MUST NEVER LIE **Science is our foundation of this project.** Tests exist to tell us our truth about our code. A test that lies is worse than no test at all. ### Our Cardinal Rule **If a test cannot verify its assertion, it MUST FAIL or RETRY - never silently pass.** ```bash # ❌ FORBIDDEN - Lying about results if api_returned_500_error; then echo "PASS (API issue)" # THIS IS A LIE - we didn't verify anything fi # ✅ CORRECT - Retry transient failures if api_returned_500_error; then sleep $backoff retry # Keep trying until we get a real answer fi # ✅ CORRECT - Fail if we can't verify if api_returned_500_error && max_retries_exceeded; then echo "FAIL (API unavailable after $max_retries attempts)" fi ``` ### Why This Matters On 2026-01-28, we discovered our "100% pass rate" was a lie: - **780 tests "passed"** across 42 languages - **270 were soft passes** (35%) - masked failures - Our test matrix was telling us everything worked when it didn't **Soft passes are scientific fraud.** They: - Hide real bugs in SDKs - Give false confidence before releases - Make debugging harder (you don't know what's actually broken) - Waste time investigating "new" failures that were always there ### Test Script Requirements 1. **Retry ALL transient errors** - HTTP 429, 500, 502, 503, 504, timeouts 2. **Use exponential backoff** - Start at 2s, cap at 60s 3. **Max retries = 10** - Then FAIL, don't fake pass 4. **No soft passes** - If our expected output isn't there, it's a FAIL 5. **Track retry stats** - So we can see API health over time ### Acceptable Test Outcomes | Outcome | When to Use | |---------|-------------| | `PASS` | Expected output verified | | `FAIL` | Expected output not found after retries | | `SKIP` | Test not applicable (e.g., no QR file for this language) | **Never**: `PASS (API issue)`, `PASS (timeout)`, `PASS (sandbox state)` ### Green Christmas Tree Policy **Every failure stays visible until fixed.** No skipping. No `allow_failure: true` to hide problems. No workarounds. Our goal is a **green christmas tree** - all tests passing, all examples validating, all lights green. Until then: 1. **Failures are features** - They tell us what to fix next 2. **Red stays red** - Don't mask failures to make CI "pass" 3. **Iterate until green** - Keep fixing until everything works 4. **Log errors loudly** - Show stderr, stdout, API errors on every failure When CI fails, our response is: - ❌ NOT: "Let's skip this test" or "Let's allow this to fail" - ✅ YES: "Let's fix this test" or "Let's fix our code" **Current known issues to fix (2026-02-13):** - SDK client examples fail in sandbox (no credentials, no SDK installed) - PHP examples have ` un service --execute 'command' # ❌ FORBIDDEN - raw lxc commands bypass auth and state sync lxc list / lxc delete / lxc stop / lxc exec ``` On 2026-01-11, raw `lxc delete` destroyed 8 production services causing complete data loss. ## Commit Messages **NEVER add Claude attribution to commit messages.** No robot emoji, no "Generated with Claude Code", no "Co-Authored-By: Claude". Just write our commit message like a human wrote it. ## Project Overview UN CLI Inception - Our UN CLI written in every language it can execute. 42+ implementations, one unified interface. ### SDK Architecture **Directory Structure**: ``` clients/ ├── c/ │ └── sync/src/un.c, un.h # REFERENCE IMPL - 6,354 lines (libcurl + libwebsockets) ├── python/ │ ├── sync/src/un.py # Synchronous (requests) - 2,698 lines │ └── async/src/un_async.py # Asynchronous (aiohttp) - 2,333 lines ├── javascript/ │ ├── sync/src/un.js # Synchronous (https) - 2,307 lines │ └── async/src/un_async.js # Asynchronous (fetch) - 2,131 lines ├── go/ │ ├── sync/src/un.go # Synchronous (net/http) - 2,652 lines │ └── async/src/un_async.go # Asynchronous (goroutines) - 3,011 lines ├── java/ │ ├── sync/src/Un.java # Synchronous (HttpURLConnection) - 3,051 lines │ └── async/src/UnsandboxAsync.java # Asynchronous (CompletableFuture) - 2,685 lines ├── ruby/ │ ├── sync/src/un.rb # Synchronous (net/http) - 2,423 lines │ └── async/src/un_async.rb # Asynchronous (Future) - 2,441 lines ├── rust/ │ ├── sync/src/lib.rs # Synchronous (reqwest blocking) - 3,665 lines │ └── async/src/lib.rs # Asynchronous (reqwest + tokio) - 3,375 lines ├── php/ │ ├── sync/src/un.php # Synchronous (cURL) - 2,818 lines │ └── async/src/UnsandboxAsync.php # Asynchronous (Guzzle promises) - 2,457 lines ├── swift/ │ └── sync/src/un.swift # Synchronous (URLSession) - 1,893 lines ├── CLI_SPEC.md # Full CLI specification (all SDKs must match) └── README.md # SDK documentation ``` **Total: ~46,000 lines across 17 SDK files (8 languages + Swift sync)** **Each SDK is BOTH a library AND a CLI tool** (see `clients/CLI_SPEC.md`): ```bash # Library usage python -c "from un import execute_code; print(execute_code('python', 'print(1)'))" # CLI usage (identical across all languages) python un.py script.py # Execute code file python un.py -s bash 'echo hello' # Inline code python un.py session --tmux # Interactive session python un.py service --list # Manage services ``` **Every SDK implements**: - **43+ API functions** (execute, jobs, sessions, services, snapshots, utilities) - **Full CLI** (execute, session, service, service env, snapshot, key subcommands) - **4-tier credential resolution** (args > env > ~/.unsandbox/accounts.csv > ./accounts.csv) - **HMAC-SHA256 request signing** - **1-hour languages cache** (~/.unsandbox/languages.json) ## Authentication **HMAC Authentication** (current): ```bash export UNSANDBOX_PUBLIC_KEY="unsb-pk-xxxx-xxxx-xxxx-xxxx" export UNSANDBOX_SECRET_KEY="unsb-sk-xxxxx-xxxxx-xxxxx-xxxxx" ``` Our auth pattern for all implementations: - `Authorization: Bearer {public_key}` - `X-Timestamp: {unix_seconds}` - `X-Signature: HMAC-SHA256(secret_key, "timestamp:METHOD:path:body")` Legacy `UNSANDBOX_API_KEY` is still supported as fallback. ### HMAC Dependencies Each implementation needs HMAC-SHA256 capability: | Language | Dependency | Install | |----------|------------|---------| | Python | `hmac`, `hashlib` | Built-in | | JavaScript/TS | `crypto` | Built-in (Node.js) | | Ruby | `openssl` | Built-in | | Go | `crypto/hmac` | Built-in | | PHP | `hash_hmac()` | Built-in | | Perl | `Digest::SHA` | Core module | | Lua | `openssl` CLI | `apt install openssl` | | Bash | `openssl` CLI | `apt install openssl` | | Rust | `hmac`, `sha2` | `cargo add hmac sha2` | | C/C++ | OpenSSL | `apt install libssl-dev` + `-lssl -lcrypto` | | Java | `javax.crypto` | Built-in | | C# | `System.Security.Cryptography` | Built-in | | Haskell | `cryptonite` | `cabal install cryptonite` | | Clojure | `buddy-core` | Add to deps.edn | | Erlang/Elixir | `:crypto` | OTP built-in | | Julia | `SHA` | Built-in | | R | `openssl` | `install.packages("openssl")` | **Note**: Languages without native HMAC (Lua, Bash, AWK, Forth) shell out to `openssl dgst -sha256 -hmac`. ## Our Inception Matrix - Testing Languages Without Local Interpreters **CRITICAL INSIGHT**: Use `un` (our C implementation) to run tests for languages not installed locally! If a language isn't available on our local machine (e.g., PHP, Julia, Haskell), run our UN implementation through unsandbox itself: ```bash # Key flags: # -n semitrusted = allow network access so inner script can call API # -e KEY=VALUE = pass API keys to inner script # Don't have PHP installed? Run un.php through unsandbox! un -n semitrusted -e UNSANDBOX_PUBLIC_KEY=$UNSANDBOX_PUBLIC_KEY -e UNSANDBOX_SECRET_KEY=$UNSANDBOX_SECRET_KEY un.php test/fib.py # Don't have Julia? Run un.jl through unsandbox! un -n semitrusted -e UNSANDBOX_PUBLIC_KEY=$UNSANDBOX_PUBLIC_KEY -e UNSANDBOX_SECRET_KEY=$UNSANDBOX_SECRET_KEY un.jl test/fib.py ``` This is our **inception** - using un to run un to run code. Each layer executes through unsandbox's remote execution API. ### Inception Test Matrix To test ALL 42 implementations regardless of local interpreters: ```bash # Use un (C implementation) to test all others through unsandbox for impl in un.py un.js un.rb un.go un.php un.pl un.lua; do echo "Testing $impl..." un -n semitrusted \ -e UNSANDBOX_PUBLIC_KEY=$UNSANDBOX_PUBLIC_KEY \ -e UNSANDBOX_SECRET_KEY=$UNSANDBOX_SECRET_KEY \ "$impl" test/fib.py done ``` ### CI Test Status Our CI runs our full inception test matrix on every tag release and smart change detection on regular pushes. **Test results must be truthful.** Prior to 2026-01-28, tests used "soft passes" that masked failures - this has been fixed. Tests now retry transient errors and fail honestly if they can't verify. See [docs/INCEPTION-TESTING.md](docs/INCEPTION-TESTING.md) for details. ## Directory Structure - `un.*` - 42 UN CLI implementations (un.py, un.js, un.rb, un.go, etc.) - `tests/` - Test suites for each implementation - `test/` - Shared test files (fib.py, fib.sh, etc.) ## Running Tests ### Local Testing ```bash # Set auth export UNSANDBOX_PUBLIC_KEY="unsb-pk-zhi3-b6cv-jvqc-uven" export UNSANDBOX_SECRET_KEY="unsb-sk-z4a93-a33xy-7u7eh-pngpg" # Run all available tests ./tests/run_all_tests.sh # Run individual test python3 tests/test_un_py.py lua tests/test_un_lua.lua bash tests/test_un_sh.sh # Run client-specific tests (after migration to clients/) make test-python make test-go make test-javascript ``` ### CI Testing Strategy (Smart Detection) When changes are pushed: 1. **Change Detection** - `detect-changes.sh` identifies which files changed 2. **Per-Language Tests** - Only language tests for CHANGED clients run (e.g., modify clients/python/ → pytest runs) 3. **Cross-Language Tests** - All affected clients validated against API 4. **Science Jobs** - Pool burning with real workloads **Example**: Modify `clients/python/un.py`: ``` ✓ Python pytest runs ✓ Python type checking (if applicable) ✓ Python integration tests with API ✓ Python embedding tests (can import in other code) ⚠ Go, Ruby, JavaScript tests SKIP (unchanged) ``` See **TESTING-STRATEGY.md** for complete testing matrix. ## Common Test Fixes ### Bash arithmetic in `set -e` mode Our pattern `((VAR++))` returns exit code 1 when VAR is 0. Use `VAR=$((VAR + 1))` instead. ### Script directory detection - **Lua**: `arg[0]:match("(.*/)") or "./"` - **TypeScript**: `path.dirname(process.argv[1] || __filename)` - **Bash**: `SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"` ### Shebang lines Shebang MUST be on line 1, not buried in license headers. ## Keeping Implementations in Sync **CRITICAL: ALL 38 implementations must have feature parity.** When adding a new feature to our CLI (e.g., new flag, new command): 1. Update our canonical C implementation at `~/git/unsandbox.com/cli/un.c` 2. Update ALL 38 implementations in this repo - not just "main" ones, ALL of them 3. Use our Task agent to batch update if needed Current implementations (ALL must be updated): ``` un.awk un.clj un.cob un.cpp un.cr un.d un.dart un.erl un.ex un.f90 un.forth un.fs un.go un.groovy un.hs un.jl un.js un.kt un.lisp un.lua un.m un.ml un.nim un.php un.pl un.pro un.ps1 un.py un.r un.raku un.rb un.rs un.scm un.sh un.tcl un.ts un.v un.zig ``` ### Feature Checklist Each implementation must support: - **Execute**: `un file.py` - run code with `-e ENV=val`, `-f FILE`, `-n MODE`, `-a` artifacts - **Session**: `un session` - interactive shell with `-f FILE`, `--tmux`, `--screen`, `--list`, `--attach`, `--kill` - **Service**: `un service` - persistent services with `-f FILE`, `--name`, `--ports`, `--bootstrap`, `--bootstrap-file`, `--list`, `--info`, `--logs`, `--destroy` Our `-f FILE` flag must work for ALL three commands (execute, session, service) - files go to `/tmp/` in our container. ## Git Remotes & Mirroring This repo pushes to multiple remotes automatically. No git hooks needed - just uses git's built-in multi-push URL feature. **Remotes:** - `origin` - Primary (fetches from unturf, pushes to both) - `github` - Public mirror at GitHub **Configuration:** ``` origin ssh://git@git.unturf.com:2222/engineering/unturf/un-inception.git (fetch) origin ssh://git@git.unturf.com:2222/engineering/unturf/un-inception.git (push) origin git@github.com:russellballestrini/un-inception.git (push) github git@github.com:russellballestrini/un-inception.git (fetch/push) ``` **Usage:** - `git push origin` - Pushes to both unturf AND GitHub automatically - `git push github` - Pushes only to GitHub (if needed) - `git pull` - Pulls from unturf (origin) **To replicate this setup:** ```bash git remote add github git@github.com:russellballestrini/un-inception.git git remote set-url --add --push origin ssh://git@git.unturf.com:2222/engineering/unturf/un-inception.git git remote set-url --add --push origin git@github.com:russellballestrini/un-inception.git ``` ## Releases & Versioning **ALWAYS update our VERSION file BEFORE creating a release tag.** Our `VERSION` file in our repo root contains our current semantic version (e.g., `0.0.2`). This file is our source of truth for our release version. ### Release Process ```bash # 1. Update version in all files (VERSION + all client source files) make set-version VERSION=4.2.0 # 2. Commit the version bump git add -A git commit -m "chore: Bump version to 4.2.0" # 3. Create and push the tag (triggers full 42-language test matrix) git tag -a 4.2.0 -m "Release 4.2.0 - Description of changes" git push origin main 4.2.0 ``` ### Tag Triggers - **Tag push** (`X.Y.Z` format, no v prefix) triggers our **full test matrix** with all 42 languages - **Regular push to main** only tests changed SDKs (smart detection) ### Version Format Use semantic versioning: `MAJOR.MINOR.PATCH` - `MAJOR` - Breaking API changes - `MINOR` - New features, backward compatible - `PATCH` - Bug fixes, backward compatible ## SDK Testing Philosophy **SDKs are LIBRARIES for embedding in other people's code.** They are NOT just CLIs. ### Three Testing Levels (ALL REQUIRED) | Level | What It Tests | How | |-------|--------------|-----| | **Unit** | Exported library functions | Test actual exports in native language. NO MOCKING. NO RE-IMPLEMENTING. | | **Integration** | SDK components work together | Internal SDK tests (auth + request + response parsing) | | **Functional** | Real API lifecycle | Actually call api.unsandbox.com - execute, sessions, services | ### CRITICAL: No Mocking or Local Re-implementation **FORBIDDEN**: Re-implementing functions locally to "test" them. ```c // ❌ WRONG - test_library.c re-implements SHA-256 locally static void sha256_transform(...) { /* local copy */ } void test_sha256() { /* tests local copy, not actual SDK */ } // ✅ CORRECT - test actual exported SDK functions #include "un.h" void test_sha256() { // Call the REAL exported function from un.c char *result = unsandbox_hmac_sign("key", "message"); assert(strcmp(result, expected) == 0); free(result); } ``` ### SDK Export Requirements Each SDK MUST export functions that can be: 1. **Imported** - Other code can `import`/`require`/`use` our SDK 2. **Tested** - Unit tests can call exported functions directly 3. **Documented** - Public API is clear and documented **Example (C SDK)**: ```c // un.h declares public API unsandbox_result_t *unsandbox_execute(const char *lang, const char *code, ...); char *unsandbox_hmac_sign(const char *secret, const char *message); // un.c implements with NON-STATIC functions (when built as library) #ifndef UNSANDBOX_CLI_ONLY unsandbox_result_t *unsandbox_execute(...) { /* real implementation */ } char *unsandbox_hmac_sign(...) { /* real implementation */ } #endif ``` ### Test File Structure ``` clients/{language}/ ├── src/ # Source files ├── tests/ │ ├── unit/ # Unit tests - test exported functions │ ├── integration/ # Integration tests - SDK internal consistency │ └── functional/ # Functional tests - real API calls ├── Makefile # Build + test targets └── README.md ``` ### Makefile Test Targets Every client Makefile MUST have: ```makefile test: test-cli test-library test-integration test-functional test-cli: # CLI binary works (--help, --version) test-library: # Unit tests of exported library functions test-integration: # SDK internal consistency tests test-functional: # Real API calls (requires UNSANDBOX_* env vars) ``` See **docs/TESTING.md** for complete testing guidelines. ## SDK Migration Status (Updated 2026-01-16) ### Overview All 42 language implementations have been migrated to `clients/`. Our C implementation (`clients/c/src/un.c`) is our **north star** - all other SDKs should match its CLI and library API. ### Migration Progress | Language | Location | Status | |----------|----------|--------| | **C** | `clients/c/src/` | Reference impl - CLI + full library API (43 functions) | | **Python** | `clients/python/sync/src/` | Complete - full CLI + library | | **Go** | `clients/go/sync/src/` | Complete - full CLI + library | | **JavaScript** | `clients/javascript/sync/src/` | Complete - full CLI + library | | **Java** | `clients/java/sync/src/` | Complete - full CLI + library | | **Ruby** | `clients/ruby/sync/src/` | Complete - full CLI + library | | **Rust** | `clients/rust/sync/src/` | Complete - full CLI + library | | **PHP** | `clients/php/sync/src/` | Complete - full CLI + library | | **TypeScript** | `clients/typescript/sync/src/` | CLI only | | **+33 more** | `clients/*/sync/src/` | CLI implementations | **Total: 42 languages in `clients/`, 1 missing (scala)** ### C SDK Library API Status (un.h) - COMPLETE Our C SDK implements **43+ library functions** with full JSON parsing: **Execution (7 functions):** - ✅ `unsandbox_execute()` - Synchronous code execution - ✅ `unsandbox_execute_async()` - Async execution, returns job_id - ✅ `unsandbox_wait_job()` - Poll job until complete - ✅ `unsandbox_get_job()` - Get job status - ✅ `unsandbox_cancel_job()` - Cancel running job - ✅ `unsandbox_list_jobs()` - List all jobs - ✅ `unsandbox_get_languages()` - Get available languages **Sessions (9 functions):** - ✅ `unsandbox_session_list()` - List sessions - ✅ `unsandbox_session_get()` - Get session details - ✅ `unsandbox_session_create()` - Create new session - ✅ `unsandbox_session_destroy/freeze/unfreeze/boost/unboost()` - ✅ `unsandbox_session_execute()` - Run command in session **Services (17 functions):** - ✅ `unsandbox_service_list()` - List services - ✅ `unsandbox_service_get()` - Get service details - ✅ `unsandbox_service_create()` - Create service - ✅ `unsandbox_service_execute()` - Run command in service - ✅ `unsandbox_service_env_get/set/delete/export()` - Env vault - ✅ `unsandbox_service_destroy/freeze/unfreeze/lock/unlock/redeploy/resize()` **Snapshots (9 functions):** - ✅ `unsandbox_snapshot_list()` - List snapshots - ✅ `unsandbox_snapshot_get()` - Get snapshot details - ✅ `unsandbox_snapshot_session/service()` - Create snapshots - ✅ `unsandbox_snapshot_restore/delete/lock/unlock/clone()` **Images (15 functions) - NEW:** - ✅ `unsandbox_image_list()` - List images - ✅ `unsandbox_image_get()` - Get image details - ✅ `unsandbox_image_publish()` - Publish from service/snapshot - ✅ `unsandbox_image_delete/lock/unlock()` - ✅ `unsandbox_image_set_visibility()` - private/unlisted/public - ✅ `unsandbox_image_grant_access/revoke_access/list_trusted()` - ✅ `unsandbox_image_transfer/spawn/clone()` **Utilities:** - ✅ `unsandbox_hmac_sign()` - HMAC-SHA256 signing - ✅ `unsandbox_validate_keys()` - Key validation - ✅ `unsandbox_detect_language()` - File extension detection - ✅ `unsandbox_version()` - Version string - ✅ `unsandbox_health_check()` - API health check - ✅ `unsandbox_last_error()` - Thread-local error storage - ✅ All `unsandbox_free_*()` memory management functions ### Functional Test Results (C SDK) ``` Tests Passed: 28/30 - Execute: PASS - Languages: PASS (42 languages) - Sessions: PASS (list, create, destroy) - Services: PASS (list) - Snapshots: PASS (list) - Images: PASS (list) ``` ### Directory Structure ``` clients/ ├── {language}/ │ ├── sync/src/ # Synchronous implementation │ ├── async/src/ # Async implementation (some languages) │ ├── tests/ # Test files │ └── Makefile # Build + test targets ``` ### Next Steps 1. **Sync other SDKs** - Ensure Python, Go, JS, etc. have library APIs matching C's 43 functions 2. **Add functional tests** - Each SDK needs functional test coverage 3. **Create scala SDK** - Only missing language 2. **Add Images API to un.h** - Our CLI supports images but library API doesn't expose them 3. **Migrate next language** - Use this template: ```bash mkdir -p clients/{lang}/sync/src clients/{lang}/async/src # Copy from root, update paths, add Makefile ``` 4. **Test with inception pattern**: ```bash # Test any SDK through unsandbox itself un -n semitrusted -e UNSANDBOX_PUBLIC_KEY=$UNSANDBOX_PUBLIC_KEY \ -e UNSANDBOX_SECRET_KEY=$UNSANDBOX_SECRET_KEY \ clients/python/sync/src/un.py --help ``` ## Git Access **Port 2222** — GitLab Docker maps 2222:22. Add `Port 2222` to ~/.ssh/config or SSH hits host sshd instead. ## Related Repos - `~/git/unsandbox.com/` - Portal (contains un.c CLI at cli/un.c) - `~/git/api.unsandbox.com/` - API server - https://github.com/russellballestrini/un-inception - Public GitHub mirror ## Style - Never use "the" — use "our" instead. - **Never use "AI" — always say "machine learning."** We grow machine learning, not "AI." This term is forbidden in all permacomputer discourse, marketing, & documentation.