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
33 changes: 29 additions & 4 deletions scripts/agent-branch-start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,33 @@ done

sanitize_slug() {
local raw="$1"
local fallback="${2:-task}"
local slug
slug="$(printf '%s' "$raw" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//; s/-{2,}/-/g')"
if [[ -z "$slug" ]]; then
slug="task"
slug="$fallback"
fi
printf '%s' "$slug"
}

resolve_active_codex_snapshot_name() {
local override="${MUSAFETY_CODEX_AUTH_SNAPSHOT:-}"
if [[ -n "$override" ]]; then
printf '%s' "$override"
return 0
fi

local codex_auth_bin="${MUSAFETY_CODEX_AUTH_BIN:-codex-auth}"
if ! command -v "$codex_auth_bin" >/dev/null 2>&1; then
return 0
fi

"$codex_auth_bin" list 2>/dev/null \
| sed -n 's/^[[:space:]]*\*[[:space:]]\+//p' \
| head -n 1 \
| tr -d '\r' || true
}

if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
echo "[agent-branch-start] Not inside a git repository." >&2
exit 1
Expand All @@ -72,10 +91,16 @@ else
start_ref="${BASE_BRANCH}"
fi

task_slug="$(sanitize_slug "$TASK_NAME")"
agent_slug="$(sanitize_slug "$AGENT_NAME")"
task_slug="$(sanitize_slug "$TASK_NAME" "task")"
agent_slug="$(sanitize_slug "$AGENT_NAME" "agent")"
snapshot_name="$(resolve_active_codex_snapshot_name)"
snapshot_slug="$(sanitize_slug "$snapshot_name" "")"
timestamp="$(date +%Y%m%d-%H%M%S)"
branch_name="agent/${agent_slug}/${timestamp}-${task_slug}"
if [[ -n "$snapshot_slug" ]]; then
branch_name="agent/${agent_slug}/${timestamp}-${snapshot_slug}-${task_slug}"
else
branch_name="agent/${agent_slug}/${timestamp}-${task_slug}"
fi

if git show-ref --verify --quiet "refs/heads/${branch_name}"; then
echo "[agent-branch-start] Branch already exists: ${branch_name}" >&2
Expand Down
33 changes: 29 additions & 4 deletions templates/scripts/agent-branch-start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,33 @@ fi

sanitize_slug() {
local raw="$1"
local fallback="${2:-task}"
local slug
slug="$(printf '%s' "$raw" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//; s/-{2,}/-/g')"
if [[ -z "$slug" ]]; then
slug="task"
slug="$fallback"
fi
printf '%s' "$slug"
}

resolve_active_codex_snapshot_name() {
local override="${MUSAFETY_CODEX_AUTH_SNAPSHOT:-}"
if [[ -n "$override" ]]; then
printf '%s' "$override"
return 0
fi

local codex_auth_bin="${MUSAFETY_CODEX_AUTH_BIN:-codex-auth}"
if ! command -v "$codex_auth_bin" >/dev/null 2>&1; then
return 0
fi

"$codex_auth_bin" list 2>/dev/null \
| sed -n 's/^[[:space:]]*\*[[:space:]]\+//p' \
| head -n 1 \
| tr -d '\r' || true
}

if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
echo "[agent-branch-start] Not inside a git repository." >&2
exit 1
Expand All @@ -101,10 +120,16 @@ else
start_ref="${BASE_BRANCH}"
fi

task_slug="$(sanitize_slug "$TASK_NAME")"
agent_slug="$(sanitize_slug "$AGENT_NAME")"
task_slug="$(sanitize_slug "$TASK_NAME" "task")"
agent_slug="$(sanitize_slug "$AGENT_NAME" "agent")"
snapshot_name="$(resolve_active_codex_snapshot_name)"
snapshot_slug="$(sanitize_slug "$snapshot_name" "")"
timestamp="$(date +%Y%m%d-%H%M%S)"
branch_name="agent/${agent_slug}/${timestamp}-${task_slug}"
if [[ -n "$snapshot_slug" ]]; then
branch_name="agent/${agent_slug}/${timestamp}-${snapshot_slug}-${task_slug}"
else
branch_name="agent/${agent_slug}/${timestamp}-${task_slug}"
fi

if git show-ref --verify --quiet "refs/heads/${branch_name}"; then
echo "[agent-branch-start] Branch already exists: ${branch_name}" >&2
Expand Down
52 changes: 52 additions & 0 deletions test/install.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ function createFakeScorecardScript(scriptBody) {
return fakePath;
}

function createFakeCodexAuthScript(scriptBody) {
const fakeBin = fs.mkdtempSync(path.join(os.tmpdir(), 'musafety-fake-codex-auth-'));
const fakePath = path.join(fakeBin, 'codex-auth');
fs.writeFileSync(fakePath, `#!/usr/bin/env bash\nset -e\n${scriptBody}\n`, 'utf8');
fs.chmodSync(fakePath, 0o755);
return { fakeBin, fakePath };
}

function initRepo() {
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'musafety-'));
const repoDir = path.join(tempDir, 'repo');
Expand Down Expand Up @@ -241,6 +249,50 @@ test('setup agent-branch-start requires --allow-in-place when using --in-place',
assert.match(result.stderr, /--in-place --allow-in-place/);
});

test('setup agent-branch-start includes active codex snapshot slug in branch name', () => {
const repoDir = initRepo();

let result = runNode(['setup', '--target', repoDir], repoDir);
assert.equal(result.status, 0, result.stderr || result.stdout);
seedCommit(repoDir);

const { fakeBin } = createFakeCodexAuthScript(`
if [[ "$1" != "list" ]]; then
exit 1
fi
cat <<'OUT'
default
* Zeus Edix Hu
OUT
`);

result = runCmd(
'bash',
['scripts/agent-branch-start.sh', 'restore-snapshot', 'planner', 'dev'],
repoDir,
{ env: { PATH: `${fakeBin}:${process.env.PATH || ''}` } },
);
assert.equal(result.status, 0, result.stderr || result.stdout);
assert.match(result.stdout, /Created branch: agent\/planner\/\d{8}-\d{6}-zeus-edix-hu-restore-snapshot/);
});

test('setup agent-branch-start supports explicit snapshot override without codex-auth', () => {
const repoDir = initRepo();

let result = runNode(['setup', '--target', repoDir], repoDir);
assert.equal(result.status, 0, result.stderr || result.stdout);
seedCommit(repoDir);

result = runCmd(
'bash',
['scripts/agent-branch-start.sh', 'ship-fix', 'bot', 'dev'],
repoDir,
{ env: { MUSAFETY_CODEX_AUTH_SNAPSHOT: 'Prod Snapshot One' } },
);
assert.equal(result.status, 0, result.stderr || result.stdout);
assert.match(result.stdout, /Created branch: agent\/bot\/\d{8}-\d{6}-prod-snapshot-one-ship-fix/);
});

test('default invocation runs non-mutating status output', () => {
const repoDir = initRepo();

Expand Down
Loading