Skip to content
Merged
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
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ Use this exact checklist to setup multi-agent safety in this repository for Code
6) Optional: protect extra branches:
musafety protect add release staging

7) Optional: sync your current agent branch with latest dev:
7) Optional: sync your current agent branch with latest base branch:
musafety sync --check
musafety sync
```
Expand Down Expand Up @@ -212,7 +212,7 @@ musafety scan [--target <path>] [--json]
musafety report help
```

## Keep agent branches synced with dev
## Keep agent branches synced with your base branch

Use sync checks before finishing agent branches:

Expand All @@ -223,9 +223,16 @@ musafety sync

Defaults:

- base branch: `dev` (or `multiagent.baseBranch`)
- `musafety sync` base branch: `dev` (or `multiagent.baseBranch`)
- strategy: `rebase` (or `multiagent.sync.strategy`)

`agent-branch-start.sh` and `agent-branch-finish.sh` resolve base branch in this order:

1. explicit `--base`
2. `multiagent.baseBranch`
3. branch-linked base metadata / source upstream / current checked-out branch (context-dependent)
4. fallback `dev`

Useful variants:

```sh
Expand Down
2 changes: 1 addition & 1 deletion bin/multiagent-safety.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ const AI_SETUP_PROMPT = `Use this exact checklist to setup multi-agent safety in
6) Optional: protect extra branches:
musafety protect add release staging

