* 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>
91 lines
No EOL
2.6 KiB
Bash
Executable file
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" |