Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
f3da4b8
feat: add managed rules and hooks parity
salmonumbrella Apr 11, 2026
bb40b34
docs: add v0.19.0 managed resources refactor spec
salmonumbrella Apr 11, 2026
c6d7d49
docs: clarify managed resources follow v0.19.0 sync split
salmonumbrella Apr 11, 2026
ac54695
refactor: extract managed resource sync executor
salmonumbrella Apr 11, 2026
19fda9a
refactor: extract managed resource collect helpers
salmonumbrella Apr 11, 2026
e81e4b7
refactor: align managed collect preview validation
salmonumbrella Apr 11, 2026
b2a3b0c
fix: wrap managed collect parity errors
salmonumbrella Apr 11, 2026
3be17fc
refactor: route CLI managed resources through shared package
salmonumbrella Apr 11, 2026
67d5b0b
chore: drop dead CLI managed sync helper
salmonumbrella Apr 11, 2026
425d52a
refactor: route server managed resources through shared package
salmonumbrella Apr 11, 2026
95ac2f8
fix: preserve managed sync continuation on server
salmonumbrella Apr 11, 2026
b432e3d
feat: fold managed rules and hooks into resources
salmonumbrella Apr 11, 2026
1b215a6
refactor: align navigation with shared resources surface
salmonumbrella Apr 11, 2026
3fe338c
fix: narrow resources mode param
salmonumbrella Apr 11, 2026
d11d924
docs: add managed hooks and rules design
salmonumbrella Apr 11, 2026
99ba420
feat: persist managed hook and rule metadata
salmonumbrella Apr 11, 2026
e865938
fix: harden rule metadata sidecar handling
salmonumbrella Apr 11, 2026
b9b14da
feat: expose managed hook and rule metadata backend
salmonumbrella Apr 11, 2026
a181af8
feat: preserve managed resource metadata in detail pages
salmonumbrella Apr 11, 2026
9742461
feat: honor managed hook and rule targeting
salmonumbrella Apr 11, 2026
d634dfa
docs: add native rules and hooks families design
salmonumbrella Apr 11, 2026
ce70d11
docs: clarify pi rules and hooks split
salmonumbrella Apr 11, 2026
7d2400b
docs: classify all supported targets in rules hooks spec
salmonumbrella Apr 12, 2026
b5d826d
docs: add target family decision rule
salmonumbrella Apr 12, 2026
edd7417
feat: add managed capability registry
salmonumbrella Apr 12, 2026
dbc5106
fix: expand managed capability fallback
salmonumbrella Apr 12, 2026
5a9c825
fix: skip unsupported gemini hook sync
salmonumbrella Apr 12, 2026
348e4ee
fix: restore managed target compatibility fallback
salmonumbrella Apr 12, 2026
9197294
feat: add pi managed rules family
salmonumbrella Apr 12, 2026
74e8383
fix: complete pi managed rules preview
salmonumbrella Apr 12, 2026
58aaa80
fix: reject unsupported pi managed rules
salmonumbrella Apr 12, 2026
421cf4c
refactor pi managed rule surface
salmonumbrella Apr 12, 2026
f1e07ab
fix: reject duplicate pi rule collects
salmonumbrella Apr 12, 2026
f6b3c4d
fix: reject unsupported pi collect paths early
salmonumbrella Apr 12, 2026
74db37c
fix: support global pi rule discovery
salmonumbrella Apr 12, 2026
44c82f4
fix: isolate pi managed rule sync
salmonumbrella Apr 12, 2026
389f412
Fix managed Pi AGENTS sync conflicts
salmonumbrella Apr 12, 2026
8dfbc2c
Expand codex-family AGENTS conflict checks
salmonumbrella Apr 12, 2026
ea55a77
Use configured targets for managed rule conflicts
salmonumbrella Apr 12, 2026
8068314
Fix same-family managed rule conflicts
salmonumbrella Apr 12, 2026
28d3b26
Handle project-root Pi AGENTS ownership
salmonumbrella Apr 12, 2026
0bb6a23
Clear stale managed AGENTS claims
salmonumbrella Apr 12, 2026
d520e0b
Tighten managed family resolution
salmonumbrella Apr 12, 2026
72fa0fd
Support nested Pi AGENTS managed rules
salmonumbrella Apr 12, 2026
169437b
Advertise nested Pi AGENTS surfaces
salmonumbrella Apr 12, 2026
ff1d458
Track nested pi managed rule outputs
salmonumbrella Apr 12, 2026
9ebfd05
Keep tracked pi outputs on repeated sync
salmonumbrella Apr 12, 2026
ab63456
feat: add gemini managed hooks family
salmonumbrella Apr 12, 2026
56a7c59
Refactor managed hook resolution helpers
salmonumbrella Apr 12, 2026
de31969
Drop stale CLI hook root helper
salmonumbrella Apr 12, 2026
60dacd2
Align gemini hook timeout validation
salmonumbrella Apr 12, 2026
b33da87
Support legacy gemini timeout records
salmonumbrella Apr 12, 2026
2011980
Cover matcherless gemini hooks
salmonumbrella Apr 12, 2026
0a79400
feat: expose managed capability metadata
salmonumbrella Apr 12, 2026
ac54308
fix(ui): align managed resources hooks with v0.19
salmonumbrella Apr 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 39 additions & 9 deletions cmd/skillshare/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ func previewBackup(targetName, targetPath string) error {
return nil
}

