Browse Source

fix: surface staged skill reviews

Alvin Unreal 3 weeks ago
parent
commit
3fbd226a01
2 changed files with 66 additions and 4 deletions
  1. 46 1
      src/hooks/auto-update-checker/index.test.ts
  2. 20 3
      src/hooks/auto-update-checker/index.ts

+ 46 - 1
src/hooks/auto-update-checker/index.test.ts

@@ -250,6 +250,51 @@ describe('auto-update-checker/index', () => {
     });
   });
 
+  test('shows a manual-review toast for newly staged startup skills when up to date', async () => {
+    checkerMocks.getCurrentRuntimePackageJsonPath.mockImplementation(
+      () => '/tmp/opencode/package.json',
+    );
+    checkerMocks.findPluginEntry.mockImplementation(() => ({
+      pinnedVersion: null,
+      isPinned: false,
+    }));
+    checkerMocks.getCachedVersion.mockImplementation(() => '0.9.11');
+    checkerMocks.getLatestCompatibleVersion.mockImplementation(async () => ({
+      latestVersion: '0.9.11',
+      latestMajorVersion: null,
+      blockedByMajor: false,
+    }));
+    skillSyncMocks.syncBundledSkillsFromPackage.mockImplementation(() => ({
+      installed: [],
+      skippedExisting: [],
+      failed: [],
+      staged: ['reflect'],
+      adopted: [],
+      customized: ['reflect'],
+      stagedThisSync: ['reflect'],
+    }));
+
+    const { createAutoUpdateCheckerHook } = await import(
+      `./index?test=${importCounter++}`
+    );
+    const { ctx, showToast } = createCtx();
+
+    createAutoUpdateCheckerHook(ctx as never).event({
+      event: { type: 'session.created', properties: {} },
+    });
+    await waitForCalls(showToast);
+
+    expect(showToast).toHaveBeenCalledTimes(1);
+    expect(showToast).toHaveBeenCalledWith({
+      body: {
+        title: 'Skill updates need review',
+        message: 'Manual review required: reflect',
+        variant: 'info',
+        duration: 8000,
+      },
+    });
+  });
+
   test('includes newly installed bundled skills in success toast', async () => {
     checkerMocks.findPluginEntry.mockImplementation(() => ({
       pinnedVersion: null,
@@ -416,7 +461,7 @@ describe('auto-update-checker/index', () => {
       staged: [],
       adopted: ['reflect'],
       customized: [],
-      stagedThisSync: [],
+      stagedThisSync: ['reflect'],
     }));
 
     const { createAutoUpdateCheckerHook } = await import(

+ 20 - 3
src/hooks/auto-update-checker/index.ts

@@ -170,6 +170,7 @@ async function runBackgroundUpdateCheck(
       '[auto-update-checker] Already on latest version for channel:',
       channel,
     );
+    showStagedSkillsReviewToast(ctx, stagedSkillsThisUpdate);
     return;
   }
 
@@ -198,6 +199,7 @@ async function runBackgroundUpdateCheck(
       8000,
     );
     log('[auto-update-checker] Auto-update disabled, notification only');
+    showStagedSkillsReviewToast(ctx, stagedSkillsThisUpdate);
     return;
   }
 
@@ -224,12 +226,12 @@ async function runBackgroundUpdateCheck(
     try {
       const syncResult = syncBundledSkillsFromPackage(packageRoot);
       installedSkills = syncResult.installed;
-      for (const skill of [...syncResult.installed, ...syncResult.adopted]) {
-        stagedSkillsThisUpdate.delete(skill);
-      }
       for (const skill of syncResult.stagedThisSync) {
         stagedSkillsThisUpdate.add(skill);
       }
+      for (const skill of [...syncResult.installed, ...syncResult.adopted]) {
+        stagedSkillsThisUpdate.delete(skill);
+      }
       if (syncResult.failed.length > 0) {
         log(
           `[auto-update-checker] Skill sync warnings/failures: ${syncResult.failed.join(', ')}`,
@@ -322,6 +324,21 @@ function showMajorUpgradeToast(ctx: PluginInput, version: string): void {
   );
 }
 
+function showStagedSkillsReviewToast(
+  ctx: PluginInput,
+  stagedSkills: ReadonlySet<string>,
+): void {
+  if (stagedSkills.size === 0) return;
+
+  showToast(
+    ctx,
+    'Skill updates need review',
+    `Manual review required: ${[...stagedSkills].join(', ')}`,
+    'info',
+    8000,
+  );
+}
+
 export function getAutoUpdateInstallDir(): string {
   return resolveInstallContext()?.installDir ?? CACHE_DIR;
 }