Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
c0dc782
Fix changelog
dzikowski May 13, 2026
6080750
Perf: parallelize jaiph install missing-library clones
dzikowski May 14, 2026
e468c2b
Perf: single-parse compile prep for local jaiph run
dzikowski May 14, 2026
63177c8
design: parser & compiler simplification plan + dev-ready queue
dzikowski May 15, 2026
9e7aaee
Refactor: promote CompilePrep to ModuleGraph with I/O-pure pipeline
dzikowski May 16, 2026
be7643d
Refactor: split source-fidelity data into a Trivia / CST layer
dzikowski May 16, 2026
a873b0c
Refactor: collapse call args into typed Arg[] across AST
dzikowski May 16, 2026
f27e54c
Refactor: collapse AST around a single Expr type
dzikowski May 16, 2026
ad60e5a
Refactor: fold validator pre-passes into a single workflow walk
dzikowski May 16, 2026
7466444
Refactor: aggregate compile errors via Diagnostics collector
dzikowski May 16, 2026
551540a
Refactor: split validator into per-step visitor table by scope
dzikowski May 16, 2026
6d2c92f
Refactor: decouple validator from runtime semantics
dzikowski May 16, 2026
b661672
Refactor: unify catch/recover parsing into one attached-block routine
dzikowski May 16, 2026
d849c18
Refactor: replace parseBlockStatement cascade with dispatch table
dzikowski May 16, 2026
30f0552
Docs: rewrite agent skill as a workflow-authoring guide
dzikowski Jun 10, 2026
ed7f783
Queue: add 17 dev-ready improvement tasks
dzikowski Jun 10, 2026
4711756
Workflows: dedupe helpers, recover-based CI loop, security review
dzikowski Jun 10, 2026
6ec1906
Docs: route docs prompts through vendored Diátaxis skill
dzikowski Jun 10, 2026
9a3b077
Fix: apply callee module config on cross-module run
dzikowski Jun 10, 2026
73c856a
Fix: pair Docker exit guard with try/finally to stop listener leak
dzikowski Jun 10, 2026
917481c
Fix: normalize imported channel keys at send time
dzikowski Jun 10, 2026
a4b13bc
Feat: cap inbox dispatch iterations to prevent circular send OOM
dzikowski Jun 10, 2026
c3a8312
Fix: honor workflow-level run.recover_limit in recover loops
dzikowski Jun 10, 2026
7d88155
Feat: add else branch to if statements in workflows and rules
dzikowski Jun 10, 2026
12deb33
Feat: allow catch/recover on inline-script run steps
dzikowski Jun 10, 2026
d227959
Feat: allow dot-notation subjects in if and match
dzikowski Jun 10, 2026
4d76c80
Feat: add per-subcommand -h/--help handling
dzikowski Jun 10, 2026
c9f3007
Feat: exit 0 when jaiph test discovers no *.test.jh files
dzikowski Jun 10, 2026
644fc20
Fix: reject mixing mock prompt block with queued mocks
dzikowski Jun 10, 2026
ba450e9
Fix: preserve quotes on top-level const string values in format
dzikowski Jun 10, 2026
e20878b
Queue: Installation from binary, support for libs
dzikowski Jun 11, 2026
52843d6
Fix: add context to async handle, Docker timeout, and stderr errors
dzikowski Jun 11, 2026
e90207b
Fix: lazy-load Docker overlay script on overlay path only
dzikowski Jun 11, 2026
8164046
Refactor: remove dead formatDiagnosticLine from stderr parser
dzikowski Jun 11, 2026
afbfcb5
Docs: document Docker env-var allowlist and workarounds
dzikowski Jun 11, 2026
29aaaf7
Feat: make standalone binary self-contained via self-spawn
dzikowski Jun 11, 2026
d7e0038
Feat: add release workflow for per-platform standalone binaries
dzikowski Jun 11, 2026
c58eecf
Feat: rewrite install script to download release binaries
dzikowski Jun 11, 2026
36ba5f9
Feat: add registry name resolution to jaiph install
dzikowski Jun 11, 2026
8c0fcd1
Feat: pin commit SHAs and strip .git in jaiph install
dzikowski Jun 11, 2026
2afdab8
Feat: add registry:build to regenerate docs/registry from upstream
dzikowski Jun 11, 2026
4583245
Feat: add prepare_release.jh workflow and single-source CLI version
dzikowski Jun 11, 2026
faaf180
Docs: queue inplace sandbox mode + run sandbox flags
dzikowski Jun 18, 2026
42c7815
Feat: add inplace Docker sandbox mode + raise default timeout to 4h
dzikowski Jun 18, 2026
24029ac
Feat: add jaiph run flags --workspace --inplace --unsafe --yes
dzikowski Jun 18, 2026
43f01e0
Feat: retry prompt steps on transient failure with backoff
dzikowski Jun 18, 2026
ef089cd
Fix: support --flag=value form in jaiph run arg parsing
dzikowski Jun 18, 2026
3729857
Docs: queue agent-credential fail-fast task
dzikowski Jun 18, 2026
f635097
Feat: fail fast on missing agent credentials with host pre-flight
dzikowski Jun 18, 2026
084cb00
Fix: skip agent-credential pre-flight in unsafe mode
dzikowski Jun 19, 2026
1368c06
Release: bump version to 0.10.0 and stamp changelog
dzikowski Jun 19, 2026
c4d3b39
Docs: queue Diataxis docs-redesign series; lock documentation-writer …
dzikowski Jun 19, 2026
575010f
Docs: mark docs-redesign task 8/8 not dev-ready (needs standalone jai…
dzikowski Jun 19, 2026
e43f30a
Docs: quarantine pre-redesign pages under docs/_legacy/
dzikowski Jun 19, 2026
64d1d37
Docs: add Diátaxis front-matter convention and docs-lint harness
dzikowski Jun 19, 2026
eae7772
Docs: land Diátaxis Explanation quadrant (docs redesign 3/8)
dzikowski Jun 19, 2026
369b469
Docs: land Diátaxis How-to quadrant (docs redesign 4/8)
dzikowski Jun 19, 2026
0140a66
Docs: land Diátaxis Reference quadrant (docs redesign 5/8)
dzikowski Jun 19, 2026
d9a852f
Docs: finalize Diátaxis IA (docs redesign 6+7/8)
dzikowski Jun 19, 2026
3e9a87c
Docs: add redesign-aware parity workflow; make task 8 post-parity cle…
dzikowski Jun 20, 2026
1b6438f
Docs: mark docs-redesign task 8/8 dev-ready (post-parity cleanup)
dzikowski Jun 20, 2026
3a9eb85
Chore: make docs_parity_redesign.jh executable
dzikowski Jun 20, 2026
5da52fa
Fix: harden docs_parity_redesign workflow (vendor exclude, pattern gu…
dzikowski Jun 21, 2026
16e3012
Fix: docs-lint resolves relative .md links via target permalink
dzikowski Jun 21, 2026
f02412a
Docs: land Diataxis redesign parity pass
dzikowski Jun 21, 2026
8ae5dc2
Chore: re-embed jaiph-skill.md after docs parity edits
dzikowski Jun 21, 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
204 changes: 204 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
name: Release

on:
push:
tags:
- "v*"
branches:
- nightly
workflow_dispatch:

jobs:
ci-gate:
name: Wait for CI to pass on this ref
runs-on: ubuntu-latest
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Wait for CI workflow conclusion on ${{ github.sha }}
run: |
set -euo pipefail
# Poll up to 60 minutes for the matching CI run on this SHA.
for i in $(seq 1 120); do
json="$(gh run list --workflow CI --commit "${GITHUB_SHA}" --limit 1 --json status,conclusion 2>/dev/null || echo '[]')"
count="$(echo "${json}" | jq 'length')"
if [ "${count}" -eq 0 ]; then
echo "[${i}/120] No CI run yet for ${GITHUB_SHA}"
sleep 30
continue
fi
status="$(echo "${json}" | jq -r '.[0].status')"
conclusion="$(echo "${json}" | jq -r '.[0].conclusion')"
if [ "${status}" = "completed" ]; then
if [ "${conclusion}" = "success" ]; then
echo "CI succeeded for ${GITHUB_SHA}."
exit 0
fi
echo "CI for ${GITHUB_SHA} completed with conclusion: ${conclusion}"
exit 1
fi
echo "[${i}/120] CI status=${status}"
sleep 30
done
echo "Timed out waiting for CI on ${GITHUB_SHA}."
exit 1

build:
name: Build ${{ matrix.os }}-${{ matrix.arch }}
needs: ci-gate
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
include:
- target: bun-darwin-arm64
os: darwin
arch: arm64
- target: bun-darwin-x64
os: darwin
arch: x64
- target: bun-linux-x64
os: linux
arch: x64
- target: bun-linux-arm64
os: linux
arch: arm64
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"
cache: npm

- name: Setup Bun
uses: oven-sh/setup-bun@v2

- name: Install dependencies
run: npm ci

- name: Build TypeScript + embed assets
run: npm run build

- name: Cross-compile standalone binary for ${{ matrix.target }}
run: |
set -euo pipefail
bun build --compile --target=${{ matrix.target }} ./src/cli.ts --outfile "jaiph-${{ matrix.os }}-${{ matrix.arch }}"
ls -la "jaiph-${{ matrix.os }}-${{ matrix.arch }}"

- name: Upload binary artifact
uses: actions/upload-artifact@v4
with:
name: jaiph-${{ matrix.os }}-${{ matrix.arch }}
path: jaiph-${{ matrix.os }}-${{ matrix.arch }}
if-no-files-found: error
retention-days: 7

release:
name: Publish release assets
needs: build
runs-on: ubuntu-latest
permissions:
contents: write
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Resolve tag and channel
id: meta
run: |
set -euo pipefail
case "${GITHUB_REF}" in
refs/tags/v*)
tag="${GITHUB_REF_NAME}"; channel="stable" ;;
refs/heads/nightly|refs/tags/nightly)
tag="nightly"; channel="nightly" ;;
*)
echo "Unsupported ref for release: ${GITHUB_REF}" >&2; exit 1 ;;
esac
echo "tag=${tag}" >> "${GITHUB_OUTPUT}"
echo "channel=${channel}" >> "${GITHUB_OUTPUT}"

