mirror of
https://github.com/awizemann/scarf.git
synced 2026-05-10 10:36:35 +00:00
feat(profiles): add --no-skills toggle to create-profile sheet
Adds an "Empty profile (no skills)" toggle to the Mac create-profile sheet, gated on `hasProfileNoSkills` (v0.13+). When ON, the create flow appends `--no-skills` to `hermes profile create`. The toggle is disabled (greyed out) when "Full copy of active profile" is on, per WS-7 plan Decision H — a full clone copies skills wholesale, so `--no-skills` would be a contradiction at the UX layer. The wire itself stays permissive: a user can stack `--clone --no-skills` to clone config but skip skills, which is a plausible workflow. Defensive write-strip: even though the toggle is hidden on pre-v0.13 hosts, the call site reads `createNoSkills` through the capability gate so a stale state value can't sneak `--no-skills` past argparse on a CLI that doesn't know it. iOS Profiles is read-only (per CLAUDE.md "v0.12 iOS catch-up Phase H") so no toggle there. TODO marker (WS-7-Q8) flags the assumed `--clone-all` interaction — verify Hermes's behaviour with both flags during integration. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -112,10 +112,17 @@ final class ProfilesViewModel {
|
||||
}
|
||||
}
|
||||
|
||||
func create(name: String, cloneConfig: Bool, cloneAll: Bool) {
|
||||
func create(name: String, cloneConfig: Bool, cloneAll: Bool, noSkills: Bool = false) {
|
||||
var args = ["profile", "create", name]
|
||||
if cloneAll { args.append("--clone-all") }
|
||||
else if cloneConfig { args.append("--clone") }
|
||||
// v0.13+: Empty-profile creation. The wire is independent of
|
||||
// --clone / --clone-all per the v0.13 release notes — the user
|
||||
// can stack `--clone --no-skills` to clone config but skip
|
||||
// skills, which is a plausible workflow. The UI still disables
|
||||
// the toggle under --clone-all (Decision H, see ProfilesView)
|
||||
// but the wire is permissive.
|
||||
if noSkills { args.append("--no-skills") }
|
||||
runAndReload(args, success: "Profile '\(name)' created")
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,12 @@ struct ProfilesView: View {
|
||||
@State private var createName = ""
|
||||
@State private var createCloneConfig = true
|
||||
@State private var createCloneAll = false
|
||||
/// v0.13+ `--no-skills` toggle. Mutually exclusive with `--clone-all`
|
||||
/// at the UX layer (Decision H from the WS-7 plan): a full clone
|
||||
/// copies skills wholesale — `--no-skills` would be a contradiction.
|
||||
@State private var createNoSkills = false
|
||||
@State private var showRename = false
|
||||
@Environment(\.hermesCapabilities) private var capabilitiesStore
|
||||
|
||||
init(context: ServerContext) {
|
||||
_viewModel = State(initialValue: ProfilesViewModel(context: context))
|
||||
@@ -123,7 +128,7 @@ struct ProfilesView: View {
|
||||
}
|
||||
Spacer()
|
||||
Button {
|
||||
createName = ""; createCloneConfig = true; createCloneAll = false
|
||||
createName = ""; createCloneConfig = true; createCloneAll = false; createNoSkills = false
|
||||
showCreate = true
|
||||
} label: {
|
||||
Label("Create", systemImage: "plus")
|
||||
@@ -300,11 +305,31 @@ struct ProfilesView: View {
|
||||
Toggle("Clone config, .env, SOUL.md from active profile", isOn: $createCloneConfig)
|
||||
.disabled(createCloneAll)
|
||||
Toggle("Full copy of active profile (all state)", isOn: $createCloneAll)
|
||||
// TODO(WS-7-Q8): Decision H — disable --no-skills when --clone-all
|
||||
// is on. A full clone copies skills wholesale; --no-skills would
|
||||
// be a contradiction. Verify Hermes's behaviour with both flags
|
||||
// (argparse mutual exclusion vs. last-flag-wins vs. clone-but-
|
||||
// skip-skills) and relax the disabled state if Hermes does
|
||||
// something useful with the combination.
|
||||
if capabilitiesStore?.capabilities.hasProfileNoSkills ?? false {
|
||||
Toggle("Empty profile (no skills)", isOn: $createNoSkills)
|
||||
.disabled(createCloneAll)
|
||||
}
|
||||
HStack {
|
||||
Spacer()
|
||||
Button("Cancel") { showCreate = false }
|
||||
Button("Create") {
|
||||
viewModel.create(name: createName, cloneConfig: createCloneConfig, cloneAll: createCloneAll)
|
||||
viewModel.create(
|
||||
name: createName,
|
||||
cloneConfig: createCloneConfig,
|
||||
cloneAll: createCloneAll,
|
||||
// Defensive: if the toggle isn't visible (pre-v0.13)
|
||||
// the state is always `false`, but read it through
|
||||
// the capability gate anyway so a stale state value
|
||||
// can't sneak `--no-skills` to a CLI that doesn't
|
||||
// know it.
|
||||
noSkills: (capabilitiesStore?.capabilities.hasProfileNoSkills ?? false) ? createNoSkills : false
|
||||
)
|
||||
showCreate = false
|
||||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
|
||||
Reference in New Issue
Block a user