Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f6dc89f
feat: add scoped standalone command
nadavlac Jul 30, 2026
c00bd6f
feat: isolate standalone runner configuration
nadavlac Jul 30, 2026
f1d56c4
feat: add embedded standalone Vitest config
nadavlac Jul 30, 2026
facc9f1
feat: run standalone evals with bundled Vitest
nadavlac Jul 30, 2026
083dc48
test: isolate standalone changed-run coverage
nadavlac Jul 30, 2026
730417c
feat: bundle Codex app-server runtime
nadavlac Jul 31, 2026
ad22a3d
fix: reject native Windows Codex runtime
nadavlac Jul 31, 2026
7ba1883
fix: harden bundled Codex startup
nadavlac Jul 31, 2026
af669fe
feat: report standalone runtime provenance
nadavlac Jul 31, 2026
0e8bf7f
fix: complete standalone provenance contracts
nadavlac Jul 31, 2026
04af15d
fix: harden standalone provenance
nadavlac Jul 31, 2026
bfeb66c
test: verify standalone npm artifacts
nadavlac Jul 31, 2026
4825a29
fix: dispose structural standalone agents
nadavlac Jul 31, 2026
f570d93
docs: ship standalone Pathgrade workflow
nadavlac Jul 31, 2026
c0871c3
fix: harden standalone release evidence
nadavlac Jul 31, 2026
3c71b8c
fix: verify release provenance cryptographically
nadavlac Jul 31, 2026
033ca05
fix: avoid eager Codex launch in standalone provenance
nadavlac Aug 2, 2026
079b400
feat: complete standalone terminal UX
nadavlac Aug 10, 2026
8ad231a
Simplify npm staging workflow
nadavlac Aug 10, 2026
85c25a0
ci: streamline package validation
nadavlac Aug 10, 2026
21e8377
refactor: remove obsolete release verification ceremony
nadavlac Aug 10, 2026
df21859
docs: remove standalone release evidence template
nadavlac Aug 10, 2026
ff4355d
test: remove publish workflow contract test
nadavlac Aug 10, 2026
daa8529
Publish packages directly from tagged releases
nadavlac Aug 10, 2026
659adf0
Remove standalone CLI UX plan
nadavlac Aug 10, 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
93 changes: 72 additions & 21 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,84 @@ name: CI
on:
pull_request:
push:
branches:
- master
branches: [master]

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
test:
name: Build and test
runs-on: ubuntu-latest

compatibility:
name: Test (Node 20.11.0)
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683

- name: Setup Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
with:
node-version-file: .nvmrc
node-version: 20.11.0
package-manager-cache: false
- run: yarn install --immutable
- run: yarn build && yarn vitest run && yarn test:runner-cli-smoke

- name: Install dependencies
run: printf 'y\n' | NPQ_PKG_MGR=yarn npx --yes npq install
env:
GITHUB_TOKEN: ${{ github.token }}

