opencode-config/.opencode/scripts/scaffold-handoff.sh
Sergey 0bf97cf1c5
fix(scripts): compute next ADR as max+1 not count+1 in scaffold (#182)
* fix(scripts): compute next ADR as max+1 not count+1 in scaffold

* docs(handoff): add handoff and ADR-079 for ADR numbering fix

* docs(handoff): set PR number

---------

Co-authored-by: opencode-agent <agent@opencode.local>
2026-07-31 22:13:30 +03:00

91 lines
No EOL
2.6 KiB
Bash
Executable file

#!/usr/bin/env bash
# Create handoff + ADR templates for a PR.
# Usage: bash .opencode/scripts/scaffold-handoff.sh <PR#> <slug>
# Idempotent: does not overwrite existing files.
set -euo pipefail
PR="${1:?Usage: scaffold-handoff.sh <PR#> <slug>}"
SLUG="${2:?Usage: scaffold-handoff.sh <PR#> <slug>}"
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo "")"
if [ -z "$REPO_ROOT" ]; then
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
fi
HANDOFF_DIR="$REPO_ROOT/docs/handoff"
ADR_DIR="$REPO_ROOT/docs/decisions"
mkdir -p "$HANDOFF_DIR" "$ADR_DIR"
HANDOFF="$HANDOFF_DIR/pr-${PR}-${SLUG}.md"
TODAY="$(date +%Y-%m-%d)"
if [ -f "$HANDOFF" ]; then
echo "handoff already exists: $HANDOFF"
else
cat > "$HANDOFF" <<EOF
---
pr: ${PR}
title: <заполни>
---
## Что сделано
<заполни>
## Почему
<заполни>
## Pending
<заполни, или «—»>
## Watch out
<заполни, или «—»>
EOF
echo "created: $HANDOFF"
fi
EXISTING_ADR="$(ls "$ADR_DIR"/*-pr-${PR}-${SLUG}.md 2>/dev/null | head -n1 || true)"
if [ -n "$EXISTING_ADR" ]; then
ADR="$EXISTING_ADR"
echo "ADR already exists: $ADR"
else
# Next ADR number = max(existing) + 1, NOT count + 1.
# count+1 collides when files are added out of order or in parallel
# (e.g. two PRs both computed wc -l = 72 → both wrote ADR-073, see issue #176).
# max+1 is race-resistant: each run reads the current highest number.
# Guard loop handles the residual race: if max+1 file already exists
# (created between the max-read and our write), increment to a free slot.
# 10# forces base-10 (leading zeros like 078 are invalid octal in bash).
# `|| true` neutralizes grep's exit 1 under set -euo pipefail when the
# directory is empty (no ADRs yet → max=0 → next=001).
MAX_N="$(ls "$ADR_DIR" 2>/dev/null | grep -E '^[0-9]{3}-' | cut -c1-3 | sort -n | tail -n1 || true)"
NEXT_N=$((10#${MAX_N:-0} + 1))
while :; do
NN="$(printf "%03d" "$NEXT_N")"
ADR="$ADR_DIR/${NN}-pr-${PR}-${SLUG}.md"
if ! ls "$ADR_DIR"/${NN}-pr-*.md >/dev/null 2>&1; then
break
fi
NEXT_N=$((NEXT_N + 1))
done
cat > "$ADR" <<EOF
# ADR-${NN}: <title>
## Статус
Accepted (${TODAY})
## Контекст
<заполни, или «—» если архитектурных решений не было>
## Решение
<заполни, или «—»>
## Альтернативы
<заполни, или «—»>
EOF
echo "created: $ADR"
fi
echo ""
echo "handoff: $HANDOFF"
echo "adr: $ADR"