Skip to content

v0.9.3#14

Open
dzikowski wants to merge 22 commits intomainfrom
nightly
Open

v0.9.3#14
dzikowski wants to merge 22 commits intomainfrom
nightly

Conversation

@dzikowski
Copy link
Copy Markdown
Contributor

No description provided.

dzikowski and others added 10 commits April 17, 2026 15:55
Protect the host-mounted .jaiph/runs contract by asserting Docker-backed runs create and grow step .out/.err files before the workflow exits.

Made-with: Cursor
Keep nested run/ensure calls explicit across validation, formatting, and runtime execution, and make Docker use the local Jaiph package with a writable workspace fallback so container behavior matches local runs.

Made-with: Cursor
Enforce that nested call-like expressions inside argument positions must
use an explicit `run` or `ensure` keyword. Bare call-like forms
(`run foo(bar())`, `run foo(rule_bar())`, `run foo(\`echo x\`())`,
`const x = bar()`) are now rejected at compile time with actionable
error messages. The explicit forms (`run foo(run bar())`,
`run foo(ensure rule_bar())`, `run foo(run \`echo x\`())`) execute
the nested call first and pass the result as a single argument.

Validator extended with inline script detection, runtime evaluates
managed argument tokens before outer dispatch, and the formatter
round-trips all valid nested forms. Regression tests cover all
accepted and rejected patterns. Docs and grammar updated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nfig file

Signed-off-by: Jakub Dzikowski <jakub.t.dzikowski@gmail.com>
…runtime images

Remove all auto-derivation and runtime bootstrap paths from Docker mode.
The runtime no longer builds derived images via npm pack or installs
jaiph into arbitrary base images at run time. Every Docker image must
already contain a working jaiph CLI; missing jaiph now fails fast with
an actionable error.

Default docker_image switches from node:20-bookworm to the official
ghcr.io/jaiphlang/jaiph-runtime image. A new CI workflow publishes
that image for release tags and nightly builds. Docs, init scaffolding,
and E2E tests are updated to reflect the strict contract.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Support module.name, module.version, and module.description as optional
string keys in the module-level config { } block. Values are stored on
WorkflowMetadata.module as descriptive metadata only — they do not
affect agent, run, or runtime behavior. Workflow-level config blocks
reject module.* keys with E_PARSE, consistent with the existing
runtime.* guard. The formatter round-trips all three keys. Unit tests
cover happy path, partial keys, coexistence, round-trip, and
workflow-level rejection. Docs and grammar updated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add mount denylist rejecting dangerous host paths (/, /proc, /sys, /dev,
Docker socket) at validation time with E_VALIDATE_MOUNT. Add environment
variable denylist (SSH_*, GPG_*, AWS_*, GCP_*, AZURE_*, GOOGLE_*, DOCKER_*,
KUBE*, NPM_TOKEN*) preventing host credential leakage into containers.
Launch containers with --cap-drop ALL --cap-add SYS_ADMIN --security-opt
no-new-privileges for least-privilege capability control.

Document threat model in docs/sandboxing.md covering what Docker does and
does not protect against (hooks on host, network egress, agent credential
forwarding, image supply chain, container escapes). Add failure-modes
reference table, expanded network-mode guidance, and env denylist spec.
Unit tests cover all new validation and filtering paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Docker is now enabled by default when neither CI=true nor
JAIPH_UNSAFE=true is set in the environment. This makes sandboxed
execution the safe default for local development while keeping Docker
off in CI (where it is typically unavailable or redundant) and when
the user explicitly opts out via JAIPH_UNSAFE=true.

Precedence: JAIPH_DOCKER_ENABLED env > in-file runtime.docker_enabled
> CI/unsafe default rule. The test harness and E2E runner set
JAIPH_UNSAFE=true so existing tests continue to run on host.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Docker runs enforce an immutability contract: the host workspace is
bind-mounted read-only and /jaiph/workspace is a sandbox-local
copy-on-write layer discarded on exit. The only persistence channel
to the host is the run-artifacts directory. During teardown, the
runtime now automatically exports a workspace.patch file (git diff
--binary) into the run directory so sandbox edits can be reviewed or
applied on the host. Patch export is best-effort, owned by the
runtime (not workflow logic), and runs regardless of workflow exit
status. When there are no changes, the file is omitted.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nd eliminate outdated content.

Signed-off-by: Jakub Dzikowski <jakub.t.dzikowski@gmail.com>
dzikowski and others added 12 commits April 20, 2026 13:57
Signed-off-by: Jakub Dzikowski <jakub.t.dzikowski@gmail.com>
Introduce `recover` as a first-class repair-and-retry primitive for
`run` steps, distinct from the existing one-shot `catch`. When a run
step fails, the recover block binds the error, executes a repair body,
and retries the step in a loop until it succeeds or the retry limit
(default 10, configurable via `config`) is exhausted.

Covers parser, formatter, validator, runtime, e2e acceptance test, and
docs-site syntax highlighting for the new keyword.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…osition

Replace the implicit end-of-workflow join with a first-class Handle<T>
that run async returns immediately. Handles resolve transparently on
first non-passthrough read (argument passing to run, interpolation,
comparison, branching) while passthrough operations (assignment, list
storage, unchanged forwarding) leave them unresolved. Workflow exit
implicitly joins any remaining unresolved handles.

