@nightkatana/kronosys-app 1.0.0-beta.2 → 1.0.0-beta.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/README.md +28 -1
  2. package/app/api/action/route.ts +39 -3
  3. package/app/api/action-logs/route.ts +24 -0
  4. package/app/api/backup/route.ts +1 -1
  5. package/app/api/restore/route.ts +145 -0
  6. package/app/changelog/page.tsx +71 -4
  7. package/app/globals.css +127 -0
  8. package/app/guide/page.tsx +61 -15
  9. package/app/implementation/page.tsx +700 -0
  10. package/app/layout.tsx +14 -3
  11. package/app/licenses/page.tsx +99 -37
  12. package/app/logs/page.tsx +258 -0
  13. package/app/manifest.ts +5 -5
  14. package/app/page.tsx +784 -229
  15. package/app/reporting/page.tsx +1266 -474
  16. package/app/settings/page.tsx +252 -18
  17. package/bin/kronosys.mjs +140 -15
  18. package/components/KronosysPayloadProvider.tsx +2 -0
  19. package/components/RouteTransition.tsx +18 -0
  20. package/components/dashboard/AppShellCommandCenterPlaceholder.tsx +17 -0
  21. package/components/dashboard/AppShellHeaderSessionMeta.tsx +210 -0
  22. package/components/dashboard/AppShellHeaderWallClock.tsx +54 -0
  23. package/components/dashboard/AppShellLiveSessionDrawer.tsx +154 -38
  24. package/components/dashboard/AppShellRouteNav.tsx +323 -48
  25. package/components/dashboard/DashboardPauseBackdrop.tsx +50 -0
  26. package/components/dashboard/DashboardSimpleModal.tsx +168 -25
  27. package/components/dashboard/DashboardTour.tsx +115 -29
  28. package/components/dashboard/GlobalPauseConfirmModal.tsx +183 -0
  29. package/components/dashboard/KronosysDatetimePopoverField.tsx +167 -122
  30. package/components/dashboard/KronosysTimePopoverField.tsx +54 -12
  31. package/components/dashboard/NewSessionScopeModal.tsx +211 -20
  32. package/components/dashboard/PlannedTaskBoundaryConflictWatcher.tsx +275 -0
  33. package/components/dashboard/ReportingTour.tsx +87 -21
  34. package/components/dashboard/SavedProjectPicker.tsx +16 -3
  35. package/components/dashboard/SelectedSessionSidebarBlock.tsx +512 -142
  36. package/components/dashboard/SessionListPanel.tsx +327 -44
  37. package/components/dashboard/SettingsTagsProjectsSection.tsx +1073 -264
  38. package/components/dashboard/SettingsTaskTemplatesSection.tsx +316 -0
  39. package/components/dashboard/SettingsTour.tsx +86 -21
  40. package/components/dashboard/TagPills.tsx +14 -1
  41. package/components/dashboard/TaskFocusPanel.tsx +1081 -478
  42. package/components/dashboard/TaskSessionLiveCard.tsx +650 -135
  43. package/components/dashboard/TaskTimelineGanttModal.tsx +601 -0
  44. package/components/dashboard/taskFieldStyles.ts +20 -4
  45. package/components/dashboard/useReportingInteractionState.ts +80 -0
  46. package/lib/appShellHeaderClasses.ts +13 -0
  47. package/lib/businessRulesMatrix.ts +210 -0
  48. package/lib/copyToClipboard.ts +43 -0
  49. package/lib/dashboardCopy.ts +494 -84
  50. package/lib/dashboardQuickSearch.ts +54 -2
  51. package/lib/dashboardTimeZone.ts +109 -0
  52. package/lib/formatAppShellWallClock.ts +66 -0
  53. package/lib/formatSessionNameTemplate.ts +141 -0
  54. package/lib/generatedUserChangelog.ts +177 -6
  55. package/lib/globalPausePreview.ts +292 -0
  56. package/lib/implementationNotes.ts +1188 -0
  57. package/lib/kronosysApi.ts +6 -0
  58. package/lib/kronosysDashboardModalGates.ts +24 -0
  59. package/lib/plannedBoundaryAttention.ts +9 -0
  60. package/lib/plannedBoundaryConflict.ts +23 -0
  61. package/lib/reportingAggregate.ts +517 -75
  62. package/lib/reportingMetricHelp.ts +8 -0
  63. package/lib/reportingStrings.ts +37 -3
  64. package/lib/sessionListMerge.ts +4 -0
  65. package/lib/sessionTaskSidebarStats.ts +182 -21
  66. package/lib/settingsCopy.ts +178 -4
  67. package/lib/taskParsing.ts +360 -103
  68. package/lib/taskTemplateDraft.ts +135 -0
  69. package/lib/taskTimelineGantt.ts +265 -0
  70. package/lib/temporalDisplayPlanned.ts +71 -0
  71. package/lib/userGuideCopy.ts +121 -47
  72. package/next.config.ts +7 -0
  73. package/package.json +12 -24
  74. package/server/actionDispatch.ts +1000 -77
  75. package/server/actionTaskSession.ts +337 -24
  76. package/server/db.ts +7 -15
  77. package/server/dbSchema.ts +24 -0
  78. package/server/defaultCfg.ts +5 -0
  79. package/server/gitlabTokenStore.ts +0 -12
  80. package/server/liveHistorySync.ts +53 -0
  81. package/server/mainTimerHydrate.ts +38 -2
  82. package/server/payloadStore.ts +33 -11
  83. package/server/sessionWallHydrate.ts +66 -3
  84. package/server/userActionLog.ts +126 -0
  85. package/sonar-project.properties +11 -0
  86. package/tsconfig.json +2 -1
  87. package/components/dashboard/IssuePickerModal.tsx +0 -168
  88. package/components/dashboard/ThemeToggle.test.tsx +0 -26
  89. package/lib/backupCsvExport.test.ts +0 -149
  90. package/lib/dashboardQuickSearchQuery.test.ts +0 -63
  91. package/lib/dataDir.test.ts +0 -87
  92. package/lib/formatIsoShort.test.ts +0 -46
  93. package/lib/kronoFocusRhythm.test.ts +0 -130
  94. package/lib/kronoFocusTimerUrgency.test.ts +0 -74
  95. package/lib/legacyKronoFocusStorageKeys.test.ts +0 -29
  96. package/lib/reportingAggregate.test.ts +0 -325
  97. package/lib/reportingNonFinalIndicators.test.ts +0 -157
  98. package/lib/reportingTagWeekBreakdown.test.ts +0 -141
  99. package/lib/reportingWeekLayout.test.ts +0 -239
  100. package/lib/sessionAssiduity.test.ts +0 -25
  101. package/lib/sessionEndWarnings.test.ts +0 -200
  102. package/lib/sessionListMerge.test.ts +0 -101
  103. package/lib/sessionTaskSidebarStats.test.ts +0 -24
  104. package/lib/taskParsing.test.ts +0 -153
  105. package/lib/usageProfile.test.ts +0 -84
  106. package/server/actionDispatch.test.ts +0 -723
  107. package/server/actionTaskSession.test.ts +0 -713
  108. package/server/kronoFocusHydrate.test.ts +0 -142
  109. package/server/kronoFocusMigrate.test.ts +0 -53
  110. package/server/mainTimerHydrate.test.ts +0 -65
  111. package/server/payloadStore.test.ts +0 -78
  112. package/server/sessionWallHydrate.test.ts +0 -46
