Libraries

When workflows grow, you want to reuse modules: shared rules, script wrappers, and small “standard library” flows. Jaiph does not publish those as a global install path; instead, each workspace can hold project-scoped libraries under <workspace>/.jaiph/libs/. The compiler resolves import paths against that tree (after normal relative resolution), and the CLI can clone git repositories into that folder and record them in a lockfile. This matches the import story in Architecture (validator + resolveImportPath with workspace root).

How imports resolve

  1. Relative to the current file — the same as for local modules (import "./foo", import "../lib/util").
  2. Library paths — if the import string contains a / and the relative path does not exist, the compiler tries
    <workspace>/.jaiph/libs/<lib-name>/<rest>.jh
    (see resolveImportPath in the transpiler; the workspace root is required everywhere imports are checked).

The library name is the first path segment (e.g. queue-lib in import "queue-lib/queue"). A module that declares export names only exposes those names to importers, as described in Grammar — Imports and Exports.

Installing third-party libraries

# Install a library (shallow git clone into .jaiph/libs/<name>/)
jaiph install https://github.com/you/queue-lib.git

# Install a specific tag or branch (ref must follow the .git in the URL)
jaiph install https://github.com/you/queue-lib.git@v1.0

# Restore all libraries from the lockfile (e.g. after git clone)
jaiph install

jaiph install writes .jaiph/libs.lock. Commit the lockfile; add .jaiph/libs/ to .gitignore if you do not want vendored clones in git. Use --force to replace an existing clone (see CLI — jaiph install for details).

Example: import from a clone under .jaiph/libs/

jaiph install creates queue-lib/… on disk, so a path like queue-lib/queue resolves the same as any other library layout. The exported names are defined by that repository; here is a self-contained example using the documented jaiphlang/queue API (after you have .jaiph/libs/jaiphlang/ in the workspace).

import "jaiphlang/queue" as q

workflow default() {
  ensure q.has_tasks()
  const t = run q.get_first_task()
  log "${t}"
}

The jaiphlang/ standard libraries

The jaiphlang/ prefix is a naming convention for first-party helper modules (queue, artifacts, …). They are not bundled inside the npm jaiph package; the canonical source lives in the jaiph repository under .jaiph/libs/jaiphlang/. Copy that directory into your own workspace as .jaiph/libs/jaiphlang/ (or track it in git) so import "jaiphlang/..." resolves. They use the same import / export workflow (and export rule) pattern as any other library.

jaiphlang/queueQUEUE.md task queue

Manages a markdown task file QUEUE.md at ${JAIPH_WORKSPACE:-.} (see queue.jh and queue.py). Task sections use ## headers; optional tags are #hashtags on the header line (e.g. ## My task #dev-ready).

Export Kind Description
get_first_task() workflow Returns the first task block (header + body).
next_task(tag) workflow Returns the first task whose header has the given tag.
get_task_by_header(header) workflow Returns a task by title (tags stripped for matching).
get_all_task_headers() workflow Newline-separated task titles (no ## prefix).
mark_task_dev_ready(header) workflow Adds #dev-ready to the matching header.
remove_completed_task(header) workflow Removes the task with that title.
set_task_description_from_file(header, bodyPath) workflow Replaces body text from a UTF-8 file; header unchanged.
has_tasks() rule Passes if the queue has at least one task.
task_is_dev_ready(task) rule Passes if the task text has #dev-ready on the header.
all_dev_ready() rule Passes if every task has #dev-ready.

The module also defines a default workflow for direct CLI use (arguments are forwarded to the Python helper). For example: jaiph .jaiph/libs/jaiphlang/queue.jh headers.

jaiphlang/artifacts — publishing files out of the sandbox

Copies files from the workspace (or sandbox overlay) into the run’s artifacts/ tree so they remain on the host after a Docker run or process exit. The kernel sets JAIPH_ARTIFACTS_DIR to the writable directory for the current run. See Architecture and Sandboxing for how that interacts with the read-only workspace in Docker.

import "jaiphlang/artifacts" as artifacts

workflow default() {
  # Copy a file into the artifacts directory under a chosen name.
  # Returns the absolute path of the saved artifact.
  const path = run artifacts.save("./build/output.bin", "build-output.bin")
}

Exported workflows

Workflow Description
save(local_path, name) Requires local_path to be a file. Copies to ${JAIPH_ARTIFACTS_DIR}/${name} (creates parent dirs). Returns the absolute destination path.