Skip to content

fix: rebuild the task-agent card footer around an always-available trigger#3591

Merged
matthiasn merged 2 commits into
mainfrom
feat/improve_task_agent_card_footer
Jul 25, 2026
Merged

fix: rebuild the task-agent card footer around an always-available trigger#3591
matthiasn merged 2 commits into
mainfrom
feat/improve_task_agent_card_footer

Conversation

@matthiasn

@matthiasn matthiasn commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Why

The AI summary card's bottom section was scored by a design-expert panel at
4.08/10 and a user-persona panel at 3.8/10, both against reproducible
screenshots. All six experts and all five personas led with the same blocker:
while an automatic update was scheduled, the manual wake button was not
disabled — it was gone from the tree entirely (#3508's "one wake affordance
per state"), so running the agent by hand meant cancelling the countdown first.

Alongside it: a nested card inside the footer band, hover state layers that
spanned the whole card, an attribution line that wrapped mid-value, and a
bottom section that became unusable at phone width in longer languages.

What changed

The footer is now three bands with no nested surface — what state the summary
is in
, when it updates, which AI answers.

Before After
Manual trigger absent during a countdown always present; a run in flight swaps label+glyph in place
Automation controls filled/bordered/rounded card inside the band the band's wash + top hairline is the only surface
Countdown at 320px / German / 1.3× Nächste Aktualisier… — no time, no action wording ladder drops prose, never the digits
Freshness bare orange triangle glyph and word ("Up to date" / "Out of date")
Cancel one run unlabelled beside the switch labelled Skip, grouped with the countdown it cancels
Automation on, nothing pending empty gap that resized the card "Updates when this task changes"
Button copy "Wake agent" "Update now", so the band reads as one sentence

Layout is measured, not guessed. TaskAgentAutomationRow (new) measures its
localized labels with a TextPainter at the live textScaler instead of
branching on a pixel breakpoint — no constant can know whether "Automatische
Aktualisierungen" fits beside a trigger at 1.3× text scale. The schedule steps
down Next update in 1:30in 1:301:30, and only when no rung fits does
the row stack. The countdown value, the trigger and the switch never degrade.

Hover containment. A stretching Column hands its children a tight width,
which silently defeated the MainAxisSize.min the identity row already
declared — so the ink spanned the full reading measure and started flush against
the brain glyph. Same root cause in TldrHeader, via Expanded. Both now
shrink-wrap and carry their inset inside the ink.

ai_summary_card.dart needed no behavioural change: runNow was already live
throughout a countdown. The regression was entirely in the view.

Localization

Update now, Up to date, Out of date, Skip, in {countdown} and
Updates when this task changes are hand-authored across all 11 locales.
The agent-internals surfaces (Wake Cycles, Last wake, Wake count) keep the wake
vocabulary — this is the everyday surface, those are the expert ones.

Testing

  • task_agent_automation_row_test.dart (new) mirrors the new widget: trigger
    liveness during a countdown, in-place running swap, the wording ladder, the
    stacking decision, and a width × locale × text-scale matrix that pins
    no-overflow with the trigger and switch surviving every cell.
  • task_agent_controls_footer_test.dart is now a composition test — band
    chrome, the shared leading edge, and "no surface between the band and the
    controls".
  • Stable-geometry coverage at both levels: a 1:00:0059:59 crossing moves
    neither the label, the trigger, the switch, nor the identity region.
  • The hover and truncation regressions each have a test verified to fail
    against the pre-fix code
    .
  • The committed screenshot matrix gains a 320px viewport, German at 1.3×, split
    attribution, and the two hover states driven with a real mouse pointer.

make analyze clean (zero warnings, zero infos), formatter clean, 2199 tests
green across test/features/agents/ui/ and test/features/tasks/ui/.

Note

A second panel round on the redesigned screenshots is running; I'll post the
scores here when it lands. pubspec.yaml is deliberately untouched.

Summary by CodeRabbit

  • New Features
    • Added clearer AI summary freshness indicators showing whether reports are up to date.
    • Added an always-available Update now action and a Skip option for pending scheduled updates.
    • Added automatic-update controls with improved countdown and responsive layouts.
    • Improved display of report attribution and agent names in narrow spaces.
  • Bug Fixes
    • Restored manual updates after scheduling automatic updates.
    • Fixed text truncation, hover highlighting, and layout issues across screen sizes.
  • Documentation
    • Updated guidance and release notes for the revised AI summary controls.

…igger

The AI summary card's bottom section was rated 4.08/10 by a design-expert
panel and 3.8/10 by a user-persona panel, with the same top blocker from all
five personas and all six experts: while an automatic update was scheduled,
the manual wake button was not disabled — it was gone from the tree entirely
(#3508's "one wake affordance per state"), so running the agent by hand meant
cancelling the countdown first.

The footer is now three bands with no nested surface — what state the summary
is in, when it updates, which AI answers:

- `TaskAgentAutomationRow` (new) owns the status, the trigger and the switch.
  The trigger is present in every state; a run in flight swaps its label and
  glyph in place instead of vacating the slot.
- The nested filled/bordered/rounded automation box is gone. The band's wash
  and top hairline are the only surface; in the light theme that inner fill
  was the band's own fill, so it cost a nesting level and bought nothing.
- `Wrap(spaceBetween)` is replaced by a measured fit: the schedule wording
  degrades "Next update in 1:30" → "in 1:30" → "1:30" and the row stacks only
  when nothing else fits. The countdown value, the trigger and the switch
  never degrade. Measurement uses the painted style — tabular figures change
  digit advance, and measuring without them clipped the payload.
- Freshness carries a word ("Up to date" / "Out of date"), not just a colour.
- The bare "✕" becomes a labelled "Skip", grouped with the countdown it
  cancels rather than sitting beside the switch it does not control.
- "Wake agent" becomes "Update now" so the footer reads as one sentence with
  "Next update in …" and "Automatic updates". Hand-authored across all 11
  locales; the agent-internals surfaces keep the wake vocabulary.
- Automation on with nothing pending now says "Updates when this task
  changes" rather than leaving a hole that appears and disappears with the
  switch.

Hover containment, in the identity region and the card header: a stretching
Column hands its children a tight width, which silently defeated the
`MainAxisSize.min` both rows already declared, so the ink spanned the full
reading measure and started flush against the glyph. Both now shrink-wrap and
carry their inset inside the ink. The report attribution truncates with a
tooltip instead of soft-wrapping a stray fragment onto a second line.

The band pays `step4` and each row adds `step2`, so every glyph lands on
`cardPadding` — one leading edge shared with the summary prose above.

Tests: `task_agent_automation_row_test.dart` mirrors the new widget; the
footer test is now a composition test. The countdown keeps its AGENTS.md
stable-geometry coverage at both levels, and a width × locale × text-scale
matrix pins no-overflow with the trigger and switch surviving every cell.
The screenshot matrix gains 320px, German at 1.3×, split attribution and the
two hover states, driven with a real mouse pointer.
The agents README still described a `TaskAgentFreshnessStrip` that no longer
exists in `lib/` (deleted in 957f1d4) and claimed wide cards place model
identity beside the automation cluster, which has not been true since #3527 —
and the cluster itself is now gone.

Rewrites the footer rationale around what the code actually does: the band as
the only surface, the always-present trigger, the measured wording ladder, the
reserved-width countdown, and the shared leading edge. Adds a Mermaid flowchart
for the fit decision, since the ladder is a real branch in
`TaskAgentAutomationRow` rather than a styling note. Also documents why both
identity rows shrink-wrap — a stretching Column hands children a tight width,
which is what silently defeated their `MainAxisSize.min`.

Renames the button in prose to match the UI, and updates the one-line card
description in the tasks README.
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The AI summary card now uses a dedicated responsive automation row with “Update now,” “Skip,” freshness status, countdown, and automatic-update controls. Footer, identity, and header layouts were adjusted for constrained widths, with updated localization, documentation, lifecycle tests, and screenshot coverage.

Changes

Task-agent summary card controls

Layer / File(s) Summary
Responsive automation row
lib/features/agents/ui/task_agent_automation_row.dart, test/features/agents/ui/task_agent_automation_row_test.dart
Adds responsive freshness, scheduling, skip, manual-update, loading, and automatic-update controls with countdown stability and expiry handling.
Footer composition and constrained content
lib/features/agents/ui/task_agent_controls_footer.dart, lib/features/agents/ui/task_agent_identity_region.dart, lib/features/agents/ui/ai_summary_card/tldr_section_part.dart, test/features/agents/ui/*
Delegates automation rendering to the new row and adjusts footer spacing, identity truncation, attribution tooltips, header wrapping, and interaction bounds.
Update control localization
lib/l10n/app_*.arb, lib/l10n/app_localizations*.dart
Adds localized countdown, skip, freshness, update-now, and updates-on-change strings and removes the Wake agent string.
Behavior and screenshot validation
test/features/agents/ui/ai_summary_card/*, test/features/tasks/ui/widgets/task_manual_screenshots_test.dart, test/test_helper.dart
Updates scheduled-update expectations and adds locale, text-scaling, hover, narrow-layout, attribution, and screenshot matrix coverage.
Documentation and release notes
CHANGELOG.md, flatpak/com.matthiasn.lotti.metainfo.xml, lib/features/agents/README.md, lib/features/tasks/README.md
Records the revised controls, wording, layout behavior, and fixed rendering cases.
Estimated code review effort: 4 (Complex) ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant AiSummaryCard
  participant TaskAgentAutomationRow
  participant TaskAgentService
  User->>TaskAgentAutomationRow: tap Update now
  TaskAgentAutomationRow->>TaskAgentService: triggerReanalysis
  TaskAgentService->>AiSummaryCard: update agent state
  User->>TaskAgentAutomationRow: tap Skip
  TaskAgentAutomationRow->>TaskAgentService: cancelScheduledWake
Loading

Possibly related PRs

Suggested reviewers: cyberk1ng

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: redesigning the task-agent card footer around an always-available manual trigger.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/improve_task_agent_card_footer

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.15%. Comparing base (9513642) to head (fb92130).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff            @@
##             main    #3591    +/-   ##
========================================
  Coverage   99.15%   99.15%            
========================================
  Files        1782     1783     +1     
  Lines      130810   130939   +129     
========================================
+ Hits       129704   129833   +129     
  Misses       1106     1106            
Flag Coverage Δ
glados 14.07% <0.00%> (-0.02%) ⬇️
standard 98.90% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@matthiasn
matthiasn merged commit 617cadb into main Jul 25, 2026
31 of 32 checks passed
@matthiasn
matthiasn deleted the feat/improve_task_agent_card_footer branch July 25, 2026 19:20

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (3)
test/features/agents/ui/ai_summary_card/tldr_section_part_test.dart (1)

144-149: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the rendered outcome, not the Text properties.

maxLines/overflow restate the widget config; they pass even if an ancestor lets the row inflate so nothing actually truncates. task_agent_identity_region_test.dart already has the behavioural probe — mirror it here.

💚 Proposed fix
-      expect(tester.widget<Text>(find.text(longName)).maxLines, 1);
-      expect(
-        tester.widget<Text>(find.text(longName)).overflow,
-        TextOverflow.ellipsis,
-      );
-      expect(tester.widget<Text>(find.text('AI summary')).maxLines, 2);
+      expect(
+        tester
+            .renderObject<RenderParagraph>(find.text(longName))
+            .didExceedMaxLines,
+        isTrue,
+      );
+      expect(tester.getSize(find.text(longName)).height, lessThan(
+        tester.getSize(find.text('AI summary')).height * 2,
+      ));

Requires import 'package:flutter/rendering.dart';.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/features/agents/ui/ai_summary_card/tldr_section_part_test.dart` around
lines 144 - 149, Update the assertions in the TLDR section test to verify
rendered truncation rather than the Text widget’s maxLines and overflow
properties. Mirror the behavioral probe used in
task_agent_identity_region_test.dart, adding the Flutter rendering import
required to inspect the rendered text outcome.

Source: Coding guidelines

lib/features/agents/ui/task_agent_automation_row.dart (1)

708-717: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Trigger/setting widths re-derive DesignSystemButton and DesignSystemToggle internals.

These estimates encode another widget's padding, icon size and gap. A padding change there silently mis-sizes the fit decision here with no compile error and no failing test unless a screenshot catches it. Consider exposing the intrinsic metrics from the components (e.g. a static DesignSystemButton.intrinsicWidth(...)) so the contract lives in one place.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/agents/ui/task_agent_automation_row.dart` around lines 708 -
717, Replace the hardcoded triggerWidth and settingWidth calculations with
intrinsic-width APIs owned by DesignSystemButton and DesignSystemToggle, such as
static intrinsicWidth methods, passing the relevant labels and text styles. Move
the component-specific padding, icon, and gap metrics into those components so
this fit decision stays synchronized with their implementations.
test/features/agents/ui/task_agent_controls_footer_test.dart (1)

67-94: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

pumpFooter/tokensOf duplicate pumpRow/tokensOf in task_agent_automation_row_test.dart.

Same view sizing, teardown, MediaQueryData and token lookup, copied verbatim across the two new test files (and partly into task_agent_identity_region_test.dart). Extract one parameterised helper (e.g. test/features/agents/ui/agent_ui_test_utils.dart) taking the widget under test.

As per coding guidelines: "Extract shared widget pump/setup helpers, repeated mock stubs, and complex state into helpers or test-bench classes; pass varying values as named parameters."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/features/agents/ui/task_agent_controls_footer_test.dart` around lines 67
- 94, Extract the duplicated pump/setup and token lookup logic from pumpFooter
and tokensOf into a shared parameterized test helper, such as
agent_ui_test_utils.dart, accepting the widget under test and named parameters
for varying width, locale, and textScaler. Update
task_agent_controls_footer_test.dart, task_agent_automation_row_test.dart, and
task_agent_identity_region_test.dart to reuse the helper while preserving their
existing sizing, teardown, MediaQueryData, and token lookup behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/features/agents/ui/task_agent_automation_row.dart`:
- Around line 499-509: The Semantics wrapper for the task-agent skip action
exposes only the tooltip text, omitting the visible “Skip” label. Update the
`Semantics` label around the `taskAgentSkipScheduledUpdate` `InkWell` so it
includes “Skip” while retaining the existing explanatory tooltip text, ensuring
the accessible name contains the visible label.

In `@lib/l10n/app_es.arb`:
- Line 4135: Update the taskAgentStatusUpToDate localization value from
“Actualizado” to “Al día”, matching the terminology already used by
taskAgentReportUpToDate for the up-to-date status.

In `@lib/l10n/app_fr.arb`:
- Line 4134: Update the taskAgentStatusOutOfDate translation value from
“Obsolète” to “Pas à jour”, preserving the existing taskAgentStatusOutOfDate key
and the intended refreshable stale-status meaning.

In `@lib/l10n/app_localizations_de.dart`:
- Around line 10102-10105: Update the German localization entry for
taskAgentNextUpdateInShort in lib/l10n/app_de.arb to capitalize the standalone
label as “In $countdown”, then regenerate app_localizations_de.dart so the
generated method returns the updated text.

In `@lib/l10n/app_nl.arb`:
- Around line 4728-4729: Update the Dutch localization entries
taskAgentUseCategoryDefault and taskAgentUseCategoryDefaultDescription to use
natural, grammatically correct wording. Clearly state that the agent copies the
category’s current settings and will not follow subsequent changes to that
category.

In `@lib/l10n/app_pt.arb`:
- Line 4720: Update the taskAgentSkipScheduledUpdate translation in app_pt.arb
from “Ignorar” to the established “Pular” translation used for skip actions in
this locale.

In `@lib/l10n/app_sv.arb`:
- Around line 4729-4731: Update the Swedish translations
taskAgentUseCategoryDefault and taskAgentUseProfileDefault to use natural
possessive wording for the default setup options, such as “Kopiera kategorins
standardinställningar” and “Använd profilens standardinställningar,” while
leaving taskAgentUseCategoryDefaultDescription unchanged.

---

Nitpick comments:
In `@lib/features/agents/ui/task_agent_automation_row.dart`:
- Around line 708-717: Replace the hardcoded triggerWidth and settingWidth
calculations with intrinsic-width APIs owned by DesignSystemButton and
DesignSystemToggle, such as static intrinsicWidth methods, passing the relevant
labels and text styles. Move the component-specific padding, icon, and gap
metrics into those components so this fit decision stays synchronized with their
implementations.

In `@test/features/agents/ui/ai_summary_card/tldr_section_part_test.dart`:
- Around line 144-149: Update the assertions in the TLDR section test to verify
rendered truncation rather than the Text widget’s maxLines and overflow
properties. Mirror the behavioral probe used in
task_agent_identity_region_test.dart, adding the Flutter rendering import
required to inspect the rendered text outcome.

In `@test/features/agents/ui/task_agent_controls_footer_test.dart`:
- Around line 67-94: Extract the duplicated pump/setup and token lookup logic
from pumpFooter and tokensOf into a shared parameterized test helper, such as
agent_ui_test_utils.dart, accepting the widget under test and named parameters
for varying width, locale, and textScaler. Update
task_agent_controls_footer_test.dart, task_agent_automation_row_test.dart, and
task_agent_identity_region_test.dart to reuse the helper while preserving their
existing sizing, teardown, MediaQueryData, and token lookup behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e12f0b9a-6e58-4898-835f-e4db6348cc71

📥 Commits

Reviewing files that changed from the base of the PR and between 9513642 and fb92130.

📒 Files selected for processing (42)
  • CHANGELOG.md
  • flatpak/com.matthiasn.lotti.metainfo.xml
  • lib/features/agents/README.md
  • lib/features/agents/ui/ai_summary_card.dart
  • lib/features/agents/ui/ai_summary_card/tldr_section_part.dart
  • lib/features/agents/ui/task_agent_automation_row.dart
  • lib/features/agents/ui/task_agent_controls_footer.dart
  • lib/features/agents/ui/task_agent_identity_region.dart
  • lib/features/tasks/README.md
  • lib/l10n/app_cs.arb
  • lib/l10n/app_da.arb
  • lib/l10n/app_de.arb
  • lib/l10n/app_en.arb
  • lib/l10n/app_es.arb
  • lib/l10n/app_fr.arb
  • lib/l10n/app_it.arb
  • lib/l10n/app_localizations.dart
  • lib/l10n/app_localizations_cs.dart
  • lib/l10n/app_localizations_da.dart
  • lib/l10n/app_localizations_de.dart
  • lib/l10n/app_localizations_en.dart
  • lib/l10n/app_localizations_es.dart
  • lib/l10n/app_localizations_fr.dart
  • lib/l10n/app_localizations_it.dart
  • lib/l10n/app_localizations_nl.dart
  • lib/l10n/app_localizations_pt.dart
  • lib/l10n/app_localizations_ro.dart
  • lib/l10n/app_localizations_sv.dart
  • lib/l10n/app_nl.arb
  • lib/l10n/app_pt.arb
  • lib/l10n/app_ro.arb
  • lib/l10n/app_sv.arb
  • test/features/agents/ui/ai_summary_card/lifecycle_test.dart
  • test/features/agents/ui/ai_summary_card/screenshots_test.dart
  • test/features/agents/ui/ai_summary_card/test_bench.dart
  • test/features/agents/ui/ai_summary_card/tldr_section_part_test.dart
  • test/features/agents/ui/ai_summary_card/wake_test.dart
  • test/features/agents/ui/task_agent_automation_row_test.dart
  • test/features/agents/ui/task_agent_controls_footer_test.dart
  • test/features/agents/ui/task_agent_identity_region_test.dart
  • test/features/tasks/ui/widgets/task_manual_screenshots_test.dart
  • test/test_helper.dart

Comment on lines +499 to +509
return Semantics(
button: true,
label: tooltip,
excludeSemantics: true,
child: Tooltip(
message: tooltip,
child: Material(
color: Colors.transparent,
child: InkWell(
key: const ValueKey('taskAgentSkipScheduledUpdate'),
onTap: onSkip,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Accessible name drops the visible word "Skip".

excludeSemantics: true plus label: tooltip means the accessible name is "Cancel pending automatic update" while the visible label reads "Skip". Voice-control users saying "Skip" won't hit this target (WCAG 2.5.3 label-in-name).

♿ Proposed fix
     return Semantics(
       button: true,
-      label: tooltip,
+      label: '$label. $tooltip',
       excludeSemantics: true,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return Semantics(
button: true,
label: tooltip,
excludeSemantics: true,
child: Tooltip(
message: tooltip,
child: Material(
color: Colors.transparent,
child: InkWell(
key: const ValueKey('taskAgentSkipScheduledUpdate'),
onTap: onSkip,
return Semantics(
button: true,
label: '$label. $tooltip',
excludeSemantics: true,
child: Tooltip(
message: tooltip,
child: Material(
color: Colors.transparent,
child: InkWell(
key: const ValueKey('taskAgentSkipScheduledUpdate'),
onTap: onSkip,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/agents/ui/task_agent_automation_row.dart` around lines 499 -
509, The Semantics wrapper for the task-agent skip action exposes only the
tooltip text, omitting the visible “Skip” label. Update the `Semantics` label
around the `taskAgentSkipScheduledUpdate` `InkWell` so it includes “Skip” while
retaining the existing explanatory tooltip text, ensuring the accessible name
contains the visible label.

Comment thread lib/l10n/app_es.arb
"taskAgentSetupTitle": "Configuración del agente",
"taskAgentSkipScheduledUpdate": "Omitir",
"taskAgentStatusOutOfDate": "Desactualizado",
"taskAgentStatusUpToDate": "Actualizado",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use “Al día” for the up-to-date status.

Actualizado means “updated,” while the existing Spanish UI uses “al día” for “up to date” (taskAgentReportUpToDate at Line 4117). Use Al día here to preserve the intended status meaning and terminology consistency.

Proposed fix
-  "taskAgentStatusUpToDate": "Actualizado",
+  "taskAgentStatusUpToDate": "Al día",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"taskAgentStatusUpToDate": "Actualizado",
"taskAgentStatusUpToDate": "Al día",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/l10n/app_es.arb` at line 4135, Update the taskAgentStatusUpToDate
localization value from “Actualizado” to “Al día”, matching the terminology
already used by taskAgentReportUpToDate for the up-to-date status.

Comment thread lib/l10n/app_fr.arb
"taskAgentSetupSemantics": "Configuration actuelle : {identity}. Active pour la modifier.",
"taskAgentSetupTitle": "Configuration de l’agent",
"taskAgentSkipScheduledUpdate": "Ignorer",
"taskAgentStatusOutOfDate": "Obsolète",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use a stale-status translation instead of “Obsolète”.

“Obsolète” suggests that the report is permanently obsolete, while this state is refreshable and the existing taskAgentReportOutdatedTitle already uses “n’est plus à jour”. Prefer “Pas à jour” to preserve the intended meaning.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/l10n/app_fr.arb` at line 4134, Update the taskAgentStatusOutOfDate
translation value from “Obsolète” to “Pas à jour”, preserving the existing
taskAgentStatusOutOfDate key and the intended refreshable stale-status meaning.

Comment on lines +10102 to +10105
@override
String taskAgentNextUpdateInShort(String countdown) {
return 'in $countdown';
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Capitalize the standalone German countdown label.

TaskAgentAutomationRow can render this compact value as a complete schedule line, so German should use In $countdown, not in $countdown.

As per coding guidelines, update lib/l10n/app_de.arb and regenerate this generated file.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/l10n/app_localizations_de.dart` around lines 10102 - 10105, Update the
German localization entry for taskAgentNextUpdateInShort in lib/l10n/app_de.arb
to capitalize the standalone label as “In $countdown”, then regenerate
app_localizations_de.dart so the generated method returns the updated text.

Source: Coding guidelines

Comment thread lib/l10n/app_nl.arb
Comment on lines 4728 to 4729
"taskAgentUseCategoryDefault": "Standaard categorie kopiëren",
"taskAgentUseCategoryDefaultDescription": "Kopieert de categorie . Huidige setup. Latere categorie wijzigingen zal dit agent niet beïnvloeden.",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Fix the Dutch category-default wording.

The label is awkward, and the description is grammatically incorrect and unclear. Use wording that explains that the agent copies the category’s current settings and will not follow later category changes.

Proposed wording
-  "taskAgentUseCategoryDefault": "Standaard categorie kopiëren",
-  "taskAgentUseCategoryDefaultDescription": "Kopieert de categorie . Huidige setup. Latere categorie wijzigingen zal dit agent niet beïnvloeden.",
+  "taskAgentUseCategoryDefault": "Standaard van categorie gebruiken",
+  "taskAgentUseCategoryDefaultDescription": "Kopieert de huidige categorie-instellingen. Latere wijzigingen aan de categorie hebben geen invloed op deze agent.",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"taskAgentUseCategoryDefault": "Standaard categorie kopiëren",
"taskAgentUseCategoryDefaultDescription": "Kopieert de categorie . Huidige setup. Latere categorie wijzigingen zal dit agent niet beïnvloeden.",
"taskAgentUseCategoryDefault": "Standaard van categorie gebruiken",
"taskAgentUseCategoryDefaultDescription": "Kopieert de huidige categorie-instellingen. Latere wijzigingen aan de categorie hebben geen invloed op deze agent.",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/l10n/app_nl.arb` around lines 4728 - 4729, Update the Dutch localization
entries taskAgentUseCategoryDefault and taskAgentUseCategoryDefaultDescription
to use natural, grammatically correct wording. Clearly state that the agent
copies the category’s current settings and will not follow subsequent changes to
that category.

Comment thread lib/l10n/app_pt.arb
}
},
"taskAgentSetupTitle": "Configuração do agente",
"taskAgentSkipScheduledUpdate": "Ignorar",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use the established translation for “Skip”.

Ignorar reads as “ignore” rather than skipping/cancelling the scheduled update. Use Pular, which is already used for skip actions elsewhere in this locale.

Proposed translation
-  "taskAgentSkipScheduledUpdate": "Ignorar",
+  "taskAgentSkipScheduledUpdate": "Pular",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"taskAgentSkipScheduledUpdate": "Ignorar",
"taskAgentSkipScheduledUpdate": "Pular",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/l10n/app_pt.arb` at line 4720, Update the taskAgentSkipScheduledUpdate
translation in app_pt.arb from “Ignorar” to the established “Pular” translation
used for skip actions in this locale.

Comment thread lib/l10n/app_sv.arb
Comment on lines 4729 to 4731
"taskAgentUseCategoryDefault": "Kopiera kategori standard",
"taskAgentUseCategoryDefaultDescription": "Kopierar kategorins nuvarande uppställning. Senare kategoriändringar påverkar inte denna agent.",
"taskAgentUseProfileDefault": "Använd profilstandard",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files:"
git ls-files 'lib/l10n/*.arb' | sort

echo
echo "Relevant Swedish lines:"
nl -ba lib/l10n/app_sv.arb | sed -n '4715,4740p'

echo
echo "Reference English lines:"
nl -ba lib/l10n/app_en.arb | sed -n '1,80p' | rg -n '"taskAgentUseCategoryDefault"|"taskAgentUseProfileDefault"|"taskAgentUseProfileDescription|taskAgentUseCategory' -C 2 || true

echo
echo "All target keys across locales:"
for f in lib/l10n/app_*.arb; do
  printf '\n--- %s ---\n' "$f"
  rg -n '"taskAgentUseCategoryDefault|"taskAgentUseCategoryDefaultDescription|"taskAgentUseProfileDefault|"taskAgentUseProfileDescription' "$f"
done

echo
echo "Make lint/check for sort?"
if [ -f Makefile ]; then rg -n 'sort_arb|ARB|l10n' Makefile || true; fi
fd -a '.*arb$' lib/l10n | wc -l

Repository: matthiasn/lotti

Length of output: 468


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Relevant Swedish lines:"
awk 'NR>=4715 && NR<=4740 { printf "%7d  %s\n", NR, $0 }' lib/l10n/app_sv.arb

echo
echo "Relevant English lines:"
awk 'NR>=1 && NR<=80 { if (/taskAgentUseCategoryDefault|taskAgentUseProfileDefault|taskAgentUseProfileDescription|taskAgentUseCategory/) printf "%7d  %s\n", NR, $0 }' lib/l10n/app_en.arb

echo
echo "All target keys across locales:"
for f in lib/l10n/app_*.arb; do
  printf '\n--- %s ---\n' "$f"
  awk '{ if (/taskAgentUseCategoryDefault|taskAgentUseCategoryDefaultDescription|taskAgentUseProfileDefault|taskAgentUseProfileDescription/) printf "%7d  %s\n", NR, $0 }' "$f"
done

echo
echo "Locales count and nearby Swedish context:"
python3 - <<'PY'
from pathlib import Path
for path in sorted(Path('lib/l10n').glob('app_*.arb')):
    lines = path.read_text(encoding='utf-8').splitlines()
    for i, line in enumerate(lines, 1):
        if i == 4730:
            print(f'{path}: {line}')
            start=max(1,i-15); end=min(len(lines), i+15)
            print(f'{path}: lines {start}-{end}')
            for n in range(start,end+1):
                print(f'{n:4}: {lines[n-1]}')
            break
    else:
        print(f'{path}: no line 4730')
PY

Repository: matthiasn/lotti

Length of output: 14851


Use Swedish possessive wording for these default setup options.

Kopiera kategori standard is grammatically unnatural in Swedish, and Använd profilstandard reads as clumsy compound-phrase shorthand. Use clearer phrasing that matches the source semantics, such as Kopiera kategorins standardinställningar / Kopiera kategoriens standard and Använd profilens standardinställningar / Använd profilen som standard.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/l10n/app_sv.arb` around lines 4729 - 4731, Update the Swedish
translations taskAgentUseCategoryDefault and taskAgentUseProfileDefault to use
natural possessive wording for the default setup options, such as “Kopiera
kategorins standardinställningar” and “Använd profilens standardinställningar,”
while leaving taskAgentUseCategoryDefaultDescription unchanged.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fb92130bfd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +201 to +203
final trigger = _UpdateNowButton(
isRunning: widget.isRunning,
onRunNow: widget.inferenceAvailable ? widget.onRunNow : null,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve the pending wake when running an immediate update

When a countdown is visible, this enables Update now without changing its callback, but that callback reaches TaskAgentService.triggerReanalysis, whose WakeOrchestrator.enqueueManualWake unconditionally calls clearThrottle(agentId) and removes the queued subscription job. Tapping the newly available button therefore clears nextWakeAt and drops the scheduled update, contrary to the new UI contract and changelog; the manual-update path must preserve or restore the pending wake rather than merely avoiding cancelScheduledWake.

Useful? React with 👍 / 👎.

Comment on lines +169 to +171
triggerLabel: widget.isRunning
? messages.aiSummaryThinkingLabel
: messages.taskAgentUpdateNow,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reserve one width for both trigger states

When the agent transitions between idle and running, this recomputes the trigger width from only the currently visible localized label. Those labels differ substantially in locales such as German (Jetzt aktualisieren versus Denkt nach …), so the button shrinks while running and, near a responsive threshold, _AutomationMetrics.resolve can even switch the footer between stacked and wide layouts. This contradicts the new fixed-slot behavior and visibly moves the status and automatic-updates control; measure the maximum of both labels and reserve that width in both states.

Useful? React with 👍 / 👎.

Comment on lines +145 to +147
// hole that appears and disappears as the user flips the switch.
if (widget.automaticUpdatesEnabled && widget.inferenceAvailable) {
return [messages.taskAgentUpdatesOnChange];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add a narrow fallback for the no-pending schedule label

When automatic updates are enabled but no wake is pending—for example immediately after the user taps Skip—this returns only the full localized sentence. Unlike the countdown path there is no shorter tier, and _ScheduleLabel renders the measured width with wrapping and ellipsis disabled, so German Aktualisiert sich, wenn sich die Aufgabe ändert exceeds the footer width on the explicitly supported 320px/1.3× layout and overflows or clips. Add shorter tiers or allow this non-payload prose to wrap/truncate.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant