feat: enable turn stats by default and prepare release notes
Turn stats was hidden unless users opted in. Show it by default, migrate implicit hidden lists, and preserve explicit section choices through reloads and settings sync. Prepare App and VS Code release notes with Turn stats as the headline and BTW composer changes under improvements. Testing: 115 focused tests passed; UI type-check passed; UI lint has one existing warning. Changelog validation and diff checks passed. Oxlint findings are limited to existing code in sections.ts; interactive app validation was not run.
This commit is contained in:
@@ -863,22 +863,22 @@ describe('updateDesktopSettings', () => {
|
||||
expect(saveCalls.some((changes) => changes.toolJsonViewMode === 'formatted')).toBe(true);
|
||||
});
|
||||
|
||||
test('legacy server lists keep telemetry hidden, while explicit opt-ins survive hydration', async () => {
|
||||
test('legacy server lists show telemetry, while explicit hiding survives hydration', async () => {
|
||||
getWindow();
|
||||
for (const explicit of [undefined, false, true]) {
|
||||
invalidateSettingsCache();
|
||||
registerSettingsApi(async (changes) => changes, async () => ({
|
||||
settings: { workStatusHiddenSections: ['mcp'], workStatusHiddenSectionsExplicit: explicit,
|
||||
settings: { workStatusHiddenSections: ['mcp', 'telemetry'], workStatusHiddenSectionsExplicit: explicit,
|
||||
draftStartersCraftGoalAdded: true, draftStartersScheduleTaskAdded: true },
|
||||
source: 'web',
|
||||
}));
|
||||
await syncDesktopSettings();
|
||||
expect(useUIStore.getState().workStatusHiddenSections).toEqual(explicit ? ['mcp'] : ['mcp', 'telemetry']);
|
||||
expect(useUIStore.getState().workStatusHiddenSections).toEqual(explicit ? ['mcp', 'telemetry'] : ['mcp']);
|
||||
expect(useUIStore.getState().workStatusHiddenSectionsExplicit).toBe(explicit === true);
|
||||
}
|
||||
});
|
||||
|
||||
test('autosaves telemetry opt-in and its list together, then restores them through settings load', async () => {
|
||||
test('autosaves telemetry hiding and its list together, then restores them through settings load', async () => {
|
||||
getWindow();
|
||||
invalidateSettingsCache();
|
||||
let server: SettingsPayload = { workStatusHiddenSections: [], draftStartersCraftGoalAdded: true, draftStartersScheduleTaskAdded: true };
|
||||
@@ -886,23 +886,20 @@ describe('updateDesktopSettings', () => {
|
||||
registerSettingsApi(async (changes) => { saves.push(changes); server = { ...server, ...changes }; return changes; },
|
||||
async () => ({ settings: server, source: 'web' }));
|
||||
await syncDesktopSettings();
|
||||
expect(useUIStore.getState().workStatusHiddenSections).toEqual(['telemetry']);
|
||||
expect(useUIStore.getState().workStatusHiddenSections).toEqual([]);
|
||||
startAppearanceAutoSave();
|
||||
useUIStore.getState().setWorkStatusSectionVisible('telemetry', true);
|
||||
useUIStore.getState().setWorkStatusSectionVisible('telemetry', false);
|
||||
await delay(600);
|
||||
// The list itself already matches the server ([]), so only the explicit
|
||||
// marker needs to travel; the server merges per key, so the end state is
|
||||
// the same as sending both.
|
||||
expect(saves.some((changes) => changes.workStatusHiddenSectionsExplicit === true)).toBe(true);
|
||||
expect(server.workStatusHiddenSections).toEqual([]);
|
||||
expect(server.workStatusHiddenSections).toEqual(['telemetry']);
|
||||
expect(server.workStatusHiddenSectionsExplicit).toBe(true);
|
||||
invalidateSettingsCache();
|
||||
await syncDesktopSettings();
|
||||
expect(useUIStore.getState().workStatusHiddenSections).toEqual([]);
|
||||
expect(useUIStore.getState().workStatusHiddenSections).toEqual(['telemetry']);
|
||||
expect(useUIStore.getState().workStatusHiddenSectionsExplicit).toBe(true);
|
||||
// An unrelated partial save response must not turn an opt-in back off.
|
||||
// An unrelated partial save response must not re-enable a hidden section.
|
||||
await updateDesktopSettings({ workStatusPanelEnabled: useUIStore.getState().workStatusPanelEnabled });
|
||||
expect(useUIStore.getState().workStatusHiddenSections).toEqual([]);
|
||||
expect(useUIStore.getState().workStatusHiddenSections).toEqual(['telemetry']);
|
||||
});
|
||||
|
||||
test('applies persisted autoSaveEnabled from server settings', async () => {
|
||||
@@ -1116,7 +1113,7 @@ describe('updateDesktopSettings', () => {
|
||||
favoriteModels: [{ providerID: 'anthropic', modelID: 'claude-sonnet-4' }],
|
||||
// A legacy list the client normalises on read: the normalised copy is
|
||||
// still not this window's change and must not be written back.
|
||||
workStatusHiddenSections: ['mcp'],
|
||||
workStatusHiddenSections: ['mcp', 'telemetry'],
|
||||
draftStartersCraftGoalAdded: true,
|
||||
draftStartersScheduleTaskAdded: true,
|
||||
},
|
||||
@@ -1137,7 +1134,7 @@ describe('updateDesktopSettings', () => {
|
||||
expect(useUIStore.getState().showReasoningTraces).toBe(false);
|
||||
expect(useUIStore.getState().terminalShell).toBe('fish');
|
||||
expect(useUIStore.getState().favoriteModels).toHaveLength(1);
|
||||
expect(useUIStore.getState().workStatusHiddenSections).toEqual(['mcp', 'telemetry']);
|
||||
expect(useUIStore.getState().workStatusHiddenSections).toEqual(['mcp']);
|
||||
expect(saveCalls).toEqual([]);
|
||||
} finally {
|
||||
stopModelPrefs();
|
||||
|
||||
@@ -87,11 +87,11 @@ describe('settings registry', () => {
|
||||
});
|
||||
|
||||
test('applies the hidden-sections list together with its explicit marker', () => {
|
||||
applySettingsToStores({ workStatusHiddenSections: ['mcp'] });
|
||||
expect(useUIStore.getState().workStatusHiddenSections).toEqual(['mcp', 'telemetry']);
|
||||
expect(useUIStore.getState().workStatusHiddenSectionsExplicit).toBe(false);
|
||||
applySettingsToStores({ workStatusHiddenSections: ['mcp'], workStatusHiddenSectionsExplicit: true });
|
||||
applySettingsToStores({ workStatusHiddenSections: ['mcp', 'telemetry'] });
|
||||
expect(useUIStore.getState().workStatusHiddenSections).toEqual(['mcp']);
|
||||
expect(useUIStore.getState().workStatusHiddenSectionsExplicit).toBe(false);
|
||||
applySettingsToStores({ workStatusHiddenSections: ['mcp', 'telemetry'], workStatusHiddenSectionsExplicit: true });
|
||||
expect(useUIStore.getState().workStatusHiddenSections).toEqual(['mcp', 'telemetry']);
|
||||
expect(useUIStore.getState().workStatusHiddenSectionsExplicit).toBe(true);
|
||||
});
|
||||
|
||||
|
||||
@@ -296,8 +296,8 @@ export const SETTINGS_REGISTRY = {
|
||||
parse: parseWorkStatusHiddenSections,
|
||||
ui: {
|
||||
read: () => useUIStore.getState().workStatusHiddenSections,
|
||||
// The explicit marker decides whether a legacy list implicitly hides
|
||||
// telemetry; both land in one store update so subscribers never see the
|
||||
// The explicit marker distinguishes chosen lists from the old telemetry
|
||||
// default; both land in one store update so subscribers never see the
|
||||
// list without its marker.
|
||||
write: (value, snapshot) => {
|
||||
const explicit = snapshot.workStatusHiddenSectionsExplicit === true;
|
||||
|
||||
Reference in New Issue
Block a user