7) Optional: sync your current agent branch with latest dev:
7) Optional: sync your current agent branch with latest base branch:
musafety sync --check
musafety sync
`;
Expand Down
37 changes: 34 additions & 3 deletions scripts/agent-branch-finish.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail

BASE_BRANCH="dev"
BASE_BRANCH=""
BASE_BRANCH_EXPLICIT=0
SOURCE_BRANCH=""
PUSH_ENABLED=1
Expand Down Expand Up @@ -64,15 +64,46 @@ fi
repo_root="$(git rev-parse --show-toplevel)"
current_worktree="$(pwd -P)"

if [[ -z "$SOURCE_BRANCH" ]]; then
SOURCE_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
fi

if [[ "$BASE_BRANCH_EXPLICIT" -eq 1 && -z "$BASE_BRANCH" ]]; then
echo "[agent-branch-finish] --base requires a non-empty branch name." >&2
exit 1
fi

if [[ "$BASE_BRANCH_EXPLICIT" -eq 0 ]]; then
configured_base="$(git -C "$repo_root" config --get multiagent.baseBranch || true)"
if [[ -n "$configured_base" ]]; then
BASE_BRANCH="$configured_base"
fi
fi

if [[ -z "$SOURCE_BRANCH" ]]; then
SOURCE_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
if [[ -z "$BASE_BRANCH" ]]; then
branch_stored_base="$(git -C "$repo_root" config --get "branch.${SOURCE_BRANCH}.musafetyBase" || true)"
if [[ -n "$branch_stored_base" ]]; then
BASE_BRANCH="$branch_stored_base"
fi
fi

if [[ -z "$BASE_BRANCH" ]]; then
source_upstream="$(git -C "$repo_root" for-each-ref --format='%(upstream:short)' "refs/heads/${SOURCE_BRANCH}" | head -n 1)"
source_upstream="${source_upstream:-}"
if [[ "$source_upstream" == */* ]]; then
BASE_BRANCH="${source_upstream#*/}"
fi
fi

if [[ -z "$BASE_BRANCH" ]]; then
current_branch="$(git -C "$repo_root" rev-parse --abbrev-ref HEAD 2>/dev/null || true)"
if [[ -n "$current_branch" && "$current_branch" != "HEAD" && "$current_branch" != "$SOURCE_BRANCH" ]]; then
BASE_BRANCH="$current_branch"
fi
fi

if [[ -z "$BASE_BRANCH" ]]; then
BASE_BRANCH="dev"
fi

if [[ "$SOURCE_BRANCH" == "$BASE_BRANCH" ]]; then
Expand Down
31 changes: 29 additions & 2 deletions scripts/agent-branch-start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@ set -euo pipefail

TASK_NAME="${1:-task}"
AGENT_NAME="${2:-agent}"
BASE_BRANCH="${3:-dev}"
BASE_BRANCH="${3:-}"
BASE_BRANCH_EXPLICIT=0
WORKTREE_MODE=1
WORKTREE_ROOT_REL=".omx/agent-worktrees"

if [[ -n "${3:-}" ]]; then
BASE_BRANCH_EXPLICIT=1
fi

while [[ $# -gt 0 ]]; do
case "$1" in
--task)
Expand All @@ -18,7 +23,8 @@ while [[ $# -gt 0 ]]; do
shift 2
;;
--base)
BASE_BRANCH="${2:-dev}"
BASE_BRANCH="${2:-}"
BASE_BRANCH_EXPLICIT=1
shift 2
;;
--in-place)
Expand Down Expand Up @@ -80,6 +86,25 @@ fi

repo_root="$(git rev-parse --show-toplevel)"

if [[ "$BASE_BRANCH_EXPLICIT" -eq 1 && -z "$BASE_BRANCH" ]]; then
echo "[agent-branch-start] --base requires a non-empty branch name." >&2
exit 1
fi

if [[ "$BASE_BRANCH_EXPLICIT" -eq 0 ]]; then
configured_base="$(git -C "$repo_root" config --get multiagent.baseBranch || true)"
if [[ -n "$configured_base" ]]; then
BASE_BRANCH="$configured_base"
else
current_branch="$(git -C "$repo_root" rev-parse --abbrev-ref HEAD 2>/dev/null || true)"
if [[ -n "$current_branch" && "$current_branch" != "HEAD" ]]; then
BASE_BRANCH="$current_branch"
else
BASE_BRANCH="dev"
fi
fi
fi

if git show-ref --verify --quiet "refs/remotes/origin/${BASE_BRANCH}"; then
git fetch origin "${BASE_BRANCH}" --quiet
start_ref="origin/${BASE_BRANCH}"
Expand Down Expand Up @@ -123,6 +148,7 @@ if [[ "$WORKTREE_MODE" -eq 0 ]]; then
fi

git checkout -b "$branch_name"
git -C "$repo_root" config "branch.${branch_name}.musafetyBase" "$BASE_BRANCH" >/dev/null 2>&1 || true
echo "[agent-branch-start] Created in-place branch: ${branch_name}"
echo "$branch_name"
exit 0
Expand All @@ -138,6 +164,7 @@ if [[ -e "$worktree_path" ]]; then
fi

git -C "$repo_root" worktree add -b "$branch_name" "$worktree_path" "$start_ref"
git -C "$repo_root" config "branch.${branch_name}.musafetyBase" "$BASE_BRANCH" >/dev/null 2>&1 || true

if git -C "$repo_root" show-ref --verify --quiet "refs/remotes/origin/${BASE_BRANCH}"; then
git -C "$worktree_path" branch --set-upstream-to="origin/${BASE_BRANCH}" "$branch_name" >/dev/null 2>&1 || true
Expand Down
37 changes: 34 additions & 3 deletions templates/scripts/agent-branch-finish.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
set -euo pipefail

BASE_BRANCH="dev"
BASE_BRANCH=""
BASE_BRANCH_EXPLICIT=0
SOURCE_BRANCH=""
PUSH_ENABLED=1
Expand Down Expand Up @@ -64,15 +64,46 @@ fi
repo_root="$(git rev-parse --show-toplevel)"
current_worktree="$(pwd -P)"

if [[ -z "$SOURCE_BRANCH" ]]; then
SOURCE_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
fi

if [[ "$BASE_BRANCH_EXPLICIT" -eq 1 && -z "$BASE_BRANCH" ]]; then
echo "[agent-branch-finish] --base requires a non-empty branch name." >&2
exit 1
fi

if [[ "$BASE_BRANCH_EXPLICIT" -eq 0 ]]; then
configured_base="$(git -C "$repo_root" config --get multiagent.baseBranch || true)"
if [[ -n "$configured_base" ]]; then
BASE_BRANCH="$configured_base"
fi
fi

if [[ -z "$SOURCE_BRANCH" ]]; then
SOURCE_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
if [[ -z "$BASE_BRANCH" ]]; then
branch_stored_base="$(git -C "$repo_root" config --get "branch.${SOURCE_BRANCH}.musafetyBase" || true)"
if [[ -n "$branch_stored_base" ]]; then
BASE_BRANCH="$branch_stored_base"
fi
fi

if [[ -z "$BASE_BRANCH" ]]; then
source_upstream="$(git -C "$repo_root" for-each-ref --format='%(upstream:short)' "refs/heads/${SOURCE_BRANCH}" | head -n 1)"
source_upstream="${source_upstream:-}"
if [[ "$source_upstream" == */* ]]; then
BASE_BRANCH="${source_upstream#*/}"
fi
fi

if [[ -z "$BASE_BRANCH" ]]; then
current_branch="$(git -C "$repo_root" rev-parse --abbrev-ref HEAD 2>/dev/null || true)"
if [[ -n "$current_branch" && "$current_branch" != "HEAD" && "$current_branch" != "$SOURCE_BRANCH" ]]; then
BASE_BRANCH="$current_branch"
fi
fi

if [[ -z "$BASE_BRANCH" ]]; then
BASE_BRANCH="dev"
fi

if [[ "$SOURCE_BRANCH" == "$BASE_BRANCH" ]]; then
Expand Down
28 changes: 26 additions & 2 deletions templates/scripts/agent-branch-start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ set -euo pipefail

TASK_NAME="task"
AGENT_NAME="agent"
BASE_BRANCH="dev"
BASE_BRANCH=""
BASE_BRANCH_EXPLICIT=0
WORKTREE_MODE=1
ALLOW_IN_PLACE=0
WORKTREE_ROOT_REL=".omx/agent-worktrees"
Expand All @@ -20,7 +21,8 @@ while [[ $# -gt 0 ]]; do
shift 2
;;
--base)
BASE_BRANCH="${2:-dev}"
BASE_BRANCH="${2:-}"
BASE_BRANCH_EXPLICIT=1
shift 2
;;
--in-place)
Expand Down Expand Up @@ -71,6 +73,7 @@ fi

if [[ "${#POSITIONAL_ARGS[@]}" -ge 3 ]]; then
BASE_BRANCH="${POSITIONAL_ARGS[2]}"
BASE_BRANCH_EXPLICIT=1
fi

sanitize_slug() {
Expand Down Expand Up @@ -109,6 +112,25 @@ fi

repo_root="$(git rev-parse --show-toplevel)"

if [[ "$BASE_BRANCH_EXPLICIT" -eq 1 && -z "$BASE_BRANCH" ]]; then
echo "[agent-branch-start] --base requires a non-empty branch name." >&2
exit 1
fi

if [[ "$BASE_BRANCH_EXPLICIT" -eq 0 ]]; then
configured_base="$(git -C "$repo_root" config --get multiagent.baseBranch || true)"
if [[ -n "$configured_base" ]]; then
BASE_BRANCH="$configured_base"
else
current_branch="$(git -C "$repo_root" rev-parse --abbrev-ref HEAD 2>/dev/null || true)"
if [[ -n "$current_branch" && "$current_branch" != "HEAD" ]]; then
BASE_BRANCH="$current_branch"
else
BASE_BRANCH="dev"
fi
fi
fi

if git show-ref --verify --quiet "refs/remotes/origin/${BASE_BRANCH}"; then
git fetch origin "${BASE_BRANCH}" --quiet
start_ref="origin/${BASE_BRANCH}"
Expand Down Expand Up @@ -158,6 +180,7 @@ if [[ "$WORKTREE_MODE" -eq 0 ]]; then
fi

git checkout -b "$branch_name"
git -C "$repo_root" config "branch.${branch_name}.musafetyBase" "$BASE_BRANCH" >/dev/null 2>&1 || true
echo "[agent-branch-start] Created in-place branch: ${branch_name}"
echo "$branch_name"
exit 0
Expand All @@ -173,6 +196,7 @@ if [[ -e "$worktree_path" ]]; then
fi

git -C "$repo_root" worktree add -b "$branch_name" "$worktree_path" "$start_ref"
git -C "$repo_root" config "branch.${branch_name}.musafetyBase" "$BASE_BRANCH" >/dev/null 2>&1 || true

if git -C "$repo_root" show-ref --verify --quiet "refs/remotes/origin/${BASE_BRANCH}"; then
git -C "$worktree_path" branch --set-upstream-to="origin/${BASE_BRANCH}" "$branch_name" >/dev/null 2>&1 || true
Expand Down
21 changes: 19 additions & 2 deletions templates/scripts/codex-agent.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@ set -euo pipefail

TASK_NAME="${MUSAFETY_TASK_NAME:-task}"
AGENT_NAME="${MUSAFETY_AGENT_NAME:-agent}"
BASE_BRANCH="${MUSAFETY_BASE_BRANCH:-dev}"
BASE_BRANCH="${MUSAFETY_BASE_BRANCH:-}"
BASE_BRANCH_EXPLICIT=0
CODEX_BIN="${MUSAFETY_CODEX_BIN:-codex}"

if [[ -n "$BASE_BRANCH" ]]; then
BASE_BRANCH_EXPLICIT=1
fi

while [[ $# -gt 0 ]]; do
case "$1" in
--task)
Expand All @@ -18,6 +23,7 @@ while [[ $# -gt 0 ]]; do
;;
--base)
BASE_BRANCH="${2:-$BASE_BRANCH}"
BASE_BRANCH_EXPLICIT=1
shift 2
;;
--codex-bin)
Expand All @@ -40,13 +46,19 @@ while [[ $# -gt 0 ]]; do
fi
if [[ $# -gt 0 && "${1:-}" != -* ]]; then
BASE_BRANCH="$1"
BASE_BRANCH_EXPLICIT=1
shift
fi
break
;;
esac
done

if [[ "$BASE_BRANCH_EXPLICIT" -eq 1 && -z "$BASE_BRANCH" ]]; then
echo "[codex-agent] --base requires a non-empty branch name." >&2
exit 1
fi

if ! command -v "$CODEX_BIN" >/dev/null 2>&1; then
echo "[codex-agent] Missing Codex CLI command: $CODEX_BIN" >&2
echo "[codex-agent] Install Codex first, then retry." >&2
Expand All @@ -58,7 +70,12 @@ if [[ ! -x "scripts/agent-branch-start.sh" ]]; then
exit 1
fi

start_output="$(bash scripts/agent-branch-start.sh "$TASK_NAME" "$AGENT_NAME" "$BASE_BRANCH")"
start_args=("$TASK_NAME" "$AGENT_NAME")
if [[ "$BASE_BRANCH_EXPLICIT" -eq 1 ]]; then
start_args+=("$BASE_BRANCH")
fi

start_output="$(bash scripts/agent-branch-start.sh "${start_args[@]}")"
printf '%s\n' "$start_output"

worktree_path="$(printf '%s\n' "$start_output" | sed -n 's/^\[agent-branch-start\] Worktree: //p' | tail -n1)"
Expand Down
Loading
Loading