Add diff-upstream.sh and document framework change workflow

New script extracts a diff of framework files against the upstream
ref in .diachron-version.  Both DIACHRON.md and diachron/AGENTS.md
now explain how to use it and recommend keeping framework changes
in discrete, well-described commits to ease upstreaming.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-08 16:43:43 -05:00
parent 8318e60c33
commit ae077886ba
4 changed files with 143 additions and 2 deletions

View File

@@ -88,8 +88,24 @@ There are two owners of files in a diachron project:
`backend/diachron/`, and the top-level scripts (`cmd`, `develop`, `mgmt`, `backend/diachron/`, and the top-level scripts (`cmd`, `develop`, `mgmt`,
`sync.sh`, `check.sh`). `sync.sh`, `check.sh`).
Don't modify framework-owned files. This separation keeps framework upgrades Don't modify framework-owned files unless you need to. This separation
clean. keeps framework upgrades clean. If you do need to change framework files
(especially early on, there are rough edges), you can extract your changes
as a patch:
```bash
./diff-upstream.sh # full diff against upstream
./diff-upstream.sh --stat # just list changed files
```
This diffs every file in `file-list` against the upstream ref recorded in
`.diachron-version`.
When you do change framework files, make each change in its own commit with
a clear message explaining what the change is and why it's needed. Mixing
framework fixes with application work in a single commit makes it much
harder to upstream later. A clean history of discrete, well-explained
framework commits is the easiest thing to turn into contributions.
## Getting started ## Getting started

View File

@@ -137,6 +137,14 @@ Do not edit: master/*, logger/*, diachron/*, backend/diachron/*
``` ```
If a task requires framework changes, confirm with the user first. If a task requires framework changes, confirm with the user first.
When framework files are modified, the changes can be extracted as a
diff against upstream with `./diff-upstream.sh` (or `--stat` to list
changed files only).
When committing framework changes, keep them in separate commits from
application code. Each framework commit should have a clear message
explaining what was changed and why. This makes it much easier to
upstream the changes later.
### Command safety tiers ### Command safety tiers

116
diff-upstream.sh Executable file
View File

@@ -0,0 +1,116 @@
#!/bin/bash
# Generate a diff of framework files against the upstream version this
# project is based on. Useful for contributing changes back to diachron.
#
# Usage:
# ./diff-upstream.sh # diff against .diachron-version
# ./diff-upstream.sh <ref> # diff against a specific ref
# ./diff-upstream.sh --stat # show changed files only
set -eu
set -o pipefail
IFS=$'\n\t'
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
stat_only=false
ref=""
for arg in "$@"; do
case "$arg" in
--stat) stat_only=true ;;
*) ref="$arg" ;;
esac
done
if [ -z "$ref" ]; then
if [ ! -f "$DIR/.diachron-version" ]; then
echo "Error: .diachron-version not found and no ref specified." >&2
echo "Usage: $0 [--stat] [<ref>]" >&2
exit 1
fi
ref=$(cat "$DIR/.diachron-version")
fi
cached_repo="$HOME/.cache/diachron/v1/repositories/diachron.git"
if [ ! -d "$cached_repo" ]; then
echo "Error: cached repository not found at $cached_repo" >&2
echo "Run ./update-cached-repository.sh first." >&2
exit 1
fi
# Update cached repo
"$DIR/update-cached-repository.sh"
# Verify ref exists
if ! git -C "$cached_repo" rev-parse --verify "$ref^{commit}" >/dev/null 2>&1; then
echo "Error: ref '$ref' not found in cached repository." >&2
exit 1
fi
# Read file-list
files=()
while IFS= read -r line; do
[[ "$line" =~ ^[[:space:]]*# ]] && continue
[[ -z "$line" ]] && continue
files+=("$line")
done < "$DIR/file-list"
# Check out upstream into a temp directory
tmpdir=$(mktemp -d)
cleanup() { rm -rf "$tmpdir"; }
trap cleanup EXIT
git clone --quiet "$cached_repo" "$tmpdir/upstream"
git -C "$tmpdir/upstream" checkout --quiet "$ref"
# Generate diff
if $stat_only; then
diff -rq "$tmpdir/upstream" "$DIR" \
--no-dereference \
2>/dev/null \
| grep -v '^\.' \
|| true
# Simpler: just list files that differ
for f in "${files[@]}"; do
# Skip directories
[ -d "$DIR/$f" ] && continue
upstream="$tmpdir/upstream/$f"
local="$DIR/$f"
if [ ! -f "$upstream" ] && [ -f "$local" ]; then
echo "added: $f"
elif [ -f "$upstream" ] && [ ! -f "$local" ]; then
echo "removed: $f"
elif [ -f "$upstream" ] && [ -f "$local" ]; then
if ! diff -q "$upstream" "$local" >/dev/null 2>&1; then
echo "modified: $f"
fi
fi
done
else
for f in "${files[@]}"; do
[ -d "$DIR/$f" ] && continue
upstream="$tmpdir/upstream/$f"
local="$DIR/$f"
if [ ! -f "$upstream" ] && [ -f "$local" ]; then
diff -u /dev/null "$local" \
--label "a/$f" --label "b/$f" \
|| true
elif [ -f "$upstream" ] && [ ! -f "$local" ]; then
diff -u "$upstream" /dev/null \
--label "a/$f" --label "b/$f" \
|| true
elif [ -f "$upstream" ] && [ -f "$local" ]; then
diff -u "$upstream" "$local" \
--label "a/$f" --label "b/$f" \
|| true
fi
done
fi

View File

@@ -26,6 +26,7 @@ backend/watch.sh
bootstrap.sh bootstrap.sh
cmd cmd
develop develop
diff-upstream.sh
diachron diachron
diachron/AGENTS.md diachron/AGENTS.md
file-list file-list