From de0ad50d5db1af094e5fae2a6931764d9314aadc Mon Sep 17 00:00:00 2001 From: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com> Date: Sun, 28 Jun 2026 14:26:54 -0700 Subject: [PATCH 1/2] ci: auto-format staged code with a pre-commit hook Adds .githooks/pre-commit that runs oxfmt --write on staged JS/TS/JSON and re-stages them, and wires git config core.hooksPath .githooks into bootstrap so every fresh checkout and worktree activates it. Commits now land already-formatted, so the CI format job (oxfmt --check) stops failing on contributions that skipped running format manually. The hook only touches staged files, matching the existing rule to stage just your own files. It honours .oxfmtrc.json ignorePatterns and no-ops when oxfmt is not yet installed. --- .githooks/pre-commit | 47 ++++++++++++++++++++++++++++++++++++++++++++ scripts/bootstrap.ts | 6 ++++++ 2 files changed, 53 insertions(+) create mode 100755 .githooks/pre-commit diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 000000000..49dbd4cf9 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# Auto-format staged code with oxfmt before each commit, so the CI `format` job +# (`oxfmt --check .`) can never fail on a commit that originated here. Activated +# by `git config core.hooksPath .githooks`, which `bun run bootstrap` sets for +# every fresh checkout / agent worktree. +# +# Behaviour: formats the staged JS/TS/JSON files in place and re-stages them. +# oxfmt honours `.oxfmtrc.json` `ignorePatterns` even for explicitly-passed +# paths, so generated/vendored files (bun.lock, routeTree.gen.ts, ...) are +# skipped automatically. +# +# NUL-delimited end to end (handles spaces/newlines in paths) and compatible +# with the bash 3.2 that ships on macOS, so no `mapfile`. A shell variable +# cannot hold NUL bytes, so the staged list is read into an array directly. +# +# Caveat: a file that is only partially staged (staged hunk + a separate +# unstaged hunk in the same file) gets fully re-staged after formatting. Agent +# flows stage whole files (`git add -A`), so this is not a concern in practice. + +set -euo pipefail + +cd "$(git rev-parse --show-toplevel)" + +oxfmt="node_modules/.bin/oxfmt" +if [[ ! -x "$oxfmt" ]]; then + echo "pre-commit: oxfmt not found ($oxfmt) - run 'bun run bootstrap'; skipping format." >&2 + exit 0 +fi + +# Staged Added/Copied/Modified/Renamed files, restricted to extensions oxfmt +# formats. Read NUL records into an array (no NUL-in-variable bug). +files=() +while IFS= read -r -d '' f; do + case "$f" in + *.ts | *.tsx | *.mts | *.cts | *.js | *.jsx | *.mjs | *.cjs | *.json | *.jsonc) + files+=("$f") + ;; + esac +done < <(git diff --cached --name-only --diff-filter=ACMR -z) + +((${#files[@]})) || exit 0 + +# Format in place, then re-stage whatever oxfmt may have rewritten. +# --no-error-on-unmatched-pattern keeps the hook from failing when every staged +# file is ignored by .oxfmtrc.json. +"$oxfmt" --write --no-error-on-unmatched-pattern "${files[@]}" +git add -- "${files[@]}" diff --git a/scripts/bootstrap.ts b/scripts/bootstrap.ts index 923d868d7..347044f7f 100644 --- a/scripts/bootstrap.ts +++ b/scripts/bootstrap.ts @@ -31,4 +31,10 @@ if (!existsSync(resolve(repoRoot, "node_modules/.bin/vitest"))) { throw new Error("bootstrap: vitest missing after install — bun install likely failed"); } +// Point git at the tracked .githooks dir so the pre-commit hook auto-formats +// staged code with oxfmt. hooksPath is local config, never cloned or copied +// into worktrees, so every fresh checkout and agent worktree must re-set it; +// without it, unformatted commits slip through and CI's `format` job fails. +run("git hooks", "git", ["config", "core.hooksPath", ".githooks"]); + console.log("\n[bootstrap] done — `cd e2e && bun run test` runs the full suite."); From 536d31c7c5726002dee1b025f5ba71bc642edaa5 Mon Sep 17 00:00:00 2001 From: Rhys Sullivan <39114868+RhysSullivan@users.noreply.github.com> Date: Sun, 28 Jun 2026 14:36:34 -0700 Subject: [PATCH 2/2] chore: format package.json publishConfig to fix CI baseline origin/main was already failing oxfmt --check on 20 package.json files (publishConfig key order: access sorts before exports), so every PR inherited a red Format check regardless of its own contents. Format them once to make the baseline green. --- packages/core/cli/package.json | 4 ++-- packages/core/config/package.json | 4 ++-- packages/core/execution/package.json | 4 ++-- packages/core/integrations-registry/package.json | 4 ++-- packages/core/sdk/package.json | 4 ++-- packages/core/vite-plugin/package.json | 4 ++-- packages/kernel/core/package.json | 4 ++-- packages/kernel/runtime-quickjs/package.json | 4 ++-- packages/plugins/desktop-settings/package.json | 4 ++-- packages/plugins/example/package.json | 4 ++-- packages/plugins/file-secrets/package.json | 4 ++-- packages/plugins/google/package.json | 4 ++-- packages/plugins/graphql/package.json | 4 ++-- packages/plugins/keychain/package.json | 4 ++-- packages/plugins/mcp/package.json | 4 ++-- packages/plugins/microsoft/package.json | 4 ++-- packages/plugins/onepassword/package.json | 4 ++-- packages/plugins/openapi/package.json | 4 ++-- packages/plugins/toolkits/package.json | 4 ++-- packages/plugins/workos-vault/package.json | 4 ++-- 20 files changed, 40 insertions(+), 40 deletions(-) diff --git a/packages/core/cli/package.json b/packages/core/cli/package.json index e9f58c766..e02474f3d 100644 --- a/packages/core/cli/package.json +++ b/packages/core/cli/package.json @@ -23,6 +23,7 @@ ".": "./src/index.ts" }, "publishConfig": { + "access": "public", "exports": { ".": { "import": { @@ -30,8 +31,7 @@ "default": "./dist/index.js" } } - }, - "access": "public" + } }, "scripts": { "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", diff --git a/packages/core/config/package.json b/packages/core/config/package.json index a2ded694a..a01b40d83 100644 --- a/packages/core/config/package.json +++ b/packages/core/config/package.json @@ -19,6 +19,7 @@ ".": "./src/index.ts" }, "publishConfig": { + "access": "public", "exports": { ".": { "import": { @@ -26,8 +27,7 @@ "default": "./dist/index.js" } } - }, - "access": "public" + } }, "scripts": { "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", diff --git a/packages/core/execution/package.json b/packages/core/execution/package.json index 4173b1c6d..88f3a0009 100644 --- a/packages/core/execution/package.json +++ b/packages/core/execution/package.json @@ -20,6 +20,7 @@ "./promise": "./src/promise.ts" }, "publishConfig": { + "access": "public", "exports": { ".": { "import": { @@ -33,8 +34,7 @@ "default": "./dist/core.js" } } - }, - "access": "public" + } }, "scripts": { "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", diff --git a/packages/core/integrations-registry/package.json b/packages/core/integrations-registry/package.json index 44456c112..26511416d 100644 --- a/packages/core/integrations-registry/package.json +++ b/packages/core/integrations-registry/package.json @@ -20,6 +20,7 @@ ".": "./src/index.ts" }, "publishConfig": { + "access": "public", "exports": { ".": { "import": { @@ -27,8 +28,7 @@ "default": "./dist/index.js" } } - }, - "access": "public" + } }, "scripts": { "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", diff --git a/packages/core/sdk/package.json b/packages/core/sdk/package.json index 1c8430712..b318481c1 100644 --- a/packages/core/sdk/package.json +++ b/packages/core/sdk/package.json @@ -28,6 +28,7 @@ "./public-origin": "./src/public-origin.ts" }, "publishConfig": { + "access": "public", "exports": { ".": { "import": { @@ -83,8 +84,7 @@ "default": "./dist/public-origin.js" } } - }, - "access": "public" + } }, "scripts": { "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", diff --git a/packages/core/vite-plugin/package.json b/packages/core/vite-plugin/package.json index d8dfac836..22aae8890 100644 --- a/packages/core/vite-plugin/package.json +++ b/packages/core/vite-plugin/package.json @@ -23,6 +23,7 @@ } }, "publishConfig": { + "access": "public", "exports": { ".": { "import": { @@ -30,8 +31,7 @@ "default": "./dist/index.js" } } - }, - "access": "public" + } }, "scripts": { "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", diff --git a/packages/kernel/core/package.json b/packages/kernel/core/package.json index 17cb18c9f..4ae6a5096 100644 --- a/packages/kernel/core/package.json +++ b/packages/kernel/core/package.json @@ -19,6 +19,7 @@ ".": "./src/index.ts" }, "publishConfig": { + "access": "public", "exports": { ".": { "import": { @@ -26,8 +27,7 @@ "default": "./dist/index.js" } } - }, - "access": "public" + } }, "scripts": { "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", diff --git a/packages/kernel/runtime-quickjs/package.json b/packages/kernel/runtime-quickjs/package.json index 0d886c180..0896805fc 100644 --- a/packages/kernel/runtime-quickjs/package.json +++ b/packages/kernel/runtime-quickjs/package.json @@ -19,6 +19,7 @@ ".": "./src/index.ts" }, "publishConfig": { + "access": "public", "exports": { ".": { "import": { @@ -26,8 +27,7 @@ "default": "./dist/index.js" } } - }, - "access": "public" + } }, "scripts": { "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", diff --git a/packages/plugins/desktop-settings/package.json b/packages/plugins/desktop-settings/package.json index cc766ff3e..b2b05839d 100644 --- a/packages/plugins/desktop-settings/package.json +++ b/packages/plugins/desktop-settings/package.json @@ -20,6 +20,7 @@ "./client": "./src/client.tsx" }, "publishConfig": { + "access": "public", "exports": { "./server": { "import": { @@ -33,8 +34,7 @@ "default": "./dist/client.js" } } - }, - "access": "public" + } }, "scripts": { "build": "tsup", diff --git a/packages/plugins/example/package.json b/packages/plugins/example/package.json index 45ebbb303..488d2ccbf 100644 --- a/packages/plugins/example/package.json +++ b/packages/plugins/example/package.json @@ -21,6 +21,7 @@ "./shared": "./src/shared.ts" }, "publishConfig": { + "access": "public", "exports": { "./server": { "import": { @@ -40,8 +41,7 @@ "default": "./dist/shared.js" } } - }, - "access": "public" + } }, "scripts": { "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", diff --git a/packages/plugins/file-secrets/package.json b/packages/plugins/file-secrets/package.json index bcfbf732a..0e02900d0 100644 --- a/packages/plugins/file-secrets/package.json +++ b/packages/plugins/file-secrets/package.json @@ -20,6 +20,7 @@ "./promise": "./src/promise.ts" }, "publishConfig": { + "access": "public", "exports": { ".": { "import": { @@ -33,8 +34,7 @@ "default": "./dist/core.js" } } - }, - "access": "public" + } }, "scripts": { "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", diff --git a/packages/plugins/google/package.json b/packages/plugins/google/package.json index ba5379814..dff35716f 100644 --- a/packages/plugins/google/package.json +++ b/packages/plugins/google/package.json @@ -23,6 +23,7 @@ "./client": "./src/react/plugin-client.tsx" }, "publishConfig": { + "access": "public", "exports": { ".": { "import": { @@ -42,8 +43,7 @@ "default": "./dist/client.js" } } - }, - "access": "public" + } }, "scripts": { "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", diff --git a/packages/plugins/graphql/package.json b/packages/plugins/graphql/package.json index d69119197..c6736d58e 100644 --- a/packages/plugins/graphql/package.json +++ b/packages/plugins/graphql/package.json @@ -25,6 +25,7 @@ "./testing": "./src/testing/index.ts" }, "publishConfig": { + "access": "public", "exports": { ".": { "import": { @@ -50,8 +51,7 @@ "default": "./dist/testing.js" } } - }, - "access": "public" + } }, "scripts": { "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", diff --git a/packages/plugins/keychain/package.json b/packages/plugins/keychain/package.json index f4160085f..2ddb7b5ca 100644 --- a/packages/plugins/keychain/package.json +++ b/packages/plugins/keychain/package.json @@ -20,6 +20,7 @@ "./promise": "./src/promise.ts" }, "publishConfig": { + "access": "public", "exports": { ".": { "import": { @@ -33,8 +34,7 @@ "default": "./dist/core.js" } } - }, - "access": "public" + } }, "scripts": { "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", diff --git a/packages/plugins/mcp/package.json b/packages/plugins/mcp/package.json index c6ee01021..2d51f5597 100644 --- a/packages/plugins/mcp/package.json +++ b/packages/plugins/mcp/package.json @@ -25,6 +25,7 @@ "./testing": "./src/testing/index.ts" }, "publishConfig": { + "access": "public", "exports": { ".": { "import": { @@ -50,8 +51,7 @@ "default": "./dist/testing.js" } } - }, - "access": "public" + } }, "scripts": { "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", diff --git a/packages/plugins/microsoft/package.json b/packages/plugins/microsoft/package.json index 45f35d5db..d3d60aed8 100644 --- a/packages/plugins/microsoft/package.json +++ b/packages/plugins/microsoft/package.json @@ -23,6 +23,7 @@ "./client": "./src/react/plugin-client.tsx" }, "publishConfig": { + "access": "public", "exports": { ".": { "import": { @@ -42,8 +43,7 @@ "default": "./dist/client.js" } } - }, - "access": "public" + } }, "scripts": { "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", diff --git a/packages/plugins/onepassword/package.json b/packages/plugins/onepassword/package.json index c30fec111..7ba86b757 100644 --- a/packages/plugins/onepassword/package.json +++ b/packages/plugins/onepassword/package.json @@ -23,6 +23,7 @@ "./client": "./src/react/plugin-client.tsx" }, "publishConfig": { + "access": "public", "exports": { ".": { "import": { @@ -42,8 +43,7 @@ "default": "./dist/client.js" } } - }, - "access": "public" + } }, "scripts": { "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", diff --git a/packages/plugins/openapi/package.json b/packages/plugins/openapi/package.json index 2602e4837..12887f36e 100644 --- a/packages/plugins/openapi/package.json +++ b/packages/plugins/openapi/package.json @@ -25,6 +25,7 @@ "./testing": "./src/testing/index.ts" }, "publishConfig": { + "access": "public", "exports": { ".": { "import": { @@ -50,8 +51,7 @@ "default": "./dist/testing.js" } } - }, - "access": "public" + } }, "scripts": { "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", diff --git a/packages/plugins/toolkits/package.json b/packages/plugins/toolkits/package.json index 2858a6d9d..880751288 100644 --- a/packages/plugins/toolkits/package.json +++ b/packages/plugins/toolkits/package.json @@ -21,6 +21,7 @@ "./shared": "./src/shared.ts" }, "publishConfig": { + "access": "public", "exports": { "./server": { "import": { @@ -40,8 +41,7 @@ "default": "./dist/shared.js" } } - }, - "access": "public" + } }, "scripts": { "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)", diff --git a/packages/plugins/workos-vault/package.json b/packages/plugins/workos-vault/package.json index 191bc70ed..1f1017918 100644 --- a/packages/plugins/workos-vault/package.json +++ b/packages/plugins/workos-vault/package.json @@ -23,6 +23,7 @@ "./testing": "./src/sdk/testing.ts" }, "publishConfig": { + "access": "public", "exports": { ".": { "import": { @@ -42,8 +43,7 @@ "default": "./dist/testing.js" } } - }, - "access": "public" + } }, "scripts": { "build": "tsup && (tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src || true)",