Skip to content

feat(harness): /orchestrator:sync — re-stamp managed files after plugin updates (closes #38) - #46

Merged
robercano-ghbot merged 2 commits into
mainfrom
feat/issue-38-orchestrator-sync
Jul 5, 2026
Merged

feat(harness): /orchestrator:sync — re-stamp managed files after plugin updates (closes #38)#46
robercano-ghbot merged 2 commits into
mainfrom
feat/issue-38-orchestrator-sync

Conversation

@robercano-ghbot

Copy link
Copy Markdown
Collaborator

Packaging phase 3: /orchestrator:sync

Adds the sibling of /orchestrator:setup that reconciles scaffolded-but-MANAGED files in a consuming repo after a plugin update. Mirrors the setup deliverable's structure, style, version-marker convention, and shell idioms.

Files (all under .claude/**, module:harness)

  • .claude/commands/sync-orchestrator.md — thin command entry (pointer to the skill), mirroring setup-orchestrator.md.
  • .claude/skills/sync/SKILL.md — the reconcile flow: read version markers, re-stamp managed files, three-way local-edit detection, print a diff summary, never touch user-owned files.
  • .claude/skills/sync/sync.sh — idempotent, offline, no-network reconcile logic mirroring scaffold.sh.

Behavior

  • Re-stamps MANAGED files (today: .claude/workflows/feature-fanout.js) using the @orchestrator-managed <name> vN markers /orchestrator:setup writes. The managed-file table is one-line-per-file for easy extension.
  • NEVER touches user-owned files: gates.json, CLAUDE.md, settings.local.json, .claude/state/ (reuses the MANIFEST ownership classification — no divergent scheme).
  • Three-way local-edit detection: strips the marker line and byte-compares installed vs shipped pristine; a behind-but-locally-edited file is reported conflict and left untouched — never silently overwritten (offer merge or leave).
  • Single source of truth for the version: shipped_version is derived from the template's own marker (the bytes a restamp writes), so restamp is inherently idempotent.
  • is_sane_version bounds parsed version integers so a malformed/oversized marker can't bypass the never-downgrade guard.
  • Broken-install conditions (missing/markerless template) emit a clear stderr diagnostic and exit non-zero; per-file conflict exits 0.

Verification

  • Gates: build/lint/typecheck/test/coverage are N/A here (repo's .claude/gates.json is still the template placeholder — no real commands). bash -n clean on sync.sh.
  • Reviewed adversarially through all four lenses (correctness, tests, security, performance) — consensus all, every lens APPROVE after one fix iteration. Reviewers independently ran the full re-stamp ladder plus idempotency and malformed-marker regression cases against throwaway trees.

Closes #38.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WNHtY86twXHEKsLEucSJyY

robercano added 2 commits July 4, 2026 12:08
…rd/bound version parse; doc error vocab (#38)

Reviewers found two linked defects: (1) sync.sh derived shipped_version by parsing
scaffold.sh's MANAGED_VERSION= variable instead of the template file's own marker
line, so the two could drift and a restamp would never converge (infinite
re-restamp); (2) an oversized/malformed installed version marker made the -gt/-eq
integer guards silently evaluate false under `if` (set -e does not abort there),
falling through to a downgrade cp.

Fix: derive shipped_version from managed_version_of() against the template path
itself (the exact bytes a restamp writes), eliminating the scaffold.sh parse
entirely and making restamp inherently idempotent. Add is_sane_version() to bound
every parsed version (installed and shipped) to 1-9 digits before any integer
comparison; malformed/oversized installed markers are now reported as a conflict
instead of falling through to cp. Broken-install conditions (missing template,
template with no valid marker) now consistently emit `error:` to stderr and exit
nonzero, documented in both sync.sh's header and SKILL.md's vocabulary list.
@robercano-ghbot
robercano-ghbot merged commit 1e70ab1 into main Jul 5, 2026
9 checks passed
@robercano-ghbot
robercano-ghbot deleted the feat/issue-38-orchestrator-sync branch July 5, 2026 10:39
robercano-ghbot pushed a commit that referenced this pull request Jul 5, 2026
…; sync is now shipped (#46)

- Union-merge docs/USAGE.md: keep #48's plugin-flow rewrite structure, fold in
  main's phone-testing section for /orchestrator:test-pr (renamed from the
  unnamespaced /test-pr to match this branch's convention).
- Update USAGE.md and MIGRATION.md: /orchestrator:sync is no longer
  "forthcoming" — it shipped in #46 — so document it as available and point
  at .claude/skills/sync/SKILL.md instead of telling readers to fall back to
  /orchestrator:setup.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Packaging phase 3: /orchestrator:sync — re-stamp managed files after plugin updates

2 participants