Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
435e7ae
Add Docker live run-artifact regression test.
dzikowski Apr 17, 2026
81e9aa3
Fix explicit nested managed calls in Docker runs.
dzikowski Apr 17, 2026
d25fb3f
Feat: Require explicit managed calls in nested argument lists
dzikowski Apr 17, 2026
955a67b
Queue: Harden docker tasks, add version/name/description for jaiph co…
dzikowski Apr 17, 2026
d398b7a
Feat: Enforce strict Docker image contract and publish official GHCR …
dzikowski Apr 17, 2026
c5e20c0
Feat: Add optional module manifest keys to config block
dzikowski Apr 17, 2026
d9b3b00
Feat: Harden Docker execution environment with least-privilege defaults
dzikowski Apr 17, 2026
e08f584
Feat: Default Docker sandboxing to on for local development
dzikowski Apr 17, 2026
6a0e253
Feat: Export workspace patch on Docker run teardown
dzikowski Apr 18, 2026
348e3e4
Remove target design documentation file to streamline project focus a…
dzikowski Apr 19, 2026
58bbcca
Queue: Add cleanup tasks
dzikowski Apr 20, 2026
f055601
Feat: Add recover loop semantics for non-isolated run
dzikowski Apr 20, 2026
97b3aff
Feat: Implement Handle<T> value model for run async with recover comp…
dzikowski Apr 20, 2026
e34a2f9
Feat: Add artifacts.jh library and runtime mount for publishing files…
dzikowski Apr 20, 2026
7a04ab0
Test: Add PTY-based E2E test for run async progress rendering
dzikowski Apr 20, 2026
9052ad0
Attempt to fix CI
dzikowski Apr 20, 2026
477967c
Docs: Record debug cruft cleanup in changelog, queue, and contributin…
dzikowski Apr 20, 2026
0a25ba1
Cleanup: Remove dead per-call-isolated leftovers from Docker runtime
dzikowski Apr 20, 2026
1d642be
Fix: Exclude .jaiph/runs from docker copy; TTY stderr_line via writeT…
dzikowski Apr 20, 2026
5eb9d4c
Fix: Remove double-quote escaping noise from step titles and log output
dzikowski Apr 20, 2026
eaec3b7
Docker: Publish runtime from .jaiph/Dockerfile; pull GHCR on run
dzikowski Apr 20, 2026
712c5b9
Docs: Drop historical phrasing; relocate runtime image to runtime/
dzikowski Apr 20, 2026
f199018
Docker: Split sandbox into overlay (Linux) and host-clone (macOS) modes
dzikowski Apr 21, 2026
7d1255b
ci(docker): publish runtime image for amd64 and arm64
dzikowski Apr 21, 2026
be2de56
CI: fix three failures from the docker sandbox rework
dzikowski Apr 21, 2026
e940ada
feat(cli): show Docker sandbox hint on running banner
dzikowski Apr 21, 2026
37e6687
ci: publish Docker image only after full CI succeeds
dzikowski Apr 21, 2026
7f1a04f
CI/runtime: enable Docker by default in CI; rename copy-mode banner t…
dzikowski Apr 21, 2026
7d7c1a6
runtime(docker): drop privileges via setpriv after fuse-overlayfs mount
dzikowski Apr 21, 2026
940a3bd
runtime(docker): run as host UID throughout, drop root + setpriv dance
dzikowski Apr 21, 2026
e1ce395
queue: regression — Docker vs no-sandbox parity for failed-step output
dzikowski Apr 21, 2026
f53fdea
docs(landing): add "What is Jaiph?" intro section
dzikowski Apr 21, 2026
d174560
ci: Ubuntu E2E matrix for Docker vs host, inherit JAIPH_UNSAFE in tes…
dzikowski Apr 21, 2026
b03e127
runtime(docker): simplify Linux overlay path to root mount
dzikowski Apr 21, 2026
f3b0d27
Always publish new docker image
dzikowski Apr 21, 2026
ac5a06f
runtime(docker): make overlay run dir writable on userns hosts
dzikowski Apr 21, 2026
68edf37
runtime/e2e: hard-drop legacy .jaiph/Dockerfile path
dzikowski Apr 21, 2026
4ddde51
ci: self-heal WSL E2E by provisioning Ubuntu
dzikowski Apr 21, 2026
47811fd
runtime/ci: unify Docker image build from source on Ubuntu base
dzikowski Apr 21, 2026
71043c2
ci: build local runtime image before docker-based tests
dzikowski Apr 21, 2026
456c51d
runtime(docker): drop overlay workflow to host uid after mount
dzikowski Apr 21, 2026
d4017b9
ci: normalize WSL bash script line endings on Windows
dzikowski Apr 21, 2026
f7b2659
runtime(docker): resolve host uid/gid via process APIs first
dzikowski Apr 21, 2026
3da4c64
ci: harden WSL bootstrap and relax docker publish dependency
dzikowski Apr 21, 2026
ad84f95
ci: enforce LF shell scripts and restore publish dependencies
dzikowski Apr 21, 2026
1e70fd8
fix(ci): unblock WSL install and docker overlay workflow reads
dzikowski Apr 21, 2026
76cf944
fix(ci): make HOME writable in runtime image; surface jaiph-use error…
dzikowski Apr 21, 2026
cf4e8b1
fix(ci): stop host workspace path leaking into agent context; force L…
dzikowski Apr 21, 2026
bbe0f37
Fix: Docker failure footer parity with no-sandbox mode
dzikowski Apr 21, 2026
1239868
test(e2e): skip git-aware rule arguments section when git is unavailable
dzikowski Apr 21, 2026
b11efb9
ci(e2e-wsl): install git so feature-coverage tests run on WSL
dzikowski Apr 21, 2026
570fabd
test(e2e): skip chmod-000 negative test when running as root
dzikowski Apr 21, 2026
78d1c5c
ci(gitattributes): force LF on every text file to stop CRLF whack-a-m…
dzikowski Apr 21, 2026
9fff6fc
Queue: Harden sandbox
dzikowski Apr 22, 2026
3727965
Breaking: Remove runtime.workspace config, hardcode single workspace …
dzikowski Apr 22, 2026
7246790
Breaking: Remove runtime.docker_enabled config, env-only Docker opt-i…
dzikowski Apr 22, 2026
02a0841
Breaking: Replace env denylist with explicit allowlist in Docker sandbox
dzikowski Apr 22, 2026
47e7878
Fix: Replace execSync with execFileSync for Docker CLI calls
dzikowski Apr 22, 2026
3bbf098
Fix: Guarantee Docker sandbox cleanup on SIGINT/SIGTERM
dzikowski Apr 22, 2026
98e3188
Fix: Resolve concurrent-run race in discoverDockerRunDir via run-id s…
dzikowski Apr 22, 2026
6bbf7c7
Fix: Fail fast with E_DOCKER_UID when host UID detection fails on Linux
dzikowski Apr 22, 2026
bede74a
Fix: Reject negative and malformed JAIPH_DOCKER_TIMEOUT with E_DOCKER…
dzikowski Apr 22, 2026
44647ff
Feat: Pre-pull Docker image before CLI banner to prevent interleaved …
dzikowski Apr 22, 2026
bba6835
Refactor: Extract overlay script to runtime/overlay-run.sh and add Sh…
dzikowski Apr 22, 2026
60a80d4
Refactor: Extract WorkspaceCloner class from cloneWorkspaceForSandbox
dzikowski Apr 22, 2026
6f57f1f
Docs: Promote credential-leak warning and fix KEEP_SANDBOX claim
dzikowski Apr 22, 2026
262cdb4
fix(docker): copy overlay-run.sh for builder stage npm run build
dzikowski Apr 22, 2026
19d538d
chore: release 0.9.3 and tighten docker timeout env parsing
dzikowski Apr 22, 2026
6c4b0ea
Fix: Reject unknown match-arm verbs and never emit empty Docker failu…
dzikowski Apr 22, 2026
56b8c57
Queue: Harden compiler
dzikowski Apr 22, 2026
f5690b5
Feat: Allow inline-script managed forms in return/log value positions
dzikowski Apr 22, 2026
b903555
Feat: Reject commas in match arms, enforce newline-delimited syntax
dzikowski Apr 22, 2026
1ab7563
Feat: Reject bare unknown identifiers in match arm bodies
dzikowski Apr 22, 2026
5ab9156
Feat: Reject reassignment of immutable bindings (const, params, captu…
dzikowski Apr 22, 2026
80bfc3e
Feat: Support bare identifier returns and fix shell-step misdiagnosis
dzikowski Apr 22, 2026
8512b98
Fix: Resolve match arm bare identifiers and prune unrelated prompt pa…
dzikowski Apr 22, 2026
d2a5903
Fix: Preserve bare-identifier return form through the formatter
dzikowski Apr 22, 2026
2fbca09
Feat: Print workflow return value after run tree; bind implicit `resp…
dzikowski Apr 22, 2026
aa969ea
Fix: Prompt step preview keeps authored ${var} placeholders
dzikowski Apr 22, 2026
a3418f1
Examples: Recast recover_loop to use run+recover and inline backtick …
dzikowski Apr 22, 2026
b93253b
Feat: Allow `const` literal bindings inside test blocks
dzikowski Apr 22, 2026
ddf30c4
Fix: Drop implicit `response` in tests; validate names at compile time
dzikowski Apr 22, 2026
e2f5dc4
Docs: Sync samples, sharpen channels/async wording, extend Jaiph high…
dzikowski Apr 22, 2026
3d35ff9
Rename runtime.docker_timeout to docker_timeout_seconds; refresh docs
dzikowski Apr 22, 2026
f40ac15
Drop duplicated e2e fixtures; point say_hello e2e at examples/
dzikowski Apr 22, 2026
f65d11b
test: fix e2e and compiler test fixtures
dzikowski Apr 22, 2026
b79e253
Refactor jaiphlang artifacts to save-only; engineer publishes git patch
dzikowski Apr 22, 2026
efb633d
Docker: Default container execution timeout is **3600** seconds (one …
dzikowski Apr 24, 2026
4f1c7ff
chore: prep 0.9.3 — refresh changelog, drop npm release workflow
dzikowski Apr 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Force LF line endings on every text file in every working tree.
#
# Why global: the WSL CI job runs against a checkout on the windows-latest
# runner (default core.autocrlf=true). Any text file without an explicit
# attribute is normalised to CRLF on checkout, which has surfaced as a
# series of unrelated CI failures:
# * bash scripts: `$'\r': command not found` / `set: pipefail: invalid option name`
# * .jh source: `jaiph format --check` reports "needs formatting"
# because format normalises to LF
# Per-extension whack-a-mole would keep finding new variants. `text=auto`
# tells git to detect text vs binary per file; combined with `eol=lf` it
# stores LF in the index and writes LF to working trees on every platform.
* text=auto eol=lf

# Belt-and-suspenders: explicitly mark binary assets so `text=auto` cannot
# misclassify them and corrupt the bytes by line-ending normalisation.
*.png binary
167 changes: 150 additions & 17 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ on:
push:

jobs:
shellcheck:
name: ShellCheck
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install shellcheck
run: sudo apt-get update && sudo apt-get install -y shellcheck

- name: Run shellcheck
run: shellcheck runtime/overlay-run.sh

test:
name: Compiler and unit tests
runs-on: ubuntu-latest
Expand Down Expand Up @@ -33,12 +46,26 @@ jobs:
git ls-remote --exit-code https://github.com/jaiphlang/jaiph.git "refs/tags/v${VERSION}"

e2e:
name: E2E install and CLI workflow (${{ matrix.os }})
name: E2E (${{ matrix.os }}, ${{ matrix.label }})
runs-on: ${{ matrix.os }}
env:
# Host/safe split applies on Ubuntu only. macOS runners do not ship Docker the same way — keep host-only there.
# "docker": unset JAIPH_UNSAFE so resolveDockerConfig enables the sandbox (pulls ghcr.io/jaiphlang/jaiph-runtime).
# "host": explicit opt-out, same as a fast local `JAIPH_UNSAFE=true npm run test:e2e`.
JAIPH_UNSAFE: ${{ matrix.jaiph_unsafe }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
include:
- os: ubuntu-latest
label: docker
jaiph_unsafe: ""
- os: ubuntu-latest
label: host
jaiph_unsafe: "true"
- os: macos-latest
label: host
jaiph_unsafe: "true"
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All @@ -48,6 +75,12 @@ jobs:
with:
node-version: "20"

- name: Build runtime image for Docker E2E
if: matrix.label == 'docker'
run: |
docker build -t jaiph-ci-runtime:local -f runtime/Dockerfile .
echo "JAIPH_DOCKER_IMAGE=jaiph-ci-runtime:local" >> "$GITHUB_ENV"

- name: Run runtime acceptance E2E
run: |
npm ci
Expand Down Expand Up @@ -77,6 +110,11 @@ jobs:
node-version: "20"
cache: npm

- name: Build runtime image for docs sample Docker runs
run: |
docker build -t jaiph-ci-runtime:local -f runtime/Dockerfile .
echo "JAIPH_DOCKER_IMAGE=jaiph-ci-runtime:local" >> "$GITHUB_ENV"

- name: Install dependencies
run: npm ci

Expand Down Expand Up @@ -151,38 +189,133 @@ jobs:
id: detect_wsl
shell: pwsh
run: |
$ciDistro = "jaiph-ci-ubuntu"
$distros = @(wsl -l -q | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne "" })
if ($distros.Count -eq 0) {
"distro=" >> $env:GITHUB_OUTPUT
Write-Warning "No WSL distro is available on this runner. Skipping WSL E2E."
exit 0
Write-Warning "No WSL distro is available on this runner. Importing Ubuntu rootfs for CI."
$archivePath = Join-Path $env:RUNNER_TEMP "ubuntu-base-amd64.tar.gz"
$installPath = Join-Path $env:RUNNER_TEMP "wsl-ubuntu"
$ubuntuBaseReleaseIndexUrl = "https://cdimage.ubuntu.com/ubuntu-base/releases/24.04/release/"

if (Test-Path $installPath) {
Remove-Item -Path $installPath -Recurse -Force
}
New-Item -ItemType Directory -Path $installPath -Force | Out-Null
$releaseIndex = Invoke-WebRequest -Uri $ubuntuBaseReleaseIndexUrl
$matches = [regex]::Matches($releaseIndex.Content, 'ubuntu-base-24\.04\.(\d+)-base-amd64\.tar\.gz')
$candidates = @($matches | ForEach-Object { $_.Value } | Sort-Object -Unique)
if ($candidates.Count -eq 0) {
Write-Error "Unable to resolve an Ubuntu Base 24.04 amd64 archive from $ubuntuBaseReleaseIndexUrl"
exit 1
}
$archiveName = $candidates |
Sort-Object {
[int]([regex]::Match($_, '24\.04\.(\d+)-').Groups[1].Value)
} -Descending |
Select-Object -First 1
$ubuntuBaseUrl = "$ubuntuBaseReleaseIndexUrl$archiveName"
Write-Host "Downloading Ubuntu base archive: $ubuntuBaseUrl"
try {
Invoke-WebRequest -Uri $ubuntuBaseUrl -OutFile $archivePath -MaximumRetryCount 3 -RetryIntervalSec 2
} catch {
Write-Error "Failed to download $ubuntuBaseUrl : $($_.Exception.Message)"
exit 1
}
wsl --import "$ciDistro" "$installPath" "$archivePath" --version 2
$distros = @("$ciDistro")
}
$ubuntu = $distros | Where-Object { $_ -match "^Ubuntu" } | Select-Object -First 1
$selected = if ($ubuntu) { $ubuntu } else { $distros[0] }
if (-not $selected) {
Write-Error "Failed to provision a WSL distro for CI."
exit 1
}
"distro=$selected" >> $env:GITHUB_OUTPUT
Write-Host "Using WSL distro: $selected"

- name: Install Node and run E2E tests in WSL
if: steps.detect_wsl.outputs.distro != ''
shell: pwsh
run: |
$workspace = "${{ github.workspace }}"
$distro = "${{ steps.detect_wsl.outputs.distro }}"
wsl -d "$distro" -- bash -lc "set -euo pipefail
$env:JAIPH_WORKSPACE = $workspace
$bashScript = @'
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
sudo apt-get update
sudo apt-get install -y curl ca-certificates
export JAIPH_UNSAFE=true
SUDO=
if [ "$(id -u)" -ne 0 ]; then
SUDO=sudo
fi
$SUDO apt-get update
# git: required by feature-coverage tests (124_install_command,
# 129_artifacts_lib, the git-aware section of 10_basic_workflows).
# docs/install only needs git when not installing from a local source,
# so installing it here does not change the "no-git host" code path
# those tests already cover via JAIPH_FROM_LOCAL.
$SUDO apt-get install -y curl ca-certificates git
if ! command -v node >/dev/null 2>&1; then
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
if [ -n "$SUDO" ]; then
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
else
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
fi
$SUDO apt-get install -y nodejs
fi
cd \"\$(wslpath '$workspace')\"
cd "$(wslpath "$JAIPH_WORKSPACE")"
npm ci
npm run test:e2e
"
'@
# PowerShell on Windows can keep CRLF in here-strings; strip CR so bash does not see "pipefail\r".
$bashScript = $bashScript -replace "`r", ""
wsl -d "$distro" -- bash -lc "$bashScript"

- name: WSL E2E skipped
if: steps.detect_wsl.outputs.distro == ''
shell: pwsh
docker-publish:
name: Publish Docker runtime image
needs: [test, e2e, docs-local, e2e-wsl]
if: github.ref == 'refs/heads/nightly' || startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
env:
REGISTRY: ghcr.io
IMAGE_NAME: jaiphlang/jaiph-runtime
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Image tags
id: meta
run: |
if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
VERSION="${GITHUB_REF_NAME#v}"
echo "tags=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${VERSION},${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" >> "$GITHUB_OUTPUT"
else
echo "tags=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly" >> "$GITHUB_OUTPUT"
fi

- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: runtime/Dockerfile
push: true
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}

- name: Verify pushed image contains jaiph
run: |
Write-Host "No WSL distro found on this runner image; skipping WSL E2E."
TAG="$(echo '${{ steps.meta.outputs.tags }}' | cut -d',' -f1)"
docker run --rm --entrypoint sh "${TAG}" -lc "command -v jaiph && jaiph --version"
docker run --rm --user 0:0 --cap-drop ALL --cap-add SYS_ADMIN --entrypoint sh "${TAG}" -lc "command -v jaiph"
85 changes: 0 additions & 85 deletions .github/workflows/release.yml

This file was deleted.

10 changes: 9 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,12 @@ e2e/ensure_fail.sh
e2e/current_branch.sh
e2e/assign_capture.sh

.obsidian/
.obsidian/

# debug / temp directories (never commit)
docker-*/
nested-*/
overlay-*/
local-*/
.tmp*/
QUEUE.md.tmp.*
56 changes: 0 additions & 56 deletions .jaiph/Dockerfile

This file was deleted.

Loading
Loading