Ship recover composition for run async in the same change: the parser
now accepts recover(err) { ... } after run async ref(args), and the
runtime wires up the same retry-limit semantics used by non-async
recover. Includes the spec document, parser/formatter/runtime tests,
updated grammar and language docs, and syntax highlighter support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… out of the sandbox

Introduce a two-layer artifacts system for workflows running inside the
Docker sandbox (or on the host). The runtime layer creates a
.jaiph/runs/<run_id>/artifacts/ directory before workflow execution and
exposes its path via the JAIPH_ARTIFACTS_DIR env var (resolving to
/jaiph/run/artifacts in the container, the host path otherwise). The
library layer ships .jaiph/libs/jaiphlang/artifacts.jh paired with
artifacts.sh, providing three export workflow entries: save (copy a file
into artifacts), save_patch (git diff excluding .jaiph/), and
apply_patch (git apply). The library mirrors the existing queue.jh
pattern. Includes runtime unit tests, an E2E test, and docs updates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Exercise the live TTY progress tree path for `run async` workflows
under a real pseudo-terminal. The test spawns `jaiph run` with two
concurrent async branches (branch_a, branch_b), each emitting
deterministic progress events via log and script steps with sleeps.
A Python pty.openpty() harness captures the raw PTY stream and asserts
per-branch events render under correct subscript nodes (₁, ₂), resolved
Handle<T> return values appear in the final frame, and no orphaned ANSI
escape sequences survive after CSI stripping. This closes the regression
gap left by the sync-only 81_tty_progress_tree.sh test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Jakub Dzikowski <jakub.t.dzikowski@gmail.com>
…g guide

The actual filesystem cleanup (deleting 22+ leftover debug directories,
removing tracked cruft files safe_name and QUEUE.md.tmp.4951, and adding
.gitignore patterns for docker-*/, nested-*/, overlay-*/, local-*/,
.tmp*/, QUEUE.md.tmp.*) was committed earlier. This commit records the
bookkeeping side:

- CHANGELOG.md: add entry describing the cleanup and disposition of
  safe_name, lib/, and run/ (all deleted — no live consumers found).
- QUEUE.md: remove the completed task from the queue.
- docs/contributing.md: add "Workspace hygiene" section documenting the
  .gitignore patterns and how to override them with git add -f.

Disposition of investigated paths:
  - safe_name: deleted (tracked file, no live consumers)
  - lib/: deleted (empty top-level directory, no live consumers)
  - run/: deleted (empty top-level directory, no live consumers)

No code changes; documentation and queue bookkeeping only.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Delete exportWorkspacePatch and findRunArtifacts from src/runtime/docker.ts,
exportPatchIfDocker from node-workflow-runtime.ts, and the findRunArtifacts
call in src/cli/commands/run.ts. These functions served the abandoned per-call
isolated keyword and are fully replaced by the artifacts.jh library
(artifacts.save_patch() for workspace patches, JAIPH_ARTIFACTS_DIR for
artifact discovery). Also removes ~150 LoC of dead tests in docker.test.ts
and updates docs (sandboxing.md, architecture.md, artifacts.md) to reflect
the removal.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…TYLine

When fuse overlay is unavailable, rsync and the cp fallback no longer copy
.jaiph/runs; emit a clear stderr line before the temp workspace copy.

In TTY mode, stderr_line events use writeTTYLine so lines show immediately
without clearing/redrawing the running status line.

Add QUEUE item for agent_inbox workflow quoting noise.

Signed-off-by: Jakub Dzikowski <jakub.t.dzikowski@gmail.com>
Strip backslash-escaped quotes from display formatting so workflow step
labels and log lines render human-readably. Three layers changed:
formatNamedParamsForDisplay and formatParamsForDisplay no longer escape
inner double quotes with backslash (the surrounding key="value"
delimiters are structural, not shell-safe); formatStartLine in display.ts
applies the same change for prompt previews; and node-workflow-runtime
strips outer quotes from interpolated channel-send payloads via
stripOuterQuotes so messages flow through dispatch without literal quote
wrappers. Regression tests added; E2E golden output updated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- CI: build/push ghcr.io/jaiphlang/jaiph-runtime from .jaiph/Dockerfile on
  nightly branch (:nightly) and version tags (:<semver>, :latest); pass
  JAIPH_REPO_REF for install ref.
- Runtime: resolveImage always uses configured/default image with pull +
  jaiph check; stop auto docker build of workspace .jaiph/Dockerfile on
  jaiph run (keep runtime.docker_image / JAIPH_DOCKER_*).
- Docs and E2E aligned; unit test contract updated for resolveImage.

Signed-off-by: Jakub Dzikowski <jakub.t.dzikowski@gmail.com>
- Move published Docker recipe to runtime/Dockerfile; CI builds from runtime/.
- jaiph init: stop creating .jaiph/Dockerfile; bootstrap prompt and tests/e2e updated.
- Reference docs: describe current behavior only (sandboxing patches, inbox send,
  grammar/testing notes, jaiph-skill, libraries comment).

Signed-off-by: Jakub Dzikowski <jakub.t.dzikowski@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant