{
  "interval": {
    "intervalStart": "2026-04-26T00:00:00.000Z",
    "intervalEnd": "2026-04-27T00:00:00.000Z",
    "intervalType": "day"
  },
  "repository": "elizaos/eliza",
  "overview": "From 2026-04-26 to 2026-04-27, elizaos/eliza had 29 new PRs (26 merged), 1 new issues, and 7 active contributors.",
  "topIssues": [
    {
      "id": "I_kwDOMT5cIs8AAAABAho_OQ",
      "title": "[tracking] Integrate shaw/checkpoint-20260426-eliza branch (29 unique commits) into develop",
      "author": "lalalune",
      "number": 7108,
      "repository": "elizaos/eliza",
      "body": "## What\n\nThe branch `shaw/checkpoint-20260426-eliza` has 29 commits that are not yet on `develop`, including significant work that should land:\n\n- `a07ff6c598` lifeops(inbox): LLM priority scoring + Missed surface + model setting\n- `53ae1e2890` chore(submodules): bump plugin-discord + plugin-telegram for P3 owner-pairing\n- `0c92b770d3` chore(plugin-elizacloud): bump submodule for cloud SSO helpers\n- `2e6389755a` feat(electrobun): P1 desktop loopback auto-session bridge\n- `476cf2a547` lifeops: finish smart money and security pass\n- `1dc5ad67fc` Move Steward wallet services to app package\n- `debb5e9194` Polish relationships page\n- `2f9cae31b1` Remove Steward agent shims\n- `f12baf1793` Strengthen LifeOps PII redaction\n- `000a9e09eb` lifeops: label subscription playbook capability\n- `f60b3a951c` Fix Gmail reply draft fallback safety\n- `458b4b64e0` Refine Gmail recommendation context policy\n- Plugin resolver fixes (`d183bfcea1`, `47ea85ed2e`, `868f04ebc6`)\n- Cloud SDK / submodule checkpoint chain\n- `2ad44a27ea` fix(lifeops): checkpoint telegram auth encryption update (branch tip)\n\n## Why this isn't merged yet\n\nA naive `git merge origin/shaw/checkpoint-20260426-eliza` into develop produces:\n\n**23 plugin submodule conflicts** — each plugin has divergent SHAs between develop and the branch:\n- `cloud`\n- `plugins/plugin-agent-skills`\n- `plugins/plugin-anthropic`\n- `plugins/plugin-cli`\n- `plugins/plugin-cron`\n- `plugins/plugin-discord`\n- `plugins/plugin-evm`\n- `plugins/plugin-google-genai`\n- `plugins/plugin-groq`\n- `plugins/plugin-imessage`\n- `plugins/plugin-music-library`\n- `plugins/plugin-music-player`\n- `plugins/plugin-ollama`\n- `plugins/plugin-openai`\n- `plugins/plugin-openrouter`\n- `plugins/plugin-pdf`\n- `plugins/plugin-shell`\n- `plugins/plugin-shopify`\n- `plugins/plugin-solana`\n- `plugins/plugin-sql`\n- `plugins/plugin-telegram`\n- `plugins/plugin-wechat`\n- `plugins/plugin-whatsapp`\n\n**9 content conflicts** that need real engineering judgment:\n- `apps/app-lifeops/src/actions/computer-use.ts` — develop renamed `inferSurface → selectSurface`, added helper functions\n- `apps/app-lifeops/src/actions/twilio-call.ts`\n- `packages/agent/src/actions/extract-params.ts`\n- `packages/agent/src/runtime/plugin-resolver.ts`\n- `packages/app-core/src/components/character/CharacterHubView.tsx`\n- `packages/app-core/src/components/pages/AppsView.tsx`\n- `packages/app-core/src/components/pages/BrowserWorkspaceView.test.tsx`\n- `packages/elizaos/templates-manifest.json`\n- `packages/typescript/src/features/advanced-capabilities/personality/actions/set-voice-config.ts`\n\n## How to integrate\n\nFor each plugin submodule conflict: determine which SHA is the descendant (or whether they need their own merge in the plugin repo).\n\nFor each content conflict: review both versions to merge intent — develop's recent work generally took the form of refactors (renames, adds helpers, refines imports) while the branch has its own additions on top of an older base.\n\nThe milady-side counterpart PRs (milady-ai/milady#2045, milady-ai/milady#2044) have been marked merged through the milady-side build/test infra changes that already landed; this branch still holds the eliza-side feature work that needs proper integration.",
      "createdAt": "2026-04-26T06:48:18Z",
      "closedAt": "2026-04-27T21:03:24Z",
      "state": "CLOSED",
      "commentCount": 0
    }
  ],
  "topPRs": [
    {
      "id": "PR_kwDOMT5cIs7Vug-V",
      "title": "feat(app-core): apps as native windows + App Details page (test-green)",
      "author": "Dexploarer",
      "number": 7115,
      "body": "## Summary\n\nThis is the org-owned (milady-ai/eliza) version of [Dexploarer/eliza#26 → elizaOS/eliza#7114](https://github.com/elizaOS/eliza/pull/7114) — same changes, pushed from the org fork instead of a personal fork.\n\n- Every app — internal tool, overlay, registry/catalog — launches in its own Electrobun BrowserWindow with slug-based dedupe and persisted bounds.\n- New `AppWindowRenderer` mounts only the app's content (no surrounding shell chrome) at `/apps/<slug>` when `appWindow=1`.\n- New `AppDetailsView` page (config + diagnostics + widget toggles + Launch button) for apps that declare `hasDetailsPage: true`. Zero-config viewers keep direct-launch.\n- Application menu and tray expose every known app via a single Apps menu (replaces per-surface menus).\n- `<scheme>://apps/<slug>` deep links route via `findAppMenuEntryBySlug` + `getDesktopManager().openAppWindow`.\n- Per-slug window bounds persistence in `userData/app-window-bounds.json` (debounced 500ms saves).\n- Branch is rebased on `develop` (commit `4e110bcb5b`) — 4 conflicts in `AppsView.tsx` resolved (state decl, handlers, `openAppRouteWindow` gate, header UI).\n\n## Test fixes pulled in for green CI\n\n- `apps-routes-hero.test.ts`: Content-Type by file extension (svg/png/jpg/webp/avif/gif), not hardcoded PNG. Hero generator now renders the trimmed display label as an SVG `<text>` overlay.\n- `helpers.APPS_VIEW_HIDDEN_APP_NAMES` adds `@elizaos/app-screenshare` so catalog-coverage doesn't flag it as orphan.\n- `useWalletState.test.tsx` clientMock gains `getConfig` + `updateConfig` stubs.\n- `startup-phase-hydrate.test.ts` mocks `./vrm` so the app-companion re-export doesn't load `getBootConfig` at module-init time.\n- `CharacterOverviewSection.test.tsx` asserts section title + click handler instead of caption text (captions are passed through `widget.body` by callers).\n- `lifeops-activity-signals-client.test.ts` imports the side-effect first and pulls `ElizaClient` from the direct sub-path `@elizaos/app-core/api/client-base` to avoid a barrel cycle that left the binding undefined under vitest's ESM bundling.\n- Default vitest config aliases `@elizaos/plugin-sql` + sub-paths so the auth-store test suite imports work via the test runner's invocation path.\n\n## Test plan\n\n- [ ] Click any app → opens in own native window with no Milady shell chrome\n- [ ] Re-clicking same app focuses existing window\n- [ ] Resize/move app window, close, relaunch → restores bounds\n- [ ] Click LifeOps / Fine Tuning / Steward / ElizaMaker → details page (not launch)\n- [ ] Toggle launch mode in details + click Launch → opens in chosen mode\n- [ ] Toggle widget visibility from details → reflected in chat sidebar\n- [ ] `open elizaos://apps/plugins` from terminal opens Plugin Viewer\n- [ ] Web fallback (open in browser) still uses iframe + sidebar tab path\n- [ ] CI green\n\n<!-- greptile_comment -->\n\n<details><summary><h3>Greptile Summary</h3></summary>\n\nThis PR introduces apps-as-native-windows for Electrobun, a new `AppDetailsView` (config + diagnostics + launch), `AppWindowRenderer` (full-bleed renderer at `/apps/<slug>`), per-slug window bounds persistence, and deep-link routing — a significant architectural addition.\n\n- **P1**: `resolveAppFromSlug` in `AppDetailsView` performs a `windowPath === /apps/${slug}` lookup for internal tools. For \\\"Fine Tuning\\\" (`slug:\\\"training\\\"`, `windowPath:\\\"/apps/fine-tuning\\\"`) and \\\"Steward\\\" (`slug:\\\"steward\\\"`, `windowPath:\\\"/apps/inventory\\\"`), no match is found, so the catalog fallback derives `windowPath: \\\"/apps/training\\\"`. The Launch button then opens the window at that wrong path, and `AppWindowRenderer` falls through to `RegistryAppWindowView` instead of rendering `FineTuningView`/`InventoryView`.\n- **P1**: `handleLaunch` navigates to the details page with only `pushAppsUrl(slug, \\\"details\\\")` (no direct `setAppsDetailsSlug` call). In non-hash routing mode (`replaceState` fires no events), `appsDetailsSlug` stays null and `AppDetailsView` never mounts. The `desktopAppDetailsRequested` handler already contains a comment explaining this exact issue and applies the fix — the same pattern needs to be applied in `handleLaunch`.\n</details>\n\n<h3>Confidence Score: 3/5</h3>\n\nTwo confirmed P1 bugs affecting the hasDetailsPage apps (Fine Tuning and Steward) on both the menu/tray and catalog-card click paths.\n\nTwo independent P1 defects: AppDetailsView resolves wrong windowPath for training/steward slugs causing wrong window content; handleLaunch doesn't update appsDetailsSlug state directly causing details page to not mount in non-hash routing mode.\n\nAppDetailsView.tsx (resolveAppFromSlug lookup strategy) and AppsView.tsx (handleLaunch missing setAppsDetailsSlug call).\n\n<details><summary><h3>Important Files Changed</h3></summary>\n\n| Filename | Overview |\n|----------|----------|\n| packages/app-core/src/components/pages/AppDetailsView.tsx | New 662-line component for app config/diagnostics/launch. P1: `resolveAppFromSlug` lookup by windowPath fails for \"training\" and \"steward\" apps whose APP_MENU_ENTRIES slug doesn't match their windowPath segment. |\n| packages/app-core/src/components/pages/AppsView.tsx | Refactored to add details-page routing and native window launch. P1: `handleLaunch` details redirect uses only `pushAppsUrl` without calling `setAppsDetailsSlug`, so the details page doesn't mount in non-hash routing mode. |\n| packages/app-core/platforms/electrobun/src/application-menu.ts | New `APP_MENU_ENTRIES` list with slug/windowPath mismatches (training/fine-tuning, steward/inventory) that feed the P1 in AppDetailsView. |\n| packages/app-core/platforms/electrobun/src/index.ts | Adds `handleDeepLink`, per-slug bounds store, tray-clicked listener, and `desktopAppDetailsRequested` sender. |\n| packages/app-core/src/shell/AppWindowRenderer.tsx | New full-bleed renderer for `appWindow=1#/apps/<slug>` routes; correctly dispatches to internal tab views, overlay apps, or registry app iframe. |\n| packages/app-core/platforms/electrobun/src/surface-windows.ts | Adds slug-based dedup, per-slug bounds persistence via injected BoundsStore, and debounced resize/move save listeners. Clean implementation. |\n| packages/app-core/src/components/apps/internal-tool-apps.ts | Adds windowPath and hasDetailsPage fields; slug/windowPath mismatches (training/\"fine-tuning\", steward/\"inventory\") are the root cause of the AppDetailsView P1. |\n| packages/app-core/src/components/apps/per-app-config.ts | New per-app localStorage config with robust parsing/sanitization and cross-window sync via storage events. |\n| packages/app-core/src/components/apps/useRegistryCatalog.ts | New hook coalescing concurrent catalog+installed-apps fetches with a module-level promise; correct cancellation on unmount. |\n| packages/app-core/src/components/apps/launch-history.ts | New 20-slot ring buffer for launch attempt diagnostics stored in localStorage; solid implementation. |\n\n</details>\n\n</details>\n\n<details><summary><h3>Sequence Diagram</h3></summary>\n\n```mermaid\nsequenceDiagram\n    participant User\n    participant BunSide as Electrobun (bun)\n    participant Renderer as Renderer (React)\n    participant AppWin as App Window\n\n    User->>BunSide: Click Fine Tuning in menu/tray\n    BunSide->>BunSide: findAppMenuEntryBySlug(training) hasDetailsPage:true\n    BunSide->>Renderer: desktopAppDetailsRequested slug:training\n    Renderer->>Renderer: setAppsDetailsSlug(training)\n    Renderer->>Renderer: AppDetailsView slug=training\n    Renderer->>Renderer: resolveAppFromSlug — looks for windowPath==/apps/training — NO MATCH\n    Renderer->>Renderer: Falls to catalog, windowPath:/apps/training\n    User->>Renderer: Clicks Launch\n    Renderer->>BunSide: openAppWindow path:/apps/training\n    BunSide->>AppWin: Open window at /apps/training\n    AppWin->>AppWin: resolveInternalToolTabFromSlug(training) NO MATCH\n    AppWin->>AppWin: Falls to RegistryAppWindowView — wrong!\n    Note over AppWin: FineTuningView never rendered\n```\n</details>\n\n<a href=\"https://app.greptile.com/ide/claude-code?prompt=Fix%20the%20following%202%20code%20review%20issues.%20Work%20through%20them%20one%20at%20a%20time%2C%20proposing%20concise%20fixes.%0A%0A---%0A%0A%23%23%23%20Issue%201%20of%202%0Apackages%2Fapp-core%2Fsrc%2Fcomponents%2Fpages%2FAppDetailsView.tsx%3A287-305%0A**%60resolveAppFromSlug%60%20slug%20%E2%89%A0%20windowPath%20segment%20breaks%20%22Fine%20Tuning%22%20and%20%22Steward%22%20details%20pages**%0A%0AThe%20internal-tool%20lookup%20uses%20%60d.windowPath%20%3D%3D%3D%20%5C%60%2Fapps%2F%24%7Bslug%7D%5C%60%60%20but%20two%20of%20the%20four%20%60hasDetailsPage%3A%20true%60%20apps%20have%20slugs%20that%20don't%20match%20their%20%60windowPath%60%20last%20segment%3A%0A-%20%60APP_MENU_ENTRIES%60%20slug%20%60%22training%22%60%20%E2%86%92%20%60INTERNAL_TOOL_APPS%60%20has%20%60windowPath%3A%20%22%2Fapps%2Ffine-tuning%22%60%20%E2%86%92%20lookup%20finds%20nothing%0A-%20%60APP_MENU_ENTRIES%60%20slug%20%60%22steward%22%60%20%E2%86%92%20%60INTERNAL_TOOL_APPS%60%20has%20%60windowPath%3A%20%22%2Fapps%2Finventory%22%60%20%E2%86%92%20lookup%20finds%20nothing%0A%0AThe%20lookup%20falls%20through%20to%20the%20catalog%20path%2C%20which%20derives%20%60windowPath%3A%20%22%2Fapps%2Ftraining%22%60.%20When%20the%20Launch%20button%20calls%20%60openAppWindow%28%7B%20path%3A%20%22%2Fapps%2Ftraining%22%20%7D%29%60%2C%20%60AppWindowRenderer%60%20resolves%20slug%20%60%22training%22%60%20via%20%60resolveInternalToolTabFromSlug%60%2C%20which%20also%20uses%20%60descriptor.windowPath%20%3D%3D%3D%20%22%2Fapps%2Ftraining%22%60%20%E2%80%94%20again%20no%20match%20%E2%80%94%20so%20it%20falls%20through%20to%20%60RegistryAppWindowView%60%20and%20tries%20to%20%60client.launchApp%60%20instead%20of%20rendering%20%60FineTuningView%60%20%2F%20%60InventoryView%60.%0A%0AThe%20fix%20is%20to%20also%20match%20by%20slug%20derived%20from%20the%20package%20name%3A%0A%0A%60%60%60ts%0Aconst%20internal%20%3D%20getInternalToolAppDescriptors%28%29.find%28%0A%20%20%28d%29%20%3D%3E%0A%20%20%20%20d.windowPath%20%3D%3D%3D%20%60%2Fapps%2F%24%7Bslug%7D%60%20%7C%7C%0A%20%20%20%20pluginIdFromName%28d.name%29%20%3D%3D%3D%20slug%2C%0A%29%3B%0A%60%60%60%0A%0A%60%22elizamaker%22%60%20and%20%60%22lifeops%22%60%20are%20unaffected%20because%20their%20slugs%20coincidentally%20match%20their%20%60windowPath%60%20segments.%0A%0A%23%23%23%20Issue%202%20of%202%0Apackages%2Fapp-core%2Fsrc%2Fcomponents%2Fpages%2FAppsView.tsx%3A738-753%0A**%60handleLaunch%60%20details-page%20redirect%20doesn't%20update%20%60appsDetailsSlug%60%20state%20in%20non-hash%20routing%20mode**%0A%0AWhen%20a%20catalog-card%20click%20hits%20%60appNeedsDetailsPage%60%2C%20the%20handler%20calls%20%60pushAppsUrl%28slug%2C%20%22details%22%29%60%20and%20returns.%20In%20non-hash%20routing%20mode%20this%20calls%20%60window.history.replaceState%60%2C%20which%20fires%20neither%20%60hashchange%60%20nor%20%60popstate%60.%20The%20%60appsDetailsSlug%60%20state%20never%20updates%2C%20so%20%60AppDetailsView%60%20never%20mounts%20%E2%80%94%20the%20user%20sees%20the%20catalog%20grid%20with%20a%20changed%20URL.%0A%0AThe%20%60desktopAppDetailsRequested%60%20handler%20already%20acknowledges%20this%20exact%20problem%20and%20includes%20the%20direct%20state%20update%3A%0A%0A%60%60%60ts%0A%2F%2F%20desktopAppDetailsRequested%20handler%3A%0AsetAppsDetailsSlug%28slug%29%3B%0ApushAppsUrl%28slug%2C%20%22details%22%29%3B%0A%60%60%60%0A%0AThe%20same%20fix%20needs%20to%20be%20applied%20in%20%60handleLaunch%60%3A%0A%0A%60%60%60ts%0Aif%20%28!isAppWindow%20%26%26%20appNeedsDetailsPage%28app.name%29%29%20%7B%0A%20%20const%20slug%20%3D%20getAppSlug%28app.name%29%3B%0A%20%20pushRecentApp%28app.name%29%3B%0A%20%20setState%28%22appsSubTab%22%2C%20%22browse%22%29%3B%0A%20%20setAppsDetailsSlug%28slug%29%3B%20%20%20%2F%2F%20add%20this%0A%20%20pushAppsUrl%28slug%2C%20%22details%22%29%3B%0A%20%20return%3B%0A%7D%0A%60%60%60%0A%0A&repo=elizaos%2Feliza&pr=7115&platform=github\"><picture><source media=\"(prefers-color-scheme: dark)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInClaudeDark.svg?v=2\"><source media=\"(prefers-color-scheme: light)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInClaude.svg?v=2\"><img alt=\"Fix All in Claude Code\" src=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInClaude.svg?v=2\" height=\"20\"></picture></a> <a href=\"https://chatgpt.com/codex/deeplink?prompt=IMPORTANT%3A%20Work%20in%20the%20repository%20%22elizaos%2Feliza%22%20on%20the%20existing%20branch%20%22feat%2Fapps-native-windows%22.%20Checkout%20that%20branch%20%E2%80%94%20do%20NOT%20create%20a%20new%20branch%20or%20open%20a%20new%20PR.%20Push%20your%20changes%20to%20%22feat%2Fapps-native-windows%22.%0A%0AFix%20the%20following%202%20code%20review%20issues.%20Work%20through%20them%20one%20at%20a%20time%2C%20proposing%20concise%20fixes.%0A%0A---%0A%0A%23%23%23%20Issue%201%20of%202%0Apackages%2Fapp-core%2Fsrc%2Fcomponents%2Fpages%2FAppDetailsView.tsx%3A287-305%0A**%60resolveAppFromSlug%60%20slug%20%E2%89%A0%20windowPath%20segment%20breaks%20%22Fine%20Tuning%22%20and%20%22Steward%22%20details%20pages**%0A%0AThe%20internal-tool%20lookup%20uses%20%60d.windowPath%20%3D%3D%3D%20%5C%60%2Fapps%2F%24%7Bslug%7D%5C%60%60%20but%20two%20of%20the%20four%20%60hasDetailsPage%3A%20true%60%20apps%20have%20slugs%20that%20don't%20match%20their%20%60windowPath%60%20last%20segment%3A%0A-%20%60APP_MENU_ENTRIES%60%20slug%20%60%22training%22%60%20%E2%86%92%20%60INTERNAL_TOOL_APPS%60%20has%20%60windowPath%3A%20%22%2Fapps%2Ffine-tuning%22%60%20%E2%86%92%20lookup%20finds%20nothing%0A-%20%60APP_MENU_ENTRIES%60%20slug%20%60%22steward%22%60%20%E2%86%92%20%60INTERNAL_TOOL_APPS%60%20has%20%60windowPath%3A%20%22%2Fapps%2Finventory%22%60%20%E2%86%92%20lookup%20finds%20nothing%0A%0AThe%20lookup%20falls%20through%20to%20the%20catalog%20path%2C%20which%20derives%20%60windowPath%3A%20%22%2Fapps%2Ftraining%22%60.%20When%20the%20Launch%20button%20calls%20%60openAppWindow%28%7B%20path%3A%20%22%2Fapps%2Ftraining%22%20%7D%29%60%2C%20%60AppWindowRenderer%60%20resolves%20slug%20%60%22training%22%60%20via%20%60resolveInternalToolTabFromSlug%60%2C%20which%20also%20uses%20%60descriptor.windowPath%20%3D%3D%3D%20%22%2Fapps%2Ftraining%22%60%20%E2%80%94%20again%20no%20match%20%E2%80%94%20so%20it%20falls%20through%20to%20%60RegistryAppWindowView%60%20and%20tries%20to%20%60client.launchApp%60%20instead%20of%20rendering%20%60FineTuningView%60%20%2F%20%60InventoryView%60.%0A%0AThe%20fix%20is%20to%20also%20match%20by%20slug%20derived%20from%20the%20package%20name%3A%0A%0A%60%60%60ts%0Aconst%20internal%20%3D%20getInternalToolAppDescriptors%28%29.find%28%0A%20%20%28d%29%20%3D%3E%0A%20%20%20%20d.windowPath%20%3D%3D%3D%20%60%2Fapps%2F%24%7Bslug%7D%60%20%7C%7C%0A%20%20%20%20pluginIdFromName%28d.name%29%20%3D%3D%3D%20slug%2C%0A%29%3B%0A%60%60%60%0A%0A%60%22elizamaker%22%60%20and%20%60%22lifeops%22%60%20are%20unaffected%20because%20their%20slugs%20coincidentally%20match%20their%20%60windowPath%60%20segments.%0A%0A%23%23%23%20Issue%202%20of%202%0Apackages%2Fapp-core%2Fsrc%2Fcomponents%2Fpages%2FAppsView.tsx%3A738-753%0A**%60handleLaunch%60%20details-page%20redirect%20doesn't%20update%20%60appsDetailsSlug%60%20state%20in%20non-hash%20routing%20mode**%0A%0AWhen%20a%20catalog-card%20click%20hits%20%60appNeedsDetailsPage%60%2C%20the%20handler%20calls%20%60pushAppsUrl%28slug%2C%20%22details%22%29%60%20and%20returns.%20In%20non-hash%20routing%20mode%20this%20calls%20%60window.history.replaceState%60%2C%20which%20fires%20neither%20%60hashchange%60%20nor%20%60popstate%60.%20The%20%60appsDetailsSlug%60%20state%20never%20updates%2C%20so%20%60AppDetailsView%60%20never%20mounts%20%E2%80%94%20the%20user%20sees%20the%20catalog%20grid%20with%20a%20changed%20URL.%0A%0AThe%20%60desktopAppDetailsRequested%60%20handler%20already%20acknowledges%20this%20exact%20problem%20and%20includes%20the%20direct%20state%20update%3A%0A%0A%60%60%60ts%0A%2F%2F%20desktopAppDetailsRequested%20handler%3A%0AsetAppsDetailsSlug%28slug%29%3B%0ApushAppsUrl%28slug%2C%20%22details%22%29%3B%0A%60%60%60%0A%0AThe%20same%20fix%20needs%20to%20be%20applied%20in%20%60handleLaunch%60%3A%0A%0A%60%60%60ts%0Aif%20%28!isAppWindow%20%26%26%20appNeedsDetailsPage%28app.name%29%29%20%7B%0A%20%20const%20slug%20%3D%20getAppSlug%28app.name%29%3B%0A%20%20pushRecentApp%28app.name%29%3B%0A%20%20setState%28%22appsSubTab%22%2C%20%22browse%22%29%3B%0A%20%20setAppsDetailsSlug%28slug%29%3B%20%20%20%2F%2F%20add%20this%0A%20%20pushAppsUrl%28slug%2C%20%22details%22%29%3B%0A%20%20return%3B%0A%7D%0A%60%60%60%0A%0A\"><picture><source media=\"(prefers-color-scheme: dark)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodexDark.svg?v=2\"><source media=\"(prefers-color-scheme: light)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=2\"><img alt=\"Fix All in Codex\" src=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=2\" height=\"20\"></picture></a> <a href=\"https://app.greptile.com/api/ide/cursor?prompt=Fix%20the%20following%202%20code%20review%20issues.%20Work%20through%20them%20one%20at%20a%20time%2C%20proposing%20concise%20fixes.%0A%0A---%0A%0A%23%23%23%20Issue%201%20of%202%0Apackages%2Fapp-core%2Fsrc%2Fcomponents%2Fpages%2FAppDetailsView.tsx%3A287-305%0A**%60resolveAppFromSlug%60%20slug%20%E2%89%A0%20windowPath%20segment%20breaks%20%22Fine%20Tuning%22%20and%20%22Steward%22%20details%20pages**%0A%0AThe%20internal-tool%20lookup%20uses%20%60d.windowPath%20%3D%3D%3D%20%5C%60%2Fapps%2F%24%7Bslug%7D%5C%60%60%20but%20two%20of%20the%20four%20%60hasDetailsPage%3A%20true%60%20apps%20have%20slugs%20that%20don't%20match%20their%20%60windowPath%60%20last%20segment%3A%0A-%20%60APP_MENU_ENTRIES%60%20slug%20%60%22training%22%60%20%E2%86%92%20%60INTERNAL_TOOL_APPS%60%20has%20%60windowPath%3A%20%22%2Fapps%2Ffine-tuning%22%60%20%E2%86%92%20lookup%20finds%20nothing%0A-%20%60APP_MENU_ENTRIES%60%20slug%20%60%22steward%22%60%20%E2%86%92%20%60INTERNAL_TOOL_APPS%60%20has%20%60windowPath%3A%20%22%2Fapps%2Finventory%22%60%20%E2%86%92%20lookup%20finds%20nothing%0A%0AThe%20lookup%20falls%20through%20to%20the%20catalog%20path%2C%20which%20derives%20%60windowPath%3A%20%22%2Fapps%2Ftraining%22%60.%20When%20the%20Launch%20button%20calls%20%60openAppWindow%28%7B%20path%3A%20%22%2Fapps%2Ftraining%22%20%7D%29%60%2C%20%60AppWindowRenderer%60%20resolves%20slug%20%60%22training%22%60%20via%20%60resolveInternalToolTabFromSlug%60%2C%20which%20also%20uses%20%60descriptor.windowPath%20%3D%3D%3D%20%22%2Fapps%2Ftraining%22%60%20%E2%80%94%20again%20no%20match%20%E2%80%94%20so%20it%20falls%20through%20to%20%60RegistryAppWindowView%60%20and%20tries%20to%20%60client.launchApp%60%20instead%20of%20rendering%20%60FineTuningView%60%20%2F%20%60InventoryView%60.%0A%0AThe%20fix%20is%20to%20also%20match%20by%20slug%20derived%20from%20the%20package%20name%3A%0A%0A%60%60%60ts%0Aconst%20internal%20%3D%20getInternalToolAppDescriptors%28%29.find%28%0A%20%20%28d%29%20%3D%3E%0A%20%20%20%20d.windowPath%20%3D%3D%3D%20%60%2Fapps%2F%24%7Bslug%7D%60%20%7C%7C%0A%20%20%20%20pluginIdFromName%28d.name%29%20%3D%3D%3D%20slug%2C%0A%29%3B%0A%60%60%60%0A%0A%60%22elizamaker%22%60%20and%20%60%22lifeops%22%60%20are%20unaffected%20because%20their%20slugs%20coincidentally%20match%20their%20%60windowPath%60%20segments.%0A%0A%23%23%23%20Issue%202%20of%202%0Apackages%2Fapp-core%2Fsrc%2Fcomponents%2Fpages%2FAppsView.tsx%3A738-753%0A**%60handleLaunch%60%20details-page%20redirect%20doesn't%20update%20%60appsDetailsSlug%60%20state%20in%20non-hash%20routing%20mode**%0A%0AWhen%20a%20catalog-card%20click%20hits%20%60appNeedsDetailsPage%60%2C%20the%20handler%20calls%20%60pushAppsUrl%28slug%2C%20%22details%22%29%60%20and%20returns.%20In%20non-hash%20routing%20mode%20this%20calls%20%60window.history.replaceState%60%2C%20which%20fires%20neither%20%60hashchange%60%20nor%20%60popstate%60.%20The%20%60appsDetailsSlug%60%20state%20never%20updates%2C%20so%20%60AppDetailsView%60%20never%20mounts%20%E2%80%94%20the%20user%20sees%20the%20catalog%20grid%20with%20a%20changed%20URL.%0A%0AThe%20%60desktopAppDetailsRequested%60%20handler%20already%20acknowledges%20this%20exact%20problem%20and%20includes%20the%20direct%20state%20update%3A%0A%0A%60%60%60ts%0A%2F%2F%20desktopAppDetailsRequested%20handler%3A%0AsetAppsDetailsSlug%28slug%29%3B%0ApushAppsUrl%28slug%2C%20%22details%22%29%3B%0A%60%60%60%0A%0AThe%20same%20fix%20needs%20to%20be%20applied%20in%20%60handleLaunch%60%3A%0A%0A%60%60%60ts%0Aif%20%28!isAppWindow%20%26%26%20appNeedsDetailsPage%28app.name%29%29%20%7B%0A%20%20const%20slug%20%3D%20getAppSlug%28app.name%29%3B%0A%20%20pushRecentApp%28app.name%29%3B%0A%20%20setState%28%22appsSubTab%22%2C%20%22browse%22%29%3B%0A%20%20setAppsDetailsSlug%28slug%29%3B%20%20%20%2F%2F%20add%20this%0A%20%20pushAppsUrl%28slug%2C%20%22details%22%29%3B%0A%20%20return%3B%0A%7D%0A%60%60%60%0A%0A&pr=7115&platform=github\"><picture><source media=\"(prefers-color-scheme: dark)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCursorDark.svg?v=2\"><source media=\"(prefers-color-scheme: light)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCursor.svg?v=2\"><img alt=\"Fix All in Cursor\" src=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCursor.svg?v=2\" height=\"20\"></picture></a>\n\n<sub>Reviews (3): Last reviewed commit: [\"perf(bundle): drop dead lazy() wrappers,...\"](https://github.com/elizaos/eliza/commit/20426a2ad7a447cb082aacf042989493e0aaee30) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=29760088)</sub>\n\n> Greptile also left **2 inline comments** on this PR.\n\n<!-- /greptile_comment -->",
      "repository": "elizaos/eliza",
      "createdAt": "2026-04-26T13:55:04Z",
      "mergedAt": "2026-04-26T18:59:43Z",
      "additions": 3711,
      "deletions": 1787
    },
    {
      "id": "PR_kwDOMT5cIs7VtqDi",
      "title": "feat(app-core): apps open in dedicated native windows + App Details page",
      "author": "Dexploarer",
      "number": 7114,
      "body": "## Summary\n\n- Every app — internal tool, overlay, registry/catalog — launches in its own Electrobun BrowserWindow with slug-based dedupe and persisted bounds.\n- New `AppWindowRenderer` mounts only the app's content (no surrounding Milady shell chrome) when the URL has `appWindow=1` + `/apps/<slug>`.\n- New `AppDetailsView` page (config + diagnostics + widget toggles + Launch button) for apps that declare `hasDetailsPage: true`. Zero-config viewers (Plugin Viewer, Skills Viewer, etc.) keep direct-launch behavior.\n- Application menu and tray expose every known app via a single Apps menu (replaces per-surface menus).\n- `<scheme>://apps/<slug>` deep links route via `findAppMenuEntryBySlug` + `getDesktopManager().openAppWindow`.\n- Per-slug window bounds persistence in `userData/app-window-bounds.json` (debounced 500ms saves on resize/move).\n- New `BoundsStore` interface in `surface-windows.ts` lets the manager stay pure and unit-testable; concrete fs-backed implementation lives in the bun entry.\n\n## Architecture\n\n**Renderer**\n- `AppWindowRenderer` (new): three-branch full-bleed component. Resolves slug → (a) lazy-loaded internal-tool tab component; (b) overlay's `Component` with `exitToApps={() => window.close()}`; (c) catalog app's viewer iframe with full postMessage auth handshake mirroring `GameViewOverlay`.\n- `AppDetailsView` (new, ~510 lines): Header (hero/name/source/running-count) → About (description + capabilities chips) → Recent Runs → Launch Diagnostics (last 5 from new `launch-history.ts` ring buffer) → Widgets (own plugin's widgets with enable toggle via existing chat-sidebar visibility store + collapsible live preview using `getWidgetComponent`) → Config (launch mode + always-on-top) → Launch button.\n- `internal-tool-apps`: declares `windowPath` per tool + new `hasDetailsPage?: boolean` field. Marked true for LifeOps, Fine Tuning, Steward, ElizaMaker.\n- New helpers: `getInternalToolAppHasDetailsPage`, `getInternalToolAppWindowPath`, `getInternalToolAppDescriptors`.\n- `AppsView`: `parseAppsRoute` recognises `/apps/<slug>/details`; `appsDetailsSlug` state with hashchange/popstate listeners; `pushAppsUrl(slug, \"details\")` overload; `handleLaunch` checks `appNeedsDetailsPage` first.\n\n**Bun**\n- `desktopOpenAppWindow` accepts `slug`; threaded through `DesktopManager` → `SurfaceWindowManager` → `ManagedWindowRecord`. Slug-based dedupe focuses an existing window instead of spawning a duplicate.\n- `BoundsStore` interface + optional `boundsStore` option on `SurfaceWindowManagerOptions`. `createManagedWindow` restores saved frame on slug match; `resize`/`move` listeners save with 500ms debounce. Frame validation rejects minimized-state geometry.\n- Per-surface submenus (Chat / Plugins / Connectors / Triggers / Cloud / Browser) replaced with a unified Apps menu. Bun-side `APP_MENU_ENTRIES` mirror keeps the renderer module out of the bun bundle and gains `hasDetailsPage`.\n- Tray gains one entry per app (`tray-app-<slug>`), routed through `handleApplicationMenuAction`.\n- `apps:<slug>` / `tray-app-<slug>` dispatchers respect `entry.hasDetailsPage`: if true, restore main window + send `desktopAppDetailsRequested` event; else direct `openAppWindow`.\n- `setupDeepLinks` recognises `<scheme>://apps/<slug>` and opens the matching window. Unrecognised URLs still fall through to `shareTargetReceived`.\n\n## Compat\n\nBranch is currently merged with upstream develop (commit `4e110bcb5b`). The 4 conflicts in `AppsView.tsx` were resolved as follows:\n\n- State decl: kept upstream's new `appWindowLaunchEnabled` + this branch's setter-less `appWindowAlwaysOnTop` (the global \"Keep new windows on top\" toggle was removed at the user's request — per-window pin in the running-windows list remains).\n- Handlers: dropped upstream's revived `handleAppWindowAlwaysOnTopChange` (no UI for it any more); kept new `handleAppWindowLaunchEnabledChange`.\n- `openAppRouteWindow`: kept this branch's windowPath dispatch; added upstream's `!appWindowLaunchEnabled` gate at the top so the new toggle works.\n- Header UI: kept upstream's \"Open apps in windows\" toggle; dropped the re-added \"Keep new windows on top\" one.\n\n## Test plan\n\n- [ ] Click any app on the apps page → opens in its own native window with no Milady shell chrome\n- [ ] Re-clicking same app focuses existing window (no duplicate)\n- [ ] Resize/move an app window, close it, relaunch → restores last bounds\n- [ ] Click LifeOps / Fine Tuning / Steward / ElizaMaker → routes to `/apps/<slug>/details` (config + Launch button) instead of launching\n- [ ] Toggle launch mode in details, click Launch → opens in chosen mode (window or inline)\n- [ ] Toggle a widget visibility from details → reflected in chat sidebar\n- [ ] Apps menu / tray show every app; details-having entries open the details page; others launch directly\n- [ ] `open elizaos://apps/plugins` from terminal opens Plugin Viewer\n- [ ] Web fallback (open in browser) still uses iframe + sidebar tab path\n- [ ] All app-core tests green (`bun test packages/app-core`)\n\n<!-- greptile_comment -->\n\n<details><summary><h3>Greptile Summary</h3></summary>\n\nThis PR introduces dedicated native app windows with slug-based deduplication and bounds persistence, a new `AppDetailsView` for config/diagnostics before launch, a unified Apps menu/tray replacing per-surface submenus, and `<scheme>://apps/<slug>` deep-link routing. The architecture is well-structured — `BoundsStore` is correctly injected for testability, the `desktopAppDetailsRequested` listener now calls `setAppsDetailsSlug` directly (fixing the prior hash-navigation race), and deep links now correctly respect `hasDetailsPage`.\n\n- **P1 — `resolveAppFromSlug` slug mismatch:** Two of the four `hasDetailsPage: true` apps (Steward, slug `\\\"steward\\\"`, windowPath `/apps/inventory`; Fine Tuning, slug `\\\"training\\\"`, windowPath `/apps/fine-tuning`) will fail to resolve on the details page because the lookup compares `d.windowPath === \\\\`/apps/${slug}\\\\`` — fix by matching with `getAppSlug(d.name) === slug` instead.\n</details>\n\n\n<h3>Confidence Score: 4/5</h3>\n\nSafe to merge after fixing the slug-matching bug in AppDetailsView; the Steward and Fine Tuning details pages will otherwise render as perpetual loading spinners.\n\nOne confirmed P1 logic bug: `resolveAppFromSlug` fails for two of the four apps that declare `hasDetailsPage: true`. The rest of the architecture — bounds persistence, dedup, deep links, menu restructuring — is solid. P2s (dedup filter order, debounce cleanup) are non-blocking.\n\n`packages/app-core/src/components/pages/AppDetailsView.tsx` — the `resolveAppFromSlug` function at lines 91-136 needs the slug-matching fix.\n\n<details><summary><h3>Important Files Changed</h3></summary>\n\n\n\n\n| Filename | Overview |\n|----------|----------|\n| packages/app-core/src/components/pages/AppDetailsView.tsx | New ~660-line details page for apps with `hasDetailsPage: true`. Contains a P1 slug-matching bug in `resolveAppFromSlug` that causes Steward and Fine Tuning to fail to resolve their app info. |\n| packages/app-core/platforms/electrobun/src/index.ts | Adds bounds store wiring, deep-link handler, and menu/tray app routing. Deep link now correctly respects `hasDetailsPage`. Bounds `isFrame` guard covers both x and y axes. |\n| packages/app-core/platforms/electrobun/src/surface-windows.ts | Adds `BoundsStore` interface, slug-based window deduplication, and resize/move persistence with 500 ms debounce. Debounce timer not cleaned up on window close (P2). |\n| packages/app-core/src/components/apps/useRegistryCatalog.ts | New shared hook with module-level promise coalescing. Dedup filter retains later duplicates (serverApps wins over catalogApps) which may be unintentional. |\n| packages/app-core/src/components/pages/AppsView.tsx | Adds `parseAppsRoute`, `appsDetailsSlug` state, and `desktopAppDetailsRequested` listener that now calls `setAppsDetailsSlug` directly (fixing the hash-navigation race noted in prior review). |\n| packages/app-core/src/shell/AppWindowRenderer.tsx | New three-branch renderer for slug-resolved app windows (internal tool tab / overlay Component / catalog iframe). Catalog fetch is self-contained per the shared `useRegistryCatalog` hook. |\n| apps/app/src/main.tsx | Adds `AppWindowRenderer` mount branch for `appWindow=1` + `/apps/<slug>` URLs. `resolveAppWindowSlug` strips query and hash but not sub-path segments (prior comment). |\n\n</details>\n\n\n</details>\n\n\n<details><summary><h3>Flowchart</h3></summary>\n\n```mermaid\n%%{init: {'theme': 'neutral'}}%%\nflowchart TD\n    A[\"User clicks app\\n(menu / tray / UI)\"] --> B{hasDetailsPage?}\n    B -- Yes --> C[\"restoreWindow()\\n+ send desktopAppDetailsRequested\"]\n    B -- No --> D[\"openAppWindow(slug)\"]\n    C --> E[\"AppsView listener\\nsetAppsDetailsSlug(slug)\\npushAppsUrl(slug, 'details')\"]\n    E --> F[\"AppDetailsView renders\"]\n    F --> G{launchMode}\n    G -- window --> H[\"invokeDesktopBridgeRequest\\ndesktopOpenAppWindow\"]\n    G -- inline --> I[\"setTab / setState\\nactiveOverlayApp\"]\n    D --> J[\"SurfaceWindowManager\\nopenAppWindow\"]\n    H --> J\n    J --> K{slug already open?}\n    K -- Yes --> L[\"window.focus()\"]\n    K -- No --> M[\"createWindow()\\nrestore saved bounds\"]\n    M --> N[\"on resize/move\\ndebounced save → BoundsStore\"]\n    subgraph AppWindowRenderer\n        O[\"resolveAppWindowSlug()\\nfrom URL hash\"] --> P{source type}\n        P -- internal-tool --> Q[\"lazy tab component\"]\n        P -- overlay --> R[\"overlay Component\"]\n        P -- catalog --> S[\"iframe + postMessage auth\"]\n    end\n```\n</details>\n\n\n<!-- greptile_failed_comments -->\n<details><summary><h3>Comments Outside Diff (3)</h3></summary>\n\n1. `packages/app-core/platforms/electrobun/src/index.ts`, line 499-512 ([link](https://github.com/elizaos/eliza/blob/5d940f2800e459767b5a6630e6c5ac638729b4e8/packages/app-core/platforms/electrobun/src/index.ts#L499-L512)) \n\n   <a href=\"#\"><img alt=\"P1\" src=\"https://greptile-static-assets.s3.amazonaws.com/badges/p1.svg?v=7\" align=\"top\"></a> **Deep link bypasses `hasDetailsPage` UX**\n\n   `handleDeepLink` always calls `openAppWindow` directly, even for apps like `lifeops` or `fine-tuning` that declare `hasDetailsPage: true`. The menu/tray handler checks that flag and routes to the details page instead; deep links skip it entirely. A user who runs `open elizaos://apps/lifeops` gets the LifeOps app window directly with no config review, inconsistent with a menu/tray click for the same app.\n\n   <a href=\"https://app.greptile.com/ide/claude-code?prompt=This%20is%20a%20comment%20left%20during%20a%20code%20review.%0APath%3A%20packages%2Fapp-core%2Fplatforms%2Felectrobun%2Fsrc%2Findex.ts%0ALine%3A%20499-512%0A%0AComment%3A%0A**Deep%20link%20bypasses%20%60hasDetailsPage%60%20UX**%0A%0A%60handleDeepLink%60%20always%20calls%20%60openAppWindow%60%20directly%2C%20even%20for%20apps%20like%20%60lifeops%60%20or%20%60fine-tuning%60%20that%20declare%20%60hasDetailsPage%3A%20true%60.%20The%20menu%2Ftray%20handler%20checks%20that%20flag%20and%20routes%20to%20the%20details%20page%20instead%3B%20deep%20links%20skip%20it%20entirely.%20A%20user%20who%20runs%20%60open%20elizaos%3A%2F%2Fapps%2Flifeops%60%20gets%20the%20LifeOps%20app%20window%20directly%20with%20no%20config%20review%2C%20inconsistent%20with%20a%20menu%2Ftray%20click%20for%20the%20same%20app.%0A%0AHow%20can%20I%20resolve%20this%3F%20If%20you%20propose%20a%20fix%2C%20please%20make%20it%20concise.&repo=elizaos%2Feliza&pr=7114&platform=github\"><picture><source media=\"(prefers-color-scheme: dark)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInClaudeDark.svg?v=2\"><source media=\"(prefers-color-scheme: light)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInClaude.svg?v=2\"><img alt=\"Fix in Claude Code\" src=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInClaude.svg?v=2\" height=\"20\"></picture></a> <a href=\"https://chatgpt.com/codex/deeplink?prompt=IMPORTANT%3A%20Work%20in%20the%20repository%20%22elizaos%2Feliza%22%20on%20the%20existing%20branch%20%22feat%2Fapps-native-windows%22.%20Checkout%20that%20branch%20%E2%80%94%20do%20NOT%20create%20a%20new%20branch%20or%20open%20a%20new%20PR.%20Push%20your%20changes%20to%20%22feat%2Fapps-native-windows%22.%0A%0AThis%20is%20a%20comment%20left%20during%20a%20code%20review.%0APath%3A%20packages%2Fapp-core%2Fplatforms%2Felectrobun%2Fsrc%2Findex.ts%0ALine%3A%20499-512%0A%0AComment%3A%0A**Deep%20link%20bypasses%20%60hasDetailsPage%60%20UX**%0A%0A%60handleDeepLink%60%20always%20calls%20%60openAppWindow%60%20directly%2C%20even%20for%20apps%20like%20%60lifeops%60%20or%20%60fine-tuning%60%20that%20declare%20%60hasDetailsPage%3A%20true%60.%20The%20menu%2Ftray%20handler%20checks%20that%20flag%20and%20routes%20to%20the%20details%20page%20instead%3B%20deep%20links%20skip%20it%20entirely.%20A%20user%20who%20runs%20%60open%20elizaos%3A%2F%2Fapps%2Flifeops%60%20gets%20the%20LifeOps%20app%20window%20directly%20with%20no%20config%20review%2C%20inconsistent%20with%20a%20menu%2Ftray%20click%20for%20the%20same%20app.%0A%0AHow%20can%20I%20resolve%20this%3F%20If%20you%20propose%20a%20fix%2C%20please%20make%20it%20concise.\"><picture><source media=\"(prefers-color-scheme: dark)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInCodexDark.svg?v=2\"><source media=\"(prefers-color-scheme: light)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInCodex.svg?v=2\"><img alt=\"Fix in Codex\" src=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInCodex.svg?v=2\" height=\"20\"></picture></a> <a href=\"https://app.greptile.com/api/ide/cursor?prompt=This%20is%20a%20comment%20left%20during%20a%20code%20review.%0APath%3A%20packages%2Fapp-core%2Fplatforms%2Felectrobun%2Fsrc%2Findex.ts%0ALine%3A%20499-512%0A%0AComment%3A%0A**Deep%20link%20bypasses%20%60hasDetailsPage%60%20UX**%0A%0A%60handleDeepLink%60%20always%20calls%20%60openAppWindow%60%20directly%2C%20even%20for%20apps%20like%20%60lifeops%60%20or%20%60fine-tuning%60%20that%20declare%20%60hasDetailsPage%3A%20true%60.%20The%20menu%2Ftray%20handler%20checks%20that%20flag%20and%20routes%20to%20the%20details%20page%20instead%3B%20deep%20links%20skip%20it%20entirely.%20A%20user%20who%20runs%20%60open%20elizaos%3A%2F%2Fapps%2Flifeops%60%20gets%20the%20LifeOps%20app%20window%20directly%20with%20no%20config%20review%2C%20inconsistent%20with%20a%20menu%2Ftray%20click%20for%20the%20same%20app.%0A%0AHow%20can%20I%20resolve%20this%3F%20If%20you%20propose%20a%20fix%2C%20please%20make%20it%20concise.&pr=7114&platform=github\"><picture><source media=\"(prefers-color-scheme: dark)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInCursorDark.svg?v=2\"><source media=\"(prefers-color-scheme: light)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInCursor.svg?v=2\"><img alt=\"Fix in Cursor\" src=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInCursor.svg?v=2\" height=\"20\"></picture></a>\n\n2. `packages/app-core/platforms/electrobun/src/index.ts`, line 353-363 ([link](https://github.com/elizaos/eliza/blob/5d940f2800e459767b5a6630e6c5ac638729b4e8/packages/app-core/platforms/electrobun/src/index.ts#L353-L363)) \n\n   <a href=\"#\"><img alt=\"P2\" src=\"https://greptile-static-assets.s3.amazonaws.com/badges/p2.svg?v=7\" align=\"top\"></a> **Bounds store `y` coordinate has no lower-bound guard**\n\n   `isFrame` rejects unreasonable x values (`f.x > -16000`) but places no lower-bound check on `y`. A window dragged off the top of a multi-monitor setup with a large negative y could be saved and then restored off-screen on a single-monitor system. Adding `f.y > -16000` (or a similar sentinel) would mirror the x-guard already present.\n\n   <a href=\"https://app.greptile.com/ide/claude-code?prompt=This%20is%20a%20comment%20left%20during%20a%20code%20review.%0APath%3A%20packages%2Fapp-core%2Fplatforms%2Felectrobun%2Fsrc%2Findex.ts%0ALine%3A%20353-363%0A%0AComment%3A%0A**Bounds%20store%20%60y%60%20coordinate%20has%20no%20lower-bound%20guard**%0A%0A%60isFrame%60%20rejects%20unreasonable%20x%20values%20%28%60f.x%20%3E%20-16000%60%29%20but%20places%20no%20lower-bound%20check%20on%20%60y%60.%20A%20window%20dragged%20off%20the%20top%20of%20a%20multi-monitor%20setup%20with%20a%20large%20negative%20y%20could%20be%20saved%20and%20then%20restored%20off-screen%20on%20a%20single-monitor%20system.%20Adding%20%60f.y%20%3E%20-16000%60%20%28or%20a%20similar%20sentinel%29%20would%20mirror%20the%20x-guard%20already%20present.%0A%0AHow%20can%20I%20resolve%20this%3F%20If%20you%20propose%20a%20fix%2C%20please%20make%20it%20concise.&repo=elizaos%2Feliza&pr=7114&platform=github\"><picture><source media=\"(prefers-color-scheme: dark)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInClaudeDark.svg?v=2\"><source media=\"(prefers-color-scheme: light)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInClaude.svg?v=2\"><img alt=\"Fix in Claude Code\" src=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInClaude.svg?v=2\" height=\"20\"></picture></a> <a href=\"https://chatgpt.com/codex/deeplink?prompt=IMPORTANT%3A%20Work%20in%20the%20repository%20%22elizaos%2Feliza%22%20on%20the%20existing%20branch%20%22feat%2Fapps-native-windows%22.%20Checkout%20that%20branch%20%E2%80%94%20do%20NOT%20create%20a%20new%20branch%20or%20open%20a%20new%20PR.%20Push%20your%20changes%20to%20%22feat%2Fapps-native-windows%22.%0A%0AThis%20is%20a%20comment%20left%20during%20a%20code%20review.%0APath%3A%20packages%2Fapp-core%2Fplatforms%2Felectrobun%2Fsrc%2Findex.ts%0ALine%3A%20353-363%0A%0AComment%3A%0A**Bounds%20store%20%60y%60%20coordinate%20has%20no%20lower-bound%20guard**%0A%0A%60isFrame%60%20rejects%20unreasonable%20x%20values%20%28%60f.x%20%3E%20-16000%60%29%20but%20places%20no%20lower-bound%20check%20on%20%60y%60.%20A%20window%20dragged%20off%20the%20top%20of%20a%20multi-monitor%20setup%20with%20a%20large%20negative%20y%20could%20be%20saved%20and%20then%20restored%20off-screen%20on%20a%20single-monitor%20system.%20Adding%20%60f.y%20%3E%20-16000%60%20%28or%20a%20similar%20sentinel%29%20would%20mirror%20the%20x-guard%20already%20present.%0A%0AHow%20can%20I%20resolve%20this%3F%20If%20you%20propose%20a%20fix%2C%20please%20make%20it%20concise.\"><picture><source media=\"(prefers-color-scheme: dark)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInCodexDark.svg?v=2\"><source media=\"(prefers-color-scheme: light)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInCodex.svg?v=2\"><img alt=\"Fix in Codex\" src=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInCodex.svg?v=2\" height=\"20\"></picture></a> <a href=\"https://app.greptile.com/api/ide/cursor?prompt=This%20is%20a%20comment%20left%20during%20a%20code%20review.%0APath%3A%20packages%2Fapp-core%2Fplatforms%2Felectrobun%2Fsrc%2Findex.ts%0ALine%3A%20353-363%0A%0AComment%3A%0A**Bounds%20store%20%60y%60%20coordinate%20has%20no%20lower-bound%20guard**%0A%0A%60isFrame%60%20rejects%20unreasonable%20x%20values%20%28%60f.x%20%3E%20-16000%60%29%20but%20places%20no%20lower-bound%20check%20on%20%60y%60.%20A%20window%20dragged%20off%20the%20top%20of%20a%20multi-monitor%20setup%20with%20a%20large%20negative%20y%20could%20be%20saved%20and%20then%20restored%20off-screen%20on%20a%20single-monitor%20system.%20Adding%20%60f.y%20%3E%20-16000%60%20%28or%20a%20similar%20sentinel%29%20would%20mirror%20the%20x-guard%20already%20present.%0A%0AHow%20can%20I%20resolve%20this%3F%20If%20you%20propose%20a%20fix%2C%20please%20make%20it%20concise.&pr=7114&platform=github\"><picture><source media=\"(prefers-color-scheme: dark)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInCursorDark.svg?v=2\"><source media=\"(prefers-color-scheme: light)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInCursor.svg?v=2\"><img alt=\"Fix in Cursor\" src=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInCursor.svg?v=2\" height=\"20\"></picture></a>\n\n3. `packages/app-core/src/shell/AppWindowRenderer.tsx`, line 1643-1666 ([link](https://github.com/elizaos/eliza/blob/5d940f2800e459767b5a6630e6c5ac638729b4e8/packages/app-core/src/shell/AppWindowRenderer.tsx#L1643-L1666)) \n\n   <a href=\"#\"><img alt=\"P2\" src=\"https://greptile-static-assets.s3.amazonaws.com/badges/p2.svg?v=7\" align=\"top\"></a> **Catalog fetch is duplicated between `AppDetailsView` and `RegistryAppWindowView`**\n\n   `RegistryAppWindowView` fetches `client.listApps()` + `client.listCatalogApps()` with the same deduplication logic that already exists in `AppDetailsView`. If both components are active for the same slug simultaneously, the API is hit twice with no shared cache. Extracting the catalog fetch into a shared hook or context would eliminate the duplication and reduce API load.\n\n   <a href=\"https://app.greptile.com/ide/claude-code?prompt=This%20is%20a%20comment%20left%20during%20a%20code%20review.%0APath%3A%20packages%2Fapp-core%2Fsrc%2Fshell%2FAppWindowRenderer.tsx%0ALine%3A%201643-1666%0A%0AComment%3A%0A**Catalog%20fetch%20is%20duplicated%20between%20%60AppDetailsView%60%20and%20%60RegistryAppWindowView%60**%0A%0A%60RegistryAppWindowView%60%20fetches%20%60client.listApps%28%29%60%20%2B%20%60client.listCatalogApps%28%29%60%20with%20the%20same%20deduplication%20logic%20that%20already%20exists%20in%20%60AppDetailsView%60.%20If%20both%20components%20are%20active%20for%20the%20same%20slug%20simultaneously%2C%20the%20API%20is%20hit%20twice%20with%20no%20shared%20cache.%20Extracting%20the%20catalog%20fetch%20into%20a%20shared%20hook%20or%20context%20would%20eliminate%20the%20duplication%20and%20reduce%20API%20load.%0A%0AHow%20can%20I%20resolve%20this%3F%20If%20you%20propose%20a%20fix%2C%20please%20make%20it%20concise.&repo=elizaos%2Feliza&pr=7114&platform=github\"><picture><source media=\"(prefers-color-scheme: dark)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInClaudeDark.svg?v=2\"><source media=\"(prefers-color-scheme: light)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInClaude.svg?v=2\"><img alt=\"Fix in Claude Code\" src=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInClaude.svg?v=2\" height=\"20\"></picture></a> <a href=\"https://chatgpt.com/codex/deeplink?prompt=IMPORTANT%3A%20Work%20in%20the%20repository%20%22elizaos%2Feliza%22%20on%20the%20existing%20branch%20%22feat%2Fapps-native-windows%22.%20Checkout%20that%20branch%20%E2%80%94%20do%20NOT%20create%20a%20new%20branch%20or%20open%20a%20new%20PR.%20Push%20your%20changes%20to%20%22feat%2Fapps-native-windows%22.%0A%0AThis%20is%20a%20comment%20left%20during%20a%20code%20review.%0APath%3A%20packages%2Fapp-core%2Fsrc%2Fshell%2FAppWindowRenderer.tsx%0ALine%3A%201643-1666%0A%0AComment%3A%0A**Catalog%20fetch%20is%20duplicated%20between%20%60AppDetailsView%60%20and%20%60RegistryAppWindowView%60**%0A%0A%60RegistryAppWindowView%60%20fetches%20%60client.listApps%28%29%60%20%2B%20%60client.listCatalogApps%28%29%60%20with%20the%20same%20deduplication%20logic%20that%20already%20exists%20in%20%60AppDetailsView%60.%20If%20both%20components%20are%20active%20for%20the%20same%20slug%20simultaneously%2C%20the%20API%20is%20hit%20twice%20with%20no%20shared%20cache.%20Extracting%20the%20catalog%20fetch%20into%20a%20shared%20hook%20or%20context%20would%20eliminate%20the%20duplication%20and%20reduce%20API%20load.%0A%0AHow%20can%20I%20resolve%20this%3F%20If%20you%20propose%20a%20fix%2C%20please%20make%20it%20concise.\"><picture><source media=\"(prefers-color-scheme: dark)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInCodexDark.svg?v=2\"><source media=\"(prefers-color-scheme: light)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInCodex.svg?v=2\"><img alt=\"Fix in Codex\" src=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInCodex.svg?v=2\" height=\"20\"></picture></a> <a href=\"https://app.greptile.com/api/ide/cursor?prompt=This%20is%20a%20comment%20left%20during%20a%20code%20review.%0APath%3A%20packages%2Fapp-core%2Fsrc%2Fshell%2FAppWindowRenderer.tsx%0ALine%3A%201643-1666%0A%0AComment%3A%0A**Catalog%20fetch%20is%20duplicated%20between%20%60AppDetailsView%60%20and%20%60RegistryAppWindowView%60**%0A%0A%60RegistryAppWindowView%60%20fetches%20%60client.listApps%28%29%60%20%2B%20%60client.listCatalogApps%28%29%60%20with%20the%20same%20deduplication%20logic%20that%20already%20exists%20in%20%60AppDetailsView%60.%20If%20both%20components%20are%20active%20for%20the%20same%20slug%20simultaneously%2C%20the%20API%20is%20hit%20twice%20with%20no%20shared%20cache.%20Extracting%20the%20catalog%20fetch%20into%20a%20shared%20hook%20or%20context%20would%20eliminate%20the%20duplication%20and%20reduce%20API%20load.%0A%0AHow%20can%20I%20resolve%20this%3F%20If%20you%20propose%20a%20fix%2C%20please%20make%20it%20concise.&pr=7114&platform=github\"><picture><source media=\"(prefers-color-scheme: dark)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInCursorDark.svg?v=2\"><source media=\"(prefers-color-scheme: light)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInCursor.svg?v=2\"><img alt=\"Fix in Cursor\" src=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixInCursor.svg?v=2\" height=\"20\"></picture></a>\n</details>\n\n<!-- /greptile_failed_comments -->\n\n<a href=\"https://app.greptile.com/ide/claude-code?prompt=Fix%20the%20following%203%20code%20review%20issues.%20Work%20through%20them%20one%20at%20a%20time%2C%20proposing%20concise%20fixes.%0A%0A---%0A%0A%23%23%23%20Issue%201%20of%203%0Apackages%2Fapp-core%2Fsrc%2Fcomponents%2Fpages%2FAppDetailsView.tsx%3A96-109%0A**%60resolveAppFromSlug%60%20fails%20for%20Steward%20and%20Fine%20Tuning**%0A%0AThe%20internal-tool%20lookup%20uses%20%60d.windowPath%20%3D%3D%3D%20%5C%60%2Fapps%2F%24%7Bslug%7D%5C%60%60%20to%20find%20a%20descriptor.%20This%20breaks%20for%20two%20of%20the%20four%20apps%20that%20declare%20%60hasDetailsPage%3A%20true%60%3A%0A%0A%7C%20App%20%7C%20slug%20%28from%20%60APP_MENU_ENTRIES%60%29%20%7C%20windowPath%20%7C%0A%7C---%7C---%7C---%7C%0A%7C%20Steward%20%7C%20%60%22steward%22%60%20%7C%20%60%2Fapps%2Finventory%60%20%7C%0A%7C%20Fine%20Tuning%20%7C%20%60%22training%22%60%20%7C%20%60%2Fapps%2Ffine-tuning%60%20%7C%0A%0AWhen%20the%20menu%2Ftray%20fires%20%60desktopAppDetailsRequested%60%20with%20slug%20%60%22steward%22%60%2C%20%60AppDetailsView%60%20is%20mounted%20with%20%60slug%3D%22steward%22%60.%20The%20lookup%20checks%20%60d.windowPath%20%3D%3D%3D%20%22%2Fapps%2Fsteward%22%60%20but%20finds%20no%20match%20%28steward's%20path%20is%20%60%2Fapps%2Finventory%60%29.%20The%20component%20falls%20through%20to%20the%20catalog%20lookup%2C%20which%20also%20won't%20find%20an%20internal%20tool%20by%20that%20slug%2C%20leaving%20the%20view%20stuck%20on%20the%20%22Loading%20steward%E2%80%A6%22%20spinner.%0A%0AThe%20fix%20is%20to%20match%20by%20slug%20instead%20of%20by%20window-path%20segment%3A%0A%0A%60%60%60tsx%0Aconst%20internal%20%3D%20getInternalToolAppDescriptors%28%29.find%28%0A%20%20%28d%29%20%3D%3E%20getAppSlug%28d.name%29%20%3D%3D%3D%20slug%2C%0A%29%3B%0A%60%60%60%0A%0A%60getAppSlug%60%20is%20already%20imported%20in%20this%20file%20and%20converts%20e.g.%20%60%40elizaos%2Fapp-steward%60%20%E2%86%92%20%60%22steward%22%60%2C%20which%20lines%20up%20with%20the%20slugs%20emitted%20by%20%60APP_MENU_ENTRIES%60.%0A%0A%23%23%23%20Issue%202%20of%203%0Apackages%2Fapp-core%2Fsrc%2Fcomponents%2Fapps%2FuseRegistryCatalog.ts%3A22-37%0A**Dedup%20filter%20favors%20the%20later%20duplicate%2C%20not%20the%20earlier%20one**%0A%0AThe%20catalog%20deduplication%20keeps%20the%20first%20occurrence%20of%20each%20name%20across%20the%20merged%20%60%5B...catalogApps%2C%20...serverApps%5D%60%20array%20by%20checking%20that%20no%20*later*%20entry%20shares%20the%20same%20name%3A%0A%0A%60%60%60ts%0A.filter%28%0A%20%20%28entry%2C%20index%2C%20items%29%20%3D%3E%0A%20%20%20%20!items%0A%20%20%20%20%20%20.slice%28index%20%2B%201%29%0A%20%20%20%20%20%20.some%28%28candidate%29%20%3D%3E%20candidate.name%20%3D%3D%3D%20entry.name%29%2C%0A%29%0A%60%60%60%0A%0AThis%20actually%20keeps%20the%20*last*%20duplicate%20%28the%20entry%20for%20which%20no%20later%20entry%20shares%20the%20name%29%2C%20meaning%20%60serverApps%60%20entries%20silently%20win%20over%20%60catalogApps%60%20entries%20of%20the%20same%20name.%20If%20the%20intent%20is%20for%20registry%20catalog%20data%20to%20take%20precedence%20%28e.g.%20richer%20%60description%60%20%2F%20%60heroImage%60%29%2C%20the%20order%20should%20be%20%60%5B...serverApps%2C%20...catalogApps%5D%60%2C%20or%20the%20filter%20should%20check%20%60items.slice%280%2C%20index%29%60%20instead%20of%20%60items.slice%28index%20%2B%201%29%60.%0A%0A%23%23%23%20Issue%203%20of%203%0Apackages%2Fapp-core%2Fplatforms%2Felectrobun%2Fsrc%2Fsurface-windows.ts%3A446-473%0A**Debounce%20timer%20not%20cancelled%20on%20window%20close**%0A%0A%60saveTimer%60%20lives%20inside%20the%20%60scheduleSave%60%20closure%20but%20is%20never%20cleared%20when%20the%20window%20emits%20%60%22close%22%60.%20If%20the%20user%20drags%20a%20window%20and%20immediately%20closes%20it%20within%20the%20500%20ms%20debounce%20window%2C%20the%20pending%20%60setTimeout%60%20still%20fires.%20At%20that%20point%20%60window.getFrame%3F.%28%29%60%20may%20throw%20%28destroyed%20native%20window%29%20or%20return%20stale%20geometry%20%E2%80%94%20the%20%60try%2Fcatch%60%20swallows%20the%20error%2C%20so%20nothing%20breaks%2C%20but%20the%20bounds%20file%20is%20updated%20with%20potentially%20wrong%20data%2C%20meaning%20the%20window%20restores%20to%20a%20bad%20position%20on%20next%20launch.%0A%0AHooking%20the%20cleanup%20to%20%60%22close%22%60%20prevents%20this%3A%0A%0A%60%60%60ts%0Awindow.on%28%22close%22%2C%20%28%29%20%3D%3E%20%7B%0A%20%20if%20%28saveTimer%29%20%7B%0A%20%20%20%20clearTimeout%28saveTimer%29%3B%0A%20%20%20%20saveTimer%20%3D%20null%3B%0A%20%20%7D%0A%7D%29%3B%0A%60%60%60%0A%0A&repo=elizaos%2Feliza&pr=7114&platform=github\"><picture><source media=\"(prefers-color-scheme: dark)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInClaudeDark.svg?v=2\"><source media=\"(prefers-color-scheme: light)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInClaude.svg?v=2\"><img alt=\"Fix All in Claude Code\" src=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInClaude.svg?v=2\" height=\"20\"></picture></a> <a href=\"https://chatgpt.com/codex/deeplink?prompt=IMPORTANT%3A%20Work%20in%20the%20repository%20%22elizaos%2Feliza%22%20on%20the%20existing%20branch%20%22feat%2Fapps-native-windows%22.%20Checkout%20that%20branch%20%E2%80%94%20do%20NOT%20create%20a%20new%20branch%20or%20open%20a%20new%20PR.%20Push%20your%20changes%20to%20%22feat%2Fapps-native-windows%22.%0A%0AFix%20the%20following%203%20code%20review%20issues.%20Work%20through%20them%20one%20at%20a%20time%2C%20proposing%20concise%20fixes.%0A%0A---%0A%0A%23%23%23%20Issue%201%20of%203%0Apackages%2Fapp-core%2Fsrc%2Fcomponents%2Fpages%2FAppDetailsView.tsx%3A96-109%0A**%60resolveAppFromSlug%60%20fails%20for%20Steward%20and%20Fine%20Tuning**%0A%0AThe%20internal-tool%20lookup%20uses%20%60d.windowPath%20%3D%3D%3D%20%5C%60%2Fapps%2F%24%7Bslug%7D%5C%60%60%20to%20find%20a%20descriptor.%20This%20breaks%20for%20two%20of%20the%20four%20apps%20that%20declare%20%60hasDetailsPage%3A%20true%60%3A%0A%0A%7C%20App%20%7C%20slug%20%28from%20%60APP_MENU_ENTRIES%60%29%20%7C%20windowPath%20%7C%0A%7C---%7C---%7C---%7C%0A%7C%20Steward%20%7C%20%60%22steward%22%60%20%7C%20%60%2Fapps%2Finventory%60%20%7C%0A%7C%20Fine%20Tuning%20%7C%20%60%22training%22%60%20%7C%20%60%2Fapps%2Ffine-tuning%60%20%7C%0A%0AWhen%20the%20menu%2Ftray%20fires%20%60desktopAppDetailsRequested%60%20with%20slug%20%60%22steward%22%60%2C%20%60AppDetailsView%60%20is%20mounted%20with%20%60slug%3D%22steward%22%60.%20The%20lookup%20checks%20%60d.windowPath%20%3D%3D%3D%20%22%2Fapps%2Fsteward%22%60%20but%20finds%20no%20match%20%28steward's%20path%20is%20%60%2Fapps%2Finventory%60%29.%20The%20component%20falls%20through%20to%20the%20catalog%20lookup%2C%20which%20also%20won't%20find%20an%20internal%20tool%20by%20that%20slug%2C%20leaving%20the%20view%20stuck%20on%20the%20%22Loading%20steward%E2%80%A6%22%20spinner.%0A%0AThe%20fix%20is%20to%20match%20by%20slug%20instead%20of%20by%20window-path%20segment%3A%0A%0A%60%60%60tsx%0Aconst%20internal%20%3D%20getInternalToolAppDescriptors%28%29.find%28%0A%20%20%28d%29%20%3D%3E%20getAppSlug%28d.name%29%20%3D%3D%3D%20slug%2C%0A%29%3B%0A%60%60%60%0A%0A%60getAppSlug%60%20is%20already%20imported%20in%20this%20file%20and%20converts%20e.g.%20%60%40elizaos%2Fapp-steward%60%20%E2%86%92%20%60%22steward%22%60%2C%20which%20lines%20up%20with%20the%20slugs%20emitted%20by%20%60APP_MENU_ENTRIES%60.%0A%0A%23%23%23%20Issue%202%20of%203%0Apackages%2Fapp-core%2Fsrc%2Fcomponents%2Fapps%2FuseRegistryCatalog.ts%3A22-37%0A**Dedup%20filter%20favors%20the%20later%20duplicate%2C%20not%20the%20earlier%20one**%0A%0AThe%20catalog%20deduplication%20keeps%20the%20first%20occurrence%20of%20each%20name%20across%20the%20merged%20%60%5B...catalogApps%2C%20...serverApps%5D%60%20array%20by%20checking%20that%20no%20*later*%20entry%20shares%20the%20same%20name%3A%0A%0A%60%60%60ts%0A.filter%28%0A%20%20%28entry%2C%20index%2C%20items%29%20%3D%3E%0A%20%20%20%20!items%0A%20%20%20%20%20%20.slice%28index%20%2B%201%29%0A%20%20%20%20%20%20.some%28%28candidate%29%20%3D%3E%20candidate.name%20%3D%3D%3D%20entry.name%29%2C%0A%29%0A%60%60%60%0A%0AThis%20actually%20keeps%20the%20*last*%20duplicate%20%28the%20entry%20for%20which%20no%20later%20entry%20shares%20the%20name%29%2C%20meaning%20%60serverApps%60%20entries%20silently%20win%20over%20%60catalogApps%60%20entries%20of%20the%20same%20name.%20If%20the%20intent%20is%20for%20registry%20catalog%20data%20to%20take%20precedence%20%28e.g.%20richer%20%60description%60%20%2F%20%60heroImage%60%29%2C%20the%20order%20should%20be%20%60%5B...serverApps%2C%20...catalogApps%5D%60%2C%20or%20the%20filter%20should%20check%20%60items.slice%280%2C%20index%29%60%20instead%20of%20%60items.slice%28index%20%2B%201%29%60.%0A%0A%23%23%23%20Issue%203%20of%203%0Apackages%2Fapp-core%2Fplatforms%2Felectrobun%2Fsrc%2Fsurface-windows.ts%3A446-473%0A**Debounce%20timer%20not%20cancelled%20on%20window%20close**%0A%0A%60saveTimer%60%20lives%20inside%20the%20%60scheduleSave%60%20closure%20but%20is%20never%20cleared%20when%20the%20window%20emits%20%60%22close%22%60.%20If%20the%20user%20drags%20a%20window%20and%20immediately%20closes%20it%20within%20the%20500%20ms%20debounce%20window%2C%20the%20pending%20%60setTimeout%60%20still%20fires.%20At%20that%20point%20%60window.getFrame%3F.%28%29%60%20may%20throw%20%28destroyed%20native%20window%29%20or%20return%20stale%20geometry%20%E2%80%94%20the%20%60try%2Fcatch%60%20swallows%20the%20error%2C%20so%20nothing%20breaks%2C%20but%20the%20bounds%20file%20is%20updated%20with%20potentially%20wrong%20data%2C%20meaning%20the%20window%20restores%20to%20a%20bad%20position%20on%20next%20launch.%0A%0AHooking%20the%20cleanup%20to%20%60%22close%22%60%20prevents%20this%3A%0A%0A%60%60%60ts%0Awindow.on%28%22close%22%2C%20%28%29%20%3D%3E%20%7B%0A%20%20if%20%28saveTimer%29%20%7B%0A%20%20%20%20clearTimeout%28saveTimer%29%3B%0A%20%20%20%20saveTimer%20%3D%20null%3B%0A%20%20%7D%0A%7D%29%3B%0A%60%60%60%0A%0A\"><picture><source media=\"(prefers-color-scheme: dark)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodexDark.svg?v=2\"><source media=\"(prefers-color-scheme: light)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=2\"><img alt=\"Fix All in Codex\" src=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=2\" height=\"20\"></picture></a> <a href=\"https://app.greptile.com/api/ide/cursor?prompt=Fix%20the%20following%203%20code%20review%20issues.%20Work%20through%20them%20one%20at%20a%20time%2C%20proposing%20concise%20fixes.%0A%0A---%0A%0A%23%23%23%20Issue%201%20of%203%0Apackages%2Fapp-core%2Fsrc%2Fcomponents%2Fpages%2FAppDetailsView.tsx%3A96-109%0A**%60resolveAppFromSlug%60%20fails%20for%20Steward%20and%20Fine%20Tuning**%0A%0AThe%20internal-tool%20lookup%20uses%20%60d.windowPath%20%3D%3D%3D%20%5C%60%2Fapps%2F%24%7Bslug%7D%5C%60%60%20to%20find%20a%20descriptor.%20This%20breaks%20for%20two%20of%20the%20four%20apps%20that%20declare%20%60hasDetailsPage%3A%20true%60%3A%0A%0A%7C%20App%20%7C%20slug%20%28from%20%60APP_MENU_ENTRIES%60%29%20%7C%20windowPath%20%7C%0A%7C---%7C---%7C---%7C%0A%7C%20Steward%20%7C%20%60%22steward%22%60%20%7C%20%60%2Fapps%2Finventory%60%20%7C%0A%7C%20Fine%20Tuning%20%7C%20%60%22training%22%60%20%7C%20%60%2Fapps%2Ffine-tuning%60%20%7C%0A%0AWhen%20the%20menu%2Ftray%20fires%20%60desktopAppDetailsRequested%60%20with%20slug%20%60%22steward%22%60%2C%20%60AppDetailsView%60%20is%20mounted%20with%20%60slug%3D%22steward%22%60.%20The%20lookup%20checks%20%60d.windowPath%20%3D%3D%3D%20%22%2Fapps%2Fsteward%22%60%20but%20finds%20no%20match%20%28steward's%20path%20is%20%60%2Fapps%2Finventory%60%29.%20The%20component%20falls%20through%20to%20the%20catalog%20lookup%2C%20which%20also%20won't%20find%20an%20internal%20tool%20by%20that%20slug%2C%20leaving%20the%20view%20stuck%20on%20the%20%22Loading%20steward%E2%80%A6%22%20spinner.%0A%0AThe%20fix%20is%20to%20match%20by%20slug%20instead%20of%20by%20window-path%20segment%3A%0A%0A%60%60%60tsx%0Aconst%20internal%20%3D%20getInternalToolAppDescriptors%28%29.find%28%0A%20%20%28d%29%20%3D%3E%20getAppSlug%28d.name%29%20%3D%3D%3D%20slug%2C%0A%29%3B%0A%60%60%60%0A%0A%60getAppSlug%60%20is%20already%20imported%20in%20this%20file%20and%20converts%20e.g.%20%60%40elizaos%2Fapp-steward%60%20%E2%86%92%20%60%22steward%22%60%2C%20which%20lines%20up%20with%20the%20slugs%20emitted%20by%20%60APP_MENU_ENTRIES%60.%0A%0A%23%23%23%20Issue%202%20of%203%0Apackages%2Fapp-core%2Fsrc%2Fcomponents%2Fapps%2FuseRegistryCatalog.ts%3A22-37%0A**Dedup%20filter%20favors%20the%20later%20duplicate%2C%20not%20the%20earlier%20one**%0A%0AThe%20catalog%20deduplication%20keeps%20the%20first%20occurrence%20of%20each%20name%20across%20the%20merged%20%60%5B...catalogApps%2C%20...serverApps%5D%60%20array%20by%20checking%20that%20no%20*later*%20entry%20shares%20the%20same%20name%3A%0A%0A%60%60%60ts%0A.filter%28%0A%20%20%28entry%2C%20index%2C%20items%29%20%3D%3E%0A%20%20%20%20!items%0A%20%20%20%20%20%20.slice%28index%20%2B%201%29%0A%20%20%20%20%20%20.some%28%28candidate%29%20%3D%3E%20candidate.name%20%3D%3D%3D%20entry.name%29%2C%0A%29%0A%60%60%60%0A%0AThis%20actually%20keeps%20the%20*last*%20duplicate%20%28the%20entry%20for%20which%20no%20later%20entry%20shares%20the%20name%29%2C%20meaning%20%60serverApps%60%20entries%20silently%20win%20over%20%60catalogApps%60%20entries%20of%20the%20same%20name.%20If%20the%20intent%20is%20for%20registry%20catalog%20data%20to%20take%20precedence%20%28e.g.%20richer%20%60description%60%20%2F%20%60heroImage%60%29%2C%20the%20order%20should%20be%20%60%5B...serverApps%2C%20...catalogApps%5D%60%2C%20or%20the%20filter%20should%20check%20%60items.slice%280%2C%20index%29%60%20instead%20of%20%60items.slice%28index%20%2B%201%29%60.%0A%0A%23%23%23%20Issue%203%20of%203%0Apackages%2Fapp-core%2Fplatforms%2Felectrobun%2Fsrc%2Fsurface-windows.ts%3A446-473%0A**Debounce%20timer%20not%20cancelled%20on%20window%20close**%0A%0A%60saveTimer%60%20lives%20inside%20the%20%60scheduleSave%60%20closure%20but%20is%20never%20cleared%20when%20the%20window%20emits%20%60%22close%22%60.%20If%20the%20user%20drags%20a%20window%20and%20immediately%20closes%20it%20within%20the%20500%20ms%20debounce%20window%2C%20the%20pending%20%60setTimeout%60%20still%20fires.%20At%20that%20point%20%60window.getFrame%3F.%28%29%60%20may%20throw%20%28destroyed%20native%20window%29%20or%20return%20stale%20geometry%20%E2%80%94%20the%20%60try%2Fcatch%60%20swallows%20the%20error%2C%20so%20nothing%20breaks%2C%20but%20the%20bounds%20file%20is%20updated%20with%20potentially%20wrong%20data%2C%20meaning%20the%20window%20restores%20to%20a%20bad%20position%20on%20next%20launch.%0A%0AHooking%20the%20cleanup%20to%20%60%22close%22%60%20prevents%20this%3A%0A%0A%60%60%60ts%0Awindow.on%28%22close%22%2C%20%28%29%20%3D%3E%20%7B%0A%20%20if%20%28saveTimer%29%20%7B%0A%20%20%20%20clearTimeout%28saveTimer%29%3B%0A%20%20%20%20saveTimer%20%3D%20null%3B%0A%20%20%7D%0A%7D%29%3B%0A%60%60%60%0A%0A&pr=7114&platform=github\"><picture><source media=\"(prefers-color-scheme: dark)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCursorDark.svg?v=2\"><source media=\"(prefers-color-scheme: light)\" srcset=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCursor.svg?v=2\"><img alt=\"Fix All in Cursor\" src=\"https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCursor.svg?v=2\" height=\"20\"></picture></a>\n\n<sub>Reviews (2): Last reviewed commit: [\"Merge branch &#39;develop&#39; into feat/apps-na...\"](https://github.com/elizaos/eliza/commit/a31ba1d293ee30a835d600c5a41fabc9019fe563) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=29754613)</sub>\n\n> Greptile also left **1 inline comment** on this PR.\n\n<!-- /greptile_comment -->",
      "repository": "elizaos/eliza",
      "createdAt": "2026-04-26T11:26:13Z",
      "mergedAt": null,
      "additions": 3650,
      "deletions": 1711
    },
    {
      "id": "PR_kwDOMT5cIs7VsCVk",
      "title": "Codex signal cli auto install",
      "author": "lalalune",
      "number": 7107,
      "body": "<!-- Use this template by filling in information and copying and pasting relevant items out of the HTML comments. -->\r\n\r\n# Relates to\r\n\r\n<!-- LINK TO ISSUE OR TICKET -->\r\n\r\n<!-- This risks section must be filled out before the final review and merge. -->\r\n\r\n# Risks\r\n\r\n<!--\r\nLow, medium, large. List what kind of risks and what could be affected.\r\n-->\r\n\r\n# Background\r\n\r\n## What does this PR do?\r\n\r\n## What kind of change is this?\r\n\r\n<!--\r\nBug fixes (non-breaking change which fixes an issue)\r\nImprovements (misc. changes to existing features)\r\nFeatures (non-breaking change which adds functionality)\r\nUpdates (new versions of included code)\r\n-->\r\n\r\n<!-- This \"Why\" section is most relevant if there are no linked issues explaining why. If there is a related issue, it might make sense to skip this why section. -->\r\n<!--\r\n## Why are we doing this? Any context or related work?\r\n-->\r\n\r\n# Documentation changes needed?\r\n\r\n<!--\r\nMy changes do not require a change to the project documentation.\r\nMy changes require a change to the project documentation.\r\nIf documentation change is needed: I have updated the documentation accordingly.\r\n-->\r\n\r\n<!-- Please show how you tested the PR. This will really help if the PR needs to be retested and probably help the PR get merged quicker. -->\r\n\r\n# Testing\r\n\r\n## Where should a reviewer start?\r\n\r\n## Detailed testing steps\r\n\r\n<!--\r\nNone: Automated tests are acceptable.\r\n-->\r\n\r\n<!--\r\n- As [anon/admin], go to [link]\r\n  - [do action]\r\n  - verify [result]\r\n-->\r\n\r\n<!-- If there is a UI change, please include before and after screenshots or videos. This will speed up PRs being merged. It is extra nice to annotate screenshots with arrows or boxes pointing out the differences. -->\r\n<!--\r\n## Screenshots\r\n### Before\r\n### After\r\n-->\r\n\r\n<!-- If there is anything about the deployment, please make a note. -->\r\n<!--\r\n# Deploy Notes\r\n-->\r\n\r\n<!--  Copy and paste command line output. -->\r\n<!--\r\n## Database changes\r\n-->\r\n\r\n<!--  Please specify deploy instructions if there is something more than the automated steps. -->\r\n<!--\r\n## Deployment instructions\r\n-->\r\n\r\n<!-- If you are on Discord, please join https://discord.gg/ai16z and state your Discord username here for the contributor role and join us in #development-feed -->\r\n<!--\r\n## Discord username\r\n\r\n-->\n\n<!-- greptile_comment -->\n\n<h3>Greptile Summary</h3>\n\nThis PR adds Homebrew-based auto-install of `signal-cli` on macOS/Linux when the binary is not already present, and exposes a `SIGNAL_CLI_AUTO_INSTALL` env var to opt out. The `service.ts` daemon path is cleaned up to share the new resolver from `pairing-service.ts`.\n\n- The user-facing `signalCliInstallInstructions` strings reference **\"Milady\"** (e.g. _\"Milady can auto-install...\"_) which appears to be the wrong product name for this project, and is visible whenever signal-cli is missing or fails to install.\n- The entire auto-install block is **duplicated verbatim** between `plugins/plugin-signal/typescript/src/pairing-service.ts` and `packages/agent/src/services/signal-pairing.ts`, meaning any future fix must be applied twice.\n\n<h3>Confidence Score: 4/5</h3>\n\nSafe to merge with minor follow-up items; no runtime breakage introduced.\n\nAll findings are P2 — no logic errors that cause incorrect behavior in the normal flow. The \"Milady\" branding is cosmetic, the env-var precedence issue only matters in an unusual dual-env-var configuration, and the resolveHomebrewPath empty-stdout edge case is unlikely in practice. The code duplication is the most actionable concern but doesn't affect correctness.\n\nplugins/plugin-signal/typescript/src/pairing-service.ts and packages/agent/src/services/signal-pairing.ts — duplicated auto-install logic and user-facing \"Milady\" strings.\n\n<h3>Important Files Changed</h3>\n\n| Filename | Overview |\n|----------|----------|\n| plugins/plugin-signal/typescript/src/pairing-service.ts | Core of the PR — adds auto-install logic for signal-cli via Homebrew; contains \"Milady\" branding in user-facing strings, a silent env-var precedence issue, and a resolveHomebrewPath fallback gap. |\n| packages/agent/src/services/signal-pairing.ts | Duplicate of the plugin's auto-install logic; identical issues apply — \"Milady\" strings, env-var precedence, and resolveHomebrewPath fallback. |\n| plugins/plugin-signal/typescript/src/service.ts | Removes its own resolveSignalCliPath and delegates to resolveSignalCliExecutable/missingSignalCliMessage from pairing-service; clean refactor. |\n| packages/app-core/src/registry/entries/connectors/signal.json | Adds SIGNAL_CLI_AUTO_INSTALL boolean config entry and updates SIGNAL_CLI_PATH help text; consistent with code changes. |\n| plugins/plugin-signal/typescript/package.json | Adds SIGNAL_CLI_AUTO_INSTALL to published env config schema; mirrors registry JSON change correctly. |\n| packages/agent/src/services/signal-pairing.test.ts | New unit tests covering the happy path, platform guards, opt-out env var, and custom path suppression; good coverage of the new branches. |\n| plugins/plugin-signal/typescript/src/pairing-service.test.ts | Duplicate of the agent test file for the plugin's pairing-service; same coverage gaps around the resolveHomebrewPath empty-stdout edge case. |\n| plugins/plugin-signal/typescript/src/config.ts | JSDoc comment update only — safe change. |\n\n</details>\n\n<h3>Flowchart</h3>\n\n```mermaid\n%%{init: {'theme': 'neutral'}}%%\nflowchart TD\n    A[resolveSignalCliExecutable called] --> B[resolveExecutablePath: which / existsSync]\n    B -->|found| Z[return path]\n    B -->|not found| C{canAutoInstall?\\ndarwin or linux}\n    C -->|no| N[return null]\n    C -->|yes| D{isDefaultSignalCliRequest?\\nno custom cliPath/SIGNAL_CLI_PATH}\n    D -->|no| N\n    D -->|yes| E{autoInstallEnabled?\\ncheck env vars}\n    E -->|disabled| N\n    E -->|enabled| F[resolveHomebrewPath:\\nwhich brew / COMMON_HOMEBREW_PATHS]\n    F -->|not found| N\n    F -->|found| G[brew install signal-cli]\n    G -->|error| ERR[throw Error with install instructions]\n    G -->|ok| H[resolveExecutablePath again]\n    H -->|found| Z\n    H -->|not found| N\n```\n\n<sub>Reviews (1): Last reviewed commit: [\"Cover Signal CLI install guidance across...\"](https://github.com/elizaos/eliza/commit/3e4d5904be485e59ba65097373415bea44165a6d) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=29744175)</sub>\n\n> Greptile also left **4 inline comments** on this PR.\n\n<!-- /greptile_comment -->",
      "repository": "elizaos/eliza",
      "createdAt": "2026-04-26T06:05:01Z",
      "mergedAt": "2026-04-26T06:05:09Z",
      "additions": 721,
      "deletions": 61
    },
    {
      "id": "PR_kwDOMT5cIs7VvcLe",
      "title": "feat(triggers): wire event-kind triggers to the runtime event bus",
      "author": "2-A-M",
      "number": 7116,
      "body": "## Summary\n\nAdds a `TriggerEventBridge` service that listens on the runtime event bus and dispatches matching event-kind triggers (Discord MESSAGE_RECEIVED, Telegram MESSAGE_RECEIVED, Webhook, etc.) to the trigger-handler pipeline. Without this bridge, event-kind triggers register fine but never fire — the events flow through the bus and nothing routes them to the trigger machinery.\n\n### What's new\n\n- **`packages/app-core/src/services/trigger-event-bridge.ts`** (176 lines, new file) — service that:\n  - Subscribes to the runtime event bus on boot.\n  - For each event, looks up registered triggers whose kind matches.\n  - Builds the trigger payload from the event data.\n  - Calls the trigger handler.\n  - No-ops cleanly if no triggers are registered for the event kind.\n\n- **`packages/app-core/src/services/trigger-event-bridge.test.ts`** (301 lines, new) — covers:\n  - Registered trigger fires when a matching event arrives.\n  - Unregistered trigger does not fire.\n  - Multiple triggers for the same event kind all fire.\n  - Trigger handler errors don't crash the bridge.\n  - Unsubscribe on service stop.\n\n- **`packages/app-core/src/runtime/eliza.ts`** (+45 lines) — wires the bridge service into the runtime startup sequence.\n\n### Why this is needed\n\nEvent-kind triggers (as opposed to time-kind triggers, which use cron) need a routing layer between the message bus and the trigger pipeline. Today, triggers register their kind/filter and a handler, but nothing connects the two. This PR is that connector.\n\nThis is the foundation for \"send me a Discord notification when X happens\" / \"fire this n8n workflow when a Telegram message arrives\" patterns — both verified working downstream once this lands.\n\n## Test plan\n\n- [x] Unit test suite (301 lines) covers register/unregister, fire, multi-trigger, error isolation.\n- [x] Verified live downstream: event-kind triggers now fire when their bound event arrives on the bus.\n- [ ] Reviewer: `bun test packages/app-core/src/services/trigger-event-bridge.test.ts`.\n\n<!-- This is an auto-generated comment: release notes by coderabbit.ai -->\n\n## Summary by CodeRabbit\n\n* **New Features**\n  * Event-driven triggers now react to real-time system events with configurable rate limiting and filtering.\n  * Enhanced runtime lifecycle management for trigger initialization and cleanup during system startup and shutdown.\n\n* **Tests**\n  * Comprehensive test suite for event trigger dispatch, filtering, and error handling.\n\n<!-- end of auto-generated comment: release notes by coderabbit.ai -->\n\n<!-- greptile_comment -->\n\n<h3>Greptile Summary</h3>\n\nThis PR introduces a `TriggerEventBridge` service that subscribes to the runtime event bus and routes matching event-kind triggers through the existing `executeTriggerTask` pipeline, filling the gap where event triggers were registered but never fired.\n\n- **P0 — compile error blocks the feature entirely**: Line 161 of `trigger-event-bridge.ts` contains a stray `</search>` XML tag inside the `catch` block. TypeScript cannot parse `.ts` files as JSX, so this is a hard syntax error. `ensureTriggerEventBridge` will catch the import failure, log a warning, and silently skip — meaning event-kind triggers will still never fire after this PR lands.\n\n<h3>Confidence Score: 2/5</h3>\n\nNot safe to merge — the bridge module has a syntax error that prevents it from loading, making the core feature a no-op.\n\nA P0 syntax error (</search> tag on line 161) prevents the TypeScript module from compiling. Because ensureTriggerEventBridge wraps the dynamic import in a try/catch and only logs a warning on failure, the runtime starts normally but the bridge is never armed — event-kind triggers remain permanently broken, which is the exact regression this PR intends to fix.\n\npackages/app-core/src/services/trigger-event-bridge.ts — line 161 must be fixed before merging.\n\n<h3>Important Files Changed</h3>\n\n| Filename | Overview |\n|----------|----------|\n| packages/app-core/src/services/trigger-event-bridge.ts | New bridge service wiring event-bus to trigger pipeline — blocked by a stray </search> XML tag on line 161 that is a TypeScript syntax error, preventing the module from compiling and the bridge from loading. |\n| packages/app-core/src/services/trigger-event-bridge.test.ts | Well-structured test suite covering matching, filtering, rate-limiting, kill-switch, stop/unregister, and error isolation — all via injected seams. No issues found. |\n| packages/app-core/src/runtime/eliza.ts | Adds ensureTriggerEventBridge with correct hot-reload teardown pattern and shutdown cleanup — consistent with the existing n8nAuthBridge and n8nDispatch lifecycle management. |\n\n</details>\n\n<h3>Sequence Diagram</h3>\n\n```mermaid\nsequenceDiagram\n    participant Bus as Runtime Event Bus\n    participant Bridge as TriggerEventBridge\n    participant Cache as TTL Cache (500ms)\n    participant DB as DB / listTriggerTasks\n    participant Exec as executeTriggerTask\n\n    Note over Bridge: startTriggerEventBridge()<br/>registers handlers for each EventType\n\n    Bus->>Bridge: emit(MESSAGE_RECEIVED, payload)\n    Bridge->>Bridge: triggersFeatureEnabled()?\n    Bridge->>Cache: hasTriggersForEvent(eventType)?\n    alt cache fresh and no triggers\n        Cache-->>Bridge: false - return early\n    else cache stale or unknown\n        Bridge->>DB: getCachedTriggers()\n        DB-->>Cache: tasks[]\n        Cache-->>Bridge: tasks[]\n        loop each matching task\n            Bridge->>Bridge: filter enabled + triggerType=event + eventKind match\n            Bridge->>Bridge: rate-limit check (minIntervalMs)\n            Bridge->>Exec: dispatch(runtime, task, source=event)\n            Exec-->>Bridge: result\n        end\n    end\n\n    Note over Bridge: stop() unregisterEvent() for each handler\n```\n\n<sub>Reviews (3): Last reviewed commit: [\"packages: \\`listTriggerTasks\\` is called o...\"](https://github.com/elizaos/eliza/commit/26e3335c0e993c775342c438878da381c1ebf811) | [Re-trigger Greptile](https://app.greptile.com/api/retrigger?id=29765670)</sub>\n\n> Greptile also left **1 inline comment** on this PR.\n\n<!-- /greptile_comment -->",
      "repository": "elizaos/eliza",
      "createdAt": "2026-04-26T16:20:32Z",
      "mergedAt": "2026-04-26T17:47:57Z",
      "additions": 583,
      "deletions": 0
    },
    {
      "id": "PR_kwDOMT5cIs7Vxvib",
      "title": "[codex] fix LifeOps schedule persistence and splash asset path",
      "author": "jqmwa",
      "number": 7132,
      "body": "## What changed\n- aligned LifeOps schedule persistence with the current database schema\n- updated schedule sync contracts and merged-state derivation to use the current observation model (`state`, `phase`, `confidence`)\n- filled the newer relative-time and schedule insight fields that downstream readers and tests already expect\n- switched the startup shell and template brand-asset generators from `splash-bg.jpg` to `splash-bg.png`\n\n## Why\nThe LifeOps schedule writer was still inserting the old circadian-state column set into tables that now expect `phase`, `is_probably_sleeping`, and the typical sleep-hour fields. That mismatch was surfacing raw SQL failures in the Overview UI. The splash screen path change belongs with this fix because the startup shell and template generators had also drifted from the current branded asset.\n\n## Impact\n- stops `life_schedule_insights`, `life_schedule_observations`, and `life_schedule_merged_states` from writing the stale column shape\n- preserves compatibility-only merged-state fields through metadata for existing readers while the new schema remains the source of truth\n- makes the startup shell load the new branded splash image path consistently across templates\n\n## Validation\n- `bun x vitest run --config /Users/james/milady/eliza/apps/app-lifeops/vitest.config.ts /Users/james/milady/eliza/apps/app-lifeops/test/schedule-state.test.ts /Users/james/milady/eliza/apps/app-lifeops/test/schedule-sync-client.test.ts`\n- filtered root TypeScript check for the touched files reported no matches\n\n## Notes\n- the actual `apps/app/public/splash-bg.png` asset lives in the parent Milady repo, not this submodule, so that binary asset change is not part of this PR\n",
      "repository": "elizaos/eliza",
      "createdAt": "2026-04-26T22:16:22Z",
      "mergedAt": null,
      "additions": 477,
      "deletions": 118
    }
  ],
  "codeChanges": {
    "additions": 6417,
    "deletions": 2006,
    "files": 76,
    "commitCount": 326
  },
  "completedItems": [
    {
      "title": "chore(deps): update dependency vitest to v4",
      "prNumber": 7131,
      "type": "tests",
      "body": "> ℹ️ **Note**\n> \n> This PR body was truncated due to platform limits.\n\nThis PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-con",
      "files": [
        "templates/min-app/package.json",
        "templates/min-plugin/package.json"
      ]
    },
    {
      "title": "chore(deps): update dependency vite to v8",
      "prNumber": 7130,
      "type": "other",
      "body": "This PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n| [vite](https://vite.dev) ([source](http",
      "files": [
        "templates/min-app/package.json"
      ]
    },
    {
      "title": "chore(deps): update dependency @vitejs/plugin-react to v6",
      "prNumber": 7129,
      "type": "other",
      "body": "This PR contains the following updates:\n\n| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |\n|---|---|---|---|\n| [@vitejs/plugin-react](https://redirect",
      "files": [
        "templates/min-app/package.json"
      ]
    },
    {
      "title": "fix(automations): in-flight draft selection survives stale-id check + synthesizes draft item",
      "prNumber": 7128,
      "type": "bugfix",
      "body": "## Summary\n\nTwo coupled bugs around in-flight workflow drafts in `AutomationsView`:\n\n1. **Stale-id validation effect cleared the in-flight `workflow-draft:<id>` selection** before generation finished. The `selectedItemId` validation effect ",
      "files": [
        "packages/app-core/src/components/pages/AutomationsView.tsx"
      ]
    },
    {
      "title": "feat(automations): WorkflowGenerationProgress — multi-stage progress card",
      "prNumber": 7127,
      "type": "feature",
      "body": "## Summary\n\nReplaces the single \"Building workflow...\" chip in `WorkflowGraphViewer`'s generating overlay with a **6-stage timer-cycled progress card** that gives users meaningful feedback during the ~10–30s LLM workflow-generation window.\n",
      "files": [
        "packages/app-core/src/components/pages/WorkflowGraphViewer.tsx"
      ]
    },
    {
      "title": "test(n8n): pin handleGenerateWorkflow deployWorkflow path",
      "prNumber": 7126,
      "type": "tests",
      "body": "## Summary\n\nAdds unit-test coverage for the `handleGenerateWorkflow` → `service.deployWorkflow` → `service.getWorkflow` flow introduced by [#7118](https://github.com/elizaOS/eliza/pull/7118). This is the regression net for the route's new s",
      "files": [
        "packages/app-core/src/api/client-n8n.ts",
        "packages/app-core/src/api/n8n-routes.test.ts",
        "packages/app-core/src/api/n8n-routes.ts"
      ]
    },
    {
      "title": "fix(automations): hide right-rail chat dock on Overview empty state",
      "prNumber": 7125,
      "type": "bugfix",
      "body": "## Summary\n\nWhen the Automations Overview is in its empty state (no workflows, no triggers selected), the right-rail page-scoped chat dock was visible alongside the hero-input compose surface — two compose surfaces on screen at once with ov",
      "files": [
        "packages/app-core/src/components/pages/AutomationsView.tsx",
        "packages/app-core/src/components/workspace/AppWorkspaceChrome.tsx"
      ]
    },
    {
      "title": "fix(triggers): CREATE_TRIGGER_TASK page-automations unblock + LIFE handler hardening",
      "prNumber": 7124,
      "type": "bugfix",
      "body": "## Summary\n\nThree coordinated fixes for the page-automations `LIFE`-vs-trigger routing problem:\n\n1. **`packages/agent/src/triggers/action.ts`** — remove `SET_REMINDER` from `createTriggerTaskAction`'s similes (it collides with LIFE's simile",
      "files": [
        "apps/app-lifeops/src/actions/life.test.ts",
        "apps/app-lifeops/src/actions/life.ts",
        "packages/agent/src/triggers/action.ts",
        "packages/typescript/src/__tests__/owned-action-correction.test.ts",
        "packages/typescript/src/services/message.ts"
      ]
    },
    {
      "title": "fix(lifeops): scope-reject LIFE on foreign page-* scopes",
      "prNumber": 7123,
      "type": "bugfix",
      "body": "## Summary\n\nAdjusts the `LIFE` action handler in app-lifeops to scope-reject when invoked on a foreign `page-*` scope (e.g. `page-automations`, `page-chat`). Previously, `LIFE` would accept the action even from these foreign scopes, which g",
      "files": [
        "apps/app-lifeops/src/actions/life.test.ts",
        "apps/app-lifeops/src/actions/life.ts"
      ]
    },
    {
      "title": "fix(telegram): emit MESSAGE_RECEIVED on Telegram messages so event-kind triggers fire",
      "prNumber": 7122,
      "type": "bugfix",
      "body": "## Summary\n\nEmits `MESSAGE_RECEIVED` on the runtime event bus when an inbound Telegram message arrives via the in-process Telegram shim path. Without this emission, event-kind triggers bound to Telegram messages register fine but never fire",
      "files": [
        "packages/app-core/src/runtime/eliza.ts"
      ]
    },
    {
      "title": "fix(automations): delete chat conversation when workflow is deleted + skip orphan workflow rooms in aggregator",
      "prNumber": 7121,
      "type": "bugfix",
      "body": "## Summary\n\nTwo related cleanup fixes on the Automations layer:\n\n1. **Delete the per-workflow chat conversation when the workflow is deleted.** Previously, deleting a workflow left its `workflow:<id>` chat room in the database. Those rooms ",
      "files": [
        "packages/app-core/src/api/automations-compat-routes.ts",
        "packages/app-core/src/components/pages/AutomationsView.tsx"
      ]
    },
    {
      "title": "feat(automations): disambiguate workflow vs trigger + hide empty-state chat pane",
      "prNumber": 7120,
      "type": "feature",
      "body": "## Summary\n\nTwo small UX/planner improvements on the Automations page:\n\n1. **Planner-side disambiguation prompt:** the action-planner now distinguishes between user prompts that mean \"create an n8n workflow\" (multi-node automation pipeline)",
      "files": [
        "packages/app-core/src/components/pages/N8nWorkflowsPanel.tsx",
        "packages/app-core/src/i18n/locales/en.json",
        "packages/typescript/src/prompts.ts"
      ]
    },
    {
      "title": "fix(triggers): unblock CREATE_TRIGGER_TASK dispatch on page-automations",
      "prNumber": 7119,
      "type": "bugfix",
      "body": "## Summary\n\nFixes a routing bug where `CREATE_TRIGGER_TASK` actions issued from the page-automations scope were silently dropped before reaching the trigger-action handler.\n\n### Root cause\n\n`page-scoped-conversations.ts` filtered out `CREAT",
      "files": [
        "packages/agent/src/triggers/action.test.ts",
        "packages/agent/src/triggers/action.ts",
        "packages/app-core/src/components/pages/page-scoped-conversations.ts"
      ]
    },
    {
      "title": "fix(n8n): hero-chat workflow create resolves credentials end-to-end",
      "prNumber": 7118,
      "type": "bugfix",
      "body": "## Summary\n\nWires the credential-resolution path through the hero-chat workflow-creation entry point. Previously, workflows created via `POST /api/n8n/workflows/generate` proxied straight to n8n after generation and bypassed `service.deploy",
      "files": [
        "packages/app-core/src/api/client-n8n.ts",
        "packages/app-core/src/api/n8n-routes.ts"
      ]
    },
    {
      "title": "fix(chat): bump streaming generation timeout 90s -> 180s",
      "prNumber": 7117,
      "type": "bugfix",
      "body": "## Summary\n\nBumps the streaming chat-route generation timeout from 90s to 180s.\n\n90s is too short for many real-world LLM workloads we hit downstream:\n- Workflow generation against tool-use / structured-output models routinely takes 60-120s",
      "files": [
        "packages/agent/src/api/chat-routes.ts"
      ]
    },
    {
      "title": "feat(triggers): wire event-kind triggers to the runtime event bus",
      "prNumber": 7116,
      "type": "feature",
      "body": "## Summary\n\nAdds a `TriggerEventBridge` service that listens on the runtime event bus and dispatches matching event-kind triggers (Discord MESSAGE_RECEIVED, Telegram MESSAGE_RECEIVED, Webhook, etc.) to the trigger-handler pipeline. Without ",
      "files": [
        "packages/app-core/src/runtime/eliza.ts",
        "packages/app-core/src/services/trigger-event-bridge.test.ts",
        "packages/app-core/src/services/trigger-event-bridge.ts"
      ]
    },
    {
      "title": "feat(app-core): apps as native windows + App Details page (test-green)",
      "prNumber": 7115,
      "type": "feature",
      "body": "## Summary\n\nThis is the org-owned (milady-ai/eliza) version of [Dexploarer/eliza#26 → elizaOS/eliza#7114](https://github.com/elizaOS/eliza/pull/7114) — same changes, pushed from the org fork instead of a personal fork.\n\n- Every app — intern",
      "files": [
        "apps/app-companion/src/components/companion/CompanionAppView.tsx",
        "apps/app-companion/src/components/companion/CompanionView.tsx",
        "apps/app/src/main.tsx",
        "packages/app-core/platforms/electrobun/electrobun.config.ts",
        "packages/app-core/platforms/electrobun/src/application-menu.ts",
        "packages/app-core/platforms/electrobun/src/index.ts",
        "packages/app-core/platforms/electrobun/src/native/desktop.ts",
        "packages/app-core/platforms/electrobun/src/native/steward.ts",
        "packages/app-core/platforms/electrobun/src/rpc-handlers.ts",
        "packages/app-core/platforms/electrobun/src/rpc-schema.ts",
        "packages/app-core/platforms/electrobun/src/surface-windows.ts",
        "packages/app-core/src/App.tsx",
        "packages/app-core/src/api/auth.ts",
        "packages/app-core/src/components/apps/helpers.ts",
        "packages/app-core/src/components/apps/internal-tool-apps.ts",
        "packages/app-core/src/components/apps/launch-history.ts",
        "packages/app-core/src/components/apps/per-app-config.ts",
        "packages/app-core/src/components/apps/useRegistryCatalog.ts",
        "packages/app-core/src/components/character/CharacterOverviewSection.test.tsx",
        "packages/app-core/src/components/onboarding/BootstrapStep.tsx",
        "packages/app-core/src/components/pages/AppDetailsView.tsx",
        "packages/app-core/src/components/pages/AppsView.tsx",
        "packages/app-core/src/i18n/locales/en.json",
        "packages/app-core/src/i18n/locales/es.json",
        "packages/app-core/src/i18n/locales/ko.json",
        "packages/app-core/src/i18n/locales/pt.json",
        "packages/app-core/src/i18n/locales/tl.json",
        "packages/app-core/src/i18n/locales/vi.json",
        "packages/app-core/src/i18n/locales/zh-CN.json",
        "packages/app-core/src/navigation/index.ts",
        "packages/app-core/src/shell/AppWindowRenderer.tsx",
        "packages/app-core/src/shell/DetachedShellRoot.tsx",
        "packages/app-core/src/shell/index.ts",
        "packages/app-core/src/state/startup-phase-hydrate.test.ts",
        "packages/shared/src/app-hero-art.ts"
      ]
    },
    {
      "title": "chore(deps): bump lambda_runtime from 0.13.0 to 1.1.3 in /packages/examples/aws/rust",
      "prNumber": 7113,
      "type": "other",
      "body": "Bumps [lambda_runtime](https://github.com/aws/aws-lambda-rust-runtime) from 0.13.0 to 1.1.3.\n<details>\n<summary>Release notes</summary>\n<p><em>Sourced from <a href=\"https://github.com/aws/aws-lambda-rust-runtime/releases\">lambda_runtime's r",
      "files": [
        "packages/examples/aws/rust/Cargo.lock",
        "packages/examples/aws/rust/Cargo.toml"
      ]
    },
    {
      "title": "chore(deps): update ui-tars requirement from >=0.4.2.2 to >=0.5.1 in /packages/benchmarks/OSWorld",
      "prNumber": 7112,
      "type": "other",
      "body": "Updates the requirements on ui-tars to permit the latest version.\n\nDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.\n\n[//]: ",
      "files": [
        "packages/benchmarks/OSWorld/requirements.txt"
      ]
    },
    {
      "title": "chore(deps): update transformers requirement from ~=5.6.0 to ~=5.6.2 in /packages/benchmarks/OSWorld",
      "prNumber": 7111,
      "type": "other",
      "body": "Updates the requirements on [transformers](https://github.com/huggingface/transformers) to permit the latest version.\n<details>\n<summary>Release notes</summary>\n<p><em>Sourced from <a href=\"https://github.com/huggingface/transformers/releas",
      "files": [
        "packages/benchmarks/OSWorld/pyproject.toml",
        "packages/benchmarks/OSWorld/requirements.txt"
      ]
    },
    {
      "title": "chore(deps): bump axum from 0.7.9 to 0.8.9 in /packages/examples/gcp/rust",
      "prNumber": 7110,
      "type": "other",
      "body": "Bumps [axum](https://github.com/tokio-rs/axum) from 0.7.9 to 0.8.9.\n<details>\n<summary>Release notes</summary>\n<p><em>Sourced from <a href=\"https://github.com/tokio-rs/axum/releases\">axum's releases</a>.</em></p>\n<blockquote>\n<h2>axum-v0.8.",
      "files": [
        "packages/examples/gcp/rust/Cargo.lock",
        "packages/examples/gcp/rust/Cargo.toml"
      ]
    },
    {
      "title": "chore(deps): bump tower-http from 0.5.2 to 0.6.8 in /packages/examples/a2a/rust",
      "prNumber": 7109,
      "type": "other",
      "body": "Bumps [tower-http](https://github.com/tower-rs/tower-http) from 0.5.2 to 0.6.8.\n<details>\n<summary>Release notes</summary>\n<p><em>Sourced from <a href=\"https://github.com/tower-rs/tower-http/releases\">tower-http's releases</a>.</em></p>\n<bl",
      "files": [
        "packages/examples/a2a/rust/Cargo.lock",
        "packages/examples/a2a/rust/Cargo.toml"
      ]
    },
    {
      "title": "Codex signal cli auto install",
      "prNumber": 7107,
      "type": "other",
      "body": "<!-- Use this template by filling in information and copying and pasting relevant items out of the HTML comments. -->\r\n\r\n# Relates to\r\n\r\n<!-- LINK TO ISSUE OR TICKET -->\r\n\r\n<!-- This risks section must be filled out before the final review ",
      "files": [
        "packages/agent/src/services/signal-pairing.test.ts",
        "packages/agent/src/services/signal-pairing.ts",
        "packages/app-core/src/registry/entries/connectors/signal.json",
        "plugins/plugin-signal/typescript/package.json",
        "plugins/plugin-signal/typescript/src/config.ts",
        "plugins/plugin-signal/typescript/src/pairing-service.test.ts",
        "plugins/plugin-signal/typescript/src/pairing-service.ts",
        "plugins/plugin-signal/typescript/src/service.ts"
      ]
    },
    {
      "title": "chore(deps): update supabase/postgres docker tag to v17.6.1.111",
      "prNumber": 7105,
      "type": "other",
      "body": "This PR contains the following updates:\n\n| Package | Update | Change |\n|---|---|---|\n| supabase/postgres | patch | `17.6.1.110` → `17.6.1.111` |\n\n---\n\n> [!WARNING]\n> Some dependencies could not be looked up. Check the [Dependency Dashboard]",
      "files": [
        "packages/app-core/deploy/docker-compose.supabase-db.yml"
      ]
    },
    {
      "title": "chore(deps): bump openssl from 0.10.75 to 0.10.78 in /packages/examples/telegram/rust/telegram-agent in the cargo group across 1 directory",
      "prNumber": 7104,
      "type": "other",
      "body": "Bumps the cargo group with 1 update in the /packages/examples/telegram/rust/telegram-agent directory: [openssl](https://github.com/rust-openssl/rust-openssl).\n\nUpdates `openssl` from 0.10.75 to 0.10.78\n<details>\n<summary>Release notes</summ",
      "files": [
        "packages/examples/telegram/rust/telegram-agent/Cargo.lock"
      ]
    },
    {
      "title": "chore(deps): bump lxml from 6.0.1 to 6.1.0 in /packages/benchmarks/OSWorld in the uv group across 1 directory",
      "prNumber": 7103,
      "type": "other",
      "body": "Bumps the uv group with 1 update in the /packages/benchmarks/OSWorld directory: [lxml](https://github.com/lxml/lxml).\n\nUpdates `lxml` from 6.0.1 to 6.1.0\n<details>\n<summary>Changelog</summary>\n<p><em>Sourced from <a href=\"https://github.com",
      "files": [
        "packages/benchmarks/OSWorld/uv.lock"
      ]
    }
  ],
  "topContributors": [
    {
      "username": "2-A-M",
      "avatarUrl": "https://avatars.githubusercontent.com/u/96268540?u=b7d92c0e2a91af580d09eeae862eef576955ab8a&v=4",
      "totalScore": 373.23796770605895,
      "prScore": 373.23796770605895,
      "issueScore": 0,
      "reviewScore": 0,
      "commentScore": 0,
      "summary": "2-A-M: Drove significant stability and feature enhancements for the elizaos/eliza automation and trigger systems, most notably by wiring event-kind triggers to the runtime (#7116) and implementing multi-stage workflow generation (#7127). Their work focused heavily on resolving critical bugs and unblocking automation tasks, with a primary emphasis on bugfix and feature development across 68 files."
    },
    {
      "username": "Dexploarer",
      "avatarUrl": "https://avatars.githubusercontent.com/u/211557447?u=21a243d61cc1f87574328ae07fc64d7d7577b53d&v=4",
      "totalScore": 133.38895455609278,
      "prScore": 133.1889545560928,
      "issueScore": 0,
      "reviewScore": 0,
      "commentScore": 0.2,
      "summary": "Dexploarer: Drove significant architectural improvements to the application core by merging PR #7115, which introduced native window functionality and an App Details page, while maintaining momentum on critical dependency and re-export fixes in open PRs #7133 and #7114. Their work today was primarily focused on bugfixes and core feature development, involving extensive modifications across 1,726 files to enhance system stability and functionality."
    },
    {
      "username": "greptile-apps",
      "avatarUrl": "https://avatars.githubusercontent.com/in/867647?v=4",
      "totalScore": 126.2,
      "prScore": 0,
      "issueScore": 0,
      "reviewScore": 126,
      "commentScore": 0.2,
      "summary": "greptile-apps: Focused on collaborative code review and technical discussion, providing 28 reviews and 1 PR comment across the repositories."
    },
    {
      "username": "NubsCarson",
      "avatarUrl": "https://avatars.githubusercontent.com/u/192162056?u=d2be9082dbee60fcbad21d32bf6e662ab1af3674&v=4",
      "totalScore": 61.19254514307258,
      "prScore": 60.992545143072576,
      "issueScore": 0,
      "reviewScore": 0,
      "commentScore": 0.2,
      "summary": "NubsCarson: Focused on advancing monetization features through the submission of two open pull requests in elizaos/cloud (#473, #474) aimed at debiting organization credit balances. Their work involved 3 commits and a net reduction of 44 lines of code, reflecting a primary emphasis on bugfix and feature development."
    },
    {
      "username": "lalalune",
      "avatarUrl": "https://avatars.githubusercontent.com/u/18633264?u=e2e906c3712c2506ebfa98df01c2cfdc50050b30&v=4",
      "totalScore": 58.99253078396322,
      "prScore": 56.652530783963215,
      "issueScore": 2,
      "reviewScore": 0,
      "commentScore": 0.33999999999999997,
      "summary": "lalalune: Drove significant infrastructure improvements by merging PR #7107 to implement the Codex signal CLI auto-install and initiating tracking for the shaw/checkpoint-20260426-eliza branch integration via issue #7108. Their work today was characterized by a high volume of commits across a broad range of files, with a primary focus on general project maintenance and bugfix efforts."
    },
    {
      "username": "jqmwa",
      "avatarUrl": "https://avatars.githubusercontent.com/u/95416268?u=0413977243f889f0e371484ed3d4a5f21969d8ca&v=4",
      "totalScore": 41.07820333532675,
      "prScore": 41.07820333532675,
      "issueScore": 0,
      "reviewScore": 0,
      "commentScore": 0,
      "summary": "jqmwa: Focused on stabilizing system operations by opening PR #7132 in elizaos/eliza, which addresses critical LifeOps schedule persistence and asset path issues through 477 additions and 118 deletions. This work reflects a dedicated effort toward bug resolution and documentation maintenance."
    },
    {
      "username": "odilitime",
      "avatarUrl": "https://avatars.githubusercontent.com/u/16395496?u=c9bac48e632aae594a0d85aaf9e9c9c69b674d8b&v=4",
      "totalScore": 18.34,
      "prScore": 0,
      "issueScore": 0,
      "reviewScore": 18,
      "commentScore": 0.33999999999999997,
      "summary": "odilitime: Focused on stabilizing the codebase through extensive bugfix work, committing 662 additions and 18 deletions across 22 files. Their efforts were complemented by providing 4 detailed reviews and 2 PR comments, reflecting a primary focus on bug resolution and general maintenance."
    },
    {
      "username": "chopmob-cloud",
      "avatarUrl": "https://avatars.githubusercontent.com/u/250041792?u=295fb2375e2007927789532dae29a2c2bd3c5f80&v=4",
      "totalScore": 14.693147180559945,
      "prScore": 14.693147180559945,
      "issueScore": 0,
      "reviewScore": 0,
      "commentScore": 0,
      "summary": "chopmob-cloud: Focused on expanding ecosystem capabilities by opening PR #352 in elizaos-plugins/registry to integrate multi-chain A2A payment functionality via the @algovoi/plugin-elizaos."
    },
    {
      "username": "meanstackofdoom",
      "avatarUrl": "https://avatars.githubusercontent.com/u/64149093?u=1a1540f5e733b8c122a2435890eb6f614fb6467c&v=4",
      "totalScore": 0.33999999999999997,
      "prScore": 0,
      "issueScore": 0,
      "reviewScore": 0,
      "commentScore": 0.33999999999999997,
      "summary": "meanstackofdoom: Contributed to codebase maintenance by providing two pull request comments and executing two commits that modified two files. This work was evenly split between bugfix efforts and general project tasks."
    },
    {
      "username": "sailorpepe",
      "avatarUrl": "https://avatars.githubusercontent.com/u/159828807?u=9298c48eb8b41b0a0b0968e987c029e307771855&v=4",
      "totalScore": 0.2,
      "prScore": 0,
      "issueScore": 0,
      "reviewScore": 0,
      "commentScore": 0.2,
      "summary": "sailorpepe: Focused on maintaining code stability by addressing a bug through a single commit involving a 4-line modification. This effort was dedicated entirely to bugfix work across various file types."
    }
  ],
  "newPRs": 29,
  "mergedPRs": 26,
  "newIssues": 1,
  "closedIssues": 0,
  "activeContributors": 7
}