- name: Download binary artifacts
uses: actions/download-artifact@v4
with:
path: release-assets
merge-multiple: true

- name: Generate SHA256SUMS
working-directory: release-assets
run: |
set -euo pipefail
ls -la
rm -f SHA256SUMS
sha256sum jaiph-darwin-arm64 jaiph-darwin-x64 jaiph-linux-x64 jaiph-linux-arm64 > SHA256SUMS
cat SHA256SUMS

- name: Sanity gate (linux-x64 --version)
working-directory: release-assets
run: |
set -euo pipefail
chmod +x jaiph-linux-x64
got="$(./jaiph-linux-x64 --version)"
echo "got: ${got}"
if [ "${{ steps.meta.outputs.channel }}" = "stable" ]; then
tag="${{ steps.meta.outputs.tag }}"
expected="jaiph ${tag#v}"
if [ "${got}" != "${expected}" ]; then
echo "Version sanity check failed: expected '${expected}', got '${got}'" >&2
exit 1
fi
else
if ! printf '%s\n' "${got}" | grep -Eq '^jaiph [0-9]+\.[0-9]+\.[0-9]+'; then
echo "Version sanity check failed: '${got}' does not look like a jaiph version" >&2
exit 1
fi
fi

- name: Publish stable release ${{ steps.meta.outputs.tag }}
if: steps.meta.outputs.channel == 'stable'
working-directory: release-assets
run: |
set -euo pipefail
tag="${{ steps.meta.outputs.tag }}"
if gh release view "${tag}" >/dev/null 2>&1; then
gh release upload "${tag}" --clobber \
jaiph-darwin-arm64 jaiph-darwin-x64 \
jaiph-linux-x64 jaiph-linux-arm64 \
SHA256SUMS
else
gh release create "${tag}" \
--title "${tag}" \
--notes "Jaiph ${tag} — standalone binaries (darwin/linux × arm64/x64) plus SHA256SUMS." \
jaiph-darwin-arm64 jaiph-darwin-x64 \
jaiph-linux-x64 jaiph-linux-arm64 \
SHA256SUMS
fi

