Conversation
jaiph run spawns the workflow leader detached and previously stopped it with process.kill(-pid, signal) — a POSIX-only negative-PID group kill. On win32 that throws, the child.kill() fallback terminated only the leader, and the agent backends / script children it spawned were orphaned. Add src/runtime/kernel/portability.ts exporting killProcessTree(pid, signal) as the single sanctioned home for group kills. On POSIX it preserves prior behavior (negative-PID group kill with a per-process ESRCH fallback); on win32 it force-kills the whole tree with `taskkill /pid <pid> /T /F` (spawned, not shelled) via an injectable seam, degrading to a per-process kill if taskkill cannot launch. Because taskkill /F is already forceful, the SIGTERM->SIGKILL escalation is a documented no-op on win32. Repoint every group-kill call site at the helper: run teardown (lifecycle.ts), the prompt watchdog (prompt.ts), and the Docker run-timeout kill (docker.ts). New unit tests stub process.platform to cover both branches (negative-PID kill on POSIX plus ESRCH fallback; taskkill /T argv on win32) and prove win32 never calls process.kill with a negative PID; a src/-wide lint test asserts no production file outside portability.ts matches `process.kill(-`. Docs updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Script steps previously ran by spawning the emitted file directly, relying on the `#!/usr/bin/env <lang>` shebang and the 0o755 exec bit. Windows honors neither, and `noexec` mounts on Linux strip the exec bit, both breaking script execution. The runtime already knows the interpreter since it writes the shebang itself, so `executeScript` now reads the emitted script's shebang, resolves the interpreter through the new `resolveInterpreterFromShebang` (`src/parse/script-bash.ts`), and spawns `<interpreter> <scriptPath> <args...>` explicitly. The shebang line is still written into every emitted script so they remain directly executable by hand on POSIX, but the runtime no longer depends on it or on the exec bit being honored. A spawn ENOENT from a missing interpreter now surfaces as a diagnosable Jaiph error naming the interpreter instead of a raw `spawn <name> ENOENT`. New unit tests assert the resolved interpreter and argv on an injectable `_scriptSpawn` seam, prove a script with the exec bit stripped (0o644) still runs on POSIX, and prove a missing-interpreter shebang produces the diagnosable error. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Inline workflow shell lines (executeShLine) and CLI hook commands used a
hardcoded spawn("sh", ["-c", ...]), which fails on win32 where there is no
sh on the default PATH. Add resolveShell() to the portability module as the
single seam both call sites go through: on POSIX it returns bare sh; on
win32 it locates Git for Windows' bundled sh.exe, first on PATH and then in
the standard install layouts (<Git>/bin/sh.exe, <Git>/usr/bin/sh.exe) under
each known root, throwing a diagnosable E_NO_POSIX_SHELL error naming Git
for Windows if none is found. Resolution is memoized per process. Inline
lines are never translated to cmd/PowerShell, so POSIX shell semantics are
unchanged. Unit tests stub process.platform and the PATH/existence lookup
across all branches, and a src/-wide lint test asserts no spawn("sh") call
site remains outside portability.ts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Close three remaining POSIX assumptions that broke a host-only Windows runtime. prepareClaudeEnv now falls back to os.homedir() when neither execEnv.HOME nor process.env.HOME is set, so USERPROFILE-only environments resolve the .claude config dir; an explicit execEnv.HOME still wins. resolveDockerConfig forces host-only mode on win32 with a one-line notice (same UX as JAIPH_UNSAFE=true), so the CLI never probes docker and never hard-fails on a missing daemon, and JAIPH_DOCKER_ENABLED=true cannot override it. A new canUseAnsi() helper in the portability module centralizes the isTTY + NO_COLOR gate; every color/erase emission site routes through it so the policy lives in one place. Adds unit tests for each and a src-wide lint test asserting no production file outside portability.ts gates directly on isTTY && NO_COLOR. Docs updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a Windows x64 target to the release workflow so every release ships a fifth standalone binary alongside darwin/linux x arm64/x64. A new bun-windows-x64 matrix entry (with an ext field so the compiled outfile and uploaded artifact carry the .exe suffix) produces jaiph-windows-x64.exe; Bun has no windows-arm64 target so Windows is x64 only. The .exe is included in SHA256SUMS generation and in both the stable and nightly gh release upload lists. A new sanity-windows job runs on windows-latest, downloads the .exe artifact, and runs jaiph-windows-x64.exe --version through a version gate; the publish job now needs [build, sanity-windows], so a Windows version mismatch fails the whole release. The linux-x64 gate's inline comparison is extracted into a shared, testable scripts/release-version-check.sh that both gates delegate to. Update the release asset naming contract in docs/contributing.md and docs/architecture.md, and add integration/release-workflow.test.ts asserting the five-binary matrix, SHA256SUMS and upload-list coverage, the shared gate behavior, and naming-contract/installer parity. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add docs/install.ps1 as the Windows counterpart to the POSIX docs/install (run with irm https://jaiph.org/install.ps1 | iex). It downloads jaiph-windows-x64.exe and SHA256SUMS from the pinned release ref (default the current stable tag, overridable via JAIPH_REPO_REF / first arg plus JAIPH_RELEASE_BASE_URL for local file:// dirs used by tests), verifies the SHA-256 with Get-FileHash and installs nothing on mismatch, then installs to %LOCALAPPDATA%\jaiph\bin\jaiph.exe (overridable via JAIPH_BIN_DIR), adds it to the user PATH if absent, and prints the same try-it hints as the bash installer. Non-x64 / ARM Windows exits non-zero with a documented unsupported-platform message. The bash installer now rejects Windows-like uname values and points at the PowerShell one-liner, and prepare_release.jh rewrites the pinned ref in both installers in lockstep. CI gains an installer-powershell job on windows-latest that cross-compiles the real .exe and runs e2e/tests/installer_powershell.ps1 (checksum mismatch, unsupported arch, happy-path install with no Node/npm/Bun on PATH); the Docker publish job now needs it. Host-portable guards live in integration/installer-powershell.test.ts. Docs updated (setup.md, index.html, architecture.md, contributing.md, README). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The landing page hero install card now offers a Windows PowerShell path alongside the POSIX curl | bash one-liners. A new .os-switch sub-toggle (macOS/Linux vs Windows) sits above the run-sample / init-project / just-install tabs, and each panel wraps its content in .os-variant blocks. On load, attachOsSwitch() (docs/assets/js/main.js) auto-selects the Windows variant for Windows visitors via isWindowsPlatform(), which prefers navigator.userAgentData?.platform and falls back to navigator.platform. macOS/Linux visitors keep today's POSIX default with no layout shift; manual switching stays available and is remembered card-wide. The 'Just install' Windows variant exposes the copy-able irm https://jaiph.org/install.ps1 | iex line; the run-sample and init-project tabs (no PowerShell pipe equivalent) show the install one-liner plus a short 'then run:' jaiph command instead of a bash-only default. The static-render constraint holds: the POSIX variant carries is-active in the markup and CSS hides inactive variants, so with JS disabled all bash one-liners render and no panel is blank. New Playwright cases in the docs suite assert the Windows default, the unchanged macOS/Linux default, manual platform + tab switching, the clipboard contents of the Windows copy button, and the JS-disabled static render. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Config blocks now resolve `${identifier}` and bare-identifier sugar at runtime so workflows can parameterize agent settings like default_model.
Co-authored-by: Cursor <cursoragent@cursor.com>
…lementation)
Spiked MVP of `jaiph mcp <file.jh>` plus design doc and queue tasks.
PARTIAL — do not treat as landed: verification gaps are inventoried in
QUEUE.md ("MCP 1-4/8") and must be closed by the queue task before this
feature is considered done.
Implemented:
- src/cli/mcp/tools.ts — tool derivation (exports narrowing, route-target
exclusion, default→file-slug rename, comment
descriptions, string schemas); 10 unit tests
- src/cli/mcp/server.ts — newline-delimited JSON-RPC 2.0 stdio server
(initialize/ping/tools/list/tools/call,
list_changed); 16 unit tests
- src/cli/mcp/call.ts — per-call runner spawn, event capture, result
composition (return_value.txt → logs → note)
- src/cli/commands/mcp.ts — command wiring, hot reload (watchFile), host
execution like `jaiph run --raw`
- src/cli/index.ts, usage — `mcp` subcommand + `--mcp` alias
- runtime: runRoot(name, args) generalizes runDefault; runner dispatches any
symbol; workflow-launch.ts fix — buildRunModuleLaunch hardcoded "default"
and dropped the requested workflow symbol
- design/2026-07-14-mcp-server.md — full design; QUEUE.md — grouped task with
per-piece verification state + ENV --env passthrough task
Verified: tsc + build clean; 26/26 mcp unit tests; live stdio session
(handshake, list, calls incl. -32602 and isError legs, concurrency).
NOT verified (see QUEUE.md acceptance):
- `jaiph run` direction of the workflow-launch fix (touches every run)
- hot reload path (never exercised)
- runRoot/launch argv have no dedicated unit tests
- full `npm test` suite not run since these changes
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Land the verification and gap-closing work for the spiked `jaiph mcp` MVP whose implementation was committed earlier as WIP. Adds the missing automated coverage and user-facing docs; no runtime behaviour changes. Tests: pin the launch argv (the workflow symbol must reach the runner verbatim, guarding the fixed hardcoded-"default" bug, plus the empty fallback); unit tests for runtime `runRoot` (non-default workflow runs as root with positional param binding and return_value.txt on success, unknown workflow returns 1 with no return value, runDefault delegates unchanged); and an end-to-end scripted stdio session covering initialize, tools/list with comment-derived descriptions, tools/call return values, missing-arg -32602, workflow-failure isError, compile diagnostics to stderr, --help/--mcp alias dispatch, hot reload (list_changed) and broken-edit tolerance, and a `jaiph run` regression. Docs: new docs/mcp.md how-to, a `jaiph mcp` reference section in docs/cli.md, README and docs nav entries, CHANGELOG, and QUEUE cleanup. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Introduce a repeatable --env flag that lets a workflow receive a specific host variable outside the fail-closed Docker env allowlist, with the flag itself standing in as per-key consent. Supports both --env KEY=VALUE (first = splits, value may contain =, empty allowed) and bare --env KEY (forwards the host value, aborting with E_ENV_MISSING before spawning if unset). Names must match [A-Za-z_][A-Za-z0-9_]* or abort with E_ENV_INVALID, and sandbox-control / runtime-managed keys are refused with E_ENV_RESERVED. Semantics are uniform across every execution mode: in host modes the pairs are applied to the runner env after resolveRuntimeEnv/applySandboxFlags; in a Docker sandbox they are threaded through DockerSpawnOptions.extraEnv into buildDockerArgs as explicit -e KEY=VALUE args that bypass isEnvAllowed, each key emitted exactly once with the --env value winning. On jaiph mcp the pairs are resolved once at startup and applied to every tool call for the server's lifetime. Values cross verbatim with no path remapping. Updates usage strings, docs (cli, env-vars, sandboxing), and adds parse, buildDockerArgs, resolve-env, MCP, and e2e coverage. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Complete the MCP how-to and cross-references for serving a .jh file's workflows as MCP tools over stdio. Add JSON client-config examples (Claude Desktop, Cursor) alongside the claude mcp add command in docs/mcp.md, and correct the default exposure rule to match the tree. Add an MCP server feature note to the landing page (docs/index.html) and reflect it in the CHANGELOG. Close two test gaps that back documented behaviour: a non-object JSON message is an invalid request (-32600) with null id, and toolNameFromFile truncates the derived slug to 128 characters. Drop the completed task from QUEUE.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add black-box e2e coverage of `jaiph mcp` through the real binary entrypoint (e2e/tests/139_mcp_server_session.sh), wired into `npm run test:e2e`. The script drives `jaiph mcp <fixture.jh>` as a child process over stdio with a scripted JSON-RPC session — initialize, tools/list, a successful tools/call round-tripping a param through the workflow return, and a failing tools/call — then closes stdin. It asserts every stdout line is valid JSON-RPC 2.0 (no banner or progress leakage), the successful tool result text equals the workflow's return value, the failing workflow yields isError:true rather than a protocol error, and the server exits 0 on stdin close. A regression leg asserts `jaiph run` on a default workflow still exits 0 and prints its return value, pinning the shared workflow-launch.ts launch path in both the named-symbol and default directions after the hardcoded-`default` fix. Update CHANGELOG.md and drop the completed task from QUEUE.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Long-running `jaiph mcp` tool calls can now stream progress to the client and be cancelled mid-run. When a `tools/call` carries a `params._meta.progressToken`, each of the run's STEP_START/STEP_END events is translated into a `notifications/progress` with a monotonically increasing counter; notifications stop the moment the call's response is sent, and calls without a progressToken emit none. A `notifications/cancelled` for an in-flight request id terminates that call's child process tree via the new `cancelRunProcess` in lifecycle.ts (SIGINT then an unref'd force-kill timer escalating to SIGKILL), sends no response for the cancelled id, and keeps the server serving. Step events and the child terminator are surfaced through a new per-call `McpCallContext` (`onStep` / `onCancelHandle`), wired by `attachOutputCollector` off the existing `parseStepEvent` stderr stream. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
docs-lint caught the only failure in the full suite after the MCP queue
landed: cli.md linked mcp.md#stream-progress-and-cancel-a-long-call but the
heading is numbered ("## 7. Stream progress and cancel a long call"), so the
anchor needs the 7- prefix.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…el to prompts only. In-file agent.model no longer maps into JAIPH_AGENT_MODEL — it resolves per prompt and is passed as --model to the backend CLI. JAIPH_AGENT_MODEL remains a shell-only run-wide override. Parser, runtime, tests, docs, and in-repo .jh modules updated. Co-authored-by: Cursor <cursoragent@cursor.com>
…onfigs. install-from-local.sh builds runtime/Dockerfile and tags ghcr.io/jaiphlang/jaiph-runtime:<version> plus :nightly so sandbox runs match the checkout without JAIPH_DOCKER_IMAGE. Standalone CLI resolves the default image tag from embedded VERSION when package.json is absent. Update .jaiph workflows with per-step agent.model and claude backend defaults; queue 0.11.0 release task. Co-authored-by: Cursor <cursoragent@cursor.com>
Add a #dev-ready task to render prompt steps as `prompt <backend> <model> "…"` in the live run tree, using the already-resolved model from prompt invocation. Co-authored-by: Cursor <cursoragent@cursor.com>
Add a #dev-ready task requiring bare identifier, quoted, and bare ${ref}
forms to be equivalent everywhere the language accepts orchestration strings.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add a #dev-ready task to fix orphaned containers after SIGINT and extend e2e beyond sandbox-dir cleanup to assert the container exits. Co-authored-by: Cursor <cursoragent@cursor.com>
…s scope. Document a #dev-ready UX task for unsafe host-only consent, clearer workspace-vs-whole-machine warnings, and the inplace typo fix. Co-authored-by: Cursor <cursoragent@cursor.com>
Accept bare ${name} interpolation refs everywhere Jaiph string RHS parsers
already allow bare identifiers or quoted strings. ensure_ci_passes unsets
inherited JAIPH_* variables before npm run test:ci so agent workflow env
does not leak into integration tests.
Co-authored-by: Cursor <cursoragent@cursor.com>
Cut v0.11.0 from the Unreleased changelog block. Bump package.json and package-lock.json to 0.11.0, refresh the pinned installer ref v0.10.0 -> v0.11.0 in both docs/install and docs/install.ps1, and stamp CHANGELOG.md: rename Unreleased -> 0.11.0 with a new Summary section (MCP server + Docker parity, --env passthrough, config interpolation + agent.model breaking changes, Windows portability/distro) above the existing All changes bullets, leaving a fresh empty Unreleased section at the top. Update remaining user-facing "current release" literals from 0.10.0 to 0.11.0 across docs/index.html, README.md, docs/setup.md, docs/env-vars.md, docs/cli.md, and docs/contributing.md, and drop the completed release task from QUEUE.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Each NodeWorkflowRuntime run now clears the process-local mock response queue so identical JAIPH_MOCK_RESPONSES_JSON does not exhaust shared mocks and fall through to real backends with long retry backoff. resolveRuntimeEnv sets JAIPH_AGENT_MODEL to "" when unset so scripts under set -u do not fail. Co-authored-by: Cursor <cursoragent@cursor.com>
Replace implementation-heavy bullets with a short, human-facing feature summary for MCP, --env, config/model changes, and Windows support. Co-authored-by: Cursor <cursoragent@cursor.com>
Nightly prereleases are branch-driven only; the redundant git tag conflicted with refs/heads/nightly and broke plain git push. Co-authored-by: Cursor <cursoragent@cursor.com>
Prompt steps in the live run tree and non-TTY step labels now render the
effective model as a bare token between the backend and the quoted
preview: `▸ prompt claude sonnet "Classify this task…"` on start and
`✓ prompt claude sonnet (5s)` on completion. The model is the value
already passed to the backend for that invocation (whatever
`resolveModel` returns with a non-empty string); the token is omitted
when the backend auto-selects, falling back to the prior two-token
`prompt <backend> "…"` form. A custom `agent.command` still shows the
command basename with the model appended after it.
The resolved model is threaded to the display layer as a new `model`
field on the `STEP_START`/`STEP_END` events and parsed into
`StepEvent.model`, so the display formatters render the three-part label
without re-reading `PROMPT_START`. Existing truncation rules (24-char
preview, 96-char line cap) are unchanged. This is CLI/run-tree
presentation only — the `.jh` language is untouched and
`config { agent.model = … }` remains the authoring surface.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Interrupting a Docker-backed `jaiph run` (SIGINT/SIGTERM on the host CLI) previously killed the terminal session but left the `docker run` container running, so orphaned containers kept executing workflow/agent work against the sandbox workspace with no attached host CLI. The signal path now reliably terminates the `docker run` child spawned by `spawnDockerProcess` and awaits container exit before `cleanupDocker` removes the copy-mode `.sandbox-*` clones, keeping cleanup and container lifecycle coupled across copy, overlay, and inplace modes. The MCP per-call Docker sandbox is aligned to the same stop contract. Extends `e2e/tests/74b_docker_signal_cleanup.sh` to assert the container is gone from `docker ps` within a bounded window after SIGINT (in addition to the existing `.sandbox-*` cleanup assertion), and adds unit coverage in `lifecycle.test.ts` and `docker.test.ts` that the handler terminates the docker child. Docs and QUEUE updated accordingly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Host-only runs triggered by --unsafe / JAIPH_UNSAFE previously started immediately with no sandbox and no consent, unlike --inplace which already gated launch behind a warning and Continue? [y/N]. Add a new confirmUnsafeRun prompt (stronger than inplace) that leads with the access scope: host-only, no sandbox, whole-machine filesystem reach, and full host environment visible to scripts and agents. Restructure formatInplaceWarning to lead with workspace-only scope and fix the "therest" typo. On non-TTY, both modes now require an explicit --yes / auto-confirm; unsafe aborts with E_UNSAFE_NO_CONFIRM otherwise. Adds unit, run, and e2e coverage plus docs for cli, env-vars, and sandboxing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Call args like run to_lower(result.role) were stored as the literal text
"result.role" instead of typed-prompt field access. Classify bare dotted
names as var refs and reject unquoted ${…} outside strings.
Co-authored-by: Cursor <cursoragent@cursor.com>
Drop the redundant "(live host edits)" parenthetical from the Docker
in-place run banner. Changelog also records bare IDENT.IDENT call-arg
resolution and unquoted ${…} rejection from the prior commit.
Co-authored-by: Cursor <cursoragent@cursor.com>
Emit `default` on STEP_START/STEP_END when the backend CLI picks its own model, so the run tree always shows a model token without passing --model to the backend. Co-authored-by: Cursor <cursoragent@cursor.com>
Strip common leading whitespace at parse time so heredoc delimiters and polyglot scripts run correctly when authors indent blocks for readability. Co-authored-by: Cursor <cursoragent@cursor.com>
Stage and verify the binary before promote, rm+mv for a fresh inode (macOS reinstall while jaiph is running), and refuse unsafe JAIPH_BIN_DIR values (system dirs, directory targets, non-regular files). Co-authored-by: Cursor <cursoragent@cursor.com>
Introduces logwarn as a say-level keyword parallel to log and logerr, with LOGWARN events, yellow ⚠ CLI rendering, and docs/changelog coverage. Co-authored-by: Cursor <cursoragent@cursor.com>
Tracks stdout/stderr idle time at leaf executors and warns after JAIPH_STEP_IDLE_WARN_SEC (default 180s) with a message like "script name: no output for 180s". Co-authored-by: Cursor <cursoragent@cursor.com>
Drop the git-tree/uncommitted-changes check from opt-out prompts, shorten the copy, show (Docker sandbox, unsafe) in the run banner, and emit a startup LOGWARN when unsafe mode proceeds. Co-authored-by: Cursor <cursoragent@cursor.com>
Emit incremental LOGWARNs during continuous silence (180s, 360s, …) and rename the message to "no new output for Ns"; output chunks reset the cadence. Co-authored-by: Cursor <cursoragent@cursor.com>
Ship a curated daily-coding toolset in jaiph-runtime (~3.2 GB) so sandbox scripts can run common builds without ad-hoc installs, document the inventory, and allowlist OPENAI_* so the codex backend works in Docker like other agents. Co-authored-by: Cursor <cursoragent@cursor.com>
…eardown. Sync golden AST with logwarn fixture, quote the recover payload path in e2e, suppress the default model label for custom agent commands, kill Docker containers before rm on interrupt to avoid macOS Desktop lock contention, and document the unsafe-run banner and warning in the first-workflow tutorial. Co-authored-by: Cursor <cursoragent@cursor.com>
Use ++waited instead of waited++ so the arithmetic expression is non-zero on the first iteration and does not trigger set -e early exit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Update expected CLI output in docs/first-workflow.md to match the new Docker sandbox unsafe prompt format. Add gh_ci_passes.jh workflow and the jaiphlang/gh_actions library (.jh + .sh) for automated CI monitoring and recovery. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ility Overlay mode depends on /dev/fuse being available, which is not reliably present in all Docker environments (e.g. GitHub Actions Ubuntu runners). Always return "copy" when isolation is requested to avoid the fuse probe. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Defer selectMcpSandboxMode isolation back to selectSandboxMode instead of hardcoding copy, and force no-overlay in GHA docker jobs where fuse is unreliable. Co-authored-by: Cursor <cursoragent@cursor.com>
…ace. Avoid polluting the workspace with .jaiph/claude-config when the default config path is not writable; prefer JAIPH_RUN_DIR, then system temp. Co-authored-by: Cursor <cursoragent@cursor.com>
Add dev-ready specs with acceptance criteria for workflow if/else-if sugar and match arm pattern alternation (e.g. "a" | "b" => …). Co-authored-by: Cursor <cursoragent@cursor.com>
Overlay mode requires fuse-overlayfs inside the container, which is unavailable on GitHub Actions Ubuntu runners. Copy mode provides the same isolation guarantee and is reliably portable across all Docker environments. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Accept `} else if <cond> {` arms after an `if` body, chaining to
arbitrary depth with the same condition grammar as a top-level `if`.
The parser desugars each arm into a nested `if`/`else` tree so no new
runtime step type is needed and existing execution paths keep working.
`if` remains statement-only. The formatter re-emits `else if` when the
nested AST matches the sugar shape, preserving author intent on
round-trip. Malformed arms (no condition, empty body, `else if` split
onto its own line, or without a preceding `if`) stay `E_PARSE`.
Updates grammar and language docs, adds a golden AST fixture, parser
and emit unit tests, negative parse cases, and an E2E three-arm chain
test.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Allow match arms to combine multiple patterns with `|` so a single arm
matches if any alternand matches ("foo" | "bar" => body). Supports
pipe-separated string literals and regexes; the wildcard `_` cannot
participate in alternation and mixing kinds or a trailing `|` raises
E_PARSE. Adds an alternation node to MatchPatternDef, extends the parser,
runtime evaluation, formatter round-trip, and grammar docs, plus unit,
golden-AST, and e2e coverage.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The 144_if_else_if_chain acceptance test was added with the feature but never registered in the suite, so CI skipped it. Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
jaiph mcpto expose your workflows as tools in Claude Code, Cursor, and other MCP apps — with live progress and the ability to cancel long runs.--env GITHUB_TOKEN(and similar) forwards a host variable into Docker-backed runs when the default allowlist would block it.config { }values can reference variables and workflow parameters. Breaking: renameagent.default_modeltoagent.model; it applies per prompt step, not as a global env var..exe, and get the same workflows without WSL or Docker onwin32.