Skip to content

feat(downloads): Chrome-style downloads indicator in the titlebar - #3441

Merged
jeanfbrito merged 2 commits into
masterfrom
feat/downloads-titlebar-indicator
Aug 6, 2026
Merged

feat(downloads): Chrome-style downloads indicator in the titlebar#3441
jeanfbrito merged 2 commits into
masterfrom
feat/downloads-titlebar-indicator

Conversation

@jeanfbrito

@jeanfbrito jeanfbrito commented Aug 6, 2026

Copy link
Copy Markdown
Member

What

Screen.Recording.2026-08-06.at.4.06.12.PM.mov

Adds a Chrome-style downloads indicator to the titlebar, mounted next to the update label in all four platform/layout branches (Windows/macOS × tabs/no-tabs).

Pill button

  • Appears when a download starts; hidden at app launch even with download history.
  • Shows a download icon plus live aggregate percent across all active downloads (summed bytes), painted with the same progress-gradient technique as UpdateLabel; shows a count when more than one download is active.
  • After the last download finishes it stays as a plain icon for the rest of the session, like Chrome's toolbar button.

Popup (Fuselage Dropdown, same backdrop/Escape pattern as the update panel)

  • Lists the 5 most recent session downloads: filename, sizes, and a slim progress bar for active items with pause/resume/cancel (existing downloads/* IPC channels — no new IPC).
  • Completed rows open the file location on click (downloads/show-in-folder), with a "Show in folder" tooltip/aria-label.
  • Canceled rows show a muted "Canceled" status with a ban icon and are not clickable; interrupted/expired rows show "Failed" (Chrome parity).
  • Header has a dismiss ✕: hides the pill until a new download starts. While a download is in flight the pill stays visible so it can't be lost mid-download.
  • Footer "Show all downloads" opens the existing Downloads manager view.

Bug fix: formatBytes(0) in src/i18n/common.ts returned '???' because Math.log(0) is -Infinity, so just-started downloads rendered "??? of 901.8 kB". Now renders "0 B". The Downloads manager masked this by hiding the size text at 0 bytes.

Why

Downloads currently give no ambient feedback — the only way to see progress is opening the Downloads manager. This mirrors the browser pattern users already know, using state and IPC channels that already exist (state.downloads via redux-over-IPC).

i18n

New tabBar.downloads namespace (tooltip, title, showAll, pause, resume, cancel, showInFolder, percent, canceled, failed, dismiss) in English and translated in all 16 other locales, reusing each locale's established downloads terminology.

Verification

  • npx tsc --noEmit — 0 errors
  • yarn lint — clean
  • yarn test --runTestsByPath src/ui/components/TopBar/DownloadsIndicator.spec.tsx src/ui/components/TopBar/UpdateLabel.spec.tsx — 40/40 pass (13 new specs covering visibility rules, progress text, popup actions, canceled/failed rendering, dismiss behavior)
  • yarn test --runTestsByPath src/i18n/__tests__/common.spec.ts — 32/32 pass (0-byte fix)
  • Locale key parity checked by script across all 18 files

Summary by CodeRabbit

New Features

  • Added a downloads indicator to the top bar across supported layouts.
  • View active and recent downloads with progress, file sizes, and status details.
  • Pause, resume, cancel, dismiss, or open completed downloads in their containing folder.
  • Access all downloads and close the panel using Escape or the backdrop.

Localization

  • Added download-related translations across supported languages.

Bug Fixes

  • Zero-byte files now display as 0 byte instead of an unknown value.

A pill button appears in the titlebar when a download starts, showing
live aggregate progress across active downloads. Clicking it opens a
recent-downloads popup (5 latest, session-scoped) with pause/resume/
cancel for active items, click-to-reveal for completed ones, muted
Canceled/Failed rows for terminal states, a dismiss button that hides
the pill until a new download starts, and a link to the full Downloads
manager. Mounted next to UpdateLabel in all four platform/layout
branches of Shell.

Also fixes formatBytes(0) returning '???' (Math.log(0) is -Infinity),
which surfaced as '??? of 901.8 kB' for just-started downloads.

i18n: new tabBar.downloads namespace in en and all 16 locales.
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0daf7f84-f612-4e93-95d8-d36d7617a8d7

📥 Commits

Reviewing files that changed from the base of the PR and between dc5ef0a and 306e3af.

📒 Files selected for processing (6)
  • src/i18n/ja.i18n.json
  • src/i18n/no.i18n.json
  • src/i18n/pl.i18n.json
  • src/i18n/sv.i18n.json
  • src/ui/components/TopBar/DownloadsIndicator.tsx
  • src/ui/components/TopBar/DownloadsIndicatorItem.tsx
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/i18n/sv.i18n.json
  • src/i18n/ja.i18n.json
  • src/ui/components/TopBar/DownloadsIndicator.tsx
  • src/i18n/no.i18n.json
  • src/i18n/pl.i18n.json
  • src/ui/components/TopBar/DownloadsIndicatorItem.tsx

Walkthrough

Adds a tab-bar downloads indicator with localized controls, progress display, dismissal, download actions, shell integration across platforms, and tests. Updates zero-byte formatting to return a base-unit value instead of a sentinel.

Changes

Downloads indicator

Layer / File(s) Summary
Zero-byte formatting
src/i18n/common.ts, src/i18n/__tests__/common.spec.ts
formatBytes formats zero bytes as a base-unit value. The test validates the new result.
Download item states and localization
src/ui/components/TopBar/DownloadsIndicatorItem.tsx, src/i18n/*.i18n.json
Adds localized download labels and state-specific controls for pausing, resuming, canceling, showing folders, progress, and terminal statuses.
Indicator visibility and shell integration
src/ui/components/TopBar/DownloadsIndicator.tsx, src/ui/components/Shell/index.tsx, src/ui/components/TopBar/DownloadsIndicator.spec.tsx
Adds the downloads popup, current-session filtering, aggregate progress, dismissal behavior, shell placement, and interaction tests.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DownloadsStore
  participant DownloadsIndicator
  participant DownloadsIndicatorItem
  participant ElectronIPC

  DownloadsStore->>DownloadsIndicator: provide download state
  DownloadsIndicator->>DownloadsIndicatorItem: render download data
  DownloadsIndicatorItem->>ElectronIPC: pause, resume, cancel, or show folder
  DownloadsIndicator->>DownloadsStore: dispatch show-all downloads
Loading

Possibly related PRs

Suggested labels: type: feature, type: bug

🚥 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 clearly summarizes the primary change: adding a Chrome-style downloads indicator to the titlebar.
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.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (2)
src/ui/components/TopBar/DownloadsIndicator.spec.tsx (2)

112-138: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Rename this test to match what it verifies.

The mock at lines 14-26 replaces t, so the real i18next formatter and formatBytes never run. The assertion at line 131 therefore cannot detect the '???' sentinel. What this test proves is that receivedBytes and totalBytes reach the interpolation options. The sentinel behavior is covered in src/i18n/__tests__/common.spec.ts.

💚 Proposed rename
-  it('renders progress size text for a 0-byte-received download without the ??? sentinel', async () => {
+  it('passes 0 received bytes through to the progress size interpolation', async () => {
🤖 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 `@src/ui/components/TopBar/DownloadsIndicator.spec.tsx` around lines 112 - 138,
Rename the test around the DownloadsIndicator progress-size case to reflect that
it verifies receivedBytes and totalBytes are passed as interpolation options,
not that formatting avoids the '???' sentinel. Keep the existing assertions for
those serialized values, and leave sentinel-formatting coverage to the common
i18n tests.

153-167: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider covering the remaining item actions and the list cap.

This suite covers downloads/pause and downloads/show-in-folder. downloads/resume from the paused state, downloads/cancel, and the MAX_RECENT_DOWNLOADS cap of five items have no coverage. Those paths carry user-visible IPC side effects.

🤖 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 `@src/ui/components/TopBar/DownloadsIndicator.spec.tsx` around lines 153 - 167,
Extend the DownloadsIndicator test suite with cases for the paused-state resume
action and the cancel action, asserting invokeMock receives downloads/resume or
downloads/cancel with the item ID. Add coverage for the MAX_RECENT_DOWNLOADS
limit by rendering more than five downloads and verifying only five recent items
are displayed.
🤖 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 `@src/i18n/ja.i18n.json`:
- Around line 292-303: Update the downloads.canceled translation in the Japanese
i18n resource to use wording distinct from the downloads.cancel action, while
leaving the cancel button label unchanged so terminal canceled downloads are
clearly distinguishable.

In `@src/i18n/pl.i18n.json`:
- Around line 335-346: Update the “canceled” and “failed” values in the
“downloads” localization object to use impersonal Polish wording, avoiding
feminine adjective forms and agreeing naturally with the download status labels.
Confirm the revised wording with a Polish speaker.

In `@src/i18n/sv.i18n.json`:
- Around line 522-533: Update the downloads translations to reuse the
established terminology: in src/i18n/sv.i18n.json lines 522-533, replace “Hämtar
filer”, “Hämtningar”, and “Visa alla hämtningar” with the existing “Nedladdning”
wording from line 170; in src/i18n/no.i18n.json lines 544-555, change
downloads.cancel from “Avbryt” to “Kanseller” and downloads.canceled from
“Avbrutt” to “Kansellert”, matching the existing translations at lines 202 and
206.

In `@src/ui/components/TopBar/DownloadsIndicator.tsx`:
- Around line 222-223: Align the DownloadsIndicator popup semantics with its
trigger: either add role="dialog" and an accessible label to the popup container
rendered near the isOpen content, or change aria-haspopup from "dialog" and
update the container to a correctly structured menu. Preserve aria-expanded
behavior and ensure the chosen role matches the popup’s actual interaction
model.

In `@src/ui/components/TopBar/DownloadsIndicatorItem.tsx`:
- Around line 47-60: Update the sizeLabel useMemo so the state === 'completed'
branch runs before the !totalBytes guard, allowing completed zero-byte downloads
to use i18n.format(totalBytes, 'byteSize'). Preserve the existing terminal-error
handling and progress-size behavior for non-completed downloads.

---

Nitpick comments:
In `@src/ui/components/TopBar/DownloadsIndicator.spec.tsx`:
- Around line 112-138: Rename the test around the DownloadsIndicator
progress-size case to reflect that it verifies receivedBytes and totalBytes are
passed as interpolation options, not that formatting avoids the '???' sentinel.
Keep the existing assertions for those serialized values, and leave
sentinel-formatting coverage to the common i18n tests.
- Around line 153-167: Extend the DownloadsIndicator test suite with cases for
the paused-state resume action and the cancel action, asserting invokeMock
receives downloads/resume or downloads/cancel with the item ID. Add coverage for
the MAX_RECENT_DOWNLOADS limit by rendering more than five downloads and
verifying only five recent items are displayed.
🪄 Autofix

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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 43084fc0-2efe-490b-855f-3e068954eec3

📥 Commits

Reviewing files that changed from the base of the PR and between 2c88f98 and dc5ef0a.

📒 Files selected for processing (23)
  • src/i18n/__tests__/common.spec.ts
  • src/i18n/common.ts
  • src/i18n/de-DE.i18n.json
  • src/i18n/en.i18n.json
  • src/i18n/es.i18n.json
  • src/i18n/fi.i18n.json
  • src/i18n/fr.i18n.json
  • src/i18n/hu.i18n.json
  • src/i18n/it-IT.i18n.json
  • src/i18n/ja.i18n.json
  • src/i18n/no.i18n.json
  • src/i18n/pl.i18n.json
  • src/i18n/pt-BR.i18n.json
  • src/i18n/ru.i18n.json
  • src/i18n/sv.i18n.json
  • src/i18n/tr-TR.i18n.json
  • src/i18n/uk-UA.i18n.json
  • src/i18n/zh-CN.i18n.json
  • src/i18n/zh-TW.i18n.json
  • src/ui/components/Shell/index.tsx
  • src/ui/components/TopBar/DownloadsIndicator.spec.tsx
  • src/ui/components/TopBar/DownloadsIndicator.tsx
  • src/ui/components/TopBar/DownloadsIndicatorItem.tsx
📜 Review details
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use TypeScript for new code unless explicitly told otherwise.
Use Fuselage components from @rocket.chat/fuselage for UI work unless the design requires something Fuselage does not provide.
Check Theme.d.ts for valid color tokens before using Fuselage colors.
Verify library props, APIs, and tokens against official docs or local .d.ts files instead of assuming.
Use React functional components with hooks.
Redux actions follow FSA shape.
Use camelCase for file names and PascalCase for components.
Prefer clear names over unnecessary comments.
Prefer editing existing files over creating new abstractions unless the new abstraction removes real complexity or matches an existing pattern.

**/*.{ts,tsx}: Use TypeScript for all new code unless explicitly told otherwise.
Use Fuselage components for all UI work; create custom components only when Fuselage lacks the required functionality.
Import Fuselage components from @rocket.chat/fuselage.
Use only valid color tokens documented by Theme.d.ts.
Use optional chaining with fallbacks for platform-specific APIs, especially Linux-only process APIs such as process.getuid(), getgid(), geteuid(), and getegid().
Use TypeScript strict mode.
Redux actions must follow the Flux Standard Action pattern.
Use camelCase for file names and PascalCase for component names.
Avoid unnecessary comments; prefer self-documenting code through clear naming.
Do not commit or push without explicit user permission.
Verify library APIs, props, tokens, and types against official documentation and .d.ts files instead of assuming they are valid.

Files:

  • src/i18n/__tests__/common.spec.ts
  • src/ui/components/TopBar/DownloadsIndicator.tsx
  • src/i18n/common.ts
  • src/ui/components/Shell/index.tsx
  • src/ui/components/TopBar/DownloadsIndicator.spec.tsx
  • src/ui/components/TopBar/DownloadsIndicatorItem.tsx
**/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Renderer specs use *.spec.ts / *.spec.tsx.

Files:

  • src/i18n/__tests__/common.spec.ts
  • src/ui/components/TopBar/DownloadsIndicator.spec.tsx
src/*/*/*.spec.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Renderer specs must live in a Jest-matched nested path, such as src/<module>/<subdir>/*.spec.ts(x); flat src/<module>/*.spec.ts files are not discovered by the current testMatch.

Files:

  • src/i18n/__tests__/common.spec.ts
**/*.spec.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Use *.spec.ts for renderer process tests.

Files:

  • src/i18n/__tests__/common.spec.ts
src/**/*.{spec.ts,spec.tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Renderer test files should be placed in nested module paths such as src/<module>/<subdir>/*.spec.ts(x) so Jest discovers them.

Files:

  • src/i18n/__tests__/common.spec.ts
  • src/ui/components/TopBar/DownloadsIndicator.spec.tsx
**/*.{tsx,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use React functional components with hooks.

Files:

  • src/ui/components/TopBar/DownloadsIndicator.tsx
  • src/ui/components/Shell/index.tsx
  • src/ui/components/TopBar/DownloadsIndicator.spec.tsx
  • src/ui/components/TopBar/DownloadsIndicatorItem.tsx
🧠 Learnings (1)
📚 Learning: 2026-06-26T18:14:15.295Z
Learnt from: jeanfbrito
Repo: RocketChat/Rocket.Chat.Electron PR: 3358
File: src/i18n/it-IT.i18n.json:39-42
Timestamp: 2026-06-26T18:14:15.295Z
Learning: In the i18n JSON files, the translation key `minimizeOnClose.disabledHint` is intentionally displayed when `isTrayIconEnabled` is true and the minimize-on-close toggle is disabled. The hint text should therefore instruct the user to disable the tray icon to make the setting available. During reviews, don’t “correct” this translation for seeming mismatches with the toggle state—first confirm it matches the component’s intended behavior; only update the wording if the underlying product logic/UX requirement changes.

Applied to files:

  • src/i18n/zh-CN.i18n.json
  • src/i18n/it-IT.i18n.json
  • src/i18n/zh-TW.i18n.json
  • src/i18n/en.i18n.json
  • src/i18n/es.i18n.json
  • src/i18n/fr.i18n.json
  • src/i18n/no.i18n.json
  • src/i18n/pt-BR.i18n.json
  • src/i18n/ja.i18n.json
  • src/i18n/sv.i18n.json
  • src/i18n/fi.i18n.json
  • src/i18n/de-DE.i18n.json
  • src/i18n/ru.i18n.json
  • src/i18n/tr-TR.i18n.json
  • src/i18n/uk-UA.i18n.json
  • src/i18n/hu.i18n.json
  • src/i18n/pl.i18n.json
🔇 Additional comments (18)
src/i18n/__tests__/common.spec.ts (1)

59-64: LGTM!

src/i18n/it-IT.i18n.json (1)

74-85: LGTM!

src/i18n/pt-BR.i18n.json (1)

502-513: LGTM!

src/i18n/ru.i18n.json (1)

471-482: LGTM!

src/ui/components/TopBar/DownloadsIndicator.tsx (2)

21-105: LGTM!


148-192: 🎯 Functional Correctness

No change needed. The store converts Electron DownloadItem.getStartTime() seconds into milliseconds before comparison.

src/ui/components/Shell/index.tsx (1)

24-24: LGTM!

Also applies to: 81-81, 91-91, 103-108, 117-117

src/i18n/common.ts (1)

15-21: 🎯 Functional Correctness

Keep the zero-byte branch as is.

src/i18n/en.i18n.json (1)

545-557: LGTM!

src/i18n/de-DE.i18n.json (1)

466-478: LGTM!

src/i18n/es.i18n.json (1)

496-508: LGTM!

src/i18n/fi.i18n.json (1)

464-476: LGTM!

src/i18n/fr.i18n.json (1)

465-477: LGTM!

src/i18n/hu.i18n.json (1)

653-665: LGTM!

src/i18n/tr-TR.i18n.json (1)

310-322: LGTM!

src/i18n/uk-UA.i18n.json (1)

303-315: LGTM!

src/i18n/zh-CN.i18n.json (1)

346-358: LGTM!

src/i18n/zh-TW.i18n.json (1)

268-280: LGTM!

Comment thread src/i18n/ja.i18n.json
Comment thread src/i18n/pl.i18n.json
Comment thread src/i18n/sv.i18n.json
Comment thread src/ui/components/TopBar/DownloadsIndicator.tsx
Comment thread src/ui/components/TopBar/DownloadsIndicatorItem.tsx
- show size label for completed zero-byte downloads
- add role=dialog and accessible name to the downloads popup
- ja: distinguish canceled status from cancel action
- pl: use impersonal forms for canceled/failed statuses
- sv/no: reuse existing downloads terminology
@jeanfbrito
jeanfbrito merged commit 11b719c into master Aug 6, 2026
3 of 5 checks passed
@jeanfbrito
jeanfbrito deleted the feat/downloads-titlebar-indicator branch August 6, 2026 20:55
jeanfbrito added a commit that referenced this pull request Aug 10, 2026
* docs: desktop UI guidelines and dev-app-verify skill

Distills the lessons from the downloads indicator work (PRs #3441 and
#3443) into permanent project knowledge:

- docs/desktop-ui-guidelines.md: Fuselage token semantics and traps
  (runtime-injected tokens, status-background vs bullet vs badge, the
  icon-button color chain), icon/button geometry facts, the .18s
  micro-interaction standard, tab bar button conventions (the 0.6
  dimming rule and its override, square icon-only buttons, compact
  titlebar sizing, flex-flow traps), and the SVG transform-origin
  clipping pitfall
- skills/dev-app-verify/SKILL.md: ready-made script to drive and
  screenshot the running dev app through the port-9339 inspector, with
  the three pitfalls that produce false alarms (occlusion, watcher
  restarts, singleton wedges) — plain Markdown, usable by any agent
  like skills/desktop-qa-flows
- CLAUDE.md: pointers to both from the UI and Testing sections

* docs: point AGENTS.md at the UI guidelines and dev-app-verify skill

CLAUDE.md got the pointers but AGENTS.md — what non-Claude agents read —
did not; both files now direct agents to docs/desktop-ui-guidelines.md
from UI Work and to skills/dev-app-verify from Testing.

* chore: share Claude Code skills with the repo

The blanket .claude/ gitignore was hiding project knowledge: CLAUDE.md
references .claude/skills/gitnexus/* six times, and skills like
electron-build, ship-release, and boot-wedge-debug encode repo processes
any Claude Code user needs. The ignore is now selective — only genuinely
personal/machine state stays out (settings.local.json, mytasks/,
worktrees/, rules/, commands/, scheduled_tasks.lock) — and the skills
plus the hooks-only settings.json are committed. The dev-app-verify
Claude stub points at the canonical skills/dev-app-verify/SKILL.md so
the two copies cannot drift.

* docs: AGENTS.md becomes the canonical agent guide, CLAUDE.md imports it

The two files carried parallel, drifting versions of the same guidance
that had to be edited twice. AGENTS.md is now the single source (union
of both, restoring details each copy had dropped: KMS two-phase
rationale, worktree commands, working principles, the screen-capture VM
constraint, the GitNexus block with its tool-managed markers), and
CLAUDE.md is a thin @AGENTS.md import with a marked spot for genuinely
Claude-specific additions.

* docs: CLAUDE.md stub directs writes to AGENTS.md explicitly

The stub's guidance was an HTML comment a rushed session could ignore;
it is now a visible imperative rule — loaded into every session's
context — telling agents to record shared guidance in AGENTS.md and
reserve this file for genuinely Claude-only content.

* docs: reindexing guidance and gitnexus-interference pitfall

- AGENTS.md Working Principles: reindex with --index-only at quiet
  points — a plain background analyze rewrites the tracked gitnexus doc
  blocks (stats churn) and mutates worktree git state (drops staged
  index entries, touches watched sources restarting the dev app)
- dev-app-verify skill: the same interference documented as pitfall 4

* chore: read-only permission allowlist for agent verification loops

Derived from transcript analysis (29 recent sessions): the DoD
verification commands agents run constantly (yarn test/lint, npx tsc
--noEmit, the gitnexus runner) and the read-only GitNexus/context-mode
MCP tools that AGENTS.md mandates. No interpreters, task-runner
wildcards, or mutating commands — those still prompt.

* docs: Fuselage Select needs a react-aria-recognized label

Salvaged from the retired OpenWolf buglog: Fuselage Select is backed by
react-aria useSelect, which only accepts a visible label, aria-label,
or aria-labelledby — a labeled wrapper does not satisfy it.

* docs: address CodeRabbit review feedback

- ship-release: semver-sorted baseline tags, worktree-pinned commands,
  approval gate before first push, fail-closed manual tag fallback,
  prerelease flag applied while still a draft
- dev-app-verify: per-request CDP timeouts + pending rejection on socket
  loss, fail-closed menu trigger (developerMode gate + item checks),
  stable root-window predicate, macOS-only scope note
- electron-bump: downgrade guard, unused-API list as hint not exclusion,
  drop unresolved PR placeholder from commit message
- desktop-ui-guidelines: min-width 3ch wording, progress normalization note
- AGENTS.md: drop point-in-time GitNexus counts
- CLAUDE.md: route shared vs Claude-only guidance by content
- markdown fence language identifiers across skill docs
@jeanfbrito jeanfbrito mentioned this pull request Aug 10, 2026
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant