plugins/lisa-copilot/skills/sync-down/SKILL.md
This skill should be used to run a back-sync of an environment branch DOWN the deploy chain on demand — propagating merges (e.g. hotfixes) from a higher environment to every lower one. Given a source environment name or branch (e.g. `production`), it derives the source→target chain from `.lisa.config.json` `deploy.order` + `deploy.branches` (the same chain the `claude-sync-down-branches.yml` GitHub Action uses on PR merge), then for each downward hop creates a sync branch, merges, resolves conflicts, opens or updates a PR, and enables auto-merge. Runnable by a developer locally or by GitHub Actions.
npx skillsauth add codyswanngt/lisa sync-downInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Back-sync a source environment branch DOWN the deploy chain, one hop at a time,
all the way to the lowest environment. This is the on-demand, manual-or-CI
counterpart to the claude-sync-down-branches.yml GitHub Action, which runs the
same logic automatically when a PR is merged. Both derive their chain from the
same config, so a manual run and an automatic run behave identically.
Argument ($ARGUMENTS): the source to start syncing from. Accepts:
deploy.branches (e.g. production, staging) — resolved to its branch, ordeploy.branches values (e.g. main).If $ARGUMENTS is empty, default to the highest environment in deploy.order
(the top of the chain) so a bare invocation syncs the entire chain top-to-bottom.
The sync walks downward from the source: e.g. starting at production with
deploy.order: ["dev","staging","production"] and
deploy.branches: {dev:dev, staging:staging, production:main}, it runs
main → staging, then staging → dev. Starting at staging runs only
staging → dev.
Read config with the standard local-overrides-global precedence from the
config-resolution rule (.lisa.config.local.json first, then
.lisa.config.json; use jq, never hand-parse).
Build the source→target branch chain. An explicit deploy.chain is not a config
key — the chain is always derived from deploy.order + deploy.branches:
CHAIN=$(jq -e -r '
(.deploy.branches // {}) as $b
| (.deploy.order // []) as $o
| ($b | keys | sort) as $bk
| ($o | sort) as $ok
| if ($b | length) <= 1 then "{}"
elif (($b | [.[]] | unique | length) <= 1) then "{}"
elif ($o | length) == 0 then "ERR_NO_ORDER"
elif ($bk != $ok) then "ERR_MISMATCH"
else ($o | reverse) as $hl
| [ range(0; ($hl | length) - 1) | { ($b[$hl[.]]): $b[$hl[.+1]] } ] | add
| tojson
end
' .lisa.config.json)
ERR_NO_ORDER → stop: deploy.branches has multiple environments mapped to
more than one distinct branch but deploy.order is missing. Tell the user to
add deploy.order (low→high, e.g. ["dev","staging","production"]). Do not
guess the ranking.ERR_MISMATCH → stop: deploy.order and deploy.branches name different
environments. They must match exactly.{} → nothing to sync; report and exit cleanly. This covers both a
single-environment project and a multi-environment project whose branches all
resolve to the same branch (e.g. dev/staging/production all → main), where
deploy.order is not required.Resolve $ARGUMENTS to a starting branch:
deploy.order
mapped through deploy.branches.deploy.branches (an env name) → use that env's branch.deploy.branches (a branch name) → use it directly.Starting from the resolved source branch, follow the chain (source → target,
then target → its target, …) until a branch has no entry in the chain (the
terminal/lowest environment). For each hop:
git fetch origin <source> <target>
and gh api "repos/<owner>/<repo>/branches/<target>" --silent. If the target
does not exist, log a warning and stop the walk (the chain points at a
branch this repo never created) — do not fail.AHEAD=$(git rev-list --count origin/<target>..origin/<source>).
If 0, log "already in sync" and continue to the next hop (do not open an
empty PR).git checkout -B sync/<source>-to-<target> origin/<target>.
Reusing a deterministic branch name lets a re-run update the same PR instead of
piling up new ones.git merge --no-ff origin/<source> -m "chore: sync <source> -> <target>".
git add) and commit the
merge. If a conflict genuinely cannot be reconciled safely, abort that hop
(git merge --abort), record it, and stop the walk — report which files
blocked it so a human can resolve manually.Use the smallest pattern that preserves the target branch while carrying real source-only work downward.
git rev-list <target>..<source>
shows commits but the source changes are already represented on the target via
parallel PRs or equivalent commits, keep the target tree and record ancestry
only: git merge -s ours origin/<source> -m "chore: sync <source> -> <target>".
Do not infer this from commit count alone. Verify the source ticket refs,
affected files, or distinctive code/text with git log, git show, and
rg/git grep before using -s ours. Report the hop as "ancestry reconcile,
no content change" and include the evidence checked.If residue remains after applying the appropriate pattern, abort that hop and
report the unresolved files and the evidence gathered. Do not silently choose
source-wins when the target may already contain the change or has moved the code.
5. Push the sync branch: git push -u origin sync/<source>-to-<target> --force-with-lease.
Only ever force-push the sync branch — never the target environment branch.
6. Open or update the PR. Check for an existing open PR
(gh pr list --head sync/<source>-to-<target> --base <target> --state open).
Update its body if it exists, otherwise create it
(gh pr create --base <target> --head sync/<source>-to-<target> --title "chore: sync <source> -> <target>").
Then enable auto-merge: gh pr merge <num> --auto --merge. If auto-merge is
disabled on the repo, log it and leave the PR open — do not fail.
7. Advance. The hop's target becomes the next hop's source. Continue until
the chain terminates.
Note on chaining: each hop opens a PR rather than merging immediately, so the
lower hops sync from the source branch's current tip. When the intent is to
propagate a specific just-merged change all the way down, the PRs auto-merge in
order and the Action re-fires per merge; a single manual /sync-down run opens
the first hop's PR and each subsequent merge cascades the rest. Surface this in
the summary so the user knows whether to wait for the cascade or re-run.
Summarize every hop: synced / already-in-sync / target-missing / conflict-blocked, with the PR URL for each sync opened. End with the overall outcome and any hop that needs human conflict resolution.
/lisa:sync-down production (or a branch: /lisa:sync-down main).claude-sync-down-branches.yml. For an on-demand CI run, invoke this skill from a
workflow_dispatch job via anthropics/claude-code-action with the prompt
/lisa:sync-down <env> and CLAUDE_CODE_OAUTH_TOKEN — the same identity the
Action uses so the resulting PRs trigger downstream CI.This skill and reusable-claude-sync-down-branches.yml are deliberately
equivalent: same config-derived chain, same merge/conflict strategy, same
deterministic sync-branch naming, same auto-merge behavior. The Action is the
automatic (PR-merged) trigger; this skill is the manual/dispatch trigger. Keep
their chain-derivation and conflict-resolution rules in sync when either changes.
tools
--- name: harper-realtime description: This skill should be used when adding or troubleshooting Harper (HarperDB/Fabric) real-time behavior: MQTT topics, WebSocket resource subscriptions, resource publish/subscribe handlers, SSE-style streaming routes, and local subscriber verification. Pairs with harper-resources, harper-config-yaml, harper-schema-graphql, and harper-build-and-deploy. --- # Harper Realtime ## Overview Harper exposes live data through the same Resource model used for REST and
tools
--- name: harper-realtime description: This skill should be used when adding or troubleshooting Harper (HarperDB/Fabric) real-time behavior: MQTT topics, WebSocket resource subscriptions, resource publish/subscribe handlers, SSE-style streaming routes, and local subscriber verification. Pairs with harper-resources, harper-config-yaml, harper-schema-graphql, and harper-build-and-deploy. --- # Harper Realtime ## Overview Harper exposes live data through the same Resource model used for REST and
tools
--- name: harper-realtime description: This skill should be used when adding or troubleshooting Harper (HarperDB/Fabric) real-time behavior: MQTT topics, WebSocket resource subscriptions, resource publish/subscribe handlers, SSE-style streaming routes, and local subscriber verification. Pairs with harper-resources, harper-config-yaml, harper-schema-graphql, and harper-build-and-deploy. --- # Harper Realtime ## Overview Harper exposes live data through the same Resource model used for REST and
tools
--- name: harper-realtime description: This skill should be used when adding or troubleshooting Harper (HarperDB/Fabric) real-time behavior: MQTT topics, WebSocket resource subscriptions, resource publish/subscribe handlers, SSE-style streaming routes, and local subscriber verification. Pairs with harper-resources, harper-config-yaml, harper-schema-graphql, and harper-build-and-deploy. --- # Harper Realtime ## Overview Harper exposes live data through the same Resource model used for REST and