diff --git a/apps/frontend/src/renderer/App.tsx b/apps/frontend/src/renderer/App.tsx
index 3017209f2..7ef070661 100644
--- a/apps/frontend/src/renderer/App.tsx
+++ b/apps/frontend/src/renderer/App.tsx
@@ -75,6 +75,7 @@ import { GitHubPRsPilotView } from './components/GitHubPRsPilotView';
import { GitHubIssuesPilotView } from './components/GitHubIssuesPilotView';
import { PatternsPilotView } from './components/PatternsPilotView';
import { AnalyticsPilotView } from './components/AnalyticsPilotView';
+import { ProductivityPilotView } from './components/ProductivityPilotView';
import { useSettingsStore, loadSettings, loadProfiles, saveSettings } from './stores/settings-store';
import { useClaudeProfileStore } from './stores/claude-profile-store';
import { useTerminalStore, restoreTerminalSessions } from './stores/terminal-store';
@@ -1143,6 +1144,9 @@ export function App() {
{activeView === 'productivity' && (activeProjectId || selectedProjectId) && (
)}
+ {activeView === 'productivity-next' && (activeProjectId || selectedProjectId) && (
+
+ )}
{activeView === 'model-usage' && (activeProjectId || selectedProjectId) && (
)}
diff --git a/apps/frontend/src/renderer/__tests__/productivity-ui.test.ts b/apps/frontend/src/renderer/__tests__/productivity-ui.test.ts
new file mode 100644
index 000000000..d427e67e5
--- /dev/null
+++ b/apps/frontend/src/renderer/__tests__/productivity-ui.test.ts
@@ -0,0 +1,130 @@
+/**
+ * Tests for the Productivity{Summary,Trends} → AnalyticsDashboard mappers.
+ */
+
+import { describe, expect, it } from 'vitest';
+import {
+ buildProductivityCharts,
+ buildProductivityKpis,
+ buildProductivitySections,
+ formatHours,
+} from '../lib/productivity-ui';
+import type {
+ ProductivitySummary,
+ ProductivityTrendPoint,
+} from '../../shared/types';
+
+function makeSummary(overrides: Partial = {}): ProductivitySummary {
+ return {
+ period_start: '2026-05-01T00:00:00Z',
+ period_end: '2026-05-22T00:00:00Z',
+ total_specs: 60,
+ completed_specs: 52,
+ in_progress_specs: 5,
+ failed_specs: 3,
+ total_time_saved_hours: 142.4,
+ total_build_time_hours: 38.7,
+ average_success_rate: 0.87,
+ first_attempt_success_rate: 0.71,
+ specs_by_type: {},
+ specs_by_complexity: {},
+ average_subtasks_per_spec: 4.33,
+ average_qa_iterations: 1.2,
+ total_subtasks_completed: 225,
+ specs: [],
+ ...overrides,
+ } as ProductivitySummary;
+}
+
+const TRENDS: ProductivityTrendPoint[] = [
+ { date: '2026-05-01', total_specs: 5, completed_specs: 4, time_saved_hours: 8, success_rate: 0.8 },
+ { date: '2026-05-08', total_specs: 7, completed_specs: 6, time_saved_hours: 12, success_rate: 0.85 },
+ { date: '2026-05-15', total_specs: 8, completed_specs: 7, time_saved_hours: 14, success_rate: 0.9 },
+];
+
+const KPI_LABELS = {
+ specs: 'specs',
+ specsSub: 'period',
+ timeSaved: 'saved',
+ timeSavedSub: 'est',
+ successRate: 'success',
+ buildTime: 'build',
+ buildTimeSub: 'total',
+};
+
+describe('formatHours', () => {
+ it('rounds to whole hours with an h unit', () => {
+ expect(formatHours(52.4)).toBe('52h');
+ expect(formatHours(0)).toBe('0h');
+ expect(formatHours(-5)).toBe('0h');
+ });
+});
+
+describe('buildProductivityKpis', () => {
+ it('maps the summary onto four tiles, converting the 0-1 rate to a percent', () => {
+ const kpis = buildProductivityKpis(makeSummary(), TRENDS, KPI_LABELS);
+ expect(kpis).toHaveLength(4);
+ expect(kpis[0]).toMatchObject({ value: '52', label: 'specs' });
+ expect(kpis[1].value).toBe('142h');
+ expect(kpis[2]).toMatchObject({ value: '87%', tone: 'good' });
+ expect(kpis[3].value).toBe('39h');
+ // sparkline series come from the trends.
+ expect(kpis[0].trend).toEqual([4, 6, 7]);
+ expect(kpis[2].trend).toEqual([80, 85, 90]);
+ });
+
+ it('omits sparklines when trends are too short', () => {
+ const kpis = buildProductivityKpis(makeSummary(), [TRENDS[0]], KPI_LABELS);
+ expect(kpis[0].trend).toBeUndefined();
+ });
+
+ it('tones a low success rate red', () => {
+ const kpis = buildProductivityKpis(
+ makeSummary({ average_success_rate: 0.4 }),
+ TRENDS,
+ KPI_LABELS,
+ );
+ expect(kpis[2].tone).toBe('bad');
+ });
+});
+
+describe('buildProductivityCharts', () => {
+ const labels = {
+ velocityTitle: 'Completed',
+ velocityAria: 'v',
+ velocitySeries: 'Completed',
+ timeSavedTitle: 'Time saved',
+ timeSavedAria: 't',
+ timeSavedSeries: 'Hours',
+ };
+
+ it('builds velocity + time-saved charts with UTC date labels', () => {
+ const charts = buildProductivityCharts(TRENDS, labels, 'en-US');
+ expect(charts.map((c) => c.title)).toEqual(['Completed', 'Time saved']);
+ expect(charts[0].series[0].values).toEqual([4, 6, 7]);
+ expect(charts[1].series[0].values).toEqual([8, 12, 14]);
+ expect(charts[0].xLabels).toEqual(['May 1', 'May 8', 'May 15']);
+ });
+
+ it('returns no charts without at least two trend points', () => {
+ expect(buildProductivityCharts([TRENDS[0]], labels)).toEqual([]);
+ });
+});
+
+describe('buildProductivitySections', () => {
+ it('builds outcome + effort cards with one-decimal effort figures', () => {
+ const sections = buildProductivitySections(makeSummary(), {
+ outcomesTitle: 'Outcomes',
+ completed: 'Completed',
+ inProgress: 'In progress',
+ failed: 'Failed',
+ effortTitle: 'Effort',
+ subtasksPerSpec: 'Subtasks / spec',
+ qaIterations: 'QA iterations',
+ firstAttempt: 'First-attempt rate',
+ });
+ expect(sections[0].rows[0]).toEqual({ label: 'Completed', value: '52' });
+ expect(sections[1].rows[0]).toEqual({ label: 'Subtasks / spec', value: '4.3' });
+ expect(sections[1].rows[2]).toEqual({ label: 'First-attempt rate', value: '71%' });
+ });
+});
diff --git a/apps/frontend/src/renderer/components/ProductivityPilotView.tsx b/apps/frontend/src/renderer/components/ProductivityPilotView.tsx
new file mode 100644
index 000000000..073999c74
--- /dev/null
+++ b/apps/frontend/src/renderer/components/ProductivityPilotView.tsx
@@ -0,0 +1,159 @@
+/**
+ * Productivity pilot on the shared design system (U5 B2).
+ *
+ * Renders `libs/ui`'s AnalyticsDashboard from the existing
+ * `getProductivitySummary` + `getProductivityTrends` IPC, mapped with the
+ * pure `productivity-ui` helpers. Read-only — the legacy Productivity view
+ * keeps its spec table. Reachable via the "Productivity (new UI)" sidebar
+ * item.
+ */
+
+import { useCallback, useEffect, useMemo, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { AnalyticsDashboard } from '@auto-code/ui';
+import type { UiChartCard, UiKpi, UiMetaSection } from '@auto-code/ui';
+import type {
+ ProductivitySummary,
+ ProductivityTrendPoint,
+} from '../../shared/types';
+import {
+ buildProductivityCharts,
+ buildProductivityKpis,
+ buildProductivitySections,
+} from '../lib/productivity-ui';
+
+interface ProductivityPilotViewProps {
+ projectId: string;
+}
+
+interface PilotState {
+ summary: ProductivitySummary | null;
+ trends: ProductivityTrendPoint[];
+ loading: boolean;
+ error: Error | null;
+}
+
+export function ProductivityPilotView({
+ projectId,
+}: Readonly) {
+ const { t, i18n } = useTranslation(['analytics']);
+ const [state, setState] = useState({
+ summary: null,
+ trends: [],
+ loading: true,
+ error: null,
+ });
+ const [reloadKey, setReloadKey] = useState(0);
+
+ useEffect(() => {
+ let active = true;
+ setState({ summary: null, trends: [], loading: true, error: null });
+ Promise.all([
+ window.electronAPI.getProductivitySummary(projectId),
+ window.electronAPI.getProductivityTrends(projectId),
+ ])
+ .then(([summaryResult, trendsResult]) => {
+ if (!active) return;
+ if (!summaryResult.success || summaryResult.data == null) {
+ console.error(
+ '[ProductivityPilotView] Failed to load summary:',
+ summaryResult.success ? 'no data' : summaryResult.error,
+ );
+ setState({
+ summary: null,
+ trends: [],
+ loading: false,
+ error: new Error(t('analytics:productivityPilot.error')),
+ });
+ return;
+ }
+ setState({
+ summary: summaryResult.data,
+ trends: trendsResult.success ? (trendsResult.data ?? []) : [],
+ loading: false,
+ error: null,
+ });
+ })
+ .catch((err: unknown) => {
+ if (!active) return;
+ console.error('[ProductivityPilotView] Failed to load productivity:', err);
+ setState({
+ summary: null,
+ trends: [],
+ loading: false,
+ error: new Error(t('analytics:productivityPilot.error')),
+ });
+ });
+ return () => {
+ active = false;
+ };
+ }, [projectId, reloadKey, t]);
+
+ const reload = useCallback(() => setReloadKey((key) => key + 1), []);
+
+ const kpis = useMemo(() => {
+ if (state.summary == null) return null;
+ return buildProductivityKpis(state.summary, state.trends, {
+ specs: t('analytics:productivityPilot.kpis.specs'),
+ specsSub: t('analytics:productivityPilot.kpis.specsSub'),
+ timeSaved: t('analytics:productivityPilot.kpis.timeSaved'),
+ timeSavedSub: t('analytics:productivityPilot.kpis.timeSavedSub'),
+ successRate: t('analytics:productivityPilot.kpis.successRate'),
+ buildTime: t('analytics:productivityPilot.kpis.buildTime'),
+ buildTimeSub: t('analytics:productivityPilot.kpis.buildTimeSub'),
+ });
+ }, [state.summary, state.trends, t]);
+
+ const charts = useMemo(() => {
+ if (state.summary == null) return undefined;
+ return buildProductivityCharts(
+ state.trends,
+ {
+ velocityTitle: t('analytics:productivityPilot.charts.velocityTitle'),
+ velocityAria: t('analytics:productivityPilot.charts.velocityAria'),
+ velocitySeries: t('analytics:productivityPilot.charts.velocitySeries'),
+ timeSavedTitle: t('analytics:productivityPilot.charts.timeSavedTitle'),
+ timeSavedAria: t('analytics:productivityPilot.charts.timeSavedAria'),
+ timeSavedSeries: t('analytics:productivityPilot.charts.timeSavedSeries'),
+ },
+ i18n.language,
+ );
+ }, [state.summary, state.trends, t, i18n.language]);
+
+ const sections = useMemo(() => {
+ if (state.summary == null) return undefined;
+ return buildProductivitySections(state.summary, {
+ outcomesTitle: t('analytics:productivityPilot.sections.outcomesTitle'),
+ completed: t('analytics:productivityPilot.sections.completed'),
+ inProgress: t('analytics:productivityPilot.sections.inProgress'),
+ failed: t('analytics:productivityPilot.sections.failed'),
+ effortTitle: t('analytics:productivityPilot.sections.effortTitle'),
+ subtasksPerSpec: t('analytics:productivityPilot.sections.subtasksPerSpec'),
+ qaIterations: t('analytics:productivityPilot.sections.qaIterations'),
+ firstAttempt: t('analytics:productivityPilot.sections.firstAttempt'),
+ });
+ }, [state.summary, t]);
+
+ const stateLabels = useMemo(
+ () => ({
+ loading: t('analytics:productivityPilot.states.loading'),
+ retry: t('analytics:productivityPilot.states.retry'),
+ empty: t('analytics:productivityPilot.states.empty'),
+ }),
+ [t],
+ );
+
+ return (
+
+ );
+}
diff --git a/apps/frontend/src/renderer/components/Sidebar.tsx b/apps/frontend/src/renderer/components/Sidebar.tsx
index e6dd01d30..771156d71 100644
--- a/apps/frontend/src/renderer/components/Sidebar.tsx
+++ b/apps/frontend/src/renderer/components/Sidebar.tsx
@@ -71,7 +71,7 @@ import { SessionContextIndicator } from './SessionContextIndicator';
import { NavIndicator } from './NavIndicator';
import type { Project, AutoBuildVersionInfo, GitStatus, ProjectEnvConfig } from '../../shared/types';
-export type SidebarView = 'kanban' | 'kanban-next' | 'terminals' | 'roadmap' | 'context' | 'ideation' | 'webhooks' | 'github-issues' | 'github-issues-next' | 'gitlab-issues' | 'github-prs' | 'github-prs-next' | 'gitlab-merge-requests' | 'changelog' | 'changelog-next' | 'insights' | 'worktrees' | 'agent-tools' | 'plugins' | 'analytics' | 'analytics-next' | 'productivity' | 'merge-analytics' | 'sessions' | 'scheduler' | 'feedback' | 'patterns' | 'patterns-next' | 'model-usage' | 'agent-inspector';
+export type SidebarView = 'kanban' | 'kanban-next' | 'terminals' | 'roadmap' | 'context' | 'ideation' | 'webhooks' | 'github-issues' | 'github-issues-next' | 'gitlab-issues' | 'github-prs' | 'github-prs-next' | 'gitlab-merge-requests' | 'changelog' | 'changelog-next' | 'insights' | 'worktrees' | 'agent-tools' | 'plugins' | 'analytics' | 'analytics-next' | 'productivity' | 'productivity-next' | 'merge-analytics' | 'sessions' | 'scheduler' | 'feedback' | 'patterns' | 'patterns-next' | 'model-usage' | 'agent-inspector';
interface SidebarProps {
onSettingsClick: () => void;
@@ -103,6 +103,7 @@ const baseNavItems: NavItem[] = [
{ id: 'analytics', labelKey: 'navigation:items.analytics', icon: BarChart3, shortcut: 'Y' },
{ id: 'analytics-next', labelKey: 'navigation:items.analyticsNext', icon: BarChart3 },
{ id: 'productivity', labelKey: 'navigation:items.productivity', icon: TrendingUp, shortcut: 'P' },
+ { id: 'productivity-next', labelKey: 'navigation:items.productivityNext', icon: Activity },
{ id: 'patterns', labelKey: 'navigation:items.patterns', icon: Code, shortcut: 'Z' },
{ id: 'patterns-next', labelKey: 'navigation:items.patternsNext', icon: Code },
{ id: 'agent-tools', labelKey: 'navigation:items.agentTools', icon: Wrench, shortcut: 'M' },
diff --git a/apps/frontend/src/renderer/lib/productivity-ui.ts b/apps/frontend/src/renderer/lib/productivity-ui.ts
new file mode 100644
index 000000000..fc492d832
--- /dev/null
+++ b/apps/frontend/src/renderer/lib/productivity-ui.ts
@@ -0,0 +1,170 @@
+/**
+ * Pure mapping helpers between the ProductivitySummary/Trends IPC shapes and
+ * the shared AnalyticsDashboard screen. The mockup's categorical bar panels
+ * ("when you ship", "where the time went") have no backing data, so — like
+ * the other pilots — this maps only what the backend actually provides: KPI
+ * summary figures plus the daily trend series as line charts.
+ */
+
+import type { UiChartCard, UiKpi, UiMetaSection } from '@auto-code/ui';
+import type {
+ ProductivitySummary,
+ ProductivityTrendPoint,
+} from '../../shared/types';
+import {
+ formatPercent,
+ sampleLabels,
+ shortDate,
+ successRateTone,
+} from './analytics-ui';
+
+/** Whole hours with an "h" unit, e.g. 52.4 → "52h". */
+export function formatHours(hours: number): string {
+ if (!Number.isFinite(hours) || hours < 0) return '0h';
+ return `${Math.round(hours)}h`;
+}
+
+export interface ProductivityKpiLabels {
+ specs: string;
+ specsSub: string;
+ timeSaved: string;
+ timeSavedSub: string;
+ successRate: string;
+ buildTime: string;
+ buildTimeSub: string;
+}
+
+export function buildProductivityKpis(
+ summary: ProductivitySummary,
+ trends: readonly ProductivityTrendPoint[],
+ labels: ProductivityKpiLabels,
+): UiKpi[] {
+ // Backend success rates are 0.0–1.0; the tile shows a whole percent.
+ const ratePct = summary.average_success_rate * 100;
+ const specSeries = trends.map((point) => point.completed_specs);
+ const savedSeries = trends.map((point) => point.time_saved_hours);
+ const rateSeries = trends.map((point) => point.success_rate * 100);
+ const rateTone = successRateTone(ratePct);
+ return [
+ {
+ value: String(summary.completed_specs),
+ label: labels.specs,
+ sub: labels.specsSub,
+ trend: specSeries.length >= 2 ? specSeries : undefined,
+ trendTone: 'info',
+ },
+ {
+ value: formatHours(summary.total_time_saved_hours),
+ label: labels.timeSaved,
+ sub: labels.timeSavedSub,
+ trend: savedSeries.length >= 2 ? savedSeries : undefined,
+ trendTone: 'good',
+ },
+ {
+ value: formatPercent(ratePct),
+ label: labels.successRate,
+ tone: rateTone,
+ trend: rateSeries.length >= 2 ? rateSeries : undefined,
+ trendTone: rateTone === 'bad' ? 'bad' : 'good',
+ },
+ {
+ value: formatHours(summary.total_build_time_hours),
+ label: labels.buildTime,
+ sub: labels.buildTimeSub,
+ },
+ ];
+}
+
+export interface ProductivityChartLabels {
+ velocityTitle: string;
+ velocityAria: string;
+ velocitySeries: string;
+ timeSavedTitle: string;
+ timeSavedAria: string;
+ timeSavedSeries: string;
+}
+
+export function buildProductivityCharts(
+ trends: readonly ProductivityTrendPoint[],
+ labels: ProductivityChartLabels,
+ locale?: string,
+): UiChartCard[] {
+ if (trends.length < 2) return [];
+ const xLabels = sampleLabels(trends.map((p) => shortDate(p.date, locale)));
+ return [
+ {
+ title: labels.velocityTitle,
+ ariaLabel: labels.velocityAria,
+ xLabels,
+ series: [
+ {
+ label: labels.velocitySeries,
+ tone: 'info',
+ values: trends.map((p) => p.completed_specs),
+ },
+ ],
+ },
+ {
+ title: labels.timeSavedTitle,
+ ariaLabel: labels.timeSavedAria,
+ xLabels,
+ series: [
+ {
+ label: labels.timeSavedSeries,
+ tone: 'good',
+ values: trends.map((p) => p.time_saved_hours),
+ },
+ ],
+ },
+ ];
+}
+
+export interface ProductivitySectionLabels {
+ outcomesTitle: string;
+ completed: string;
+ inProgress: string;
+ failed: string;
+ effortTitle: string;
+ subtasksPerSpec: string;
+ qaIterations: string;
+ firstAttempt: string;
+}
+
+/** Round to at most one decimal, dropping a trailing ".0". */
+function oneDecimal(value: number): string {
+ if (!Number.isFinite(value)) return '0';
+ return String(Math.round(value * 10) / 10);
+}
+
+export function buildProductivitySections(
+ summary: ProductivitySummary,
+ labels: ProductivitySectionLabels,
+): UiMetaSection[] {
+ return [
+ {
+ title: labels.outcomesTitle,
+ rows: [
+ { label: labels.completed, value: String(summary.completed_specs) },
+ { label: labels.inProgress, value: String(summary.in_progress_specs) },
+ { label: labels.failed, value: String(summary.failed_specs) },
+ ],
+ },
+ {
+ title: labels.effortTitle,
+ rows: [
+ {
+ label: labels.subtasksPerSpec,
+ value: oneDecimal(summary.average_subtasks_per_spec),
+ },
+ {
+ label: labels.qaIterations,
+ value: oneDecimal(summary.average_qa_iterations),
+ },
+ {
+ label: labels.firstAttempt,
+ value: formatPercent(summary.first_attempt_success_rate * 100),
+ },
+ ],
+ },
+ ];
+}
diff --git a/apps/frontend/src/shared/i18n/locales/en/analytics.json b/apps/frontend/src/shared/i18n/locales/en/analytics.json
index cf9364944..ae50298d0 100644
--- a/apps/frontend/src/shared/i18n/locales/en/analytics.json
+++ b/apps/frontend/src/shared/i18n/locales/en/analytics.json
@@ -105,5 +105,40 @@
"approved": "Approved",
"rejectionRate": "Rejection rate"
}
+ },
+ "productivityPilot": {
+ "error": "Failed to load productivity data.",
+ "states": {
+ "loading": "Loading productivity…",
+ "retry": "Retry",
+ "empty": "No productivity data yet."
+ },
+ "kpis": {
+ "specs": "specs completed",
+ "specsSub": "this period",
+ "timeSaved": "time saved",
+ "timeSavedSub": "estimated",
+ "successRate": "success rate",
+ "buildTime": "build time",
+ "buildTimeSub": "total"
+ },
+ "charts": {
+ "velocityTitle": "Completed specs",
+ "velocityAria": "Completed specs per day over the period",
+ "velocitySeries": "Completed",
+ "timeSavedTitle": "Time saved",
+ "timeSavedAria": "Hours saved per day over the period",
+ "timeSavedSeries": "Hours saved"
+ },
+ "sections": {
+ "outcomesTitle": "Outcomes",
+ "completed": "Completed",
+ "inProgress": "In progress",
+ "failed": "Failed",
+ "effortTitle": "Effort",
+ "subtasksPerSpec": "Subtasks / spec",
+ "qaIterations": "QA iterations",
+ "firstAttempt": "First-attempt rate"
+ }
}
}
diff --git a/apps/frontend/src/shared/i18n/locales/en/navigation.json b/apps/frontend/src/shared/i18n/locales/en/navigation.json
index 78584fd9e..00f28413d 100644
--- a/apps/frontend/src/shared/i18n/locales/en/navigation.json
+++ b/apps/frontend/src/shared/i18n/locales/en/navigation.json
@@ -34,7 +34,8 @@
"githubPRsNext": "GitHub PRs (New UI)",
"githubIssuesNext": "GitHub Issues (New UI)",
"patternsNext": "Patterns (New UI)",
- "analyticsNext": "Analytics (New UI)"
+ "analyticsNext": "Analytics (New UI)",
+ "productivityNext": "Productivity (New UI)"
},
"actions": {
"settings": "Settings",
diff --git a/apps/frontend/src/shared/i18n/locales/fr/analytics.json b/apps/frontend/src/shared/i18n/locales/fr/analytics.json
index 2b054b63d..a10d9190f 100644
--- a/apps/frontend/src/shared/i18n/locales/fr/analytics.json
+++ b/apps/frontend/src/shared/i18n/locales/fr/analytics.json
@@ -105,5 +105,40 @@
"approved": "Approuvées",
"rejectionRate": "Taux de rejet"
}
+ },
+ "productivityPilot": {
+ "error": "Échec du chargement des données de productivité.",
+ "states": {
+ "loading": "Chargement de la productivité…",
+ "retry": "Réessayer",
+ "empty": "Aucune donnée de productivité pour le moment."
+ },
+ "kpis": {
+ "specs": "spécs terminées",
+ "specsSub": "cette période",
+ "timeSaved": "temps gagné",
+ "timeSavedSub": "estimé",
+ "successRate": "taux de réussite",
+ "buildTime": "temps de build",
+ "buildTimeSub": "total"
+ },
+ "charts": {
+ "velocityTitle": "Spécs terminées",
+ "velocityAria": "Spécs terminées par jour sur la période",
+ "velocitySeries": "Terminées",
+ "timeSavedTitle": "Temps gagné",
+ "timeSavedAria": "Heures gagnées par jour sur la période",
+ "timeSavedSeries": "Heures gagnées"
+ },
+ "sections": {
+ "outcomesTitle": "Résultats",
+ "completed": "Terminées",
+ "inProgress": "En cours",
+ "failed": "Échouées",
+ "effortTitle": "Effort",
+ "subtasksPerSpec": "Sous-tâches / spéc",
+ "qaIterations": "Itérations QA",
+ "firstAttempt": "Taux au 1er essai"
+ }
}
}
diff --git a/apps/frontend/src/shared/i18n/locales/fr/navigation.json b/apps/frontend/src/shared/i18n/locales/fr/navigation.json
index c2ce10a78..ea7a36f05 100644
--- a/apps/frontend/src/shared/i18n/locales/fr/navigation.json
+++ b/apps/frontend/src/shared/i18n/locales/fr/navigation.json
@@ -34,7 +34,8 @@
"githubPRsNext": "PRs GitHub (nouvelle interface)",
"githubIssuesNext": "Issues GitHub (nouvelle interface)",
"patternsNext": "Patterns (nouvelle interface)",
- "analyticsNext": "Analytique (nouvelle interface)"
+ "analyticsNext": "Analytique (nouvelle interface)",
+ "productivityNext": "Productivité (nouvelle interface)"
},
"actions": {
"settings": "Paramètres",