timestamp := time.Now().Format("2006-01-02_15-04-05")
timestamp := backup.NewTimestamp()
backupPath := filepath.Join(backupDir, timestamp, targetName)
ui.Info("%s: would backup to %s", targetName, backupPath)

Expand Down Expand Up @@ -386,6 +386,18 @@ func cmdRestore(args []string) error {
}
}

// Preserve the legacy "restore agents" alias for the canonical shared target
// in global mode when no explicit agent target was requested.
if kind == kindAgents && targetName == "" && mode != modeProject {
cfg, cfgErr := config.Load()
if cfgErr == nil {
if _, _, resolveErr := resolveConfiguredRestoreTarget(cfg.Targets, "agents"); resolveErr == nil {
kind = kindSkills
targetName = "agents"
}
}
}

// Agent restore uses agent-specific backup entries (name suffixed with "-agents")
if kind == kindAgents {
return restoreAgentBackup(mode, cwd, targetName, fromTimestamp, force, dryRun)
Expand All @@ -406,8 +418,12 @@ func cmdRestore(args []string) error {
return err
}

target, exists := cfg.Targets[targetName]
if !exists {
resolvedTargetName, target, err := resolveConfiguredRestoreTarget(cfg.Targets, targetName)
if err != nil {
return err
}
sc := target.SkillsConfig()
if sc.Path == "" {
return fmt.Errorf("target '%s' not found in config", targetName)
}

Expand All @@ -418,20 +434,18 @@ func cmdRestore(args []string) error {
}

opts := backup.RestoreOptions{Force: force}

sc := target.SkillsConfig()
if dryRun {
if fromTimestamp != "" {
return previewRestoreFromTimestamp(targetName, sc.Path, fromTimestamp, opts)
return previewRestoreFromTimestamp(resolvedTargetName, sc.Path, fromTimestamp, opts)
}
return previewRestoreFromLatest(targetName, sc.Path, opts)
return previewRestoreFromLatest(resolvedTargetName, sc.Path, opts)
}

var restoreErr error
if fromTimestamp != "" {
restoreErr = restoreFromTimestamp(targetName, sc.Path, fromTimestamp, opts)
restoreErr = restoreFromTimestamp(resolvedTargetName, sc.Path, fromTimestamp, opts)
} else {
restoreErr = restoreFromLatest(targetName, sc.Path, opts)
restoreErr = restoreFromLatest(resolvedTargetName, sc.Path, opts)
}

e := oplog.NewEntry("restore", statusFromErr(restoreErr), time.Since(start))
Expand All @@ -447,6 +461,22 @@ func cmdRestore(args []string) error {
return restoreErr
}

func resolveConfiguredRestoreTarget(targets map[string]config.TargetConfig, requested string) (string, config.TargetConfig, error) {
candidates := make([]string, 0, len(targets))
for name := range targets {
candidates = append(candidates, name)
}

resolvedName, ok, err := config.ResolveTargetNameCandidate(requested, candidates)
if err != nil {
return "", config.TargetConfig{}, err
}
if !ok {
return "", config.TargetConfig{}, nil
}
return resolvedName, targets[resolvedName], nil
}

// restoreTUIDispatch handles the no-args TUI flow for restore.
func restoreTUIDispatch(noTUI bool) error {
cfg, err := config.Load()
Expand Down
33 changes: 33 additions & 0 deletions cmd/skillshare/backup_restore_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package main

import (
"path/filepath"
"testing"

"skillshare/internal/backup"
"skillshare/internal/config"
)

func TestCmdRestore_AliasRestoresCanonicalLatestBackup(t *testing.T) {
home := setupGlobalResourceTestEnv(t)
sourceDir := filepath.Join(t.TempDir(), "source")
mustAddSkill(t, sourceDir, "alpha")

cfg := &config.Config{
Source: sourceDir,
Targets: map[string]config.TargetConfig{
"universal": {Path: filepath.Join(home, ".agents", "skills")},
},
}
if err := cfg.Save(); err != nil {
t.Fatalf("save config: %v", err)
}

mustWriteFile(t, filepath.Join(backup.BackupDir(), "2025-03-20_18-45-00", "universal", "alpha", "SKILL.md"), "# Alpha\n")

if err := cmdRestore([]string{"agents", "--force"}); err != nil {
t.Fatalf("cmdRestore(alias latest) error = %v", err)
}

assertFileContent(t, filepath.Join(home, ".agents", "skills", "alpha", "SKILL.md"), "# Alpha\n")
}
Loading
Loading