- name: Publish nightly prerelease
if: steps.meta.outputs.channel == 'nightly'
working-directory: release-assets
run: |
set -euo pipefail
if gh release view nightly >/dev/null 2>&1; then
gh release upload nightly --clobber \
jaiph-darwin-arm64 jaiph-darwin-x64 \
jaiph-linux-x64 jaiph-linux-arm64 \
SHA256SUMS
else
gh release create nightly \
--title "Nightly" \
--notes "Rolling nightly prerelease — standalone binaries built from the latest \`nightly\` branch." \
--prerelease \
--target "${GITHUB_SHA}" \
jaiph-darwin-arm64 jaiph-darwin-x64 \
jaiph-linux-x64 jaiph-linux-arm64 \
SHA256SUMS
fi
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ docs/.bundle/
dist/
.tmp/

# Generated by tools/embed-assets.js from package.json's `version` field, so
# the CLI version lives in only one place in tree (package.json).
src/version.ts

# logs
*.log
npm-debug.log*
Expand Down
52 changes: 16 additions & 36 deletions .jaiph/architect_review.jh
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env jaiph

import "jaiphlang/queue" as queue
import "./lib_common.jh" as common

config {
agent.backend = "cursor"
Expand All @@ -10,29 +11,8 @@ config {
# agent.claude_flags = "--permission-mode bypassPermissions"
}

script first_line_str = `printf '%s\n' "$1" | head -n 1`

script rest_lines_str = `printf '%s\n' "$1" | tail -n +2`

script arg_nonempty = `[ -n "$1" ]`

script str_equals = `[ "$1" = "$2" ]`

script mkdir_p_simple = `mkdir -p "$1"`

script jaiph_tmp_dir = `printf '%s\n' "$JAIPH_WORKSPACE/.jaiph/tmp"`

script jaiph_review_body_file = `printf '%s\n' "$JAIPH_WORKSPACE/.jaiph/tmp/architect_review_body.txt"`

# Writes UTF-8 text to a path (path, then content).
script save_string_to_file = ```python3
import sys
if len(sys.argv) < 3:
sys.exit(2)
path, content = sys.argv[1], sys.argv[2]
open(path, "w", encoding="utf-8").write(content)
```

# Packed as: first line = verdict, rest = updated_description (must stay top-level:
# const … = prompt """…""" is not supported inside ensure … catch — see parseRecoverStatement).
workflow architect_agent_review(task) {
Expand Down Expand Up @@ -93,31 +73,31 @@ workflow architect_agent_review(task) {
}

workflow review_one_header(header) {
run arg_nonempty(header) catch (err) {
run common.arg_nonempty(header) catch (err) {
return ""
}
const task = run queue.get_task_by_header(header)
ensure queue.task_is_dev_ready(task) catch (err) {
const packed = run architect_agent_review(task)
const verdict = run first_line_str(packed)
const updated_description = run rest_lines_str(packed)
const verdict = run common.first_line_str(packed)
const updated_description = run common.rest_lines_str(packed)
const body_file = run jaiph_review_body_file()
run mkdir_p_simple(run jaiph_tmp_dir())
run str_equals(verdict, "dev-ready") catch (err) {
run arg_nonempty(updated_description) catch (err) {
run common.mkdir_p_simple(run common.jaiph_tmp_dir())
run common.str_equals(verdict, "dev-ready") catch (err) {
run common.arg_nonempty(updated_description) catch (err) {
fail "needs-work requires a non-empty updated_description (questions for the author)."
}
run save_string_to_file(body_file, updated_description)
run common.save_string_to_file(body_file, updated_description)
run queue.set_task_description_from_file(header, body_file)
log "Needs work (description updated): ${header}"
return ""
}
run arg_nonempty(updated_description) catch (err) {
run common.arg_nonempty(updated_description) catch (err) {
run queue.mark_task_dev_ready(header)
log "Marked dev-ready: ${header}"
return ""
}
run save_string_to_file(body_file, updated_description)
run common.save_string_to_file(body_file, updated_description)
run queue.set_task_description_from_file(header, body_file)
run queue.mark_task_dev_ready(header)
log "Marked dev-ready: ${header}"
Expand All @@ -128,25 +108,25 @@ workflow review_one_header(header) {

workflow process_headers_recursive(header, remaining) {
run review_one_header(header)
run arg_nonempty(remaining) catch (err) {
run common.arg_nonempty(remaining) catch (err) {
return ""
}
const next = run first_line_str(remaining)
const rest = run rest_lines_str(remaining)
const next = run common.first_line_str(remaining)
const rest = run common.rest_lines_str(remaining)
run process_headers_recursive(next, rest)
}

workflow maybe_process_headers(first, rest) {
run arg_nonempty(first) catch (err) {
run common.arg_nonempty(first) catch (err) {
return ""
}
run process_headers_recursive(first, rest)
}

workflow default() {
const headers = run queue.get_all_task_headers()
const first = run first_line_str(headers)
const rest = run rest_lines_str(headers)
const first = run common.first_line_str(headers)
const rest = run common.rest_lines_str(headers)
run maybe_process_headers(first, rest)
ensure queue.all_dev_ready() catch (err) {
fail "One or more tasks need work. Review the agent output above."
Expand Down
Loading
Loading