Skip to content

Add thv skill sync: restore project skills from the lock file#5895

Open
samuv wants to merge 3 commits into
skills-lock/03-install-hooksfrom
skills-lock/04-sync
Open

Add thv skill sync: restore project skills from the lock file#5895
samuv wants to merge 3 commits into
skills-lock/03-install-hooksfrom
skills-lock/04-sync

Conversation

@samuv

@samuv samuv commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Why: RFC THV-0080 needs a way to restore a project's pinned skill set on any machine — a fresh clone, CI, a teammate's laptop — and to verify on-disk content still matches the lock file without installing anything (a CI integrity gate). This ships the full sync vertical slice in one PR since the CLI command can't exist without its API endpoint.
  • What:
    • Sync reconciles installed skills against toolhive.lock.yaml: missing/drifted entries reinstall at the pinned reference (never re-resolving source — see buildPinnedReference), --check reports drift read-only, --adopt records lock entries for unmanaged installs, --prune removes installs no longer in the lock.
    • Found and fixed a real bug while building this: reinstalling at an unchanged pinned digest hit both the OCI and git install paths' "same digest means content is already correct" fast path, silently skipping re-extraction — exactly the drift sync exists to repair (a tampered file doesn't change the pinned commit/digest). A new internal SyncRestore option on InstallOptions bypasses that fast path in both install_extraction.go and install_git.go.
    • POST /api/v1beta/skills/sync, wired through a narrow skillSyncer interface in pkg/api/v1 so this PR doesn't need to ship an Upgrade stub (widens to skills.SkillLockService in PR5).
    • thv skill sync CLI: --check, --adopt, --prune, --clients, --project-root (auto-detected by walking up for .git when omitted).

Part of the production stack for #5715 (RFC THV-0080). Stack: 4/6 — lockfile → lock-service → install-hooks → sync → upgrade → cli-exitcodes. Based on #5894 (PR3).

Type of change

  • New feature

Test plan

  • Unit tests (task test)
  • E2E tests (task test-e2e, scoped: ginkgo --label-filter=skills-lock)
  • Linting (task lint-fix)

Table-driven drift-matrix tests cover up-to-date / drifted-and-reinstalled / missing-and-restored / check-mode-no-write / adopt / prune / feature-disabled-403; golden tests for buildPinnedReference (OCI digest-pin, git commit-pin with and without a subdir path) and isImmutableSource; API handler tests including the 501 "not supported" path when the underlying service lacks Sync. New E2E spec: install → delete files on disk → sync --check reports drift without touching anything → sync restores the files.

Does this introduce a user-facing change?

Not yet — same TOOLHIVE_SKILLS_LOCK_ENABLED gate as the rest of the stack (see PR3). Once the full stack lands: thv skill sync restores a project's skills to match its committed lock file.

Special notes for reviewers

  • The SyncRestore fix (install_extraction.go, install_git.go) is the part I'd like the most scrutiny on — it's a small diff but changes behavior on the existing install fast paths, gated entirely behind an internal-only option only Sync sets.
  • pkg/skills/client.Client gains Sync but does not yet assert skills.SkillLockService conformance — that lands in PR5 once Upgrade exists too.

🤖 Generated with Claude Code

@github-actions github-actions Bot added the size/XL Extra large PR: 1000+ lines changed label Jul 21, 2026
@samuv samuv self-assigned this Jul 21, 2026
@samuv
samuv force-pushed the skills-lock/04-sync branch from 784a7ce to 9c2d5f5 Compare July 21, 2026 15:31
@github-actions github-actions Bot added size/XL Extra large PR: 1000+ lines changed and removed size/XL Extra large PR: 1000+ lines changed labels Jul 21, 2026
@codecov

codecov Bot commented Jul 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 67.55319% with 61 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.61%. Comparing base (bdf19aa) to head (d94ef78).

