| name | sync |
| description | Checkpoint sync for the current checkout and recursive dirty submodules. In feature branches, paired main checkout and feature->main landing require explicit --main. |
Sync
Git here is a checkpointing mechanism, not a standard feature-branch or pull-request workflow.
Core rule
Sync is never path-scoped, but its branch boundary depends on the requested mode.
Default sync is a full checkpoint of the current checkout only:
- the checkout you are currently in,
- and the dirty submodules inside that checkout, recursively.
If the current checkout is a feature/non-main branch, default sync must not
touch the paired main checkout and must not merge the feature branch into
main.
The paired main checkout is included only when the user explicitly passes
--main or says to land/merge the current branch onto main.
Do not ask whether to sync only some files, only one repo, or only “your” changes.
If the user says sync, the default meaning is:
checkpoint everything dirty in the current checkout, recursively through its
dirty submodules, then pull/push the current branch if it has an upstream.
This is not “all worktrees on disk” and it is not “land this branch on
main”.
Within the selected boundary, it is always total, never partial.
Directional rule:
sync on a feature branch: current branch only.
sync --main: current branch + paired main checkout + feature branch landed
onto main.
main > current, merge main into this branch, or equivalent: merge main
into the current branch, never the current branch into main.
Rules
- Do not optimize for PRs.
- Do not use
git rebase.
- Use merge-based pulls only:
git pull --no-rebase.
- Never do a path-scoped sync inside the selected boundary. The branch boundary
is selected by mode: default current checkout, optional
--main, or explicit
main-into-current.
- If you are in a feature/non-main worktree, the default goal is to checkpoint
and push that feature branch, not to land it on
main.
- Do not merge a feature branch into
main unless the user explicitly passes
--main or explicitly asks to land/merge the branch onto main.
- Merging
main into the current feature branch is allowed only when the user
asks for that direction; do not infer it from plain sync.
- Sync dirty submodules first, then sync the parent repo.
- If
--main is not present, do not inspect, checkpoint, pull, push, or merge
the paired main checkout as part of sync.
- If
--main is present and the paired main checkout is dirty, commit/pull/push
there too before landing the feature branch.
- Use simple commit messages based on the changed files or area.
- Prefer durable checkpoints over perfect commit curation.
- Do not leave dirty submodules behind in the selected boundary. The paired
main checkout is part of that boundary only with explicit --main.
Recursive Model
Treat sync as a recursive checkpoint over a fixed boundary:
- default boundary repo A = current checkout
- optional boundary repo B = paired
main checkout, only with explicit --main
There is no “selected subset” mode.
SYNC_BOUNDARY(current_repo):
SYNC_REPO(current_repo)
if mode_has_explicit_main_flag and repo_is_worktree(current_repo) and branch(current_repo) != "main":
main_repo = resolve_main_checkout(current_repo)
SYNC_REPO(main_repo)
MERGE_WORKTREE_INTO_MAIN(current_repo, main_repo)
PUSH(main_repo)
if mode_is_main_into_current:
MERGE_MAIN_INTO_CURRENT(current_repo)
SYNC_REPO(repo):
children = dirty_submodules(repo) # recursive
for child in children:
SYNC_REPO(child)
CHECKPOINT(repo)
CHECKPOINT(repo):
if repo has changes:
git add .
git commit -m "<simple message based on changed files>"
if branch_has_upstream: # git rev-parse --abbrev-ref @{u} succeeds
git pull --no-rebase
git push
# else: local-only branch — skip pull/push unless explicit --main landing is requested
MERGE_WORKTREE_INTO_MAIN(current_repo, main_repo):
# Only legal with explicit --main / explicit feature->main landing request.
# cd into main_repo checkout, then:
git merge <current_worktree_branch> --no-ff --no-edit
# --no-rebase is NOT a valid merge flag; merge is merge-only by default
# --no-ff preserves the merge commit so the worktree branch is visible in history
MERGE_MAIN_INTO_CURRENT(current_repo):
# Only legal when the user explicitly asks for main > current.
# Stay in the current checkout.
git fetch origin main
git merge origin/main --no-ff --no-edit
# If conflicts appear, stop with a conflict-resolution brief.
Workflow
- Inspect the current state.
git status --short
git branch --show-current
git worktree list
git submodule status --recursive
- Determine the fixed sync boundary:
- current checkout always included
- paired
main checkout included only if --main or explicit feature->main
landing was requested
- main-into-current merge is a separate explicit direction, not the default
- Recurse into all dirty submodules inside the current checkout first.
- In each dirty repo/submodule:
git add .
git commit -m "<simple message based on changed files>" if there is anything to commit
- if the branch has an upstream (
git rev-parse --abbrev-ref @{u} succeeds): git pull --no-rebase && git push
- if no upstream (local-only branch): skip pull/push unless explicit
--main
landing was requested
- After the current checkout's submodules are synced, checkpoint the current checkout repo itself (same commit/pull/push rules).
- If
--main was explicitly requested and the current checkout is a non-main worktree:
- locate the paired
main checkout
- recurse into all dirty submodules in that
main checkout (apply step 4 to each)
- checkpoint the
main checkout repo itself (apply step 4)
- merge the current worktree branch into
main:
git merge <worktree-branch> --no-ff --no-edit (NOT --no-rebase — that flag is pull-only)
- if conflicts appear, stop with a conflict-resolution brief; do not switch to PR workflow
git pull --no-rebase (only if main tracks an upstream, which it should)
git push
- If the user explicitly requested main > current:
- stay in the current checkout
git fetch origin main
git merge origin/main --no-ff --no-edit
- if conflicts appear, stop with a conflict-resolution brief
- run the requested/current verification after resolving
- Finish by confirming the selected boundary is checkpointed:
- current checkout clean or committed
- current checkout dirty submodules handled before the parent
- paired
main checkout touched only when explicitly requested
- worktree branch landed on
main only when --main / explicit feature->main
landing was requested
Commit Message Guidance
Keep it short and obvious.
intent: callsign strict mode
data: enrichment checkpoint
sync: checkpoint current work
Conflict-Resolution Brief
When a merge or pull conflict appears, do not only list conflicted files.
Before stopping, inspect enough context to give the user actionable resolution
paths.
Required conflict inspection:
git status --short
git diff --name-only --diff-filter=U
git ls-files -u <conflicted-paths>
git diff --cc -- <conflicted-files>
- for submodules:
git -C <submodule> log --oneline --decorate --graph --all --max-count=20
- for code conflicts: inspect both sides with
git show :2:<path> and git show :3:<path> when useful
Required conflict brief:
sync_conflict:
state: blocked
conflicted_paths:
- <path>
inferred_intents:
ours: <what the local side was trying to preserve>
theirs: <what the incoming side was trying to preserve>
solution_paths:
- option: <merge both | take ours | take theirs | advance submodule pointer | manual synthesis>
blast_radius: <low|medium|high>
why: <one sentence>
risks:
- <specific risk>
validation:
- <command that would prove this option>
recommended_strategy: <one option plus why>
next_command_sequence:
- <minimal non-destructive commands to apply the recommendation>
Guidance:
- Infer intent from both sides before recommending a resolution.
- Prefer a synthesis that preserves both sides' intended behavior when the
combined behavior is coherent and testable.
- Treat submodule conflicts as pointer-selection problems backed by submodule
commit ancestry. State whether one pointer contains the other, whether a
merge commit exists, or whether a new submodule merge is required.
- Include blast radius in practical terms: affected module, tests likely to
break, deployment/runtime surfaces touched, and whether generated artifacts or
submodule pointers are involved.
- If the correct strategy is clear and low-risk, recommend it explicitly; do not
hide behind "resolve conflicts manually."
- Do not run the resolution automatically unless the user asked sync to continue
and the resolution is low-risk, non-destructive, and fully justified by the
brief.
Repo-Specific Notes
- If
--main is requested and main has submodules, recurse first. The parent
repo sync is not complete until dirty child repos are checkpointed.
- In repos like this one,
data/ is a submodule. Commit and push there before updating the parent repo pointer.
- If multiple agents touched different areas, the job is to checkpoint all dirty repos in boundary, not to preserve a per-feature narrative.
- Do not stop at “my spike files are synced”. That is the old wrong behavior. Sync means everything dirty in boundary is checkpointed.
- On
Sunny-PC or another feature branch, default boundary means the feature
branch and its submodules only. Do not merge Sunny-PC into main unless
--main is explicitly present.
What not to ask
Do not ask:
- “Do you want a scoped sync or full sync?”
- “Should I only sync my changes?”
- “Should I leave unrelated dirty files alone?”
If the user invoked sync, the answer is already:
- full checkpoint,
- current checkout + dirty recursive submodules,
- recursive submodules,
- no feature->main merge unless
--main or explicit landing request is present.
Stop Conditions
- Stop with a conflict-resolution brief if a merge conflict appears.
- Stop and report if
git push still fails after a normal git pull --no-rebase.
- Do not switch to a PR-based workflow.