coordinator-update · git:20260816.c41accb · 2026-08-16 · sha256 94ea4b6ad8f8094e
coordinator-update git:20260816.c41accbA
Immutable. This exact content is served forever at /api/v1/blob/94ea4b6ad8f8094e.
---
name: coordinator-update
description: "Check for a published coordinator update and advise a preserve-by-default migration path — never a blind overwrite."
allowed-tools: ["Bash", "Read", "Edit", "Write", "Grep"]
oss-only: true
argument-hint: "[--install-root <dir>]"
---
# /coordinator-update — Update Advisory for OSS Coordinator Installs
<!-- Spec backlink: docs/plans/2026-05-30-oss-coordinator-update-skill.md § Chunk 3 -->
<!-- OSS-only: this skill is authored in the meta-repo under dist/oss-only-skills/ and injected
into the OSS publish tree at publish time. It is NOT installed on the source-is-live machine. -->
**Purpose.** Check whether a newer version of the coordinator plugin has been published, compute
a classified delta between the published version and your live install, and advise a migration
path that **preserves your implementation shape by default** — renamed personas, custom
environment setup, structural divergence, project-specific customizations.
**Verb-name check:** `/coordinator-update` was checked against Claude Code platform vocabulary
before ship. It does not shadow a native Claude Code command or verb (per the `/fan-out` lesson;
`coordinator-improvement-queue.md` 2026-05-30).
**This skill is PM-invoked, not autonomous.** It computes and advises; it does not apply changes
without your explicit consent. No cadence trigger, no automatic recheck.
---
## HARD CONSTRAINTS (verbatim — self-contained for OSS consumers)
This SKILL.md is self-contained. The coordinator CLAUDE.md is NOT in scope for OSS consumers.
The following rules are quoted verbatim and apply throughout this skill's execution.
### Preservation Constraint
> **Never overwrite a `consumer_modified` file without the user's Claude affirmatively judging
> the upstream change worth it AND surfacing the tradeoff to the user. The user's own
> implementation shape (persona names, custom environment setup, structural divergence) is
> preserved by default.**
### Commit Safety Rule
> **Never `git add -A` or `git add .`. Always use scoped, labelled, explicit-path commits:**
> `git add -- <path1> <path2> ... && git commit -m "<label>" -- <path1> <path2> ...`
> No sweep commits. No blanket staging. Stage only the named files you are applying.
### Offer-Shape Rule
> **Compute and advise is the default. Apply is explicit-consent-gated from the user — never
> autonomous action.** The skill runs the helper, classifies the delta, and presents a
> recommendation. It does NOT apply changes unless the user explicitly says "yes, apply."
---
## Out-of-Scope (hard block — never touch these)
This skill explicitly does NOT:
- Modify your project scaffolding or session-continuity surface: `tasks/`, `state/handoffs/`,
memory entries under `projects/`, `state/lessons.md`, `.claude/settings.json`. These paths are
agent-owned, not installer-owned. No install ceremony may write into them.
- Touch `consumer_added` files — files you added to your install tree that have no upstream source.
These are entirely yours and are never offered for overwrite or modification.
- Touch `.claude-plugin/marketplace.json` — this file is installer-owned and regenerated by
re-running the `coordinator:install` flow. It is not a user customization and is excluded from the advisory set.
- Author handoffs, spinoffs, or workstream-complete artifacts.
- Push to any remote.
- Modify project-level scaffolding managed by the 2026-05-29 `coordinator-currency` surface
(that surface governs per-project structural currency, not the plugin tree).
- Run on a `source_is_live` machine (a coordinator development install where the plugin source
is authored directly). This skill is for OSS consumers who installed via the publish repo (the
`coordinator:install` flow). If you are on a development machine authoring the coordinator
source directly, you do not need this skill.
---
## Step 1: Resolve Install Root
Determine `INSTALL_ROOT` — the directory where the coordinator plugin lives on your machine.
Default: `~/.claude/plugins/coordinator-claude/`.
If the user passed `--install-root <dir>` as `$ARGUMENTS`, use that path instead.
Confirm the path exists and contains a `coordinator/` subdirectory. If not, surface:
> "Cannot locate a coordinator install at `<path>`. Pass `--install-root <dir>` with the
> correct path, or confirm you installed via the OSS `coordinator:install` flow."
Stop.
---
## Step 2: Run the Delta Helper
Run the Chunk 2 helper to produce a classified delta. The helper is co-located at:
`<skill-dir>/lib/compute-update-delta.py`
where `<skill-dir>` is the directory containing this SKILL.md — typically
`~/.claude/plugins/coordinator/skills/coordinator-update/`.
```bash
# Review: code-reviewer — $0 is unreliable when Claude runs this block via the Bash tool
# ($0 resolves to /bin/bash, not the skill path). Derive SKILL_DIR deterministically from
# INSTALL_ROOT, which was already resolved in Step 1.
SKILL_DIR="${INSTALL_ROOT}/coordinator/skills/coordinator-update"
# Interpreter resolution contract: COORDINATOR_PYTHON env -> machine-local
# registry pin (coordinator.python) -> PATH. See the coordinator wiki,
# machine-local-registry.md § coordinator.python resolution contract.
PYTHON_BIN="${COORDINATOR_PYTHON:-}"
if [ -z "$PYTHON_BIN" ]; then
for _cand in python3 python; do
command -v "$_cand" >/dev/null 2>&1 && { PYTHON_BIN="$_cand"; break; }
done
fi
if [ -z "$PYTHON_BIN" ]; then
echo "ERROR: no Python interpreter found. Set COORDINATOR_PYTHON to its absolute path and retry." >&2
exit 1
fi
_cc_ml="${COORDINATOR_SETTINGS_HOME:-$HOME/.coordinator-claude-settings}/bin/machine-local"
if [ -f "$_cc_ml" ]; then
_cc_pin="$("$PYTHON_BIN" "$_cc_ml" get coordinator.python 2>/dev/null)"
[ -n "$_cc_pin" ] && [ -x "$_cc_pin" ] && PYTHON_BIN="$_cc_pin"
fi
# The engine root this update flow depends on is resolved by the shipped
# resolver script, which is the single source of that resolution — no other
# code in this skill hardcodes how or where it is found.
_cc_engine_root="$("$PYTHON_BIN" "${INSTALL_ROOT}/coordinator/hooks/scripts/_engine_root.py" 2>/dev/null)"
if [ -z "$_cc_engine_root" ] || [ ! -d "$_cc_engine_root" ]; then
echo "ERROR: could not resolve the coordinator engine root via ${INSTALL_ROOT}/coordinator/hooks/scripts/_engine_root.py — consult your coordinator install's engine-setup documentation for how to register it, then retry." >&2
exit 1
fi
"$PYTHON_BIN" "${SKILL_DIR}/lib/compute-update-delta.py" --install-root "${INSTALL_ROOT}"
```
The helper emits a single JSON object to stdout. Capture it. The schema:
```json
{
"update_status": "current | behind | offline",
"incoming_ref": "<tag or sha, empty if offline>",
"manual_url": "<URL if offline or for manual reference>",
"recommended_path": "none | overwrite | cherry-pick | plan-to-ingest",
"counts": {
"unchanged": <n>,
"forward_safe": <n>,
"consumer_modified": <n>,
"consumer_added": <n>
},
"consumer_modified": [
{ "path": "<relpath>", "hunk": "<diff text ≤40 lines>" }
],
"consumer_added": ["<relpath>"]
}
```
Exit codes: `0` = current; `3` = behind; non-zero (not 3) = offline/error.
---
## Step 3: Branch on `update_status`
### 3a. Offline
If `update_status` is `"offline"` (helper exited non-zero and not 3):
Report:
> "Could not reach the coordinator update source. Check your network or visit the update
> manually: `<manual_url from JSON>`
> (Never reporting 'up to date' when the source is unreachable — that would be a false signal.)"
**Stop here.** Do not claim the install is current.
### 3b. Current
If `update_status` is `"current"` (exit 0, all counts zero incoming):
Report:
> "Your coordinator install is up to date (at `<incoming_ref>`). No action needed."
**Stop here.**
### 3c. Behind
Proceed to Step 4.
---
## Step 4: Classify and Present the Delta
The install is behind. Read the JSON and partition the delta into three buckets:
### Bucket A — Forward-Safe Files (`forward_safe` count)
Files the upstream changed, but you have NOT modified in your live install. These are
**safe to take** — a reinstall of these files would not destroy any of your customizations.
Summarize what they contain. Examples: "updated workstream-start.md with a new Step 3.5 gate,"
"added docs/wiki/new-feature.md — no local equivalent."
### Bucket B — Consumer-Modified Files (`consumer_modified` array)
Files where BOTH the upstream changed AND you have a local edit. These carry your
implementation shape — likely renamed reviewer personas, added project-specific steps,
custom environment setup, structural divergence that reflects your working style.
**DEFAULT: PRESERVE.** These files are NOT in any apply set unless you affirmatively judge
the upstream change worth taking.
For each file in `consumer_modified`:
1. Read the upstream `hunk` field (the diff of what the upstream wants to change).
2. Read your local version of the file from the install tree.
3. **Judge semantically** — not byte-by-byte: Is the upstream change a genuine improvement
(new gate, corrected logic, important safety rule) you would want even after rebasing your
edits? Or is it cosmetic restructuring / prose reorganization that your version already
addresses in your own way?
4. Present your judgment to the user with the tradeoff clearly stated:
- If worth taking: "Upstream changed `<path>` — this adds `<what>`. Your local version has
`<your customization>`. Taking the upstream change would mean rebasing your edit onto
the new structure. Recommend: cherry-pick this one."
- If not worth taking: "Upstream changed `<path>` — this reorganizes `<what>`. Your local
version already expresses the same intent in your own structure. Recommend: keep yours."
5. Surface the judgment to the user. Do NOT apply without their explicit consent.
### Bucket C — Consumer-Added Files (`consumer_added` array)
Files you added to your install tree with no upstream equivalent.
List them. Note: "These are your additions — never touched by this skill or any update process."
---
## Step 5: Recommend One Path
Based on the classification, recommend exactly ONE update path with reasoning:
**overwrite** — only when the delta is `forward_safe`-only (Bucket B is empty, no
consumer-modified collisions). Tradeoff-free. Offer to apply all forward-safe files.
> "The update is entirely forward-safe — none of the changed files overlap with your
> customizations. Safe to apply all `<N>` files. Want me to apply them?"
**cherry-pick** — when some upstream changes are clearly wanted (forward-safe Bucket A, plus
any Bucket B files you judged worth taking) but others collide with your implementation shape.
List the takeable subset explicitly.
> "I recommend cherry-picking `<N>` files: [list]. The remaining `<M>` files in Bucket B
> have collisions with your customizations — I recommend preserving your versions of those.
> Want me to apply the cherry-pick subset?"
**plan-to-ingest** — when the delta is substantive (many Bucket B collisions, architectural
changes, or load-bearing customized files that would need careful rebasing). Apply would be
risky without deliberate review.
> "This update contains substantive changes that overlap with your implementation shape. I
> recommend running `/plan` to ingest this deliberately rather than cherry-picking blind.
> Seeded problem statement: 'Reconcile coordinator install at `<INSTALL_ROOT>` against
> upstream `<incoming_ref>`: `<N>` consumer-modified files need manual rebase — focus on
> `<top 2-3 paths by importance>`. Preserve persona names and project-specific steps.'"
**Stop and wait for explicit user consent before proceeding to Step 6.**
---
## Step 6: Apply (on explicit user consent only)
Only proceed here if the user explicitly said "yes" / "apply" / "go ahead" in response to
Step 5's recommendation. The offer-shape rule above is non-negotiable.
### 6a. Git Safety Baseline
Check whether the install tree is git-tracked:
```bash
git -C "${INSTALL_ROOT}" rev-parse --git-dir 2>/dev/null
```
If git-tracked: confirm the working tree is clean (`git -C "${INSTALL_ROOT}" status --short`).
If dirty, surface: "Your install tree has uncommitted changes. Commit or stash them before
applying the update, so the apply is revertible." Stop and wait.
If NOT git-tracked: offer a `.bak` baseline before applying. For each file to be applied,
copy it to `<path>.bak` first. Note: "Your install tree is not git-tracked. Backing up files
before applying (`.bak` convention matching the coordinator installer's). You can restore any
file from its `.bak` if needed."
Git-tracking your `~/.claude` is recommended for exactly this reason — better future
reversibility. Consider git-initializing after this session.
### 6b. Apply the Named Files
Apply ONLY the files in the agreed apply set from Step 5 — no more, no less. Do not stage
or touch anything outside the explicit list.
For each file in the apply set:
1. Copy the incoming version from the fetched clone into the install path:
```bash
cp "${CLONE_DIR}/${REL_PATH}" "${INSTALL_ROOT}/${REL_PATH}"
# Review: code-reviewer (A-F1) — drop plugins/ prefix; SOURCE_DIR is the clone ROOT in the OSS publish repo (no plugins/ subdir).
```
2. Add it to the explicit staging list.
### 6c. Commit (git-tracked installs only)
Use a scoped, labelled commit — never `git add -A`:
```bash
git add -- <path1> <path2> ... && \
git commit -m "coordinator-update: apply <incoming_ref> (cherry-pick <N> of <M> files)" \
-- <path1> <path2> ...
```
The commit message names the incoming ref and the apply count. Revertible via `git revert`.
### 6d. Re-Stamp the Sentinel
After a successful apply, advance the install's `version.txt` sentinel to the ingested SHA.
This ensures the NEXT `/coordinator-update` run has a correct baseline and does not re-offer
already-applied changes.
Find `install-sentinel-write` in the install tree:
The entrypoint is a Python CLI, and the extensionless-vs-`.py` filename varies by install
vintage — probe both names rather than pinning one:
```bash
SENTINEL_WRITER=""
for _cand in "${INSTALL_ROOT}/coordinator/bin/install-sentinel-write" \
"${INSTALL_ROOT}/coordinator/bin/install-sentinel-write.py"; do
[ -f "$_cand" ] && { SENTINEL_WRITER="$_cand"; break; }
done
```
Run it under the resolved interpreter — never `bash`, and never as a bareword `.py`:
```bash
if [ -n "${SENTINEL_WRITER}" ] \
&& "$PYTHON_BIN" "${SENTINEL_WRITER}" --path "${INSTALL_ROOT}" --source "${CLONE_DIR}"; then
:
else
# Fallback: write the sentinel directly (same format as install-sentinel-write)
git -C "${CLONE_DIR}" rev-parse HEAD > "${INSTALL_ROOT}/version.txt"
fi
```
The re-stamp is the critical close: without it, the baseline drifts and future runs will
re-classify already-applied files as divergent.
### 6e. Report Completion
```
Applied: <N> files from coordinator <incoming_ref>
Preserved: <M> consumer-modified files (your implementation shape kept)
Consumer-added: <K> files (never touched)
Sentinel: re-stamped to <SHA>
Revertible: yes — via git revert <commit-hash> (or .bak files if untracked)
```
---
## Step 7: Discovery Surface Note
This verb is announced in the coordinator OSS getting-started documentation and the `coordinator:install`
completion summary as the recommended path for future updates. It is NOT surfaced on the
source-is-live (meta-repo) machine — it is installed and invokable only for
OSS consumers who installed via the publish-repo `coordinator:install` flow.
If you are reading this as a developer on the coordinator meta-repo: this skill lives at
`plugins/coordinator/dist/oss-only-skills/coordinator-update/SKILL.md`
and is injected into the OSS publish tree by the `20-inject-oss-only-skills.sh` percolate hook.
It is intentionally absent from the meta-repo's `skills/` tree.
---
## Notes
- **Missing sentinel (no `version.txt`):** The helper degrades to baseline-free two-way mode
(exit 2 from classifier, translated to "behind" by the helper). The first successful apply
run re-stamps the sentinel. Subsequent runs have a proper baseline. This is expected behavior
for users who installed before Chunk 1 landed the sentinel write.
- **Bundled deep-research:** If the coordinator install includes the bundled `deep-research`
add-on (installed via the `coordinator:install` flow with the `deep-research` add-on enabled), it is part of the
same plugin tree and is reconciled in the same pass. No separate `/deep-research-update`
verb exists; the coordinator tree walk covers it.
- **Standalone deep-research-claude repo (historical):** The former standalone `deep-research-claude`
repo is archived read-only — deep-research now ships bundled inside the coordinator plugin (see
above). The 2026-05-29 plan scope decision to defer standalone-repo detection is moot: there is
no live standalone repo left to detect.