Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d91e879
docs: shorten getting-started overview, drop implementation details
dzikowski Apr 25, 2026
c1ab0f3
feat: run single-line shell steps in Node runtime; align workflow val…
dzikowski Apr 25, 2026
60cc027
Fix: RHS now treats bare identifiers and bare dotted identifiers as i…
dzikowski Apr 25, 2026
d1f3a0f
Fix: CI
dzikowski Apr 25, 2026
e6f0031
Refactor: Consolidate artifacts.save to a single newline-list signature
dzikowski May 5, 2026
67f8353
Refactor: simplify parser/runtime per audit; remove ~1400 LOC of dead…
dzikowski May 5, 2026
5518000
Refactor: collapse parser/runtime duplication (B1, B10, B11)
dzikowski May 5, 2026
1b0cf32
Refactor: more parser/runtime simplification (B5-B8, C6, C9, C15, D1,…
dzikowski May 7, 2026
3bba9c3
Polish: clearer test-block error + drop stale bash-era doc refs (A10,…
dzikowski May 8, 2026
895a8d3
Refactor: rename AST recover ↔ recoverLoop to align with source keywo…
dzikowski May 8, 2026
744e322
Queue: fold remaining audit items into the queue, drop AUDIT_PROGRESS.md
dzikowski May 8, 2026
3ebb050
Update Gemfile.lock to include platform-specific versions of ffi
dzikowski May 8, 2026
34dff23
Refactor: consolidate 5-way test directory split into 3 clear locations
dzikowski May 8, 2026
8f27169
Fix: git format-patch writes real output with --stdout
dzikowski May 8, 2026
c5d85b2
Fix: failure footer uses last failed STEP_END in summary
dzikowski May 8, 2026
223847a
Breaking: remove parallel inbox dispatch; drain routes sequentially
May 8, 2026
4d9015a
Docs: add agent-proxy design doc
dzikowski May 12, 2026
2cf3719
Fix: CI
dzikowski May 12, 2026
b385950
Refactor: split node-workflow-runtime into arg-parser, emitter, mock
dzikowski May 12, 2026
a12b8ab
Cleanup: replace JAIPH_TEST_MODE event suppression with constructor opt
dzikowski May 12, 2026
718a83e
Enhancement: Update QA scripts and add new E2E tests
dzikowski May 13, 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
8 changes: 6 additions & 2 deletions .jaiph/async.jh
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@
const prompt_text = "Say: Greetings! I am [model name]."

workflow cursor_say_hello(name) {
config { agent.backend = "cursor" }
config {
agent.backend = "cursor"
}
const response = prompt "${prompt_text}"
log response
}

workflow claude_say_hello(name) {
config { agent.backend = "claude" }
config {
agent.backend = "claude"
}
const response = prompt "${prompt_text}"
log response
}
Expand Down
18 changes: 9 additions & 9 deletions .jaiph/engineer.jh
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import "jaiphlang/queue" as queue
import "jaiphlang/artifacts" as artifacts
import "./docs_parity.jh" as docs
import "./ensure_ci_passes.jh" as ci
import "./git.jh" as git
import "jaiphlang/git" as git

config {
agent.backend = "cursor"
agent.default_model = "gpt-5.3-codex"
agent.cursor_flags = "--force"
# agent.backend = "claude"
# agent.claude_flags = "--permission-mode bypassPermissions"
# agent.backend = "cursor"
# agent.default_model = "composer-2"
# agent.cursor_flags = "--force"
agent.backend = "claude"
agent.claude_flags = "--permission-mode bypassPermissions"
}

const code_philosophy = """
Expand Down Expand Up @@ -286,7 +286,7 @@ workflow default(name) {
run docs.update_from_task(task)
run queue.remove_completed_task(task_header)

const patch_file = run git.patch(task)
const target_path = run artifacts.save(patch_file, patch_file)
return target_path
const patch_file = run git.commit(task)
run artifacts.save(patch_file)
return patch_file
}
56 changes: 43 additions & 13 deletions .jaiph/libs/jaiphlang/artifacts.jh
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,57 @@
# import "jaiphlang/artifacts" as artifacts
#
# workflow default() {
# run artifacts.save("./build/output.bin", "build-output.bin")
# # Single file:
# run artifacts.save("./build/output.bin")
#
# # Or several files: newline-separated list of paths.
# const paths = """
# a.txt
# b/nested.txt
# """
# run artifacts.save(paths)
# }
#

script save_script = ```
set -euo pipefail
ARTIFACTS_DIR="${JAIPH_ARTIFACTS_DIR:?JAIPH_ARTIFACTS_DIR is not set}"
src="$1"
dest_name="$2"
if [[ ! -f "$src" ]]; then
printf 'artifacts save: file not found: %s\n' "$src" >&2
paths_list="$1"
out=""

while IFS= read -r line || [[ -n "${line-}" ]]; do
[[ -z "${line//[[:space:]]/}" ]] && continue
src="${line#"${line%%[![:space:]]*}"}"
src="${src%"${src##*[![:space:]]}"}"
if [[ ! -f "$src" ]]; then
printf 'artifacts save: file not found: %s\n' "$src" >&2
exit 1
fi
if [[ "$src" = /* ]]; then
relpath="$(basename -- "$src")"
else
relpath="${src#./}"
fi
dest="${ARTIFACTS_DIR}/${relpath}"
mkdir -p "$(dirname -- "$dest")"
cp -- "$src" "$dest"
if [[ -n "$out" ]]; then
out+=$'\n'
fi
out+="$dest"
done <<<"$paths_list"

if [[ -z "$out" ]]; then
printf 'artifacts save: no paths in list\n' >&2
exit 1
fi
dest="${ARTIFACTS_DIR}/${dest_name}"
mkdir -p "$(dirname "$dest")"
cp -- "$src" "$dest"
printf '%s' "$dest"
printf '%s' "$out"
```

# Copies the file at `local_path` into the artifacts directory under `name`.
# Returns the absolute path of the saved artifact.
export workflow save(local_path, name) {
return run save_script(local_path, name)
# `paths` is a single file path or a newline-separated list of file paths.
# Each file is copied under the same relative name as in the list
# (leading `./` stripped; absolute paths use basename only).
# Returns the absolute destination paths, one per line, in the same order.
export workflow save(paths) {
return run save_script(paths)
}
70 changes: 34 additions & 36 deletions .jaiph/git.jh → .jaiph/libs/jaiphlang/git.jh
Original file line number Diff line number Diff line change
@@ -1,23 +1,33 @@
#!/usr/bin/env jaiph

script git_inside_worktree = `git rev-parse --is-inside-work-tree >/dev/null 2>&1`
script git_inside_worktree = `git rev-parse --is-inside-work-tree 2>&1`

script git_porcelain_empty = `test -z "$(git status --porcelain)"`

script git_porcelain_nonempty = `test -n "$(git status --porcelain)"`

script git_mark_workspace_safe = `git config --global --add safe.directory "$(pwd)"`

# format-patch emits real diff to stdout only with --stdout; otherwise git writes *.patch files and stdout is only the path.
script git_create_patch_from_commit = `git config --global --add safe.directory "$(pwd)" && git format-patch -1 HEAD --stdout > $1`

rule in_git_repo() {
run git_mark_workspace_safe()
run git_inside_worktree() catch (err) {
fail "not inside a git repository"
}
}

rule branch_clean() {
run git_porcelain_empty()
run git_porcelain_empty() catch (err) {
fail "git working tree is not clean"
}
}

rule has_changes() {
run git_porcelain_nonempty()
run git_porcelain_nonempty() catch (err) {
fail "git working tree has no changes"
}
}

rule is_clean() {
Expand All @@ -26,55 +36,43 @@ rule is_clean() {
}

workflow commit(task) {
ensure in_git_repo()

ensure has_changes() catch (err) {
log "No changes to commit — skipping."
return ""
config {
agent.backend = "cursor"
agent.cursor_flags = "--force"
agent.default_model = "auto"
}

prompt """
Commit the current repository changes now.
ensure in_git_repo()
ensure has_changes()

const response = prompt """
Please commit current changes and respond with a commit message and
suggested patch file name (excluding extension).

Requirements for commit message:
1. Write a commit message - first line in imperative mood, under 72 chars.
2. Start with the common prefix like 'Feat:', 'Fix:', 'Refactor:' etc.
3. Write a body paragraph with more details about the change.

Requirements for commit:
1. Review current git changes (git diff --stat, git status).
2. Stage all relevant changes with git add.
3. Create exactly one commit.
4. Do not push.
5. Remove files that are not relevant to the commit and not git ignored.

Changes were made for the following task:
${task}
"""
returns "{ message: string, patch_file_name: string }"

const patch_file_name = "${response.patch_file_name}.patch"

run git_create_patch_from_commit(patch_file_name)

return patch_file_name
}

# Writes a unified diff (HEAD vs working tree, excluding `.jaiph/`) to `dest`.
# Returns `dest` (relative path). `task` is reserved for callers / future naming.
script write_tree_patch = ```
set -euo pipefail
dest="$1"
mkdir -p "$(dirname "$dest")"
diff_out="$(git diff HEAD -- . ':!.jaiph/' 2>/dev/null || true)"
if [[ -z "${diff_out}" ]]; then
git add -N . -- ':!.jaiph/' 2>/dev/null || true
diff_out="$(git diff HEAD -- . ':!.jaiph/' 2>/dev/null || true)"
git reset HEAD -- . 2>/dev/null || true
fi
if [[ -n "${diff_out}" ]]; then
printf '%s\n' "${diff_out}" > "$dest"
else
: > "$dest"
fi
printf '%s' "$dest"
```

workflow patch(task) {
ensure in_git_repo()
const dest = ".jaiph/tmp/engineer-workspace.patch"
return run write_tree_patch(dest)
workflow default(task) {
return run commit(task)
}
2 changes: 1 addition & 1 deletion .jaiph/main.jh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import "./engineer.jh" as implement
import "./architect_review.jh" as architect
import "./git.jh" as git
import "jaiphlang/git" as git

workflow default() {
ensure git.is_clean()
Expand Down
Loading
Loading