aboutsummaryrefslogtreecommitdiff
path: root/.ai/scripts/sync-templates
blob: c4db2125435dddfd582b843cfc7cd934dec16186 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#!/usr/bin/env bash
# sync-templates — copy rulesets' canonical .ai/ templates into this project.
#
# Extracted verbatim from startup.org Phase A step 3 (2026-07-31). This is the
# mechanism that distributes every workflow, protocol and script change to every
# project, and until the extraction it was untested inline bash running in every
# session. The extraction exists so the guard changes that follow can be tested
# before they reach a file whose failure mode is "no project starts".
#
# Behavior is deliberately identical to the inline block it replaces, including
# its rough edges. Anything that looks like a defect here is characterized by a
# test rather than fixed in passing — a change of behavior belongs in its own
# commit, not smuggled into an extraction.
#
#   Usage:  sync-templates [project-root]     (default: $PWD)
#   Output: one line naming the outcome, matching the previous inline wording
#   Exit:   0 always, as the inline block did — the outcome is on stdout
#
# Two guards decide whether the sync runs at all:
#
#   Rulesets dirty under the synced paths → skip. rsync -a --delete copies the
#   working tree by disk presence, so an in-flight edit in rulesets would land
#   downstream as drift the project never authored.
#
#   Project branch behind its upstream → skip. Syncing onto a stale committed
#   .ai/ baseline measures the diff against old content, so it comes out huge
#   and conflicts once the branch reconciles to an upstream that already
#   carries the newer templates.
#
# The rulesets location is injectable (SYNC_RULESETS_DIR) so the guards can be
# exercised against a fixture instead of the real checkout.

rs="${SYNC_RULESETS_DIR:-$HOME/code/rulesets}"
proj="${1:-$PWD}"

cd "$proj" || {
    echo "sync-templates: cannot enter '$proj'" >&2
    exit 0
}

synced_dirty=$(cd "$rs" && git status --porcelain -- \
    claude-templates/.ai/protocols.org \
    claude-templates/.ai/workflows/ \
    claude-templates/.ai/scripts/ 2>/dev/null)

# behind==0 (up-to-date or ahead-only) means HEAD contains all of upstream, so
# the baseline is current. No upstream (new/unpushed branch) → rev-list fails →
# proj_behind stays 0 → the sync runs.
proj_behind=0
if [ -d .git ]; then
    counts=$(git rev-list --left-right --count '@{u}...HEAD' 2>/dev/null) \
        && [ "$(printf '%s' "$counts" | cut -f1)" -gt 0 ] 2>/dev/null \
        && proj_behind=1
fi

if [ -n "$synced_dirty" ]; then
    echo "rulesets has uncommitted changes under the synced template paths — skipping .ai/ sync this session (catches up when rulesets is clean):"
    echo "$synced_dirty" | sed 's/^/  /'
elif [ "$proj_behind" -eq 1 ]; then
    echo "project branch is behind upstream — skipping .ai/ sync this session (templates never land on a stale baseline; the sync runs once the branch is current)"
else
    rsync -a "$rs/claude-templates/.ai/protocols.org" .ai/protocols.org
    rsync -a --delete "$rs/claude-templates/.ai/workflows/" .ai/workflows/
    # Running rulesets' own pytest leaves these in the canonical scripts/tests/,
    # and rsync -a copies by disk presence regardless of .gitignore, so without
    # the excludes every project's tree collects machine-specific cache files.
    rsync -a --delete --exclude='__pycache__' --exclude='.pytest_cache' --exclude='*.pyc' \
        "$rs/claude-templates/.ai/scripts/" .ai/scripts/
    # Known false-success path, inherited and characterized rather than fixed
    # here: this line prints unconditionally, so a run where all three rsyncs
    # failed (an absent canonical source, say) still reports a successful sync.
    # A last-synced manifest must not be written from this branch as it stands —
    # it would stamp success onto a sync that did nothing.
    echo ".ai/ synced from templates"
fi