Skip to content

v1.1.0

Latest

Choose a tag to compare

@nclandrei nclandrei released this 25 Apr 11:00

Substantial feature wave closing the v1.0.1 audit: new lifecycle commands, machine-readable output, state-durability hardening, and safety gates.

New commands

  • joust unlock --yes — abort a locked run; removes worktrees, deletes branches, resets variants to pending. Refuses if a winner has been picked.
  • joust dispatch [--json] — machine-readable enumeration of variants ready for fan-out (variant_id, branch, worktree, prompt_path, effective model). Lets non-Claude drivers drive joust.
  • joust exec <variant> -- <cmd> — run a shell command inside a variant's worktree. Exit code propagates.
  • joust completion <bash|zsh|fish> — emit a sourceable shell completion script.
  • joust log --follow / -f — block-tail the events.jsonl log. Pairs with --json for live streaming.

Lifecycle additions

  • joust score --replace — overwrite the latest score instead of appending.
  • joust record <vid> --reset --yes — destroy and re-create a single variant's worktree+branch from the recorded base SHA, clear records/scores. Re-dispatch one subagent without restarting the run.
  • joust archive --winner — also clean up the picked variant. Refuses unless joust merge --yes has run.
  • joust record --artifact is now repeatable.

Machine-readable

  • --json added to status, list, compare, scenarios list, runner show, rubric show, runs, report, diff. Payload shapes live in render.py (compare_payload, status_payload, …).
  • Per-runner PROMPT.md tip blocks for claude-code, codex, shell. Unknown runners get the generic prompt.

Safety / robustness

  • joust init refuses an existing active run for the repo without --force (prior run preserved on disk).
  • joust init refuses on a dirty working tree without --force.
  • joust lock rolls back partial state on failure: any worktrees/branches created before an error are cleaned up so re-running lock is safe.
  • joust merge refuses when the base branch has advanced past the SHA recorded at init (use --force to override).
  • events.jsonl is now fsync'd; joust log silently skips torn lines from a Ctrl-C/crash.
  • active.json writes are atomic (tmp + os.replace) and protected by fcntl.LOCK_EX.
  • Manifest.from_dict validates version and refuses unknown schema versions.
  • joust doctor detects and (with --fix) removes orphan worktree directories.
  • joust.__version__ now mirrors installed package metadata instead of a hardcoded 0.1.0.

Docs

  • CHANGELOG.md added.
  • README adds a Configuration section (JOUST_HOME, completion install) and a Platform-support note (no Windows; uses POSIX fcntl).
  • docs/troubleshooting.md covers the four most likely first-run failures.

Plugin

No plugin changes — the Claude Code plugin's SessionStart hook continues to put joust on PATH.

Migration notes

  • If you have CI scripts that rely on joust init <slug> silently rotating the active pointer, add --force (and check that you actually want the prior run orphaned).
  • If you rebase the base branch between joust init and joust merge, merge will now refuse — re-run joust init (the safe path) or pass --force (you've reviewed the drift).