feat(harness): Phase 1 — management foundation, fork & duplicate, drift detection#249
Merged
Conversation
…uplicate, drift detection Scope: CommandRunner foundation. Streamed-output shell-out with cancellation; migrate ynh callers off ad-hoc Process/Pipe to a single seam. YNH 0.3+ envelope decoding. HarnessListResponse / HarnessInfoResponse parse the structured-output envelope with capabilities and ynh_version; YnhVersionProbe gates Phase 1 affordances on capabilities ≥ 0.3.0. Detail pane refactor. Extract HarnessDetailViewModel from the view; pure formatters for source classification (HarnessSourceBadgeViewModel), editability (HarnessEditabilityResolver), and update signal (HarnessUpdateBadgeStore). Old feature-flagged badge retired. Source badges and read-only model. Sidebar rows and detail header show provenance: registry name, short Git URL, "Local", or "Forked from <X>". Registry harnesses display a Read-only pill — surfaces that direct edits will be overwritten by the next ynh update. Update detection. UpdateAvailabilityService seam + LiveUpdateAvailabilityService impl wraps ynh ls --check-updates and ynh info --check-updates. Three-state HarnessUpdateSignal classifies as versioned (manifest version bumped — orange dot, info banner), unversionedDrift (content drift without a version bump — amber warning triangle, warning banner, confirmation step listing each drifted include SHA), or none. Sidebar dots, header global-probe spinner, dependency-view warning triangle render the signal. Fork to local (single-call). ForkHarnessSheet runs ynh fork --to <path> against the pointer-model YNH; one editable working tree, no copy under ~/.ynh/harnesses/. installed_from.forked_from preserved; ghost origin shown in detail pane. Duplicate (single-call with --name). DuplicateHarnessSheet runs ynh fork --to <path> --name <newname> for local-only renamed copies. Hidden for registry harnesses (Fork covers that intent). Action menu parity. Sidebar context menu and detail action menu share a canonical five-group layout (Run, Location, Actions, Help, Destructive). "Open in…" submenu, Open in browser (URL sources), Reveal in Terminal, Copy as Pathname now consistent across both surfaces. Update menu hidden for forks (YNH refuses). Editable-path resolution. For forked-locals, Reveal/Open/Copy actions target installed_from.source (the editable working tree), not the YNH install slot. Single canonical "where this lives on disk" location. Tolerant Harness decoder. Custom init(from:) accepts null for includes and delegates_to (which YNH emits for broken-install error rows). One bad row no longer collapses the whole sidebar. Sheet first-paint fix. Fork, Update, Duplicate, Add Marketplace, Session Recovery, and Install sheets apply their .frame at the .sheet content closure rather than inside the sheet body. Eliminates the rounded-rect placeholder flash before content resolves. Vendor override picker. Per-harness vendor override (claude/codex/cursor) persists via YNHPersistence; surfaces as a picker badge in the detail header. Tutorial 13 updated for fork/duplicate/menu reorganization. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…languages) Adds and syncs localized strings for the Phase 1 harness management surface across all 40 supported locales: - Source badges (Local, Forked from <X>, Read-only pill) - Update banner copy (versioned vs unversioned-drift wording) - Update sheet phases (confirm, running, succeeded, failed) - Unversioned-drift warning banner and confirmation step - Fork sheet (title, explanation, fork button, progress) - Duplicate sheet (title, name field, duplicate button) - Action menu items new in this PR (Reveal in Terminal, Open in…, Open in browser, Copy as Pathname, Delete Harness) - Sidebar tooltips for the global-probe spinner and dependency-view warning triangle - Common error/loading copy used by CommandRunnerSheet No source-only NEEDS TRANSLATION markers remain. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…gnals Adds and updates test coverage to match the Phase 1 implementation: - HarnessUpdateBadgeStoreTests — full coverage of the three-state signal classification (none / versioned / unversionedDrift), include-level drift, harness-source drift (self-contained plugins), and version-bump precedence over drift. Regression test for nil-ref include data shape. - HarnessSourceBadgeViewModelTests — registry / git / local / forked classification from installed_from variants. - HarnessEditabilityResolverTests — editability decision per source kind and capability gate. - ForkServiceTests — single-call ynh fork --to flow, error mapping, invalidate-on-success. - YnhVersionProbeTests — semver comparison, capability gating. - YNHDecodingTests — extended for tolerant Harness decoder (null includes/delegates_to from broken-install error rows), envelope shape, --check-updates fields (version_available, ref_available, sha_available), forked_from provenance. - UpdateCheckStateTests — lifecycle transitions. - YNHPersistenceProtocolTests — vendor override persistence contract. - HarnessRepositoryTests — capability surface + selectedDetail wiring. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
224deb5 to
1a17d95
Compare
This was referenced May 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First slice of the harness-as-first-class-citizen rework. Establishes the
architecture, surfaces, and YNH coordination model that Phase 2 (YND tools)
and Phase 3 (LLM authoring) will build on. Headed for 0.10 beta.
What's in
Foundation
CommandRunner— streamed-output shell-out with cancellation; single seam for allynh/yndcallers (replaces ad-hocProcess/Pipe).HarnessListResponse/HarnessInfoResponseparsecapabilities,ynh_version, and the new--check-updatesfields (version_available,ref_available,sha_available).YnhVersionProbe— capability-based gate (≥ 0.3.0). Phase 1 features hidden silently on older binaries.Harnessdecoder — acceptsnullforincludes/delegates_to(which YNH emits for broken-install error rows). One bad row no longer collapses the sidebar.Detail pane
HarnessDetailViewModelextracted from the view — pure types own source classification, editability, and update signals, each with their own test coverage. Old feature-flagged badge retired.Local/Forked from <X>. Read-only pill on registry installs.Update detection — three-state drift signal
version_installed != version_available) — orange dot, info banner, single-click Update.installed → availableSHA. Surfaces the supply-chain signal explicitly so users review before pulling.Sidebar dots/triangles, header global-probe spinner, and the dependency-view per-include warning triangle all read from the same
HarnessUpdateSignal.Fork & Duplicate (pointer-model YNH)
Phase 1 lands alongside YNH's pointer-model rewrite (
ynh fork --to <path>self-registers via~/.ynh/installed/<name>.json).ynh forkcall. One editable working tree. No copy under~/.ynh/harnesses/.installed_from.forked_frompreserved for the ghost-origin display.ynh fork --to <path> --name <newname>call. Local-only renamed copies. Hidden for registry harnesses (Fork covers that intent).Action menu parity
Sidebar context menu and detail action menu share a canonical five-group layout. Sidebar drops Help and Export-as-Marketplace (advanced/help-only); detail keeps everything.
*denotes context-gated visibility (URL-only, source-kind, fork-state, etc.)Editable-path resolution
For forked-locals, Reveal in Finder/Terminal, Open in…, Copy as Pathname, and the Path field all target
installed_from.source(the editable working tree), not the YNH install slot. Single canonical "where this lives on disk."Sheet first-paint fix
All six sheets (Fork, Update, Duplicate, Add Marketplace, Session Recovery, Install) now apply
.frame()at the.sheetcontent closure rather than inside the sheet body. Eliminates the rounded-rect placeholder that flashed before content resolved — a long-standing issue caused by NSWindow racing the SwiftUI layout pass on switch-based bodies.Coordinated YNH changes (already merged)
--check-updatesfields)installed_from.forked_fromprovenanceynh forkself-registers via pointer modelynh fork --nameflagynh update <selfcontained>)Testing
swift package cleanbaseline — 1593 tests pass (17 pre-existing skips), 0 failures, 0 lint violations, format clean..ynh-plugin/plugin.jsondescription in source tree. Refresh. Detail pane shows the change without reinstall step. Uninstall preserves source tree on disk.installed.json, refresh, click Update from warning banner, drift clears.Manual checklist sits in
.claude/sessions/manual-test-checklist.md(gitignored).Out of scope (queued for follow-ups)
HarnessAuthor, marketplace include picker) is in place; UI not wired. Next focused branch.ynh delegate add/remove/update.Commit shape
Three logical commits:
feat(harness)— code (foundation, detail pane, fork & duplicate, drift detection, sheet sizing, tolerant decoder, action menus, editable path).feat(localization)— 40 languages translated for the new UI surface.test(harness)— coverage for fork, badges, decoder, drift signals.🤖 Generated with Claude Code