Files with missing lines Patch % Lines
pkg/skills/skillsvc/sync.go 61.06% 32 Missing and 12 partials ⚠️
pkg/skills/client/client.go 0.00% 11 Missing ⚠️
pkg/skills/skillsvc/pin.go 82.35% 3 Missing and 3 partials ⚠️
Additional details and impacted files
@@                       Coverage Diff                        @@
##           skills-lock/03-install-hooks    #5895      +/-   ##
================================================================
- Coverage                         71.64%   71.61%   -0.04%     
================================================================
  Files                               704      706       +2     
  Lines                             71919    72103     +184     
================================================================
+ Hits                              51528    51633     +105     
- Misses                            16678    16744      +66     
- Partials                           3713     3726      +13     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@samuv
samuv force-pushed the skills-lock/03-install-hooks branch from 7824f3f to 1514a9d Compare July 21, 2026 16:58
@samuv
samuv force-pushed the skills-lock/04-sync branch from 9c2d5f5 to 06a66f8 Compare July 21, 2026 16:58
@github-actions github-actions Bot added size/XL Extra large PR: 1000+ lines changed and removed size/XL Extra large PR: 1000+ lines changed labels Jul 21, 2026
@samuv
samuv force-pushed the skills-lock/03-install-hooks branch from 1514a9d to 3dd34f4 Compare July 21, 2026 17:08
@samuv
samuv force-pushed the skills-lock/04-sync branch from 06a66f8 to 42a03de Compare July 21, 2026 17:08
@github-actions github-actions Bot added size/XL Extra large PR: 1000+ lines changed and removed size/XL Extra large PR: 1000+ lines changed labels Jul 21, 2026
@samuv
samuv force-pushed the skills-lock/04-sync branch from 42a03de to 4604083 Compare July 21, 2026 17:14
@github-actions github-actions Bot added size/XL Extra large PR: 1000+ lines changed and removed size/XL Extra large PR: 1000+ lines changed labels Jul 21, 2026
@samuv

samuv commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

Tracked in #5899 (RFC THV-0080 stack).

samuv added 3 commits July 22, 2026 22:08
RFC THV-0080 needs a way to restore a project's pinned skill set on
any machine (a fresh clone, CI, a teammate's laptop) and to verify
on-disk content still matches the lock file without installing
anything. This adds the full sync vertical slice: service logic,
HTTP endpoint, client, and CLI command.

- Sync reconciles installed skills against toolhive.lock.yaml:
  missing/drifted entries reinstall at the pinned reference (never
  re-resolving source, see buildPinnedReference), --check reports
  drift read-only, --adopt/--prune handle unlocked installs
- Fixes a real bug this surfaced: reinstalling at an unchanged
  pinned digest hit both the OCI and git install paths' "same
  digest means content is already correct" fast path, silently
  skipping re-extraction — exactly the drift sync exists to repair.
  A new internal SyncRestore option bypasses that fast path.
- POST /api/v1beta/skills/sync via a narrow skillSyncer interface
  (pkg/api/v1), so this PR doesn't need to ship an Upgrade stub
- `thv skill sync` CLI (--check/--adopt/--prune/--clients/
  --project-root, auto-detected via .git when omitted)

Part of the production stack for #5715 (RFC THV-0080). Stack: 4/6.
reinstallPinned reinstalls at a pinned reference derived from the
lock entry, and that pinned string was flowing straight into
ResolvedReference via the install path — a drift repair overwrote
it with an internal restore form instead of preserving what Source
had actually resolved to, which later corrupts upgrade's ref-change
detection. Add a LockResolvedReference override on InstallOptions,
mirroring the existing LockSource one.
Picks up the AlreadyCurrent JSON tag rename and Drifted doc comment
fix from the PR2 review pass.
@samuv
samuv force-pushed the skills-lock/03-install-hooks branch from bdf19aa to 176f367 Compare July 22, 2026 20:13
@samuv
samuv force-pushed the skills-lock/04-sync branch from d94ef78 to e4b12ca Compare July 22, 2026 20:13
@github-actions github-actions Bot added size/XL Extra large PR: 1000+ lines changed and removed size/XL Extra large PR: 1000+ lines changed labels Jul 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XL Extra large PR: 1000+ lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant