diff --git a/BESTPRACTICES.md b/BESTPRACTICES.md index 582f851..b1fe98d 100644 --- a/BESTPRACTICES.md +++ b/BESTPRACTICES.md @@ -1,3 +1,7 @@ +> **Note:** Best practices are now maintained in [skynet/best-practices](https://gitea.oreillyit.nz/skynet/best-practices). +> AI agents with /best-practices mounted should read /best-practices/INDEX.md instead. +> The content below is kept as a local copy for context-load compatibility. + # Best Practices Index Generalised best practices extracted from real project work. Each topic file is self-contained — read only the files relevant to the current project. diff --git a/README.md b/README.md index fd21ab4..60e67fd 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ claude-foundations/ setup-formatters.sh # Set up formatters for a project statusline.sh # Status line renderer (symlinked from ~/.claude/status/) set-topic.sh # Set per-session topic for the status line - best-practices/ # Generalised best practices (one file per topic) + best-practices/ # Generalised best practices (one file per topic) — also maintained in skynet/best-practices context/ # Active work focus detail files memory/ # Session logs and reflections settings.yaml # Knowledge pipeline configuration diff --git a/scripts/sync-best-practices.sh b/scripts/sync-best-practices.sh new file mode 100755 index 0000000..c7edad1 --- /dev/null +++ b/scripts/sync-best-practices.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# sync-best-practices.sh — Sync best-practices/ from skynet/best-practices repo +# Usage: scripts/sync-best-practices.sh [--dry-run] +set -euo pipefail + +REPO_URL="https://gitea.oreillyit.nz/skynet/best-practices.git" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +BP_DIR="$REPO_ROOT/best-practices" +BESTPRACTICES_MD="$REPO_ROOT/BESTPRACTICES.md" +DRY_RUN=false + +if [[ "${1:-}" == "--dry-run" ]]; then + DRY_RUN=true + echo "[dry-run] No changes will be written or committed" +fi + +TMPDIR="$(mktemp -d)" +trap 'rm -rf "$TMPDIR"' EXIT + +echo "Cloning $REPO_URL ..." +git clone --depth=1 "$REPO_URL" "$TMPDIR/best-practices" + +# Copy all .md files from the source repo into best-practices/ +echo "Copying .md files to $BP_DIR ..." +if ! $DRY_RUN; then + find "$TMPDIR/best-practices" -maxdepth 1 -name "*.md" -exec cp {} "$BP_DIR/" \; + # Also copy subdirectory .md files preserving structure + find "$TMPDIR/best-practices" -mindepth 2 -name "*.md" | while read -r src; do + rel="${src#$TMPDIR/best-practices/}" + dest="$BP_DIR/$rel" + mkdir -p "$(dirname "$dest")" + cp "$src" "$dest" + done +else + echo "[dry-run] Would copy:" + find "$TMPDIR/best-practices" -name "*.md" | sed "s|$TMPDIR/best-practices/||" +fi + +# Update BESTPRACTICES.md topic list from INDEX.md, preserving the redirect header +INDEX_MD="$TMPDIR/best-practices/INDEX.md" +if [[ -f "$INDEX_MD" ]]; then + echo "Updating $BESTPRACTICES_MD topic list from INDEX.md ..." + if ! $DRY_RUN; then + # Extract the redirect header (everything up to and including the first blank line after the blockquote) + HEADER=$(awk '/^> \*\*Note:\*\*/{found=1} found{print} found && /^$/{exit}' "$BESTPRACTICES_MD") + if [[ -z "$HEADER" ]]; then + # Fallback: preserve first 4 lines (the note block) + HEADER=$(head -4 "$BESTPRACTICES_MD") + fi + + # Write header + blank line + INDEX.md content + { + echo "$HEADER" + echo "" + cat "$INDEX_MD" + } > "$BESTPRACTICES_MD" + else + echo "[dry-run] Would update $BESTPRACTICES_MD from INDEX.md" + fi +else + echo "No INDEX.md found in source repo — skipping BESTPRACTICES.md update" +fi + +# Commit if there are changes +if ! $DRY_RUN; then + cd "$REPO_ROOT" + if git diff --quiet && git diff --cached --quiet; then + echo "No changes to commit." + else + git add best-practices/ BESTPRACTICES.md + git commit -m "Sync best-practices from skynet/best-practices" + echo "Committed sync changes." + fi +fi + +echo "Done."