- name: Build
run: yarn build
package:
name: Test and package (Node 24)
runs-on: ubuntu-24.04
outputs:
sha512: ${{ steps.pack.outputs.sha512 }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
with:
node-version: 24
package-manager-cache: false
- run: yarn install --immutable
- run: yarn quality
- run: yarn build && yarn vitest run && yarn test:runner-cli-smoke && yarn test:release-contracts
- id: pack
run: |
mkdir retained
filename="$(npm pack --pack-destination retained)"
mv "retained/$filename" retained/pathgrade.tgz
echo "sha512=$(sha512sum retained/pathgrade.tgz | cut -d ' ' -f 1)" >> "$GITHUB_OUTPUT"
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: pathgrade-package
path: retained/pathgrade.tgz
if-no-files-found: error

- name: Test
run: yarn test
package-smoke:
name: Package smoke (${{ matrix.runner }}, Node ${{ matrix.node }})
needs: [compatibility, package]
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- { runner: ubuntu-24.04, node: 20.11.0 }
- { runner: ubuntu-24.04, node: 24 }
- { runner: ubuntu-24.04-arm, node: 24 }
- { runner: macos-15, node: 24 }
- { runner: macos-15-intel, node: 24 }
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
with:
node-version: ${{ matrix.node }}
package-manager-cache: false
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
name: pathgrade-package
path: retained
- run: node tests/standalone-package-smoke/run-smoke.mjs --tarball "$PWD/retained/pathgrade.tgz" --expected-sha512 "${{ needs.package.outputs.sha512 }}"
- run: |
prefix="$RUNNER_TEMP/pathgrade-prefix"
npm install --global --prefix "$prefix" --ignore-scripts retained/pathgrade.tgz
graph="$prefix/lib/node_modules/@wix/pathgrade/node_modules"
claude="$(find "$graph" -type f -name claude -perm -111 -print -quit)"
codex="$(find "$graph" -type f -name codex -perm -111 -print -quit)"
test -x "$claude" && test -x "$codex"
"$claude" --version
"$codex" --version
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,27 @@
- Debug long conversations with preserved workspaces and run snapshots
- Use the same evals locally and in CI

## Standalone—Node only

Run a TypeScript eval without adding Pathgrade, Vitest, Claude, or Codex to the target project:

```text
npx @wix/pathgrade standalone
npx @wix/pathgrade standalone run path/to/example.eval.ts
npm install --global @wix/pathgrade
pathgrade standalone
```

Standalone v0 supports Node.js 22 or 24 on macOS, Linux, or WSL (`x64` and `arm64`). It runs Claude through the bundled Claude Agent SDK and Claude Code binary, or Codex through the bundled Codex `app-server`; credentials and network access for the selected provider are still required. No local Pathgrade, Vitest, Claude, or Codex install is used, and there is no fallback to `PATH`, `npx`, or a target `node_modules` for those runtimes.

Evals may import from root `vitest`, `@wix/pathgrade`, and the documented standalone Pathgrade eval subpaths. Vitest subpaths such as `vitest/config` are not supported in standalone v0. Application dependencies remain your responsibility and must be installed or otherwise resolvable by the target project.

Standalone ignores project Vitest configuration and does not load `.env`. Its temporary HOME, cache, and workspace isolation prevents accidental project mutation, but local workspace isolation is not a security sandbox. Jest, Cursor, Codex `exec`, Docker, declarative specs, recording, and baselines are deferred beyond standalone v0.

Standalone uses a compact, color-aware progress view in interactive terminals and stable line-oriented output in CI or redirected streams. Use `--verbose` for an agent-labeled live trace, `--quiet` for failures and the final status only, or `--diagnostics` for expanded final diagnostics. `--quiet` and `--verbose` are mutually exclusive. Color is semantic and never replaces status text; `NO_COLOR` or `FORCE_COLOR=0` disables it.

Existing project-local `@wix/pathgrade` commands remain unchanged unless you select the explicit `standalone` namespace; project-local configuration, `.env`, adapters, and executable overrides retain their current behavior. This release installs and publishes only `@wix/pathgrade`: no unscoped `pathgrade` package is installed or published.

## Quick Start

**Prerequisites**: Node.js 20.11+, Vitest 4+ or Jest 30+, and at least one configured agent runtime. Claude uses the bundled `@anthropic-ai/claude-agent-sdk` binary by default; Codex requires the `codex` CLI; Cursor requires the `cursor-agent` CLI.
Expand Down
21 changes: 20 additions & 1 deletion docs/USER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Pathgrade evaluates whether AI agents correctly discover and use your skills. Yo

## Installation

**Prerequisites**: Node.js 20+, Vitest 4+ or Jest 30+
**Project-local prerequisites**: Node.js 20+, Vitest 4+ or Jest 30+. These prerequisites and the runtime overrides below apply to the existing project-local commands.

```bash
npm i @wix/pathgrade vitest
Expand All @@ -66,6 +66,23 @@ npm i @wix/pathgrade jest
- **Codex**: install the Codex CLI per OpenAI's documentation; pathgrade shells out to it.
- **Cursor**: install `cursor-agent` per Cursor's documentation; pathgrade shells out to it.

### Standalone—Node only

Standalone v0 has a separate contract: Node.js 22 or 24 on macOS, Linux, or WSL (`x64` or `arm64`). It bundles Pathgrade, Vitest, the Claude Agent SDK and Claude Code binary, and the Codex `app-server`, so it needs no local Pathgrade, Vitest, Claude, or Codex install:

```text
npx @wix/pathgrade standalone
npx @wix/pathgrade standalone run path/to/example.eval.ts
npm install --global @wix/pathgrade
pathgrade standalone
```

Credentials and network access remain required for live Claude or Codex requests. Standalone v0 supports imports from root `vitest`, not Vitest subpaths such as `vitest/config`; application dependencies remain your responsibility. The project Vitest configuration is ignored, and standalone does not load `.env`.

Temporary HOME, cache, and workspace directories isolate local state, but local workspace isolation is not a security sandbox. Jest, Cursor, Codex `exec`, Docker, declarative specs, recording, and baselines are deferred. Existing project-local commands remain unchanged unless the explicit `standalone` namespace is selected, and this release does not install or publish an unscoped `pathgrade` package.

Interactive standalone runs use the compact Calm Runner view. CI and redirected streams automatically receive stable line-oriented output. Pass `--verbose` for an agent-labeled Live Trace, `--quiet` to keep only failures and the authoritative final status, or `--diagnostics` to expand final diagnostics. `--quiet` and `--verbose` cannot be combined. Semantic color is optional: set `NO_COLOR` or `FORCE_COLOR=0` to disable it without changing the displayed status words.

## Quick Start

1. Create a `vitest.config.ts` with the Pathgrade Vitest adapter plugin:
Expand Down Expand Up @@ -1276,6 +1293,8 @@ The pathgrade vitest plugin uses `setRuntime({ onResult })` internally to captur

## Environment Variables

This section describes project-local execution. `pathgrade run` loads the project's `.env` as before. In contrast, `pathgrade standalone` does not load `.env`; provide selected-provider credentials in the invoking process environment. Standalone also ignores local runtime executable overrides and project Vitest configuration.

| Variable | Used By |
|----------|---------|
| `ANTHROPIC_API_KEY` | Claude agent, judge scorers, persona replies |
Expand Down
7 changes: 5 additions & 2 deletions knip.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,23 @@
"vitest.config.ts",
"evals/vitest.config.mts",
"examples/**/vitest.config.mts",
"scripts/*.ts"
"scripts/*.ts",
"scripts/release/*.mjs"
],
"project": [
"src/**/*.ts",
"tests/**/*.ts",
"evals/**/*.ts",
"examples/**/*.ts",
"scripts/**/*.ts",
"scripts/**/*.mjs",
"scorers/**/*.ts"
],
"ignore": [
"tests/fixtures/**"
],
"ignoreDependencies": [
"jest"
"jest",
"@openai/codex"
]
}
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,10 @@
"quality:boundaries": "scripts/check-quality-boundaries.sh",
"quality:max-lines": "scripts/check-max-lines.sh .",
"quality": "yarn lint && yarn quality:deps && yarn quality:arch && yarn quality:boundaries && yarn quality:max-lines",
"test": "yarn build && vitest run && yarn test:runner-cli-smoke",
"test": "yarn build && vitest run && yarn test:runner-cli-smoke && yarn test:standalone-package-smoke && yarn test:release-contracts",
"test:runner-cli-smoke": "node tests/runner-cli-smoke/run-smokes.mjs",
"test:standalone-package-smoke": "node tests/standalone-package-smoke/run-smoke.mjs",
"test:release-contracts": "node tests/release-platform-evidence.test.mjs && node tests/publish-workflow-contract.test.mjs",
"test:evals": "vitest run --config evals/vitest.config.mts",
"test:coverage": "vitest run --coverage",
"dev": "tsx src/pathgrade.ts",
Expand Down Expand Up @@ -118,18 +120,19 @@
"@types/jest": "^30.0.0",
"@types/picomatch": "^4.0.2",
"@vitest/coverage-v8": "4.1.7",
"jest": "^30.0.0",
"vitest": "4.1.7"
"jest": "^30.0.0"
},
"dependencies": {
"@anthropic-ai/claude-agent-sdk": "0.2.116",
"@modelcontextprotocol/sdk": "1.29.0",
"@openai/codex": "0.144.0",
"@types/node": "25.6.0",
"fs-extra": "11.3.3",
"jiti": "2.6.1",
"picomatch": "^4.0.4",
"tsx": "4.22.3",
"typescript": "^5.9.3",
"vitest": "4.1.7",
"zod": "4.3.6"
},
"resolutions": {
Expand Down
7 changes: 4 additions & 3 deletions scripts/check-max-lines.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ esac

allowlist_cap() {
case "$1" in
src/agents/codex-app-server/agent.ts) echo 811 ;;
src/agents/codex-app-server/agent.ts) echo 865 ;;
src/viewer.html) echo 1178 ;;
tests/claude-ask-user-bridge.test.ts) echo 604 ;;
tests/claude-sdk-driver.test.ts) echo 697 ;;
tests/claude-sdk-projector.test.ts) echo 774 ;;
tests/codex-app-server-agent.test.ts) echo 1285 ;;
tests/codex-app-server-agent.test.ts) echo 1437 ;;
tests/commands.run-changed.test.ts) echo 609 ;;
tests/converse.test.ts) echo 608 ;;
tests/grading-pipeline.test.ts) echo 691 ;;
Expand Down Expand Up @@ -60,7 +60,7 @@ should_check() {

emit_files() {
if git -C "$root" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
git -C "$root" ls-files -z
git -C "$root" ls-files --cached --others --exclude-standard -z
else
find "$root" \
\( -path "*/.git" -o -path "*/node_modules" -o -path "*/dist" -o -path "*/build" -o -path "*/coverage" -o -path "*/.next" -o -path "*/.nuxt" -o -path "*/.turbo" -o -path "*/.cache" \) -prune \
Expand All @@ -79,6 +79,7 @@ while IFS= read -r -d '' file; do
path="$file"
fi

[[ -f "$path" ]] || continue
should_skip "$display" && continue
should_check "$display" || continue

Expand Down
16 changes: 16 additions & 0 deletions scripts/check-quality-boundaries.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@ set -euo pipefail
root="${1:-.}"
cd "$root"

release_scripts=()
while IFS= read -r file; do
release_scripts+=("$file")
done < <(find scripts/release -type f -name '*.mjs' 2>/dev/null | sort)

for file in "${release_scripts[@]}"; do
if ! node --check "$file"; then
echo "Release script failed syntax validation: $file" >&2
exit 1
fi
done

if (( ${#release_scripts[@]} > 0 )); then
echo "Release-script syntax boundaries are clean (${#release_scripts[@]} files)."
fi

result_capture_files=()
while IFS= read -r file; do
result_capture_files+=("$file")
Expand Down
Loading