Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Handler entry tests: `cdk/test/handlers/orchestrate-task.test.ts`, `create-task.
- **`mise run build`** runs **`//agent:quality`** before CDK — the deployed image bundles **`agent/`**; agent changes belong in that tree.
- **`prek install`** fails if Git **`core.hooksPath`** is set — another hook manager owns hooks; see [CONTRIBUTING.md](./CONTRIBUTING.md).
- **Editing on `main` directly** — ALWAYS create a worktree with a feature branch for changes, even trivial ones. Main should stay clean; all work flows through worktree → branch → PR → merge.
- **Git worktrees** — Always **`git fetch origin main`** before creating a new worktree to ensure you branch from the latest remote state. `node_modules/` and `agent/.venv/` are per-tree (not shared). Run **`mise run install`** in each new worktree before building. All CDK path references (`__dirname`-relative) and mise `config_roots` resolve correctly without extra setup.
- **Git worktrees** — Always **`git fetch origin main`** before creating a new worktree to ensure you branch from the latest remote state. `node_modules/` and `agent/.venv/` are per-tree (not shared). Run **`mise run install`** in each new worktree before building. All CDK path references (`__dirname`-relative) and mise `config_roots` resolve correctly without extra setup. Run **`mise run worktree:sync`** periodically to rebase clean linked worktrees onto **`origin/main`** so they don't drift behind merged PRs.
- **Bumping Cedar engines in isolation** — `cedarpy` (Python, `agent/pyproject.toml`) and `@cedar-policy/cedar-wasm` (TypeScript, `cdk/package.json`) are two language bindings over the same Cedar Rust core. They MUST move together; even patch-version drift between bindings can yield divergent `(decision, matching_rule_ids)` on the same `(policy, input)` — invisible to per-side unit tests, caught (only) by `contracts/cedar-parity/` golden fixtures in CI. If you bump one engine you MUST bump the other to a tested-compatible version AND refresh the parity fixtures in the same commit. Both pins are EXACT (no `^`/`~`). See `docs/design/CEDAR_HITL_GATES.md` §15.6 (decision #23) and the parity-contract banner in `mise.toml`. **DO NOT** accept upstream's "Update branch" or auto-merge suggestions on cedarpy without verifying parity with cedar-wasm.

### Tech stack
Expand Down Expand Up @@ -117,6 +117,7 @@ Run `mise tasks --all` (with `MISE_EXPERIMENTAL=1`) for the full list. Common co
- **`mise run security:gh-actions`** — Static analysis of GitHub Actions under **`.github/`** ([zizmor](https://github.com/zizmorcore/zizmor)).
- **`mise run hooks:install`** — Re-install **[prek](https://github.com/j178/prek)** git hooks (also run automatically at the end of **`mise run install`** inside a Git checkout). See [CONTRIBUTING.md](./CONTRIBUTING.md) if `core.hooksPath` blocks install.
- **`mise run hooks:run`** — Run the same **pre-commit** and **pre-push** hook stages on all files (local verification).
- **`mise run worktree:sync`** — Fetch **`origin/main`** and rebase every clean linked worktree onto it (issue #197). Dirty worktrees and `main` itself are skipped; conflicting rebases are aborted and reported with a non-zero exit status.

Use these instead of running `tsc`, `jest`, or `cdk` directly when possible, so the project's scripts and config stay consistent.

Expand Down
49 changes: 49 additions & 0 deletions mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,55 @@ run = [
"mise run hooks:pre-push:tests",
]

##################
#### WORKTREE ####
##################

# Issue #197: worktrees branched from origin/main drift silently as other PRs
# merge. This task fetches origin/main and rebases every clean linked worktree
# onto it. Worktrees on already-merged branches are reported and skipped (no
# rebase needed); dirty worktrees are skipped (no rebase on uncommitted
# changes); main itself (the primary worktree) is also skipped. Branches that
# fail to rebase are aborted and reported so the next push surfaces the
# conflict explicitly rather than silently leaving a half-rebased state.
[tasks."worktree:sync"]
description = "Fetch origin/main and rebase every clean linked worktree onto it"
run = """
#!/usr/bin/env bash
set -eu -o pipefail
git fetch origin main
status=0
# tab-delimited "worktree<TAB>branch" pairs, one per linked worktree
pairs="$(git worktree list --porcelain | awk '
/^worktree / { wt = substr($0, 10) }
/^branch / { print wt "\\t" substr($0, 8); wt = "" }
')"
while IFS=$'\\t' read -r wt branch; do
[ -z "${wt:-}" ] && continue
short_branch="${branch#refs/heads/}"
# Skip the main branch — `git pull` is the right tool for it, not rebase.
case "$short_branch" in main|master) continue ;; esac
# If the branch tip is already in origin/main, the work has merged and a
# rebase would either no-op or replay merged commits depending on history.
# Report and skip so the operator can prune the worktree at their leisure.
if git -C "$wt" merge-base --is-ancestor HEAD origin/main 2>/dev/null; then
echo "MERGED $short_branch ($wt) — already in origin/main, no rebase needed"
continue
fi
if [ -n "$(git -C "$wt" status --porcelain)" ]; then
echo "SKIP $short_branch ($wt) — dirty working tree"
continue
fi
echo "Rebasing $short_branch ($wt) onto origin/main..."
if ! git -C "$wt" rebase origin/main; then
echo "FAIL $short_branch — rebase aborted (resolve conflicts manually)"
git -C "$wt" rebase --abort || true
status=1
fi
done <<< "$pairs"
exit $status
"""

##################
##### BUILD #####
##################
Expand Down
Loading