@@ -59,6 +59,8 @@ export type DashboardStrings = {
59
59
  launcherTitle: string;
60
60
  taskTrackerTitle: string;
61
61
  taskPlaceholder: string;
62
+ taskNoteLabel: string;
63
+ taskNotePlaceholder: string;
62
64
  /** Champ titre tâche — mode passé / rétroactif (formulation au passé). */
63
65
  taskPlaceholderPast: string;
64
66
  /** Texte d’aide (popover) : tâche rétroactive (début / fin, tags, limites). */
@@ -77,6 +79,14 @@ export type DashboardStrings = {
77
79
  archiveTaskEndLabel: string;
78
80
  /** Libellé court « durée » sur la ligne début / fin d’une tâche terminée. */
79
81
  taskTimingDurationLabel: string;
82
+ taskTimingAdjustModalTitle: string;
83
+ taskTimingAdjustModalMessage: string;
84
+ taskTimingAdjustKeepDuration: string;
85
+ taskTimingAdjustManualDuration: string;
86
+ taskTimingAdjustFromBounds: string;
87
+ taskTimingAdjustHours: string;
88
+ taskTimingAdjustMinutes: string;
89
+ taskTimingAdjustSeconds: string;
80
90
  /** Bouton icône : enregistrer la correction de l'heure de début d'une tâche. */
81
91
  taskStartTimeSaveAria: string;
82
92
  /** Bouton icône : enregistrer la correction de l'heure de début d'une session. */
@@ -105,17 +115,30 @@ export type DashboardStrings = {
105
115
  archiveAddTaskBtn: string;
106
116
  /** Erreur si les dates sont invalides ou si la fin n’est pas après le début. */
107
117
  archiveTaskDatetimeRangeInvalid: string;
118
+ /** Libellé des champs h/m/s — durée du minuteur (entrée passée). */
119
+ archiveTaskTimerDurationLabel: string;
120
+ /** Erreur si la durée manuelle est nulle ou dépasse l’intervalle début → fin. */
121
+ archiveTaskManualDurationInvalid: string;
108
122
  /** Infobulle / aria-label : ligne du titre de la tâche active (clic pour éditer). */
109
123
  activeTaskTitleEditHint: string;
110
124
  /** aria-label du champ d’édition du titre de la tâche active. */
111
125
  activeTaskTitleInputAria: string;
126
+ /** Toast lorsque le démarrage d’une tâche est bloqué par la modale de conflit « planifiée → en cours ». */
127
+ taskStartBlockedByPlannedBoundaryConflict: string;
112
128
  startTaskBtn: string;
129
+ taskSaveTemplateBtn: string;
130
+ taskAlreadyTemplateBtn: string;
131
+ taskTemplateSavedToast: string;
113
132
  finishTaskBtn: string;
114
133
  /** Titre du modal : terminer alors qu’il reste des points de détail ouverts. */
115
134
  finishTaskOpenSubtasksWarnTitle: string;
116
135
  /** Corps du modal : les sous-tâches ouvertes seront toutes marquées terminées. */
117
136
  finishTaskOpenSubtasksWarnBody: string;
118
137
  taskDeleteBtn: string;
138
+ /** Libellé court du bouton copier la tâche vers le formulaire (accessibilité). */
139
+ taskDuplicateBtn: string;
140
+ /** Infobulle : copie titre, étiquettes et projet vers le champ. */
141
+ taskDuplicateTooltip: string;
119
142
  /** Texte complet du modal avant suppression d’une tâche. */
120
143
  taskDeleteConfirm: string;
121
144
  /** Titre du modal : autre tâche avec suivi actif au démarrage. */
@@ -127,23 +150,60 @@ export type DashboardStrings = {
127
150
  taskConcurrentTrackingConflictParallelBtn: string;
128
151
  /** Case à cocher : mémoriser le choix pour les prochains démarrages. */
129
152
  taskConcurrentTrackingDontShowAgain: string;
130
- /** Libellé court à côté de la case (avec icône Git). */
131
- commitOnFinishShort: string;
132
- /** Description complète (infobulle / aria-label de la case). */
133
- commitOnFinishHint: string;
134
- /** aria-label du bouton bascule Git — état inactif. */
135
- commitOnFinishToggleAriaOff: string;
136
- /** aria-label du bouton bascule Git — état actif. */
137
- commitOnFinishToggleAriaOn: string;
153
+ /** Titre du modal : une tâche affichée comme planifiée entre dans la fenêtre « en cours » alors qu’un autre minuteur tournait déjà. */
154
+ taskPlannedBoundaryConflictTitle: string;
155
+ taskPlannedBoundaryConflictMessage: string;
156
+ /** Toast ou message d’erreur si la résolution (pause / terminer) échoue. */
157
+ taskPlannedBoundaryConflictResolveError: string;
158
+ /** Infobulle sur l’icône Tableau de bord lorsque l’app attire l’attention (conflit de minuteurs). */
159
+ navDashboardPlannedConflictPulseHint: string;
138
160
  /** Sous-titre : tâches en pause dans la session. */
139
161
  tasksPausedHeading: string;
140
162
  /** Sous-titre : tâches terminées. */
141
163
  tasksCompletedHeading: string;
142
164
  /** Sous-titre : tâches au minuteur (sous le formulaire d’ajout). */
143
165
  tasksRunningHeading: string;
166
+ /** Sous-titre : tâches dont le début ou la fin est encore dans le futur (affichage seulement). */
167
+ tasksPlannedHeading: string;
168
+ /** Message lorsque la vue Gantt n’a aucune entrée. */
169
+ tasksTimelineEmpty: string;
170
+ /** Bouton ouvrant la modale vue Gantt du fil chronologique. */
171
+ tasksTimelineGanttOpenBtn: string;
172
+ /** aria-label du bouton vue Gantt. */
173
+ tasksTimelineGanttOpenBtnAria: string;
174
+ tasksTimelineGanttTitle: string;
175
+ tasksTimelineGanttDescription: string;
176
+ /** Variante globale : vue Gantt sur toutes les tâches de la journée courante. */
177
+ tasksTimelineGanttTodayTitle: string;
178
+ /** Description de la variante globale « aujourd’hui ». */
179
+ tasksTimelineGanttTodayDescription: string;
180
+ /** Légende : borne gauche de la frise (alignée sur le début de session lorsque connu). */
181
+ tasksTimelineGanttWindowStartLabel: string;
182
+ /** Légende : borne droite de la frise. */
183
+ tasksTimelineGanttWindowEndLabel: string;
184
+ tasksTimelineGanttLegendWork: string;
185
+ tasksTimelineGanttLegendGap: string;
186
+ /** Légende : temps sur projets `@` (productif). */
187
+ tasksTimelineGanttLegendProductive: string;
188
+ /** Légende : temps sur projets `!` (personnel). */
189
+ tasksTimelineGanttLegendPersonal: string;
190
+ /** Résumé Gantt : total productif — placeholder `{duration}`. */
191
+ tasksTimelineGanttSummaryProductive: string;
192
+ /** Résumé Gantt : total personnel — placeholder `{duration}`. */
193
+ tasksTimelineGanttSummaryPersonal: string;
194
+ tasksTimelineGanttCloseBtn: string;
195
+ /** Infobulle segment : libellé début. */
196
+ tasksTimelineGanttTooltipStart: string;
197
+ /** Infobulle segment : libellé fin. */
198
+ tasksTimelineGanttTooltipEnd: string;
199
+ /** Infobulle segment : durée du minuteur (suivi). */
200
+ tasksTimelineGanttTooltipTimer: string;
201
+ /** Infobulle segment : durée murale (écart horloge début → fin). */
202
+ tasksTimelineGanttTooltipWall: string;
203
+ /** Infobulle lorsque la durée minuteur est inconnue. */
204
+ tasksTimelineGanttTooltipTimerUnknown: string;
144
205
  hideTaskList: string;
145
206
  showAllTasks: string;
146
- importGitIssue: string;
147
207
  pauseTaskBtn: string;
148
208
  resumeTaskBtn: string;
149
209
  taskTimerPausedManual: string;
@@ -154,6 +214,14 @@ export type DashboardStrings = {
154
214
  inspectingLabel: string;
155
215
  /** aria-label de la région « consultation d’historique » au-dessus des tâches. */
156
216
  historyInspectBannerAria: string;
217
+ /** aria-label : session live en pause (horloge murale / collecte). */
218
+ liveSessionWallPausedBannerAria: string;
219
+ /** Titre court du bandeau « session en pause » (vue live). */
220
+ liveSessionWallPausedTitle: string;
221
+ /** Détail : comment reprendre (bouton ou lecture sur une tâche). */
222
+ liveSessionWallPausedDetail: string;
223
+ /** Reprendre uniquement la session (horloge murale), sans toucher à la pause globale. */
224
+ liveSessionResumeWallBtn: string;
157
225
  autoTagsDetected: string;
158
226
  /** Ligne de prévisualisation quand un `@projet` est détecté dans le champ de démarrage. */
159
227
  autoProjectDetected: string;
@@ -224,16 +292,6 @@ export type DashboardStrings = {
224
292
  subtaskDurationTooltipNotRecorded: string;
225
293
  subtaskDurationTooltipNotShown: string;
226
294
  noData: string;
227
- selectIssue: string;
228
- /** Titre de la modale d’import d’issue GitLab. */
229
- issuePickerSearchPlaceholder: string;
230
- issuePickerSearchMinHint: string;
231
- issuePickerLoading: string;
232
- issuePickerNoResults: string;
233
- issuePickerCloseAria: string;
234
- /** Erreur si l’action `fetchRemoteIssues` (navigateur → serveur) dépasse le délai. */
235
- issuePickerDashboardRequestTimeout: string;
236
- noIssuesFound: string;
237
295
  sessionsColumnTitle: string;
238
296
  /** `aria-label` du bouton (?) unique à côté du titre Sessions. */
239
297
  sessionsColumnHelpAria: string;
@@ -270,6 +328,12 @@ export type DashboardStrings = {
270
328
  sessionListStartedPrefix: string;
271
329
  /** Liste sessions : préfixe avant l’horodatage de fin (session terminée). */
272
330
  sessionListEndedPrefix: string;
331
+ /** Liste sessions : bouton Gantt par ligne — ouvre la frise pour cette session. */
332
+ sessionListOpenGanttAria: string;
333
+ /** Carte session (barre latérale) : infobulle du bouton-icône fil chronologique. */
334
+ selectedSessionSidebarTimelineIconTooltip: string;
335
+ /** Carte session : aria-label du bouton-icône fil chronologique. */
336
+ selectedSessionSidebarTimelineIconAria: string;
273
337
  /** Terminer la session en cours : enregistrer dans l’historique sans en démarrer une nouvelle. */
274
338
  sessionEndLiveTitle: string;
275
339
  sessionEndLiveAria: string;
@@ -285,6 +349,10 @@ export type DashboardStrings = {
285
349
  sessionEndLiveWarnPausedTasks: string;
286
350
  /** Puce : au moins une sous-tâche non terminée. */
287
351
  sessionEndLiveWarnIncompleteSubtasks: string;
352
+ sessionEndLiveTasksHandlingLegend: string;
353
+ sessionEndLiveTasksHandlingKeep: string;
354
+ sessionEndLiveTasksHandlingFinish: string;
355
+ sessionEndLiveTasksHandlingMoveToPaused: string;
288
356
  /** Bouton confirmer la fin de session (modal avertissement). */
289
357
  sessionEndLiveConfirmBtn: string;
290
358
  /** Bouton rouge sous la carte « session sélectionnée » (session live uniquement). */
@@ -351,10 +419,34 @@ export type DashboardStrings = {
351
419
  taskFocusNoSessionBody: string;
352
420
  /** Toast : création automatique de session au premier envoi d’une tâche depuis la colonne Tâches. */
353
421
  taskStartAutoSessionToast: string;
354
- /** Colonne gauche : bloc nom + stats de la session sélectionnée. */
422
+ /** Colonne gauche : bloc nom + stats de la session sélectionnée (archive / onglet historique). */
355
423
  selectedSessionSidebarTitle: string;
424
+ /** Même bloc lorsque la session affichée est la session live (en cours). */
425
+ selectedSessionSidebarTitleLive: string;
426
+ /** Bloc session : titre lorsqu’aucune session n’est ouverte ni archive consultée (pas de contexte session). */
427
+ selectedSessionSidebarTitleIdle: string;
428
+ /** Badge à côté du titre « session live » lorsque la pause globale est active. */
429
+ selectedSessionSidebarPausedBadgeGlobal: string;
430
+ /** Badge à côté du titre « session live » lorsque la session est en pause collecte sans pause globale. */
431
+ selectedSessionSidebarPausedBadgeSession: string;
432
+ /** Overlay tableau de bord — titre (pause globale). */
433
+ dashboardPauseBackdropTitleGlobal: string;
434
+ dashboardPauseBackdropDetailGlobal: string;
435
+ dashboardPauseBackdropAriaGlobal: string;
436
+ /** Overlay tableau de bord — titre (pause session / murale). */
437
+ dashboardPauseBackdropTitleSession: string;
438
+ dashboardPauseBackdropDetailSession: string;
439
+ dashboardPauseBackdropAriaSession: string;
440
+ sessionNoteLabel: string;
441
+ sessionNotePlaceholder: string;
356
442
  /** Bloc session : message quand aucune session n’est active (pas d’archive inspectée). */
357
443
  selectedSessionIdleHint: string;
444
+ /** Modale — résumé métriques d’une session historique (titre). */
445
+ sessionDetailsModalTitle: string;
446
+ /** Modale — bouton × ou fermeture. */
447
+ sessionDetailsModalCloseAria: string;
448
+ /** Colonne sessions — rouvrir la modale résumé lorsqu’elle est fermée (session historique). */
449
+ sessionDetailsModalReopenBtn: string;
358
450
  /** Aide — durée de session (popover à côté du libellé). */
359
451
  statsMetricSessionDurationHelpAria: string;
360
452
  statsMetricSessionDurationHelpBody: string;
@@ -373,6 +465,8 @@ export type DashboardStrings = {
373
465
  statsTasksRowPausedList: string;
374
466
  /** Ligne courte : tâches terminées. */
375
467
  statsTasksRowCompleted: string;
468
+ /** Ligne courte : tâches planifiées (début ou fin futur). */
469
+ statsTasksRowPlanned: string;
376
470
  /** Carte dépôt Git du workspace (branches, commits, graphe, fichiers suivis). */
377
471
  gitRepoCardTitle: string;
378
472
  gitRepoNotARepo: string;
@@ -469,6 +563,11 @@ export type DashboardStrings = {
469
563
  headerClockFormat24Short: string;
470
564
  /** Libellé court format 12 h (ligne d’en-tête). */
471
565
  headerClockFormat12Short: string;
566
+ /**
567
+ * aria-label / title de l’horloge murale dans la barre d’outils.
568
+ * Placeholders : `{timeZone}`, `{datetime}` (date et heure longues dans le fuseau).
569
+ */
570
+ headerWallClockAriaLabel: string;
472
571
  /** Bannière : aucun auteur Git enregistré (tableau de bord web local). */
473
572
  gitIdentityBannerAria: string;
474
573
  gitIdentityBannerBody: string;
@@ -516,6 +615,10 @@ export type DashboardStrings = {
516
615
  dataSearchKindSession: string;
517
616
  /** Sous-titre d’une ligne tâche dans la palette. */
518
617
  dataSearchKindTask: string;
618
+ /** Sous-titre d’une ligne modèle de tâche dans la palette. */
619
+ dataSearchKindTaskTemplate: string;
620
+ /** Préfixe affiché devant une suggestion de modèle (datalist du champ nouvelle tâche). */
621
+ taskTemplateDatalistPrefix: string;
519
622
  /**
520
623
  * Deux tâches au même titre : afficher l’id pour les distinguer. Placeholder : `{id}`.
521
624
  * Ex. « ID: {id} » — l’id est en tête de la ligne de détail pour rester visible à l’écran.
@@ -619,6 +722,14 @@ export type DashboardStrings = {
619
722
  newSessionModalHelpAria: string;
620
723
  /** Popover : durée max, période calendaire, jours / horaires (comportement des rappels). */
621
724
  newSessionModalHelpBody: string;
725
+ newSessionTimingSectionTitle: string;
726
+ newSessionTimingImmediate: string;
727
+ newSessionTimingPast: string;
728
+ newSessionPastStartLabel: string;
729
+ newSessionPastStartHint: string;
730
+ newSessionPastEndLabel: string;
731
+ newSessionPastEndHint: string;
732
+ newSessionScopeFieldsetLegend: string;
622
733
  newSessionModeNone: string;
623
734
  newSessionModeMax: string;
624
735
  newSessionModeCalendar: string;
@@ -635,12 +746,72 @@ export type DashboardStrings = {
635
746
  newSessionErrorMax: string;
636
747
  newSessionErrorCalendar: string;
637
748
  newSessionErrorWeekly: string;
749
+ newSessionErrorPastMissing: string;
750
+ newSessionErrorPastEndMissing: string;
751
+ newSessionErrorPastEndBeforeStart: string;
752
+ newSessionErrorPastEndFuture: string;
753
+ newSessionErrorPastFuture: string;
754
+ newSessionErrorPastInvalid: string;
638
755
  newSessionStartBtn: string;
639
756
  newSessionCancelBtn: string;
640
757
  /** Bannière d’alerte portée de session (rôle status). */
641
758
  sessionScopeNoticeAria: string;
642
759
  /** `aria-label` du `<nav>` des raccourcis tableau de bord / rapports / paramètres (icônes). */
643
760
  appShellRouteNavAria: string;
761
+ /** Bouton de la barre de navigation : ouvre la vue Gantt globale (journée courante). */
762
+ appShellRouteNavTodayGantt: string;
763
+ /** Libellé du bouton de pause globale (session + tâches + sous-tâches). */
764
+ appShellRouteNavGlobalPause: string;
765
+ /** Libellé du bouton de reprise globale (uniquement ce qui a été mis en pause globalement). */
766
+ appShellRouteNavGlobalResume: string;
767
+ /** Infobulle lorsque la pause globale est inactive (rien ne tourne). */
768
+ appShellRouteNavGlobalPauseDisabledTooltip: string;
769
+ /** Modale — titre avant d’activer la pause globale. */
770
+ globalPauseConfirmTitle: string;
771
+ /** Modale — texte d’introduction (comportement + liste à suivre). */
772
+ globalPauseConfirmIntro: string;
773
+ /** Modale — sous-titre bloc session. */
774
+ globalPauseConfirmSessionHeading: string;
775
+ /** Modale — sous-titre résumé (chiffres) sous le nom de session. */
776
+ globalPauseConfirmSummaryHeading: string;
777
+ /** Modale — libellé début de session. */
778
+ globalPauseConfirmSummaryStart: string;
779
+ /** Modale — libellé fin de session. */
780
+ globalPauseConfirmSummaryEnd: string;
781
+ /** Modale — session sans `endAt` (live). */
782
+ globalPauseConfirmSummaryEndOngoing: string;
783
+ /** Modale — libellé durée murale. */
784
+ globalPauseConfirmSummaryWallDuration: string;
785
+ /** Modale — libellé nombre de tâches. */
786
+ globalPauseConfirmSummaryTasks: string;
787
+ /** Modale — libellé nombre de sous-tâches. */
788
+ globalPauseConfirmSummarySubtasks: string;
789
+ /** Modale — libellé temps minuteur principal (hors sous-tâches). */
790
+ globalPauseConfirmSummaryMainTimer: string;
791
+ /** Modale — libellé temps minuteurs sous-tâches. */
792
+ globalPauseConfirmSummarySubtaskTimers: string;
793
+ /** Modale — temps de codage IDE agrégé sur la session (minutes). */
794
+ globalPauseConfirmSummaryCodingSession: string;
795
+ /** Modale — temps actif IDE agrégé sur la session (minutes). */
796
+ globalPauseConfirmSummaryActiveSession: string;
797
+ /** Modale — somme des temps minuteurs tâches (total enregistré). */
798
+ globalPauseConfirmSummaryTaskTimersTotal: string;
799
+ /** Modale — instant inconnu (début non renseigné). */
800
+ globalPauseConfirmSummaryUnknownInstant: string;
801
+ /** Modale — murale pas encore en pause. */
802
+ globalPauseConfirmSessionWallWillPause: string;
803
+ /** Modale — murale déjà en pause. */
804
+ globalPauseConfirmSessionWallAlreadyPaused: string;
805
+ /** Modale — sous-titre liste des tâches. */
806
+ globalPauseConfirmTasksHeading: string;
807
+ /** Modale — aucun effet sur les minuteurs de tâche (état déjà figé). */
808
+ globalPauseConfirmNoTaskEffects: string;
809
+ /** Modale — puce minuteur principal. */
810
+ globalPauseConfirmEffectMainTimer: string;
811
+ /** Modale — puce sous-tâche ; remplacer `{title}`. */
812
+ globalPauseConfirmEffectSubtaskStop: string;
813
+ /** Modale — bouton confirmer la pause globale. */
814
+ globalPauseConfirmConfirmBtn: string;
644
815
  /** `aria-label` du panneau d’activité live (hors tableau de bord). */
645
816
  appShellLiveDrawerAria: string;
646
817
  /** Titre du panneau d’activité live. */
@@ -734,9 +905,11 @@ const en: DashboardStrings = {
734
905
  launcherTitle: "Tasks",
735
906
  taskTrackerTitle: "In focus",
736
907
  taskPlaceholder: "What are you working on?",
908
+ taskNoteLabel: "Task note",
909
+ taskNotePlaceholder: "Add a free-form note for this task…",
737
910
  taskPlaceholderPast: "What did you work on?",
738
911
  archiveAddTaskIntro:
739
- "Past entry: set start and end. Tags and @project work as usual; timers and detail items do not apply — live or archived session.",
912
+ "Past entry: set start, end, and timer duration (h/m/s, same idea as duration adjustments). Tags and @project work as usual; live timers and detail items do not apply — live or archived session.",
740
913
  archiveAddTaskIntroHelpAria: "Help: past entry",
741
914
  taskEntryModeRealtime: "Real-time",
742
915
  taskEntryModePast: "Past",
@@ -744,6 +917,14 @@ const en: DashboardStrings = {
744
917
  archiveTaskStartLabel: "Start",
745
918
  archiveTaskEndLabel: "End",
746
919
  taskTimingDurationLabel: "Duration",
920
+ taskTimingAdjustModalTitle: "Adjust duration?",
921
+ taskTimingAdjustModalMessage: "You changed task timing. Choose how duration should be recalculated.",
922
+ taskTimingAdjustKeepDuration: "Keep the recorded timer duration",
923
+ taskTimingAdjustManualDuration: "Set duration manually (h/m/s)",
924
+ taskTimingAdjustFromBounds: "Set duration from start/end timestamps",
925
+ taskTimingAdjustHours: "Hours",
926
+ taskTimingAdjustMinutes: "Minutes",
927
+ taskTimingAdjustSeconds: "Seconds",
747
928
  taskStartTimeSaveAria: "Save corrected task start time",
748
929
  sessionStartTimeSaveAria: "Save corrected session start time",
749
930
  taskEndTimeSaveAria: "Save corrected task end time",
@@ -759,14 +940,24 @@ const en: DashboardStrings = {
759
940
  archiveAddTaskBtn: "Add to session",
760
941
  archiveTaskDatetimeRangeInvalid:
761
942
  "Enter a valid start and end; the end must be after the start (local date and time).",
943
+ archiveTaskTimerDurationLabel: "Timer duration",
944
+ archiveTaskManualDurationInvalid:
945
+ "Enter a timer duration greater than zero and no longer than the gap between start and end.",
762
946
  activeTaskTitleEditHint: "Click to edit title; type #tags in the field or use the row below",
763
947
  activeTaskTitleInputAria: "Edit title; optional #tags or @project in the field, pills below for existing tags",
948
+ taskStartBlockedByPlannedBoundaryConflict:
949
+ "Close the planned-task timer dialog first, then start another task.",
764
950
  startTaskBtn: "Start tracking",
951
+ taskSaveTemplateBtn: "Save as template",
952
+ taskAlreadyTemplateBtn: "Already saved as template",
953
+ taskTemplateSavedToast: "Task template saved.",
765
954
  finishTaskBtn: "Finish",
766
955
  finishTaskOpenSubtasksWarnTitle: "Finish task?",
767
956
  finishTaskOpenSubtasksWarnBody:
768
957
  "This task still has open detail items. They will all be marked done when you finish the task.",
769
958
  taskDeleteBtn: "Delete",
959
+ taskDuplicateBtn: "Copy task to input",
960
+ taskDuplicateTooltip: "Copy title, tags, and project to the input field.",
770
961
  taskDeleteConfirm:
771
962
  "Delete this entry? Recorded time will be lost. This cannot be undone.",
772
963
  taskConcurrentTrackingConflictTitle: "Tracking already active",
@@ -777,18 +968,42 @@ const en: DashboardStrings = {
777
968
  taskConcurrentTrackingConflictParallelBtn: "Start in parallel (keep timers running)",
778
969
  taskConcurrentTrackingDontShowAgain:
779
970
  "Remember this choice and don’t show this dialog again (the same action will run automatically next time).",
780
- commitOnFinishShort: "Git commit",
781
- commitOnFinishHint: "Build Git commit message when finishing",
782
- commitOnFinishToggleAriaOff:
783
- "Offer a Git commit message when finishing — off. Press to turn on.",
784
- commitOnFinishToggleAriaOn:
785
- "Offer a Git commit message when finishing — on. Press to turn off.",
971
+ taskPlannedBoundaryConflictTitle: "Planned task is now live",
972
+ taskPlannedBoundaryConflictMessage:
973
+ "A task that was shown under Planned has reached its start time and now counts as running while another timer was already running. Choose what to do with the tasks that were already running: pause them (they move to the paused list), finish them (they move to completed), or keep them running alongside the new one.",
974
+ taskPlannedBoundaryConflictResolveError:
975
+ "Could not apply your choice for the running timers. Check the server and try again.",
976
+ navDashboardPlannedConflictPulseHint:
977
+ "Dashboard: review the timer conflict dialog",
786
978
  tasksPausedHeading: "Paused",
787
979
  tasksCompletedHeading: "Completed",
788
980
  tasksRunningHeading: "Running now",
981
+ tasksPlannedHeading: "Planned",
982
+ tasksTimelineEmpty: "No timed task intervals in this session view.",
983
+ tasksTimelineGanttOpenBtn: "Gantt",
984
+ tasksTimelineGanttOpenBtnAria: "Open task timeline as a Gantt-style chart",
985
+ tasksTimelineGanttTitle: "Task timeline (Gantt)",
986
+ tasksTimelineGanttDescription:
987
+ "Timeline aligned on the session start: one row per task; coloured bars are tracked timer intervals. Scroll horizontally when the session spans a long wall-clock range.",
988
+ tasksTimelineGanttTodayTitle: "Today timeline (Gantt)",
989
+ tasksTimelineGanttTodayDescription:
990
+ "Global timeline for the current day: all task intervals across sessions are grouped in one view.",
991
+ tasksTimelineGanttWindowStartLabel: "Timeline start",
992
+ tasksTimelineGanttWindowEndLabel: "Timeline end",
993
+ tasksTimelineGanttLegendWork: "Tracked time",
994
+ tasksTimelineGanttLegendGap: "Outside this task’s interval",
995
+ tasksTimelineGanttLegendProductive: "Productive (@ projects)",
996
+ tasksTimelineGanttLegendPersonal: "Personal (! projects)",
997
+ tasksTimelineGanttSummaryProductive: "Productive total: {duration}",
998
+ tasksTimelineGanttSummaryPersonal: "Personal total: {duration}",
999
+ tasksTimelineGanttCloseBtn: "Close",
1000
+ tasksTimelineGanttTooltipStart: "Start",
1001
+ tasksTimelineGanttTooltipEnd: "End",
1002
+ tasksTimelineGanttTooltipTimer: "Timer duration",
1003
+ tasksTimelineGanttTooltipWall: "Wall-clock span",
1004
+ tasksTimelineGanttTooltipTimerUnknown: "—",
789
1005
  hideTaskList: "Hide list",
790
1006
  showAllTasks: "Show full list",
791
- importGitIssue: "Import issue from Git",
792
1007
  pauseTaskBtn: "Pause — moves to the paused list",
793
1008
  resumeTaskBtn: "Resume tracking",
794
1009
  taskTimerPausedManual: "Timer paused (manual).",
@@ -797,6 +1012,11 @@ const en: DashboardStrings = {
797
1012
  resumeBtn: "Resume active session",
798
1013
  inspectingLabel: "Viewing session:",
799
1014
  historyInspectBannerAria: "Past session view",
1015
+ liveSessionWallPausedBannerAria: "Live session paused",
1016
+ liveSessionWallPausedTitle: "Session tracking is paused",
1017
+ liveSessionWallPausedDetail:
1018
+ "Wall-clock time is frozen. Use Resume below or press play on a task — both restart session tracking.",
1019
+ liveSessionResumeWallBtn: "Resume session",
800
1020
  autoTagsDetected: "Tags detected",
801
1021
  autoProjectDetected: "Project",
802
1022
  tagsHelpAriaLabel: "Tag help",
@@ -858,17 +1078,6 @@ const en: DashboardStrings = {
858
1078
  subtaskDurationTooltipNotShown:
859
1079
  "No duration is shown for completed items without recorded time in this archived view.",
860
1080
  noData: "No data yet.",
861
- selectIssue: "Search a GitLab issue",
862
- issuePickerSearchPlaceholder: "Title, description, or internal issue number (e.g. 12 or #12)…",
863
- issuePickerSearchMinHint:
864
- "Use at least 2 letters for a text search on GitLab. For an internal issue number only, one digit is enough (e.g. 7 or #7).",
865
- issuePickerLoading: "Searching…",
866
- issuePickerNoResults:
867
- "No issues match. Try a few letters from the title or description, or search by internal number only (e.g. 42).",
868
- issuePickerCloseAria: "Close",
869
- issuePickerDashboardRequestTimeout:
870
- "Timed out waiting for the dashboard server (GitLab search). Check that the server is running, your instance URL, then try again.",
871
- noIssuesFound: "No open issues or CLI not configured.",
872
1081
  sessionsColumnTitle: "Sessions",
873
1082
  sessionsColumnHelpAria: "Help: Sessions column",
874
1083
  sessionsColumnHelpBody:
@@ -891,6 +1100,10 @@ const en: DashboardStrings = {
891
1100
  "At or past the alert threshold ({hours} h) — adjust under Settings → Web dashboard.",
892
1101
  sessionListStartedPrefix: "Start:",
893
1102
  sessionListEndedPrefix: "End:",
1103
+ sessionListOpenGanttAria: "Open Gantt timeline for this session",
1104
+ selectedSessionSidebarTimelineIconTooltip: "Gantt",
1105
+ selectedSessionSidebarTimelineIconAria:
1106
+ "Open the horizontal task timeline for this session",
894
1107
  sessionEndLiveTitle: "End session — save to history without starting a new one (tracking can stay on)",
895
1108
  sessionEndLiveAria: "End current session",
896
1109
  sessionEndLiveConfirmTitle: "End this session?",
@@ -901,6 +1114,12 @@ const en: DashboardStrings = {
901
1114
  sessionEndLiveWarnActiveTask: "Something is currently being tracked (in progress).",
902
1115
  sessionEndLiveWarnPausedTasks: "One or more entries are paused or not finished.",
903
1116
  sessionEndLiveWarnIncompleteSubtasks: "One or more items are not marked done.",
1117
+ sessionEndLiveTasksHandlingLegend: "When ending, what should happen to open tasks?",
1118
+ sessionEndLiveTasksHandlingKeep:
1119
+ "Leave tasks unfinished in this session’s snapshot — timers stop (recorded time is kept)",
1120
+ sessionEndLiveTasksHandlingFinish: "Finish open tasks with this session",
1121
+ sessionEndLiveTasksHandlingMoveToPaused:
1122
+ "Move open tasks to a new paused session",
904
1123
  sessionEndLiveConfirmBtn: "End session",
905
1124
  sessionEndLiveSidebarBtn: "End this session",
906
1125
  sessionEndReasonModalHint:
@@ -934,7 +1153,8 @@ const en: DashboardStrings = {
934
1153
  tagsProjectsColumnHelpAria: "Help: tags & projects column",
935
1154
  tagsProjectsColumnHelpBody:
936
1155
  "Global tags apply to any task. Project-linked tags use Project#code and only appear when that task’s @project matches.\n\nIn this column, the Global tags tab lists shortcuts, hidden tags, and descriptions; the Projects & linked tags tab lists saved projects and per-project codes.\n\nThis column mirrors the Tags & saved projects section in Settings; changes sync immediately.\n\nUse the (?) next to task tags on a card for the full help and use cases.",
937
- tasksColumnSubtitle: "In progress, paused, and completed for the selected session.",
1156
+ tasksColumnSubtitle:
1157
+ "Running, planned (future start or end), paused, and completed for the selected session.",
938
1158
  tasksColumnSubtitleHelpAria: "Help: what this column shows",
939
1159
  taskFocusNoSessionTitle: "No active session",
940
1160
  taskFocusNoSessionBody:
@@ -942,8 +1162,25 @@ const en: DashboardStrings = {
942
1162
  taskStartAutoSessionToast:
943
1163
  "No active session — starting one now so your task can be tracked in this session.",
944
1164
  selectedSessionSidebarTitle: "Selected session",
1165
+ selectedSessionSidebarTitleLive: "Active session",
1166
+ selectedSessionSidebarTitleIdle: "No active session",
1167
+ selectedSessionSidebarPausedBadgeGlobal: "Global pause",
1168
+ selectedSessionSidebarPausedBadgeSession: "Paused",
1169
+ dashboardPauseBackdropTitleGlobal: "Global pause is on",
1170
+ dashboardPauseBackdropDetailGlobal:
1171
+ "Tracking is frozen for this session, tasks, and subtasks. Resume from the global pause control in the top bar.",
1172
+ dashboardPauseBackdropAriaGlobal: "Dashboard: global pause is active",
1173
+ dashboardPauseBackdropTitleSession: "Session tracking is paused",
1174
+ dashboardPauseBackdropDetailSession:
1175
+ "Wall-clock time and affected timers are frozen. Resume from the banner above Tasks or the usual resume control.",
1176
+ dashboardPauseBackdropAriaSession: "Dashboard: session wall-clock pause is active",
1177
+ sessionNoteLabel: "Session note",
1178
+ sessionNotePlaceholder: "Add a free-form note for this session…",
945
1179
  selectedSessionIdleHint:
946
- "No session is active. Start one to record time, tracking, and metrics.",
1180
+ "Start a session from the Sessions column to record time, tracking, and metrics.",
1181
+ sessionDetailsModalTitle: "Session summary",
1182
+ sessionDetailsModalCloseAria: "Close session summary",
1183
+ sessionDetailsModalReopenBtn: "Session summary",
947
1184
  statsMetricSessionDurationHelpAria: "Help: session duration",
948
1185
  statsMetricSessionDurationHelpBody:
949
1186
  "Wall-clock time from the first activity event recorded in this session until now (live session) or until the snapshot was saved (archived). Separate from active time, coding time, and tracking or item timers.",
@@ -955,10 +1192,11 @@ const en: DashboardStrings = {
955
1192
  "Time accumulated from workstation activity: edits, file open, selection changes, active editor changes, and window focus. Gaps longer than about three minutes are not counted. Often between coding time and session wall-clock.",
956
1193
  statsMetricTasksHelpAria: "Help: task counts by status",
957
1194
  statsMetricTasksHelpBody:
958
- "For the selected session: tasks with the tracking timer running (“Running now”), tasks not marked done in the task list (“Paused”), and completed tasks. Matches the three sections in the Tasks column.",
1195
+ "For the selected session: tasks with the tracking timer running (“Running now”), tasks whose start or end is still in the future (“Planned”), other tasks not marked done (“Paused”), and completed tasks whose end is not in the future. Matches the sections in the Tasks column.",
959
1196
  statsTasksRowRunning: "Running (timer)",
960
1197
  statsTasksRowPausedList: "Not done (list)",
961
1198
  statsTasksRowCompleted: "Completed",
1199
+ statsTasksRowPlanned: "Planned (future)",
962
1200
  gitRepoCardTitle: "Workspace Git repository",
963
1201
  gitRepoNotARepo: "The first workspace folder is not a Git checkout (or Git is unavailable).",
964
1202
  gitRepoCardHelpAria: "Help: workspace Git overview",
@@ -1050,6 +1288,8 @@ const en: DashboardStrings = {
1050
1288
  headerDisplayRegionTitle: "Display time zone {timeZone}; clock {clock}.",
1051
1289
  headerClockFormat24Short: "24 h",
1052
1290
  headerClockFormat12Short: "12 h (AM/PM)",
1291
+ headerWallClockAriaLabel:
1292
+ "Wall clock in display time zone {timeZone}: {datetime}.",
1053
1293
  gitIdentityBannerAria: "Git author not configured",
1054
1294
  gitIdentityBannerBody:
1055
1295
  "Set the Git author (name, email, optional forge username) for the line under the dashboard title. Use Set up here to enter them in a quick dialog — values stay local; you can change them anytime under Settings → Git identity.",
@@ -1082,16 +1322,18 @@ const en: DashboardStrings = {
1082
1322
  sessionMongoPushFailedUri: "MongoDB connection is incomplete (URI or password).",
1083
1323
  dashboardLoadingAriaLabel: "Loading dashboard, please wait",
1084
1324
  dashboardLoadingMessage: "Fetching session data from the Kronosys server…",
1085
- dataSearchTrigger: "Search data…",
1325
+ dataSearchTrigger: "Spotlight…",
1086
1326
  dataSearchPlaceholder:
1087
- "Filter sessions, tasks, projects, tags, dates, or duration (e.g. 12:55 <, 0:10 >)…",
1088
- dataSearchPaletteAriaLabel: "Quick search",
1327
+ "Filter sessions, tasks, templates, projects, tags, dates, or duration (e.g. 12:55 <, 0:10 >)…",
1328
+ dataSearchPaletteAriaLabel: "Spotlight search",
1089
1329
  dataSearchTypePrompt:
1090
- "Type to filter sessions, tasks, projects, and tags in this workspace. You can also use a calendar day or a full timestamp (e.g. 2026-01-15 14:30:00) or a recorded duration condition: minutes:seconds (or h:m:s) with < or >, e.g. 45:00 > or 1:0:0 <.",
1091
- dataSearchEmpty: "No matching sessions or tasks.",
1330
+ "Type to filter sessions, tasks, saved task templates, projects, and tags in this workspace. You can also use a calendar day or a full timestamp (e.g. 2026-01-15 14:30:00) or a recorded duration condition: minutes:seconds (or h:m:s) with < or >, e.g. 45:00 > or 1:0:0 <. Choosing a template fills the task draft.",
1331
+ dataSearchEmpty: "No matching sessions, tasks, or templates.",
1092
1332
  dataSearchFooter: "↑↓ to move · Enter to open · Esc to close",
1093
1333
  dataSearchKindSession: "Session",
1094
1334
  dataSearchKindTask: "Task",
1335
+ dataSearchKindTaskTemplate: "Task template",
1336
+ taskTemplateDatalistPrefix: "Template:",
1095
1337
  dataSearchTaskDistinguishId: "ID: {id}",
1096
1338
  dataSearchTaskStopwatchLabel: "Timer",
1097
1339
  dataSearchTaskRecordedTimeLabel: "Logged",
@@ -1117,7 +1359,7 @@ const en: DashboardStrings = {
1117
1359
  shortcutsChangeBtn: "Change…",
1118
1360
  shortcutsRecordPrompt: "Press keys…",
1119
1361
  shortcutsResetAll: "Reset all to defaults",
1120
- shortcutsPaletteRow: "Quick data search — Ctrl+K or ⌘K (fixed)",
1362
+ shortcutsPaletteRow: "Spotlight search — Ctrl+K or ⌘K (fixed)",
1121
1363
  tourProgressLabel: "Step {n} of {total}",
1122
1364
  tourStep1Title: "Welcome to the Kronosys dashboard",
1123
1365
  tourStep1Body:
@@ -1130,13 +1372,13 @@ const en: DashboardStrings = {
1130
1372
  "Browse your session history, start a new session, and inspect the selected session’s duration, coding time, and stats.\n\nWhen a live session is open, you can end it from here; archived sessions open in read-only mode.\n\nFor advanced timing, open Settings (gear): under Dashboard & API, set the **session duration alert** (when a long wall-clock session is highlighted in this column). The **Work schedule** section starts and stops tracking on your weekday hours, and **Specific planned sessions** define recurring blocks that override the general schedule during their time window.",
1131
1373
  tourStep4Title: "Tasks & focus (center)",
1132
1374
  tourStep4Body:
1133
- "Track what you are working on, finish tasks, and use subtasks or Git-linked options when you need them.\n\nThis column follows the session you select in the Sessions column — the rest of the header aligns with that choice.\n\nYou only track one work stream at a time on other parents: starting subtask time on a task also runs that parent’s main stopwatch, and it stops time on other tasks (their segments are saved). If you pause the main stopwatch, any subtask segment in progress on the same task stops and records time. Resuming a parent’s main stopwatch anywhere ends subtask timers on the other tasks and pauses their main stopwatches.\n\nDetail items are optional. The task’s total time is always at least the sum of time on those items; the rest is work recorded on the task without a per-item breakdown.",
1375
+ "Track what you are working on, finish tasks, and use subtasks or Git-linked options when you need them.\n\nThis column follows the session you select in the Sessions column — the rest of the header aligns with that choice.\n\nYou only track one work stream at a time on other parents: starting subtask time on a task also runs that parent’s main stopwatch, and it stops time on other tasks (their segments are saved). If you pause the main stopwatch, any subtask segment in progress on the same task stops and records time. Resuming a parent’s main stopwatch anywhere ends subtask timers on the other tasks and pauses their main stopwatches.\n\nDetail items are optional. The task’s total time is always at least the sum of time on those items; the rest is work recorded on the task without a per-item breakdown.\n\nOn a running, paused, or completed task, **Save as template** stores its title, #tags, and @project so you can reuse them later — the new-task field suggests them with a **Template:** prefix and the Ctrl+K / ⌘K palette lists them too. You can also **adjust task time bounds** by keeping the recorded duration, entering a manual h/m/s value, or recalculating from start and end.",
1134
1376
  tourStep5Title: "Tags & projects (right)",
1135
1377
  tourStep5Body:
1136
1378
  "Pin tags, manage saved projects, and add descriptions — the same controls as in Settings, available while you work. Two tabs separate global tags from projects and project-linked tags.\n\nIn task titles you can use @project and #tags (including @project#code) to organise work across projects.\n\nReporting (charts) depends heavily on these objects: consistent tags and projects make breakdowns, filters, and trends in Reporting far more meaningful.",
1137
1379
  tourStep6Title: "Top toolbar: every icon",
1138
1380
  tourStep6Body:
1139
- "From left to right in this cluster: quick data search / command palette (same as Ctrl+K or ⌘K), the keyboard icon for shortcut help and custom bindings, navigation icons to Reporting (charts) and Settings (gear), the light/dark theme toggle, refresh data from the API without reloading the whole browser tab, and the language menu (FR / EN).\n\nEach icon has a tooltip on hover; Reporting and Settings open other pages while keeping the same Kronosys shell.",
1381
+ "From left to right in this cluster: quick data search / command palette (same as Ctrl+K or ⌘K — sessions, tasks, **task templates**, projects, and tags), the keyboard icon for shortcut help and custom bindings, route icons for Dashboard, Reporting (charts), Settings (gear), User Guide (book), and **Implementation** (code file — exhaustive ✓ / ✗ list of user stories), the **Today Gantt** button (task intervals across all sessions of the current day), the **global pause** toggle, the light/dark theme toggle, refresh data from the API without reloading the whole browser tab, and the language menu (FR / EN).\n\nThe global pause stays inactive when nothing is running. Otherwise it opens a confirmation modal with a summary (start, end or *ongoing*, wall duration, coding/active session times when the host records them, task and subtask counts, total recorded task-timer time, plus the split between main task time and subtask timers) before pausing the session, its tasks, and any active subtasks; the next click resumes only that paused set.\n\nEach control has a tooltip on hover; route icons keep you in the same Kronosys shell.",
1140
1382
  tourStep7Title: "Your Git identity & storage badge",
1141
1383
  tourStep7Body:
1142
1384
  "This area shows your Git author line and forge account when they are configured in Settings → Git identity, the workspace roots detected for metrics, and a small badge for how session data is stored here: SQLite (default), JSON driver, or MongoDB mirror when enabled.\n\nSQLite keeps the dashboard payload on this machine under your Kronosys data directory; this page reads and writes it through the local API.",
@@ -1197,9 +1439,19 @@ const en: DashboardStrings = {
1197
1439
  reportingTourStep6Body:
1198
1440
  "This block is the main Reporting layout: your content on the left and, on wide screens, a sticky jump list on the right. On phones, the same anchors appear as chips above the filters.",
1199
1441
  newSessionModalTitle: "New session — scope",
1200
- newSessionModalHelpAria: "Help: session scope (duration, dates, weekdays)",
1442
+ newSessionModalHelpAria: "Help: session start and scope (duration, dates, weekdays)",
1201
1443
  newSessionModalHelpBody:
1202
- "These options set expectations for this session only. They do not stop Kronosys automatically: you get reminders from the collector (heartbeat) and a banner here when you are close to or outside the limits.\n\n• Maximum wall-clock duration — counted from the first tracked event in the session.\n\n• Calendar period — local dates inclusive (start and/or end).\n\n• Weekdays — restrict to selected days; you can add a daily time window (local 24 h). Overnight windows are supported (e.g. 22:00–06:00).",
1444
+ "Choose whether the session starts now or fully in the past. For a past session, enter **both** start and end (local browser time); that closed interval is stored on the history row. Starting now while a session is already live opens the end-session dialog first; a backdated row leaves the current session running and adds a history row you can switch to. Then these scope options set expectations for this session only. They do not stop Kronosys automatically: you get reminders from the collector (heartbeat) and a banner here when you are close to or outside the limits.\n\n• Maximum wall-clock duration — counted from the first tracked event in the session.\n\n• Calendar period — local dates inclusive (start and/or end).\n\n• Weekdays — restrict to selected days; you can add a daily time window (local 24 h). Overnight windows are supported (e.g. 22:00–06:00).",
1445
+ newSessionTimingSectionTitle: "Session start",
1446
+ newSessionTimingImmediate: "Now (start immediately)",
1447
+ newSessionTimingPast: "In the past (backdated start)",
1448
+ newSessionPastStartLabel: "Session started at (local)",
1449
+ newSessionPastStartHint:
1450
+ "Uses your browser’s local timezone. The session wall clock starts from this instant; you can still add tasks and adjust times afterward.",
1451
+ newSessionPastEndLabel: "Session ended at (local)",
1452
+ newSessionPastEndHint:
1453
+ "Must be after the start time and not in the future. Together with the start, this defines the closed interval for this history row.",
1454
+ newSessionScopeFieldsetLegend: "Scope (reminders)",
1203
1455
  newSessionModeNone: "No limit",
1204
1456
  newSessionModeMax: "Maximum wall-clock duration",
1205
1457
  newSessionModeCalendar: "Calendar period (dates)",
@@ -1216,10 +1468,45 @@ const en: DashboardStrings = {
1216
1468
  newSessionErrorMax: "Enter a maximum duration between 0.1 and 8760 hours.",
1217
1469
  newSessionErrorCalendar: "Choose at least one date (from and/or to).",
1218
1470
  newSessionErrorWeekly: "Select at least one weekday.",
1471
+ newSessionErrorPastMissing: "Enter the start date and time for a backdated session.",
1472
+ newSessionErrorPastEndMissing: "Enter the end date and time for a backdated session.",
1473
+ newSessionErrorPastEndBeforeStart: "The end must be strictly after the start.",
1474
+ newSessionErrorPastEndFuture: "The end date and time cannot be in the future.",
1475
+ newSessionErrorPastFuture: "Pick a date and time in the past or now (not in the future).",
1476
+ newSessionErrorPastInvalid: "Unrecognized date or time.",
1219
1477
  newSessionStartBtn: "Start session",
1220
1478
  newSessionCancelBtn: "Cancel",
1221
1479
  sessionScopeNoticeAria: "Session scope reminder",
1222
1480
  appShellRouteNavAria: "Main sections",
1481
+ appShellRouteNavTodayGantt: "Open today timeline (Gantt)",
1482
+ appShellRouteNavGlobalPause: "Pause session, tasks, and subtasks in this context",
1483
+ appShellRouteNavGlobalResume: "Resume everything paused by global pause in this context",
1484
+ appShellRouteNavGlobalPauseDisabledTooltip:
1485
+ "Nothing is active to pause: the session wall clock is already paused and no task or subtask timer is running.",
1486
+ globalPauseConfirmTitle: "Global pause",
1487
+ globalPauseConfirmIntro:
1488
+ "Global pause freezes the session wall clock when it is running, pauses each task timer that is not already paused, and stops any active subtask timer (recording elapsed time). The next click on this control resumes only what was paused in this operation.\n\nReview what will be affected:",
1489
+ globalPauseConfirmSessionHeading: "Session",
1490
+ globalPauseConfirmSummaryHeading: "Summary",
1491
+ globalPauseConfirmSummaryStart: "Start",
1492
+ globalPauseConfirmSummaryEnd: "End",
1493
+ globalPauseConfirmSummaryEndOngoing: "Ongoing (no end yet)",
1494
+ globalPauseConfirmSummaryWallDuration: "Wall duration",
1495
+ globalPauseConfirmSummaryTasks: "Tasks",
1496
+ globalPauseConfirmSummarySubtasks: "Subtasks",
1497
+ globalPauseConfirmSummaryMainTimer: "Task timers (excl. subtasks)",
1498
+ globalPauseConfirmSummarySubtaskTimers: "Subtask timers",
1499
+ globalPauseConfirmSummaryCodingSession: "Session coding time",
1500
+ globalPauseConfirmSummaryActiveSession: "Session active time",
1501
+ globalPauseConfirmSummaryTaskTimersTotal: "Total recorded (task timers)",
1502
+ globalPauseConfirmSummaryUnknownInstant: "—",
1503
+ globalPauseConfirmSessionWallWillPause: "Wall-clock time for this session will pause.",
1504
+ globalPauseConfirmSessionWallAlreadyPaused: "The session wall clock is already paused; it stays frozen.",
1505
+ globalPauseConfirmTasksHeading: "Tasks and subtasks",
1506
+ globalPauseConfirmNoTaskEffects: "No task or subtask timers need freezing in the current state.",
1507
+ globalPauseConfirmEffectMainTimer: "Main task timer will pause.",
1508
+ globalPauseConfirmEffectSubtaskStop: "Subtask timer stops — « {title} ».",
1509
+ globalPauseConfirmConfirmBtn: "Pause now",
1223
1510
  appShellLiveDrawerAria: "Live session activity",
1224
1511
  appShellLiveDrawerTitle: "In progress",
1225
1512
  appShellLiveDrawerOpenDashboard: "Open dashboard",
@@ -1296,9 +1583,11 @@ const fr: DashboardStrings = {
1296
1583
  launcherTitle: "Tâches",
1297
1584
  taskTrackerTitle: "En cours",
1298
1585
  taskPlaceholder: "Sur quoi travaillez-vous ?",
1586
+ taskNoteLabel: "Note de tâche",
1587
+ taskNotePlaceholder: "Ajouter une note libre pour cette tâche…",
1299
1588
  taskPlaceholderPast: "Sur quoi avez-vous travaillé ?",
1300
1589
  archiveAddTaskIntro:
1301
- "Entrée passée : indiquez le début et la fin. Les étiquettes et le @projet suivent les mêmes règles ; minuteurs et points de détail ne s’appliquent pas — session en cours ou archivée.",
1590
+ "Entrée passée : indiquez le début, la fin et la durée du minuteur (h/m/s, comme lors des ajustements de durée). Les étiquettes et le @projet suivent les mêmes règles ; minuteurs « live » et points de détail ne s’appliquent pas — session en cours ou archivée.",
1302
1591
  archiveAddTaskIntroHelpAria: "Aide : saisie d’une entrée passée",
1303
1592
  taskEntryModeRealtime: "Temps réel",
1304
1593
  taskEntryModePast: "Passé",
@@ -1306,6 +1595,15 @@ const fr: DashboardStrings = {
1306
1595
  archiveTaskStartLabel: "Début",
1307
1596
  archiveTaskEndLabel: "Fin",
1308
1597
  taskTimingDurationLabel: "Durée",
1598
+ taskTimingAdjustModalTitle: "Ajuster la durée ?",
1599
+ taskTimingAdjustModalMessage:
1600
+ "Vous avez modifié l’horaire de la tâche. Choisissez comment recalculer la durée.",
1601
+ taskTimingAdjustKeepDuration: "Conserver la durée du minuteur enregistrée",
1602
+ taskTimingAdjustManualDuration: "Définir la durée manuellement (h/m/s)",
1603
+ taskTimingAdjustFromBounds: "Définir la durée selon début/fin",
1604
+ taskTimingAdjustHours: "Heures",
1605
+ taskTimingAdjustMinutes: "Minutes",
1606
+ taskTimingAdjustSeconds: "Secondes",
1309
1607
  taskStartTimeSaveAria: "Enregistrer l'heure de début corrigée de la tâche",
1310
1608
  sessionStartTimeSaveAria: "Enregistrer l'heure de début corrigée de la session",
1311
1609
  taskEndTimeSaveAria: "Enregistrer l'heure de fin corrigée de la tâche",
@@ -1321,14 +1619,24 @@ const fr: DashboardStrings = {
1321
1619
  archiveAddTaskBtn: "Ajouter à la session",
1322
1620
  archiveTaskDatetimeRangeInvalid:
1323
1621
  "Indiquez un début et une fin valides ; la fin doit être postérieure au début (date et heure locales).",
1622
+ archiveTaskTimerDurationLabel: "Durée du minuteur",
1623
+ archiveTaskManualDurationInvalid:
1624
+ "Indiquez une durée de minuteur supérieure à zéro et au plus égale à l’intervalle entre le début et la fin.",
1324
1625
  activeTaskTitleEditHint: "Cliquer pour modifier le titre ; saisir #étiquettes dans le champ ou utiliser la ligne du bas",
1325
1626
  activeTaskTitleInputAria: "Modifier le titre ; #étiquettes ou @projet optionnels dans le champ, pastilles en dessous pour l’existant",
1627
+ taskStartBlockedByPlannedBoundaryConflict:
1628
+ "Fermez d’abord la boîte de conflit de minuteurs (tâche planifiée), puis lancez une autre tâche.",
1326
1629
  startTaskBtn: "Démarrer le suivi",
1630
+ taskSaveTemplateBtn: "Sauvegarder comme template",
1631
+ taskAlreadyTemplateBtn: "Déjà enregistré comme template",
1632
+ taskTemplateSavedToast: "Template de tâche sauvegardé.",
1327
1633
  finishTaskBtn: "Terminer",
1328
1634
  finishTaskOpenSubtasksWarnTitle: "Terminer la tâche ?",
1329
1635
  finishTaskOpenSubtasksWarnBody:
1330
1636
  "Il reste des points de détail non cochés. Ils seront tous marqués comme terminés lorsque vous terminez la tâche.",
1331
1637
  taskDeleteBtn: "Supprimer",
1638
+ taskDuplicateBtn: "Copier la tâche dans le champ",
1639
+ taskDuplicateTooltip: "Copier le titre, les étiquettes et le projet dans le champ.",
1332
1640
  taskDeleteConfirm:
1333
1641
  "Supprimer cette entrée ? Le temps enregistré sera perdu. Cette action est irréversible.",
1334
1642
  taskConcurrentTrackingConflictTitle: "Suivi déjà actif",
@@ -1339,18 +1647,43 @@ const fr: DashboardStrings = {
1339
1647
  taskConcurrentTrackingConflictParallelBtn: "Démarrer en parallèle (garder les minuteurs)",
1340
1648
  taskConcurrentTrackingDontShowAgain:
1341
1649
  "Mémoriser ce choix et ne plus afficher cette boîte (la même action sera appliquée automatiquement la prochaine fois).",
1342
- commitOnFinishShort: "Message Git",
1343
- commitOnFinishHint: "Construire le message Git à la fin",
1344
- commitOnFinishToggleAriaOff:
1345
- "Proposer un message Git à la fin — désactivé. Appuyer pour activer.",
1346
- commitOnFinishToggleAriaOn:
1347
- "Proposer un message Git à la fin — activé. Appuyer pour désactiver.",
1650
+ taskPlannedBoundaryConflictTitle: "Une tâche planifiée entre en cours",
1651
+ taskPlannedBoundaryConflictMessage:
1652
+ "Une tâche qui était sous Planifiées a atteint son heure de début et compte désormais comme en cours alors qu’un autre minuteur tournait déjà. Indiquez ce que vous faites des tâches déjà au minuteur : les mettre en pause (elles passent dans la liste des pauses), les terminer (elles passent dans les terminées), ou les laisser tourner en parallèle avec la nouvelle.",
1653
+ taskPlannedBoundaryConflictResolveError:
1654
+ "Impossible d’appliquer votre choix sur les minuteurs. Vérifiez le serveur et réessayez.",
1655
+ navDashboardPlannedConflictPulseHint:
1656
+ "Tableau de bord : modale de conflit de minuteurs à traiter",
1348
1657
  tasksPausedHeading: "En pause",
1349
1658
  tasksCompletedHeading: "Terminées",
1350
1659
  tasksRunningHeading: "En cours (minuteur)",
1660
+ tasksPlannedHeading: "Planifiées",
1661
+ tasksTimelineEmpty:
1662
+ "Aucun créneau horaire de tâche dans cette vue de session.",
1663
+ tasksTimelineGanttOpenBtn: "Gantt",
1664
+ tasksTimelineGanttOpenBtnAria: "Ouvrir le fil chronologique en vue Gantt",
1665
+ tasksTimelineGanttTitle: "Fil chronologique (vue Gantt)",
1666
+ tasksTimelineGanttDescription:
1667
+ "Frise alignée sur le début de la session : une ligne par tâche ; les barres colorées suivent les intervalles du minuteur. Faire défiler horizontalement si la session s’étire sur une longue plage.",
1668
+ tasksTimelineGanttTodayTitle: "Fil de la journée (vue Gantt)",
1669
+ tasksTimelineGanttTodayDescription:
1670
+ "Frise globale de la journée en cours : tous les intervalles de tâches de toutes les sessions sont regroupés dans une seule vue.",
1671
+ tasksTimelineGanttWindowStartLabel: "Début de la frise",
1672
+ tasksTimelineGanttWindowEndLabel: "Fin de la frise",
1673
+ tasksTimelineGanttLegendWork: "Temps suivi",
1674
+ tasksTimelineGanttLegendGap: "Hors intervalle (sur cette ligne)",
1675
+ tasksTimelineGanttLegendProductive: "Productif (projets @)",
1676
+ tasksTimelineGanttLegendPersonal: "Personnel (projets !)",
1677
+ tasksTimelineGanttSummaryProductive: "Total productif : {duration}",
1678
+ tasksTimelineGanttSummaryPersonal: "Total personnel : {duration}",
1679
+ tasksTimelineGanttCloseBtn: "Fermer",
1680
+ tasksTimelineGanttTooltipStart: "Début",
1681
+ tasksTimelineGanttTooltipEnd: "Fin",
1682
+ tasksTimelineGanttTooltipTimer: "Durée minuteur",
1683
+ tasksTimelineGanttTooltipWall: "Durée murale",
1684
+ tasksTimelineGanttTooltipTimerUnknown: "—",
1351
1685
  hideTaskList: "Masquer la liste",
1352
1686
  showAllTasks: "Afficher toute la liste",
1353
- importGitIssue: "Importer une issue Git",
1354
1687
  pauseTaskBtn: "Pause — affichage dans la liste des pauses",
1355
1688
  resumeTaskBtn: "Reprendre le suivi",
1356
1689
  taskTimerPausedManual: "Minuteur en pause (manuel).",
@@ -1359,6 +1692,11 @@ const fr: DashboardStrings = {
1359
1692
  resumeBtn: "Reprendre la session active",
1360
1693
  inspectingLabel: "Consultation :",
1361
1694
  historyInspectBannerAria: "Consultation d’une session passée",
1695
+ liveSessionWallPausedBannerAria: "Session en pause (collecte)",
1696
+ liveSessionWallPausedTitle: "La session est en pause",
1697
+ liveSessionWallPausedDetail:
1698
+ "L’horloge murale est figée. Utilisez « Reprendre » ci-dessous ou le bouton lecture sur une tâche — les deux relancent le suivi de session.",
1699
+ liveSessionResumeWallBtn: "Reprendre la session",
1362
1700
  autoTagsDetected: "Étiquettes détectées",
1363
1701
  autoProjectDetected: "Projet",
1364
1702
  tagsHelpAriaLabel: "Aide sur les étiquettes",
@@ -1423,17 +1761,6 @@ const fr: DashboardStrings = {
1423
1761
  subtaskDurationTooltipNotShown:
1424
1762
  "Aucune durée n’est affichée pour ce point terminé sans temps enregistré dans cette vue archivée.",
1425
1763
  noData: "Pas encore de données.",
1426
- selectIssue: "Rechercher une issue GitLab",
1427
- issuePickerSearchPlaceholder: "Titre, description ou numéro d’issue interne (ex. 12 ou #12)…",
1428
- issuePickerSearchMinHint:
1429
- "Pour une recherche par mots sur GitLab, au moins 2 caractères. Pour un numéro d’issue seul, un chiffre suffit (ex. 7 ou #7).",
1430
- issuePickerLoading: "Recherche en cours…",
1431
- issuePickerNoResults:
1432
- "Aucun résultat. Essayez quelques lettres du titre ou de la description, ou uniquement le numéro interne (ex. 42).",
1433
- issuePickerCloseAria: "Fermer",
1434
- issuePickerDashboardRequestTimeout:
1435
- "Délai dépassé en attendant le serveur du tableau de bord (recherche GitLab). Vérifiez que le serveur tourne, l’URL d’instance, puis réessayez.",
1436
- noIssuesFound: "Aucune issue ou CLI non configurée.",
1437
1764
  sessionsColumnTitle: "Sessions",
1438
1765
  sessionsColumnHelpAria: "Aide : colonne Sessions",
1439
1766
  sessionsColumnHelpBody:
@@ -1459,6 +1786,10 @@ const fr: DashboardStrings = {
1459
1786
  "Au seuil d’alerte ou au-delà ({hours} h) — modifiable dans Paramètres → Tableau de bord web.",
1460
1787
  sessionListStartedPrefix: "Début\u202F:",
1461
1788
  sessionListEndedPrefix: "Fin\u202F:",
1789
+ sessionListOpenGanttAria: "Ouvrir la vue Gantt pour cette session",
1790
+ selectedSessionSidebarTimelineIconTooltip: "Gantt",
1791
+ selectedSessionSidebarTimelineIconAria:
1792
+ "Ouvrir la frise horizontale des tâches pour cette session",
1462
1793
  sessionEndLiveTitle:
1463
1794
  "Terminer la session — enregistrer dans l’historique sans en démarrer une nouvelle (le suivi peut rester actif)",
1464
1795
  sessionEndLiveAria: "Terminer la session en cours",
@@ -1470,6 +1801,14 @@ const fr: DashboardStrings = {
1470
1801
  sessionEndLiveWarnActiveTask: "Un suivi est actuellement actif (en cours).",
1471
1802
  sessionEndLiveWarnPausedTasks: "Au moins une entrée est en pause ou non terminée.",
1472
1803
  sessionEndLiveWarnIncompleteSubtasks: "Au moins un point n’est pas marqué comme terminé.",
1804
+ sessionEndLiveTasksHandlingLegend:
1805
+ "À la fermeture, que faire des tâches encore ouvertes ?",
1806
+ sessionEndLiveTasksHandlingKeep:
1807
+ "Laisser les tâches non terminées dans l’instantané — les minuteurs s’arrêtent (le temps déjà cumulé est conservé)",
1808
+ sessionEndLiveTasksHandlingFinish:
1809
+ "Terminer les tâches ouvertes avec cette session",
1810
+ sessionEndLiveTasksHandlingMoveToPaused:
1811
+ "Transposer les tâches ouvertes vers une nouvelle session en pause",
1473
1812
  sessionEndLiveConfirmBtn: "Terminer la session",
1474
1813
  sessionEndLiveSidebarBtn: "Terminer cette session",
1475
1814
  sessionEndReasonModalHint:
@@ -1504,7 +1843,8 @@ const fr: DashboardStrings = {
1504
1843
  tagsProjectsColumnHelpAria: "Aide : colonne étiquettes et projets",
1505
1844
  tagsProjectsColumnHelpBody:
1506
1845
  "Les étiquettes globales s’appliquent à toute tâche. Les étiquettes liées utilisent Projet#code et ne s’affichent en suggestion que si le @projet de la tâche correspond.\n\nDans cette colonne, l’onglet Étiquettes globales regroupe raccourcis, masquées et descriptions ; l’onglet Projets et étiquettes liées regroupe les projets enregistrés et les codes par projet.\n\nCette colonne reprend la section « Étiquettes et projets enregistrés » des paramètres ; les changements sont immédiats.\n\nL’aide complète et les cas d’usage sont dans le « ? » à côté des étiquettes sur une carte tâche.",
1507
- tasksColumnSubtitle: "En cours, en pause et terminées pour la session sélectionnée.",
1846
+ tasksColumnSubtitle:
1847
+ "En cours au minuteur, planifiées (début ou fin futur), en pause et terminées pour la session sélectionnée.",
1508
1848
  tasksColumnSubtitleHelpAria: "Aide : contenu de cette colonne",
1509
1849
  taskFocusNoSessionTitle: "Aucune session active",
1510
1850
  taskFocusNoSessionBody:
@@ -1512,8 +1852,25 @@ const fr: DashboardStrings = {
1512
1852
  taskStartAutoSessionToast:
1513
1853
  "Aucune session en cours — démarrage d’une session pour y rattacher cette tâche.",
1514
1854
  selectedSessionSidebarTitle: "Session sélectionnée",
1855
+ selectedSessionSidebarTitleLive: "Session en cours",
1856
+ selectedSessionSidebarTitleIdle: "Aucune session active",
1857
+ selectedSessionSidebarPausedBadgeGlobal: "Pause globale",
1858
+ selectedSessionSidebarPausedBadgeSession: "En pause",
1859
+ dashboardPauseBackdropTitleGlobal: "Pause globale active",
1860
+ dashboardPauseBackdropDetailGlobal:
1861
+ "Le suivi est figé pour cette session, les tâches et les sous-tâches concernées. Reprenez via la commande de pause globale dans la barre du haut.",
1862
+ dashboardPauseBackdropAriaGlobal: "Tableau de bord : pause globale active",
1863
+ dashboardPauseBackdropTitleSession: "Suivi de session en pause",
1864
+ dashboardPauseBackdropDetailSession:
1865
+ "La durée murale et les minuteurs concernés sont figés. Reprenez depuis le bandeau au-dessus de la colonne Tâches.",
1866
+ dashboardPauseBackdropAriaSession: "Tableau de bord : pause de session (murale) active",
1867
+ sessionNoteLabel: "Note de session",
1868
+ sessionNotePlaceholder: "Ajouter une note libre pour cette session…",
1515
1869
  selectedSessionIdleHint:
1516
- "Aucune session en cours. Démarrez-en une pour enregistrer le temps, le suivi et les métriques.",
1870
+ "Démarrez une session depuis la colonne Sessions pour enregistrer le temps, le suivi et les métriques.",
1871
+ sessionDetailsModalTitle: "Résumé de la session",
1872
+ sessionDetailsModalCloseAria: "Fermer le résumé de session",
1873
+ sessionDetailsModalReopenBtn: "Résumé session",
1517
1874
  statsMetricSessionDurationHelpAria: "Aide : durée de session",
1518
1875
  statsMetricSessionDurationHelpBody:
1519
1876
  "Temps écoulé (horloge murale) depuis le premier événement d’activité enregistré dans cette session jusqu’à maintenant (session en cours) ou jusqu’à l’enregistrement de l’instantané (archive). Distinct du temps actif, du temps de codage et des minuteurs de suivi ou de point.",
@@ -1525,10 +1882,11 @@ const fr: DashboardStrings = {
1525
1882
  "Temps cumulé à partir de signaux d’activité sur le poste : modifications, ouverture de fichier, changements de sélection, éditeur actif et focus de fenêtre. Les intervalles de plus d’environ trois minutes ne comptent pas. Souvent entre le temps de codage et la durée de session.",
1526
1883
  statsMetricTasksHelpAria: "Aide : tâches par statut",
1527
1884
  statsMetricTasksHelpBody:
1528
- "Pour la session affichée : tâches avec le minuteur de suivi actif (« En cours (minuteur) »), tâches non terminées dans la liste (section « En pause »), et tâches marquées terminées. Reprend les trois blocs de la colonne Tâches.",
1885
+ "Pour la session affichée : tâches avec le minuteur de suivi actif (« En cours (minuteur) »), tâches dont le début ou la fin est encore dans le futur (« Planifiées »), autres tâches non terminées (section « En pause »), et tâches terminées dont la fin n’est pas dans le futur. Reprend les blocs de la colonne Tâches.",
1529
1886
  statsTasksRowRunning: "En cours (minuteur)",
1530
1887
  statsTasksRowPausedList: "En liste (non terminées)",
1531
1888
  statsTasksRowCompleted: "Terminées",
1889
+ statsTasksRowPlanned: "Planifiées (futur)",
1532
1890
  gitRepoCardTitle: "Dépôt Git du workspace",
1533
1891
  gitRepoNotARepo:
1534
1892
  "Le premier dossier du workspace n’est pas un dépôt Git (ou Git n’est pas disponible).",
@@ -1622,6 +1980,8 @@ const fr: DashboardStrings = {
1622
1980
  headerDisplayRegionTitle: "Fuseau d’affichage {timeZone} ; format d’horloge {clock}.",
1623
1981
  headerClockFormat24Short: "24 h",
1624
1982
  headerClockFormat12Short: "12 h (AM/PM)",
1983
+ headerWallClockAriaLabel:
1984
+ "Horloge murale, fuseau d’affichage {timeZone} : {datetime}.",
1625
1985
  gitIdentityBannerAria: "Auteur Git non configuré",
1626
1986
  gitIdentityBannerBody:
1627
1987
  "Indiquez l’auteur Git (nom, courriel, identifiant de forge optionnel) pour la ligne sous le titre du tableau de bord. Utilisez Configurer ici pour un formulaire rapide — tout reste local et modifiable plus tard dans Paramètres → Identité Git.",
@@ -1655,16 +2015,18 @@ const fr: DashboardStrings = {
1655
2015
  sessionMongoPushFailedUri: "Connexion MongoDB incomplète (URI ou mot de passe).",
1656
2016
  dashboardLoadingAriaLabel: "Chargement du tableau de bord, veuillez patienter",
1657
2017
  dashboardLoadingMessage: "Récupération des données de session depuis le serveur Kronosys…",
1658
- dataSearchTrigger: "Rechercher dans les données…",
2018
+ dataSearchTrigger: "Spotlight…",
1659
2019
  dataSearchPlaceholder:
1660
- "Filtrer sessions, tâches, projets, étiquettes, dates, ou durée (ex. 12:55 <, 0:10 >)…",
1661
- dataSearchPaletteAriaLabel: "Recherche rapide",
2020
+ "Filtrer sessions, tâches, modèles, projets, étiquettes, dates, ou durée (ex. 12:55 <, 0:10 >)…",
2021
+ dataSearchPaletteAriaLabel: "Recherche Spotlight",
1662
2022
  dataSearchTypePrompt:
1663
- "Saisissez du texte pour filtrer les sessions, les tâches, les projets et les étiquettes. Vous pouvez aussi saisir une date, une heure, ou une condition sur la durée enregistrée : m:s (ou h:m:s) suivi (ou précédé) de < ou >, p. ex. 45:00 > ou 1:0:0 <.",
1664
- dataSearchEmpty: "Aucune session ni tâche ne correspond.",
2023
+ "Saisissez du texte pour filtrer les sessions, les tâches, les modèles de tâche enregistrés, les projets et les étiquettes. Vous pouvez aussi saisir une date, une heure, ou une condition sur la durée enregistrée : m:s (ou h:m:s) suivi (ou précédé) de < ou >, p. ex. 45:00 > ou 1:0:0 <. Choisir un modèle remplit le brouillon de tâche.",
2024
+ dataSearchEmpty: "Aucune session, tâche ou modèle ne correspond.",
1665
2025
  dataSearchFooter: "↑↓ pour se déplacer · Entrée pour ouvrir · Échap pour fermer",
1666
2026
  dataSearchKindSession: "Session",
1667
2027
  dataSearchKindTask: "Tâche",
2028
+ dataSearchKindTaskTemplate: "Modèle de tâche",
2029
+ taskTemplateDatalistPrefix: "Modèle :",
1668
2030
  dataSearchTaskDistinguishId: "ID : {id}",
1669
2031
  dataSearchTaskStopwatchLabel: "Minuterie",
1670
2032
  dataSearchTaskRecordedTimeLabel: "Temps enregistré",
@@ -1690,7 +2052,7 @@ const fr: DashboardStrings = {
1690
2052
  shortcutsChangeBtn: "Modifier…",
1691
2053
  shortcutsRecordPrompt: "Enregistrement…",
1692
2054
  shortcutsResetAll: "Tout rétablir aux valeurs par défaut",
1693
- shortcutsPaletteRow: "Recherche rapide (données) — Ctrl+K ou ⌘K (fixe)",
2055
+ shortcutsPaletteRow: "Recherche Spotlight — Ctrl+K ou ⌘K (fixe)",
1694
2056
  tourProgressLabel: "Étape {n} sur {total}",
1695
2057
  tourStep1Title: "Bienvenue dans le tableau de bord Kronosys",
1696
2058
  tourStep1Body:
@@ -1703,13 +2065,13 @@ const fr: DashboardStrings = {
1703
2065
  "Parcourez l’historique des sessions, démarrez une nouvelle session et consultez la durée, le temps de codage et les statistiques de la session sélectionnée.\n\nLorsqu’une session en cours est ouverte, vous pouvez la terminer d’ici ; les sessions archivées s’affichent en lecture seule.\n\nPour des options d’horaire plus poussées, ouvrez Paramètres (engrenage) : sous **Tableau de bord et API**, l’**alerte de durée de session** met en évidence une session trop longue dans cette colonne ; les sections **Horaire de travail** et **Sessions spécifiques planifiées** règlent le suivi automatique sur la semaine et des créneaux récurrents précis qui priment sur l’horaire général pendant leur plage horaire.",
1704
2066
  tourStep4Title: "Tâches et suivi (centre)",
1705
2067
  tourStep4Body:
1706
- "Suivez ce sur quoi vous travaillez, terminez des tâches et utilisez les sous-tâches ou les options liées à Git au besoin.\n\nCette colonne suit la session choisie dans la colonne Sessions — le reste de l’en-tête s’aligne sur ce choix.\n\nSur les autres tâches parentes, un seul flux de suivi : lancer le suivi d’une sous-tâche lance aussi le minuteur de la tâche parente et interrompt le suivi sur les autres tâches (le segment est enregistré). Mettre la tâche parente en pause met en pause le suivi d’une sous-tâche active sur la même tâche. Reprendre le minuteur d’une tâche ailleurs met fin aux suivi de sous-tâches sur les autres tâches et met en pause leur minuteur principal.\n\nLes points de détail sont facultatifs. Le total sur la tâche est toujours au moins la somme du temps enregistré sur ces points ; l’écart correspond au suivi sur la tâche sans détail par point.",
2068
+ "Suivez ce sur quoi vous travaillez, terminez des tâches et utilisez les sous-tâches ou les options liées à Git au besoin.\n\nCette colonne suit la session choisie dans la colonne Sessions — le reste de l’en-tête s’aligne sur ce choix.\n\nSur les autres tâches parentes, un seul flux de suivi : lancer le suivi d’une sous-tâche lance aussi le minuteur de la tâche parente et interrompt le suivi sur les autres tâches (le segment est enregistré). Mettre la tâche parente en pause met en pause le suivi d’une sous-tâche active sur la même tâche. Reprendre le minuteur d’une tâche ailleurs met fin aux suivi de sous-tâches sur les autres tâches et met en pause leur minuteur principal.\n\nLes points de détail sont facultatifs. Le total sur la tâche est toujours au moins la somme du temps enregistré sur ces points ; l’écart correspond au suivi sur la tâche sans détail par point.\n\nSur une tâche en cours, en pause ou terminée, **Sauvegarder comme template** enregistre son titre, ses #étiquettes et son @projet pour les réutiliser plus tard — le champ nouvelle tâche les propose avec le préfixe **Modèle :** et la palette Ctrl+K / ⌘K les liste également. Vous pouvez aussi **corriger les bornes temporelles** d’une tâche en conservant la durée enregistrée, en saisissant une durée manuelle (h/m/s) ou en recalculant depuis le début et la fin.",
1707
2069
  tourStep5Title: "Étiquettes et projets (droite)",
1708
2070
  tourStep5Body:
1709
2071
  "Épinglez des étiquettes, gérez les projets enregistrés et rédigez des descriptions — les mêmes réglages que dans les paramètres, accessibles pendant le travail. Deux onglets séparent les étiquettes globales des projets et des étiquettes liées.\n\nDans les titres de tâches, utilisez @projet et #étiquettes (y compris @projet#code) pour structurer le travail par projet.\n\nLes rapports (graphiques) s’appuient fortement sur ces objets : des étiquettes et des projets cohérents rendent les ventilations, filtres et tendances dans Rapports beaucoup plus utiles.",
1710
2072
  tourStep6Title: "Barre du haut : toutes les icônes",
1711
2073
  tourStep6Body:
1712
- "Dans ce groupe, de gauche à droite : la recherche rapide / palette de commandes (équivalent à Ctrl+K ou ⌘K), l’icône clavier pour l’aide aux raccourcis et leur personnalisation, les liens vers Rapports (graphiques) et Paramètres (engrenage), le basculement thème clair / sombre, le bouton qui actualise les données sans recharger tout l’onglet du navigateur, et le menu de langue (FR / EN).\n\nChaque contrôle a une infobulle au survol ; Rapports et Paramètres ouvrent d’autres pages dans le même habillage Kronosys.",
2074
+ "Dans ce groupe, de gauche à droite : la recherche rapide / palette de commandes (équivalent à Ctrl+K ou ⌘K — sessions, tâches, **modèles de tâche**, projets et étiquettes), l’icône clavier pour l’aide aux raccourcis et leur personnalisation, les icônes de navigation vers Tableau de bord, Rapports (graphiques), Paramètres (engrenage), Guide d’utilisation (livre) et **Implémentation** (fichier code — inventaire exhaustif ✓ / ✗ des user stories), le bouton **Gantt du jour** (intervalles des tâches de toutes les sessions du jour courant), la bascule de **pause globale**, le basculement thème clair / sombre, le bouton qui actualise les données sans recharger tout l’onglet du navigateur, et le menu de langue (FR / EN).\n\nLa pause globale reste inactive lorsque rien ne tourne. Sinon, elle ouvre une **modale de confirmation** avec un résumé (début, fin ou *en cours*, durée murale, temps de codage et temps actif de session lorsque l’hôte les fournit, décompte tâches / sous-tâches, total enregistré sur les minuteurs de tâches puis répartition principal vs sous-tâches) avant de mettre en pause la session, ses tâches et les sous-tâches actives ; le clic suivant reprend uniquement ce lot.\n\nChaque contrôle a une infobulle au survol ; les icônes de navigation conservent le même habillage Kronosys.",
1713
2075
  tourStep7Title: "Identité Git et pastille de stockage",
1714
2076
  tourStep7Body:
1715
2077
  "Ici s’affichent la ligne d’auteur Git et le compte forge lorsqu’ils sont renseignés dans Paramètres → Identité Git, les racines de workspace détectées pour les métriques, et une pastille indiquant comment les sessions sont enregistrées ici : SQLite (par défaut), pilote JSON ou miroir MongoDB si activé.\n\nSQLite conserve la charge utile du tableau de bord sur cette machine dans le répertoire de données Kronosys ; cette page lit et écrit via l’API locale.",
@@ -1770,9 +2132,19 @@ const fr: DashboardStrings = {
1770
2132
  reportingTourStep6Body:
1771
2133
  "Ce bloc correspond à la disposition principale de Rapports : le contenu à gauche et, sur grand écran, le sommaire fixe à droite. Sur téléphone, les mêmes ancres sont proposées en pastilles au-dessus des filtres.",
1772
2134
  newSessionModalTitle: "Nouvelle session — portée",
1773
- newSessionModalHelpAria: "Aide : portée de session (durée, dates, jours)",
2135
+ newSessionModalHelpAria: "Aide : début de session et portée (durée, dates, jours)",
1774
2136
  newSessionModalHelpBody:
1775
- "Ces options fixent le cadre attendu pour cette session seulement. Elles n’arrêtent pas Kronosys automatiquement : des rappels viennent de la collecte (battement de cœur) et une bannière ici lorsque vous approchez ou sortez des limites.\n\n• Durée murale maximale — comptée depuis le premier événement tracé dans la session.\n\n• Période calendaire — dates locales inclusives (début et/ou fin).\n\n• Jours de la semaine — limite aux jours choisis ; vous pouvez ajouter une plage horaire quotidienne (24 h locale). Les plages qui passent minuit sont prises en charge (ex. 22:00–06:00).",
2137
+ "Choisissez si la session commence maintenant ou entièrement dans le passé. Dans ce dernier cas, indiquez **le début et la fin** (heure locale du navigateur) : la plage fermée est enregistrée sur la ligne d’historique. Si une session est déjà en cours, « maintenant » ouvre d’abord la boîte de fin de session ; une ligne rétroactive laisse la session active et ajoute une entrée dans l’historique sur laquelle vous basculer. Ensuite, ces options de portée fixent le cadre attendu pour cette session seulement. Elles n’arrêtent pas Kronosys automatiquement : des rappels viennent de la collecte (battement de cœur) et une bannière ici lorsque vous approchez ou sortez des limites.\n\n• Durée murale maximale — comptée depuis le premier événement tracé dans la session.\n\n• Période calendaire — dates locales inclusives (début et/ou fin).\n\n• Jours de la semaine — limite aux jours choisis ; vous pouvez ajouter une plage horaire quotidienne (24 h locale). Les plages qui passent minuit sont prises en charge (ex. 22:00–06:00).",
2138
+ newSessionTimingSectionTitle: "Début de la session",
2139
+ newSessionTimingImmediate: "Maintenant (lancement immédiat)",
2140
+ newSessionTimingPast: "Dans le passé (début rétroactif)",
2141
+ newSessionPastStartLabel: "La session a commencé à (local)",
2142
+ newSessionPastStartHint:
2143
+ "Interprété dans le fuseau local du navigateur. L’horloge murale de session part de cet instant ; vous pourrez ensuite ajouter des tâches et ajuster les heures.",
2144
+ newSessionPastEndLabel: "La session s’est terminée à (local)",
2145
+ newSessionPastEndHint:
2146
+ "Doit être après le début et pas dans le futur. Avec le début, cela définit la plage close consignée dans l’historique.",
2147
+ newSessionScopeFieldsetLegend: "Portée (rappels)",
1776
2148
  newSessionModeNone: "Aucune limite",
1777
2149
  newSessionModeMax: "Durée murale maximale",
1778
2150
  newSessionModeCalendar: "Période calendaire (dates)",
@@ -1789,10 +2161,48 @@ const fr: DashboardStrings = {
1789
2161
  newSessionErrorMax: "Indiquez une durée maximale entre 0,1 et 8760 heures.",
1790
2162
  newSessionErrorCalendar: "Choisissez au moins une date (du et/ou au).",
1791
2163
  newSessionErrorWeekly: "Sélectionnez au moins un jour de la semaine.",
2164
+ newSessionErrorPastMissing: "Indiquez la date et l’heure de début pour une session passée.",
2165
+ newSessionErrorPastEndMissing: "Indiquez la date et l’heure de fin pour une session passée.",
2166
+ newSessionErrorPastEndBeforeStart: "La fin doit être strictement après le début.",
2167
+ newSessionErrorPastEndFuture: "La date et l’heure de fin ne peuvent pas être dans le futur.",
2168
+ newSessionErrorPastFuture: "Choisissez une date et une heure dans le passé ou au présent (pas dans le futur).",
2169
+ newSessionErrorPastInvalid: "Date ou heure non reconnues.",
1792
2170
  newSessionStartBtn: "Démarrer la session",
1793
2171
  newSessionCancelBtn: "Annuler",
1794
2172
  sessionScopeNoticeAria: "Rappel de portée de session",
1795
2173
  appShellRouteNavAria: "Sections principales",
2174
+ appShellRouteNavTodayGantt: "Ouvrir le fil de la journée (vue Gantt)",
2175
+ appShellRouteNavGlobalPause:
2176
+ "Mettre en pause la session, les tâches et les sous-tâches dans ce contexte",
2177
+ appShellRouteNavGlobalResume:
2178
+ "Reprendre uniquement ce qui a été mis en pause globalement dans ce contexte",
2179
+ appShellRouteNavGlobalPauseDisabledTooltip:
2180
+ "Rien n’est actif à mettre en pause : l’horloge murale est déjà figée et aucun minuteur de tâche ou de sous-tâche ne tourne.",
2181
+ globalPauseConfirmTitle: "Pause globale",
2182
+ globalPauseConfirmIntro:
2183
+ "La pause globale fige l’horloge murale de la session si elle tourne encore, met en pause chaque minuteur de tâche qui ne l’est pas déjà et arrête tout minuteur de sous-tâche actif (en consolidant le temps écoulé). Le prochain clic sur ce contrôle ne reprend que ce qui a été figé dans cette opération.\n\nVoici ce qui sera concerné :",
2184
+ globalPauseConfirmSessionHeading: "Session",
2185
+ globalPauseConfirmSummaryHeading: "Résumé",
2186
+ globalPauseConfirmSummaryStart: "Début",
2187
+ globalPauseConfirmSummaryEnd: "Fin",
2188
+ globalPauseConfirmSummaryEndOngoing: "En cours (pas encore de fin)",
2189
+ globalPauseConfirmSummaryWallDuration: "Durée murale",
2190
+ globalPauseConfirmSummaryTasks: "Tâches",
2191
+ globalPauseConfirmSummarySubtasks: "Sous-tâches",
2192
+ globalPauseConfirmSummaryMainTimer: "Minuteurs des tâches (hors sous-tâches)",
2193
+ globalPauseConfirmSummarySubtaskTimers: "Minuteurs des sous-tâches",
2194
+ globalPauseConfirmSummaryCodingSession: "Temps de codage (session)",
2195
+ globalPauseConfirmSummaryActiveSession: "Temps actif (session)",
2196
+ globalPauseConfirmSummaryTaskTimersTotal: "Total enregistré (minuteurs tâches)",
2197
+ globalPauseConfirmSummaryUnknownInstant: "—",
2198
+ globalPauseConfirmSessionWallWillPause: "L’horloge murale de cette session sera mise en pause.",
2199
+ globalPauseConfirmSessionWallAlreadyPaused: "L’horloge murale est déjà en pause ; elle demeure figée.",
2200
+ globalPauseConfirmTasksHeading: "Tâches et sous-tâches",
2201
+ globalPauseConfirmNoTaskEffects:
2202
+ "Aucun minuteur de tâche ou de sous-tâche à figer dans l’état actuel.",
2203
+ globalPauseConfirmEffectMainTimer: "Le minuteur principal de la tâche sera mis en pause.",
2204
+ globalPauseConfirmEffectSubtaskStop: "Arrêt du minuteur de sous-tâche « {title} » (temps enregistré).",
2205
+ globalPauseConfirmConfirmBtn: "Mettre en pause",
1796
2206
  appShellLiveDrawerAria: "Activité de la session en cours",
1797
2207
  appShellLiveDrawerTitle: "En cours",
1798
2208
  appShellLiveDrawerOpenDashboard: "Ouvrir le tableau de bord",