From 5a30ec8b9c4758602cc96e72ffd69e415422cd85 Mon Sep 17 00:00:00 2001 From: Blomios Date: Sat, 1 Aug 2026 16:23:56 +0200 Subject: [PATCH 1/2] fix(plugins): isole les menus plugin et durcit hello-plugin SDK contre la rechute #120 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Requalification Architect du 2026-08-01: le crash INTERFACE INTERROMPUE au chargement d'un plugin (menu + item) remonte via ProjectsView -> usePluginMenus -> MenuBar jusqu'à RootErrorBoundary, quel que soit le plugin (ancien ou reconstruit via SDK). - usePluginMenus isole la résolution/conversion des contributions plugin : toute erreur retombe sur [] au lieu de propager. - ProjectsView sépare les menus natifs des menus enrichis par plugin et rend MenuBar derrière une error boundary locale (fallback menus natifs seuls). - hello-plugin (SDK) et les tests d'installation associés durcis en cohérence. Bookkeeping ticket #120 uniquement (issue.md, carnet.md) ; les fichiers counter.json/index.json et le dossier tickets/122/ restent hors commit car une collision de numérotation #122 existe entre cette base et feature/ticket120-hello-plugin-install-path-audit (deux tickets différents revendiquent #122) — à arbitrer avant de committer le bookkeeping global. Co-Authored-By: Claude Sonnet 5 --- .ideai/tickets/120/carnet.md | 111 +++++++++++++++++- .ideai/tickets/120/issue.md | 6 +- .../tests/plugin_install_load.rs | 9 +- .../features/plugins/usePluginMenus.test.tsx | 75 ++++++++++++ .../src/features/plugins/usePluginMenus.ts | 105 ++++++++++++++--- .../src/features/projects/ProjectsView.tsx | 110 +++++++++++++---- frontend/src/plugins/runtime/loader.test.ts | 39 ++++-- frontend/src/plugins/runtime/loader.ts | 16 ++- sdk/IdeaSDK/examples/hello-plugin/README.md | 21 +++- .../examples/hello-plugin/idea-plugin.json | 22 +++- .../examples/hello-plugin/src/index.ts | 77 ++++++++++-- 11 files changed, 516 insertions(+), 75 deletions(-) create mode 100644 frontend/src/features/plugins/usePluginMenus.test.tsx diff --git a/.ideai/tickets/120/carnet.md b/.ideai/tickets/120/carnet.md index 010f5f6..97d0a74 100644 --- a/.ideai/tickets/120/carnet.md +++ b/.ideai/tickets/120/carnet.md @@ -1,6 +1,113 @@ --- issueRef: "#120" -version: 1 +version: 5 updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"} -updatedAt: 1785534496259 +updatedAt: 1785592705452 --- +# Carnet de suivi — hello-plugin + +## Etat courant + +- Ticket canonique: `#120` +- Date de rechute confirmee: 2026-08-01 +- Statut: investigation relancee sur rechute reelle post-rebuild SDK +- Severite: critique (l'UI d'IdeA tombe sur une erreur d'affichage lors de l'installation/chargement de `hello-plugin`) + +## Constat central au 2026-08-01 + +Le probleme persiste meme apres reconstruction de `hello-plugin` comme plugin d'exemple 100% SDK. + +Implication forte: +- la cause racine est probablement dans le systeme plugin / runtime frontend / chargement UI / integration layout-menu, et non dans l'ancien exemple `hello-plugin` uniquement. + +## Trace utilisateur fournie le 2026-08-01 + +Message visible: +- `IdeA a rencontre une erreur d'affichage.` +- `L'application reste ouverte. Rechargez la fenetre apres avoir copie le diagnostic si le probleme doit etre investigue.` + +Stack affichee: + +```text +kT@tauri://localhost/assets/index-CXNCu-GC.js:88:32937 +ST@tauri://localhost/assets/index-CXNCu-GC.js:88:31877 +om@tauri://localhost/assets/index-CXNCu-GC.js:38:17019 +oh@tauri://localhost/assets/index-CXNCu-GC.js:40:3141 +$b@tauri://localhost/assets/index-CXNCu-GC.js:40:39779 +SC@tauri://localhost/assets/index-CXNCu-GC.js:40:39707 +sc@tauri://localhost/assets/index-CXNCu-GC.js:40:39559 +yh@tauri://localhost/assets/index-CXNCu-GC.js:40:35923 +Ob@tauri://localhost/assets/index-CXNCu-GC.js:40:34872 +E@tauri://localhost/assets/index-CXNCu-GC.js:25:1541 +L@tauri://localhost/assets/index-CXNCu-GC.js:25:1903 + +ST@tauri://localhost/assets/index-CXNCu-GC.js:88:28096 +div +div +div +ID@tauri://localhost/assets/index-CXNCu-GC.js:94:63541 +main +div +div +G4@tauri://localhost/assets/index-CXNCu-GC.js:129:18236 +div +div +_T@tauri://localhost/assets/index-CXNCu-GC.js:88:24675 +BP@tauri://localhost/assets/index-CXNCu-GC.js:88:1862 +ez@tauri://localhost/assets/index-CXNCu-GC.js:129:31272 +mP@tauri://localhost/assets/index-CXNCu-GC.js:82:27658 +Iz@tauri://localhost/assets/index-CXNCu-GC.js:129:83025 +``` + +## Faits etablis avant cette rechute + +- Un rebuild SDK de `hello-plugin` a ete realise pour produire un plugin d'exemple minimal mais fonctionnel. +- Des verifications de build, packaging et tests locaux ont ete annoncees vertes par DevFrontend. +- QA avait pu valider partiellement: + - l'artefact SDK se reconstruit + - le plugin s'installe cote runtime/backend + - IdeA charge reellement le bundle plugin via `idea-plugin://.../dist/index.js` +- QA n'avait pas pu valider de bout en bout la surface UI visible (menu `Hello Plugin`, entree `hello-plugin`, rendu `hello-world`) faute d'une session UI observable sans ambiguite. + +## Reinterpretation apres rechute utilisateur + +- L'absence de validation UI de bout en bout n'etait pas un detail: la rechute utilisateur montre que le crash survient bien dans le flux reel d'affichage, malgre un plugin reconstruit proprement. +- Le signal pointe desormais plus fortement vers un probleme dans la consommation frontend des contributions plugin que vers le contenu fonctionnel du plugin lui-meme. + +## Requalification Architect du 2026-08-01 + +- Fait cle: le meme hash de crash apparait avec deux plugins differents: + - ancien hello-plugin minimal (menu + item, sans layout utile) + - nouveau hello-plugin reconstruit via SDK (menu + item + layout) +- Denominateur commun probable: la contribution de menu, pas le layout. +- Zone la plus suspecte identifiee: `ProjectsView.tsx` sur l'injection de `pluginMenus` dans ``. +- Point precis: le rendu des menus plugin est consomme dans l'app-shell sans isolation locale equivalente a celle deja ajoutee pour `PluginLayoutCellView`. +- Hypothese prioritaire: une entree de menu plugin ou son rendu dans `MenuBar` leve une erreur qui remonte jusqu'a `RootErrorBoundary`, produisant `INTERFACE INTERROMPUE`. + +## Correctif systeme plugin/UI par DevFrontend + +### Cause probable retenue +Deux plugins differents declenchent le meme crash minifie apres installation. Le denominateur commun le plus probable est le chemin `ProjectsView -> usePluginMenus -> MenuBar`. + +### Correctif applique +- `usePluginMenus` isole defensivement la resolution/conversion des contributions plugin. +- Si la resolution de menus ou d'items plugin throw, le hook renvoie `[]` pour la surface plugin concernee au lieu de propager l'erreur. +- `ProjectsView` separe les menus natifs des menus enrichis par plugin. +- `ProjectsView` rend `MenuBar` derriere une error boundary locale: si le rendu enrichi plante, fallback immediat sur les menus natifs seuls. +- Logs ajoutes: + - `[plugins] menu contribution rejected` avec le contexte utile quand disponible + - `[plugins] menu render failed; using native menus only` + +### Fichiers touches +- `frontend/src/features/plugins/usePluginMenus.ts` +- `frontend/src/features/plugins/usePluginMenus.test.tsx` +- `frontend/src/features/projects/ProjectsView.tsx` + +### Verifications annoncees par DevFrontend +- `cd frontend && npm run typecheck` : OK +- `cd frontend && npx vitest run src/features/plugins/usePluginMenus.test.tsx src/features/plugins/menus.test.ts src/plugins/runtime/loader.test.ts src/features/projects/projects.test.tsx src/features/projects/pluginGitRepository.test.tsx src/shared/ui/FloatingWindow.test.tsx` : OK, 48 tests +- `cd frontend && npm test` : OK, 114 fichiers, 1046 tests + +## Prochaine etape + +- QA doit valider sur le flux reel d'installation du plugin si l'UI reste vivante et si les menus natifs sont conserves en fallback au lieu de tomber sur `INTERFACE INTERROMPUE`. diff --git a/.ideai/tickets/120/issue.md b/.ideai/tickets/120/issue.md index 8efa155..da7d496 100644 --- a/.ideai/tickets/120/issue.md +++ b/.ideai/tickets/120/issue.md @@ -2,7 +2,7 @@ id: "f4218553-680a-4fbb-9514-a96eab79b8d8" number: 120 title: "Réinvestiguer l’installation de hello-plugin: écran noir / perte d’affichage IdeA" -status: "open" +status: "inProgress" priority: "critical" sprint: null links: [{"target":"#116","kind":"relatesTo"}] @@ -11,8 +11,8 @@ attachments: [] createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"} updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"} createdAt: 1785534496259 -updatedAt: 1785534496259 -version: 1 +updatedAt: 1785592705452 +version: 5 --- ## Constat utilisateur diff --git a/crates/infrastructure/tests/plugin_install_load.rs b/crates/infrastructure/tests/plugin_install_load.rs index 1b1b471..a3b3782 100644 --- a/crates/infrastructure/tests/plugin_install_load.rs +++ b/crates/infrastructure/tests/plugin_install_load.rs @@ -123,6 +123,7 @@ async fn installs_sdk_hello_plugin_and_loads_runtime_catalog() { assert_eq!(result.plugin.display_name, "Hello Plugin"); assert_eq!(result.review.contribution_summary.top_level_menus, 1); assert_eq!(result.review.contribution_summary.menu_items, 1); + assert_eq!(result.review.contribution_summary.layouts, 1); assert!(app_data .join("plugins/installed/com.example.hello-plugin/dist/index.js") .is_file()); @@ -139,10 +140,16 @@ async fn installs_sdk_hello_plugin_and_loads_runtime_catalog() { .starts_with("idea-plugin://com.example.hello-plugin/0.1.0/")); assert!(plugin.bundle_url.ends_with("/dist/index.js")); assert_eq!(plugin.contributes.menus[0].id, "hello-plugin.menu"); + assert_eq!(plugin.contributes.menus[0].label.as_str(), "Hello Plugin"); assert_eq!( plugin.contributes.menu_items[0].command.as_str(), - "hello-plugin.sayHello" + "hello-plugin" ); + assert_eq!( + plugin.contributes.layouts[0].layout_type.as_str(), + "hello-plugin.hello-world" + ); + assert_eq!(plugin.contributes.layouts[0].label.as_str(), "hello-world"); let _ = fs::remove_dir_all(app_data); } diff --git a/frontend/src/features/plugins/usePluginMenus.test.tsx b/frontend/src/features/plugins/usePluginMenus.test.tsx new file mode 100644 index 0000000..d2016ae --- /dev/null +++ b/frontend/src/features/plugins/usePluginMenus.test.tsx @@ -0,0 +1,75 @@ +import { renderHook } from "@testing-library/react"; +import { describe, expect, it, vi } from "vitest"; + +import type { MenuTargetId } from "@/domain"; +import type { PluginRuntimeRegistry, WhenContext } from "@/plugins/runtime"; +import { usePluginMenus } from "./usePluginMenus"; + +const NO_CONTEXT: WhenContext = { + projectOpen: false, + gitRepository: false, + agentSelected: false, + terminalFocused: false, + layoutCellFocused: false, +}; + +function throwingRegistry(overrides: Record): PluginRuntimeRegistry { + return { + runCommand: vi.fn(async () => {}), + topLevelMenus: vi.fn(() => []), + menuItems: vi.fn(() => []), + ...overrides, + } as unknown as PluginRuntimeRegistry; +} + +describe("usePluginMenus", () => { + it("falls back to no plugin top-level menus when plugin menu resolution throws", () => { + const consoleWarn = vi.spyOn(console, "warn").mockImplementation(() => {}); + try { + const registry = throwingRegistry({ + topLevelMenus: vi.fn(() => { + throw new Error("broken top-level contribution"); + }), + }); + + const { result } = renderHook(() => usePluginMenus(registry, NO_CONTEXT)); + + expect(result.current.topLevelMenus).toEqual([]); + expect(consoleWarn).toHaveBeenCalledWith( + "[plugins] menu contribution rejected", + expect.objectContaining({ + scope: "top-level-menus", + reason: "broken top-level contribution", + }), + ); + } finally { + consoleWarn.mockRestore(); + } + }); + + it("falls back to no plugin items for a native menu when item resolution throws", () => { + const consoleWarn = vi.spyOn(console, "warn").mockImplementation(() => {}); + try { + const registry = throwingRegistry({ + menuItems: vi.fn(() => { + throw new Error("broken item contribution"); + }), + }); + + const { result } = renderHook(() => usePluginMenus(registry, NO_CONTEXT)); + const items = result.current.itemsFor("panels" as MenuTargetId); + + expect(items).toEqual([]); + expect(consoleWarn).toHaveBeenCalledWith( + "[plugins] menu contribution rejected", + expect.objectContaining({ + scope: "items", + targetMenuId: "panels", + reason: "broken item contribution", + }), + ); + } finally { + consoleWarn.mockRestore(); + } + }); +}); diff --git a/frontend/src/features/plugins/usePluginMenus.ts b/frontend/src/features/plugins/usePluginMenus.ts index 583ec3e..86b3440 100644 --- a/frontend/src/features/plugins/usePluginMenus.ts +++ b/frontend/src/features/plugins/usePluginMenus.ts @@ -16,7 +16,7 @@ import { useMemo } from "react"; import type { MenuTargetId } from "@/domain"; import type { MenuBarItem, MenuBarMenu } from "@/shared"; import type { PluginRuntimeRegistry, WhenContext } from "@/plugins/runtime"; -import { resolveMenuItems, resolveTopLevelMenus } from "./menus"; +import { resolveMenuItems, resolveTopLevelMenus, type ResolvedTopLevelMenu } from "./menus"; export interface UsePluginMenusResult { /** Top-level plugin menus, in order, ready to splice between Panneaux/Paramètres. */ @@ -26,6 +26,25 @@ export interface UsePluginMenusResult { runCommand: (pluginId: string, commandId: string) => Promise; } +function describeError(e: unknown): string { + if (e && typeof e === "object" && "message" in e) { + return String((e as { message: unknown }).message); + } + return String(e); +} + +function rejectPluginMenuContribution( + scope: string, + details: Record, + error: unknown, +): void { + console.warn("[plugins] menu contribution rejected", { + scope, + ...details, + reason: describeError(error), + }); +} + export function usePluginMenus( registry: PluginRuntimeRegistry, whenCtx: WhenContext, @@ -36,27 +55,75 @@ export function usePluginMenus( ); const itemsFor = useMemo(() => { - return (targetMenuId: MenuTargetId): MenuBarItem[] => - resolveMenuItems(registry, targetMenuId, whenCtx).map((item) => ({ - id: item.id, - // Provenance is shown discreetly (carnet §0 UX decision) rather than - // with a visual section divider, which the shared `MenuBar` primitive - // doesn't support — a trailing "· Plugin Name" suffix is the least - // intrusive option that still surfaces where the item came from. - label: `${item.label} · ${item.pluginDisplayName}`, - disabled: !item.enabled, - onSelect: () => { - void runCommand(item.pluginId, item.command); - }, - })); + return (targetMenuId: MenuTargetId): MenuBarItem[] => { + let resolved; + try { + resolved = resolveMenuItems(registry, targetMenuId, whenCtx); + } catch (e) { + rejectPluginMenuContribution("items", { targetMenuId }, e); + return []; + } + + return resolved.flatMap((item) => { + try { + return [ + { + id: item.id, + // Provenance is shown discreetly (carnet §0 UX decision) rather than + // with a visual section divider, which the shared `MenuBar` primitive + // doesn't support — a trailing "· Plugin Name" suffix is the least + // intrusive option that still surfaces where the item came from. + label: `${item.label} · ${item.pluginDisplayName}`, + disabled: !item.enabled, + onSelect: () => { + void runCommand(item.pluginId, item.command); + }, + }, + ]; + } catch (e) { + rejectPluginMenuContribution( + "item", + { + pluginId: item.pluginId, + itemId: item.id, + targetMenuId, + commandId: item.command, + }, + e, + ); + return []; + } + }); + }; }, [registry, whenCtx, runCommand]); const topLevelMenus = useMemo(() => { - return resolveTopLevelMenus(registry).map((menu) => ({ - id: menu.id, - label: menu.label, - items: itemsFor(menu.id), - })); + let resolved: ResolvedTopLevelMenu[]; + try { + resolved = resolveTopLevelMenus(registry); + } catch (e) { + rejectPluginMenuContribution("top-level-menus", {}, e); + return []; + } + + return resolved.flatMap((menu) => { + try { + return [ + { + id: menu.id, + label: menu.label, + items: itemsFor(menu.id), + }, + ]; + } catch (e) { + rejectPluginMenuContribution( + "top-level-menu", + { pluginId: menu.pluginId, menuId: menu.id }, + e, + ); + return []; + } + }); }, [registry, itemsFor]); return { topLevelMenus, itemsFor, runCommand }; diff --git a/frontend/src/features/projects/ProjectsView.tsx b/frontend/src/features/projects/ProjectsView.tsx index 6fc803a..b89ccf8 100644 --- a/frontend/src/features/projects/ProjectsView.tsx +++ b/frontend/src/features/projects/ProjectsView.tsx @@ -33,7 +33,14 @@ * open; the project tab bar (`role="tablist"`) is always present. */ -import { useEffect, useMemo, useState, type ReactNode } from "react"; +import { + Component, + useEffect, + useMemo, + useState, + type ErrorInfo, + type ReactNode, +} from "react"; import type { Agent, DomainEvent, LayoutInfo } from "@/domain"; import { LayoutGrid, LayoutTabs } from "@/features/layout"; @@ -109,6 +116,41 @@ interface PendingConversationOpen { conversationId: string; } +interface PluginMenuRenderBoundaryProps { + resetKey: string; + fallbackMenus: MenuBarMenu[]; + children: ReactNode; +} + +class PluginMenuRenderBoundary extends Component< + PluginMenuRenderBoundaryProps, + { hasError: boolean } +> { + state = { hasError: false }; + + static getDerivedStateFromError(): { hasError: boolean } { + return { hasError: true }; + } + + componentDidCatch(error: Error, errorInfo: ErrorInfo): void { + console.error("[plugins] menu render failed; using native menus only", { + error, + componentStack: errorInfo.componentStack, + }); + } + + componentDidUpdate(prevProps: PluginMenuRenderBoundaryProps): void { + if (prevProps.resetKey !== this.props.resetKey && this.state.hasError) { + this.setState({ hasError: false }); + } + } + + render(): ReactNode { + if (this.state.hasError) return ; + return this.props.children; + } +} + function isTerminalBackgroundTaskEvent( event: DomainEvent, ): event is Extract { @@ -546,22 +588,43 @@ export function ProjectsView() { return items; } + const nativePanelItems: MenuBarItem[] = panelOrder.map((panel) => ({ + id: panel, + label: PANEL_TITLE[panel], + active: placementOf(placements, panel) !== "closed", + onSelect: () => {}, + submenu: placementSubmenu(panel), + })); + const nativeSettingsItems: MenuBarItem[] = SETTINGS_SECTIONS.map((section) => ({ + id: section, + label: SETTINGS_SECTION_LABEL[section], + active: settingsSection === section, + onSelect: () => { + setSettingsSection(section); + dismissFloating(); + }, + })); + const pluginPanelItems = pluginMenus.itemsFor("panels"); + const pluginSettingsItems = pluginMenus.itemsFor("settings"); + const nativeMenus: MenuBarMenu[] = [ + { + id: "panels", + label: "Panneaux", + items: nativePanelItems, + }, + { + id: "settings", + label: "Paramètres", + items: nativeSettingsItems, + }, + ]; const menus: MenuBarMenu[] = [ { id: "panels", label: "Panneaux", // Native items first, plugin-contributed items after in their own // (discreetly-labelled) group (#43, F3, carnet §7.2). - items: [ - ...panelOrder.map((panel) => ({ - id: panel, - label: PANEL_TITLE[panel], - active: placementOf(placements, panel) !== "closed", - onSelect: () => {}, - submenu: placementSubmenu(panel), - })), - ...pluginMenus.itemsFor("panels"), - ], + items: [...nativePanelItems, ...pluginPanelItems], }, // Top-level plugin menus render between Panneaux and Paramètres (#43, // carnet §0 UX decision + §7.1). @@ -572,20 +635,14 @@ export function ProjectsView() { // One entry per section (#68). The entries name sections and mark the open // one; closing lives in the view ("Fermer les paramètres"), so no label // alternates. Plugin-contributed items are appended after (#43, F3). - items: [ - ...SETTINGS_SECTIONS.map((section) => ({ - id: section, - label: SETTINGS_SECTION_LABEL[section], - active: settingsSection === section, - onSelect: () => { - setSettingsSection(section); - dismissFloating(); - }, - })), - ...pluginMenus.itemsFor("settings"), - ], + items: [...nativeSettingsItems, ...pluginSettingsItems], }, ]; + const pluginMenuResetKey = [ + pluginMenus.topLevelMenus.map((menu) => menu.id).join(","), + pluginPanelItems.map((item) => item.id).join(","), + pluginSettingsItems.map((item) => item.id).join(","), + ].join("|"); // The create-project form + known-projects list. Rendered inline in the // welcome area (no active project) or inside the Projects floating window. @@ -810,7 +867,12 @@ export function ProjectsView() { /> {/* ── Menu bar (replaces the former left sidebar) ── */} - + + + {/* ── Chrome row: left dock │ main │ right dock (#22). Docks are in-flow resizable columns, not overlays — they sit beside the main surface. */} diff --git a/frontend/src/plugins/runtime/loader.test.ts b/frontend/src/plugins/runtime/loader.test.ts index 5485782..dc5a3f9 100644 --- a/frontend/src/plugins/runtime/loader.test.ts +++ b/frontend/src/plugins/runtime/loader.test.ts @@ -178,12 +178,16 @@ describe("loadPlugins", () => { expect(registry.get("com.example.hello-plugin")).toBeUndefined(); }); - it("loads the hello-plugin contribution shape with omitted optional arrays", async () => { + it("loads the hello-plugin command and layout contribution shape", async () => { const bundle = dataUrl(` export function activate(ctx) { - ctx.commands.registerCommand("hello-plugin.sayHello", () => { + ctx.commands.registerCommand("hello-plugin", () => { globalThis.__helloArchiveCommandRan = true; }); + ctx.layouts.register({ + type: "hello-plugin.hello-world", + component: () => "hello-world", + }); } `); const { registry, failures } = await loadPlugins( @@ -193,13 +197,20 @@ describe("loadPlugins", () => { displayName: "Hello Plugin", bundleUrl: bundle, contributes: { - menus: [{ id: "hello-plugin.menu", label: "Hello", topLevel: true }], + menus: [{ id: "hello-plugin.menu", label: "Hello Plugin", topLevel: true }], menuItems: [ { - id: "hello-plugin.sayHello.item", + id: "hello-plugin.command.item", targetMenuId: "hello-plugin.menu", - label: "Say Hello", - command: "hello-plugin.sayHello", + label: "hello-plugin", + command: "hello-plugin", + }, + ], + layouts: [ + { + type: "hello-plugin.hello-world", + label: "hello-world", + component: "hello-world", }, ], } as unknown as PluginContributionDto, @@ -209,10 +220,22 @@ describe("loadPlugins", () => { ); expect(failures).toEqual([]); - expect(registry.get("com.example.hello-plugin")?.contributes.layouts).toEqual([]); + expect(registry.get("com.example.hello-plugin")?.contributes.layouts).toEqual([ + { + type: "hello-plugin.hello-world", + label: "hello-world", + component: "hello-world", + }, + ]); expect(registry.get("com.example.hello-plugin")?.contributes.mcpServers).toEqual([]); - await registry.runCommand("com.example.hello-plugin", "hello-plugin.sayHello"); + await registry.runCommand("com.example.hello-plugin", "hello-plugin"); expect((globalThis as Record).__helloArchiveCommandRan).toBe(true); + const Layout = registry.layoutComponent( + "com.example.hello-plugin", + "hello-plugin.hello-world", + ); + expect(Layout).toBeDefined(); + expect((Layout as unknown as () => string)()).toBe("hello-world"); }); it("confines a malformed runtime catalog entry and still loads healthy plugins", async () => { diff --git a/frontend/src/plugins/runtime/loader.ts b/frontend/src/plugins/runtime/loader.ts index 788aa36..2f7c6ef 100644 --- a/frontend/src/plugins/runtime/loader.ts +++ b/frontend/src/plugins/runtime/loader.ts @@ -301,8 +301,20 @@ export async function loadPlugins( entries.map((entry) => loadOne(entry, gateways, resolvedOptions)), ); for (const result of results) { - if ("failure" in result) failures.push(result.failure); - else registry.add(result.plugin); + if ("failure" in result) { + failures.push(result.failure); + console.warn( + `[plugins] load failed plugin=${result.failure.pluginId}: ${result.failure.reason}`, + ); + } else { + registry.add(result.plugin); + } + } + + if (entries.length > 0) { + console.info( + `[plugins] load complete loaded=${registry.list().length} failed=${failures.length}`, + ); } return { registry, failures }; diff --git a/sdk/IdeaSDK/examples/hello-plugin/README.md b/sdk/IdeaSDK/examples/hello-plugin/README.md index 94c4bc5..7119a1e 100644 --- a/sdk/IdeaSDK/examples/hello-plugin/README.md +++ b/sdk/IdeaSDK/examples/hello-plugin/README.md @@ -1,6 +1,13 @@ # Hello Plugin -Minimal IdeA plugin example using the public SDK types. +Installable IdeA plugin example rebuilt from the public SDK types. + +It exercises the current plugin primitives end to end: + +- top-level menu: `Hello Plugin`; +- menu entry: `hello-plugin`; +- command: `hello-plugin`, returning `hello-world`; +- layout contribution: `hello-plugin.hello-world`, rendered as `hello-world`. ```sh npm run typecheck:examples @@ -10,3 +17,15 @@ npm run package:hello-plugin The installable archive is emitted at `examples/hello-plugin/build/hello-plugin-0.1.0.zip`. It contains `idea-plugin.json` at the ZIP root and the compiled ESM entrypoint at `dist/index.js`, matching the manifest `main` field. + +## Diagnostics + +During activation the plugin logs: + +- whether the command and layout runtime registries are available; +- successful registration of the `hello-plugin` command; +- successful registration of the `hello-plugin.hello-world` layout; +- the first layout render, including project/node identifiers. + +These messages are intentionally small and stable so installation, bundle import, activation and +layout rendering failures can be separated quickly in IdeA logs/devtools. diff --git a/sdk/IdeaSDK/examples/hello-plugin/idea-plugin.json b/sdk/IdeaSDK/examples/hello-plugin/idea-plugin.json index 07aa8dd..28f7962 100644 --- a/sdk/IdeaSDK/examples/hello-plugin/idea-plugin.json +++ b/sdk/IdeaSDK/examples/hello-plugin/idea-plugin.json @@ -4,7 +4,7 @@ "displayName": "Hello Plugin", "publisher": "IdeA Examples", "version": "0.1.0", - "description": "Minimal IdeA plugin example.", + "description": "SDK example plugin for validating command, menu and layout loading.", "main": "dist/index.js", "engines": { "idea": ">=0.1.0" @@ -17,16 +17,26 @@ "menus": [ { "id": "hello-plugin.menu", - "label": "Hello", - "topLevel": true + "label": "Hello Plugin", + "topLevel": true, + "order": 100 } ], "menuItems": [ { - "id": "hello-plugin.sayHello.item", + "id": "hello-plugin.command.item", "targetMenuId": "hello-plugin.menu", - "label": "Say Hello", - "command": "hello-plugin.sayHello" + "label": "hello-plugin", + "command": "hello-plugin", + "order": 10 + } + ], + "layouts": [ + { + "type": "hello-plugin.hello-world", + "label": "hello-world", + "component": "hello-world", + "order": 10 } ] } diff --git a/sdk/IdeaSDK/examples/hello-plugin/src/index.ts b/sdk/IdeaSDK/examples/hello-plugin/src/index.ts index 26a9a07..e7b658e 100644 --- a/sdk/IdeaSDK/examples/hello-plugin/src/index.ts +++ b/sdk/IdeaSDK/examples/hello-plugin/src/index.ts @@ -1,15 +1,75 @@ -import type { ActivateContext, IdeAPluginModule } from "@idea/plugin-sdk"; +import type { ActivateContext, CommandDisposable, IdeAPluginModule } from "@idea/plugin-sdk"; + +const COMMAND_ID = "hello-plugin"; +const LAYOUT_TYPE = "hello-plugin.hello-world"; + +type HelloPluginLayoutProps = { + projectId?: string; + nodeId?: string; + layoutType?: string; + state?: unknown; +}; + +type LayoutRegistry = { + register(definition: { + type: string; + component: (props: HelloPluginLayoutProps) => string; + }): CommandDisposable; +}; + +type HelloPluginContext = ActivateContext & { + layouts?: LayoutRegistry; +}; + +let hasLoggedFirstLayoutRender = false; + +function HelloWorldLayout(props: HelloPluginLayoutProps): string { + if (!hasLoggedFirstLayoutRender) { + hasLoggedFirstLayoutRender = true; + console.info("[hello-plugin] layout first render", { + projectId: props.projectId, + nodeId: props.nodeId, + layoutType: props.layoutType, + hasState: props.state !== undefined + }); + } + + return "hello-world"; +} export function activate(ctx: ActivateContext): void { - ctx.logger.info("Hello from the IdeA hello plugin."); - - const disposable = ctx.commands?.registerCommand("hello-plugin.sayHello", () => { - ctx.logger.info("Hello command executed."); - return "Hello from IdeA"; + const pluginContext = ctx as HelloPluginContext; + ctx.logger.info("activating hello-plugin", { + pluginId: ctx.pluginId, + hasCommands: Boolean(pluginContext.commands), + hasLayouts: Boolean(pluginContext.layouts) }); - if (disposable) { - ctx.subscriptions.push(disposable); + const commandDisposable = pluginContext.commands?.registerCommand(COMMAND_ID, () => { + ctx.logger.info("command executed", { commandId: COMMAND_ID }); + return "hello-world"; + }); + + if (commandDisposable) { + ctx.subscriptions.push(commandDisposable); + ctx.logger.info("command registered", { commandId: COMMAND_ID }); + } else { + ctx.logger.warn("command registry unavailable", { commandId: COMMAND_ID }); + } + + const layoutDisposable = pluginContext.layouts?.register({ + type: LAYOUT_TYPE, + component: HelloWorldLayout + }); + + if (layoutDisposable) { + ctx.subscriptions.push(layoutDisposable); + ctx.logger.info("layout registered", { + layoutType: LAYOUT_TYPE, + component: "hello-world" + }); + } else { + ctx.logger.warn("layout registry unavailable", { layoutType: LAYOUT_TYPE }); } } @@ -18,4 +78,3 @@ const plugin: IdeAPluginModule = { }; export default plugin; - From add61f176d5c2e6ea8ce437793df2d9bd7b94517 Mon Sep 17 00:00:00 2001 From: Blomios Date: Sat, 1 Aug 2026 16:54:33 +0200 Subject: [PATCH 2/2] chore(tickets): consigne la rechute #120 (requalification deploiement) et enregistre #122 Co-Authored-By: Claude Opus 4.8 --- .ideai/tickets/120/carnet.md | 135 +++++++++++++++++++++++++++-------- .ideai/tickets/120/issue.md | 8 +-- .ideai/tickets/122/carnet.md | 6 ++ .ideai/tickets/122/issue.md | 17 +++++ .ideai/tickets/counter.json | 2 +- .ideai/tickets/index.json | 19 ++++- 6 files changed, 151 insertions(+), 36 deletions(-) create mode 100644 .ideai/tickets/122/carnet.md create mode 100644 .ideai/tickets/122/issue.md diff --git a/.ideai/tickets/120/carnet.md b/.ideai/tickets/120/carnet.md index 97d0a74..588f887 100644 --- a/.ideai/tickets/120/carnet.md +++ b/.ideai/tickets/120/carnet.md @@ -1,14 +1,21 @@ --- issueRef: "#120" -version: 5 +version: 8 +updatedBy: {"kind":"agent","agent_id":"dce19c75-9669-4e45-b8de-9950025157da"} +updatedAt: 1785596006134 +--- +--- +issueRef: "#120" +version: 7 updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"} -updatedAt: 1785592705452 +updatedAt: 1785595113109 --- # Carnet de suivi — hello-plugin ## Etat courant - Ticket canonique: `#120` +- Ticket parent historique: `#43` - Date de rechute confirmee: 2026-08-01 - Statut: investigation relancee sur rechute reelle post-rebuild SDK - Severite: critique (l'UI d'IdeA tombe sur une erreur d'affichage lors de l'installation/chargement de `hello-plugin`) @@ -26,37 +33,37 @@ Message visible: - `IdeA a rencontre une erreur d'affichage.` - `L'application reste ouverte. Rechargez la fenetre apres avoir copie le diagnostic si le probleme doit etre investigue.` -Stack affichee: +Stack affichee (trace la plus recente): ```text -kT@tauri://localhost/assets/index-CXNCu-GC.js:88:32937 -ST@tauri://localhost/assets/index-CXNCu-GC.js:88:31877 -om@tauri://localhost/assets/index-CXNCu-GC.js:38:17019 -oh@tauri://localhost/assets/index-CXNCu-GC.js:40:3141 -$b@tauri://localhost/assets/index-CXNCu-GC.js:40:39779 -SC@tauri://localhost/assets/index-CXNCu-GC.js:40:39707 -sc@tauri://localhost/assets/index-CXNCu-GC.js:40:39559 -yh@tauri://localhost/assets/index-CXNCu-GC.js:40:35923 -Ob@tauri://localhost/assets/index-CXNCu-GC.js:40:34872 -E@tauri://localhost/assets/index-CXNCu-GC.js:25:1541 -L@tauri://localhost/assets/index-CXNCu-GC.js:25:1903 +ST@tauri://localhost/assets/index-DxqF_K_z.js:88:33125 +wT@tauri://localhost/assets/index-DxqF_K_z.js:88:32065 +om@tauri://localhost/assets/index-DxqF_K_z.js:38:17019 +oh@tauri://localhost/assets/index-DxqF_K_z.js:40:3141 +Fb@tauri://localhost/assets/index-DxqF_K_z.js:40:39779 +SC@tauri://localhost/assets/index-DxqF_K_z.js:40:39707 +ic@tauri://localhost/assets/index-DxqF_K_z.js:40:39559 +yh@tauri://localhost/assets/index-DxqF_K_z.js:40:35923 +Bb@tauri://localhost/assets/index-DxqF_K_z.js:40:34872 +E@tauri://localhost/assets/index-DxqF_K_z.js:25:1541 +L@tauri://localhost/assets/index-DxqF_K_z.js:25:1903 -ST@tauri://localhost/assets/index-CXNCu-GC.js:88:28096 +wT@tauri://localhost/assets/index-DxqF_K_z.js:88:28284 div div div -ID@tauri://localhost/assets/index-CXNCu-GC.js:94:63541 +MD@tauri://localhost/assets/index-DxqF_K_z.js:94:63541 main div div -G4@tauri://localhost/assets/index-CXNCu-GC.js:129:18236 +G4@tauri://localhost/assets/index-DxqF_K_z.js:129:18726 div div -_T@tauri://localhost/assets/index-CXNCu-GC.js:88:24675 -BP@tauri://localhost/assets/index-CXNCu-GC.js:88:1862 -ez@tauri://localhost/assets/index-CXNCu-GC.js:129:31272 -mP@tauri://localhost/assets/index-CXNCu-GC.js:82:27658 -Iz@tauri://localhost/assets/index-CXNCu-GC.js:129:83025 +yT@tauri://localhost/assets/index-DxqF_K_z.js:88:24863 +BP@tauri://localhost/assets/index-DxqF_K_z.js:88:1862 +ez@tauri://localhost/assets/index-DxqF_K_z.js:129:31967 +mP@tauri://localhost/assets/index-DxqF_K_z.js:82:27658 +Iz@tauri://localhost/assets/index-DxqF_K_z.js:129:83720 ``` ## Faits etablis avant cette rechute @@ -74,6 +81,15 @@ Iz@tauri://localhost/assets/index-CXNCu-GC.js:129:83025 - L'absence de validation UI de bout en bout n'etait pas un detail: la rechute utilisateur montre que le crash survient bien dans le flux reel d'affichage, malgre un plugin reconstruit proprement. - Le signal pointe desormais plus fortement vers un probleme dans la consommation frontend des contributions plugin que vers le contenu fonctionnel du plugin lui-meme. +## Cadrage UX du 2026-08-01 + +- Une contribution plugin invalide ou qui plante ne doit jamais faire tomber l'app entiere. +- Le fallback attendu est local a la surface plugin en faute: + - menu plugin en erreur -> menus natifs seuls + - layout plugin en erreur -> fallback local de layout indisponible +- `INTERFACE INTERROMPUE` doit rester reserve aux crashs shell irrecoverables. +- A terme, l'etat d'erreur plugin devrait rester visible dans la gestion des plugins plutot qu'etre seulement silencieux. + ## Requalification Architect du 2026-08-01 - Fait cle: le meme hash de crash apparait avec deux plugins differents: @@ -83,8 +99,19 @@ Iz@tauri://localhost/assets/index-CXNCu-GC.js:129:83025 - Zone la plus suspecte identifiee: `ProjectsView.tsx` sur l'injection de `pluginMenus` dans ``. - Point precis: le rendu des menus plugin est consomme dans l'app-shell sans isolation locale equivalente a celle deja ajoutee pour `PluginLayoutCellView`. - Hypothese prioritaire: une entree de menu plugin ou son rendu dans `MenuBar` leve une erreur qui remonte jusqu'a `RootErrorBoundary`, produisant `INTERFACE INTERROMPUE`. +- Strate touchee: frontend prioritaire, pas de nouveau chantier backend requis pour cette cause racine. -## Correctif systeme plugin/UI par DevFrontend +## Verification DevFrontend du 2026-08-01 + +- Branche verifiee: `feature/ticket120-plugin-menu-crash-isolation` +- HEAD verifie: `5a30ec8` +- Verdict DevFrontend: le correctif existant couvre deja la rechute prioritaire sur le chemin `ProjectsView -> usePluginMenus -> MenuBar`. +- Aucun complement de code ajoute a ce stade. +- Verifications executees: + - `cd frontend && npx vitest run src/features/plugins/usePluginMenus.test.tsx src/plugins/runtime/loader.test.ts src/features/plugins/menus.test.ts` : OK (22 tests) + - `cd frontend && npx vitest run` : OK (114 fichiers, 1046 tests) + +## Correctif systeme plugin/UI deja porte par la branche ### Cause probable retenue Deux plugins differents declenchent le meme crash minifie apres installation. Le denominateur commun le plus probable est le chemin `ProjectsView -> usePluginMenus -> MenuBar`. @@ -103,11 +130,61 @@ Deux plugins differents declenchent le meme crash minifie apres installation. Le - `frontend/src/features/plugins/usePluginMenus.test.tsx` - `frontend/src/features/projects/ProjectsView.tsx` -### Verifications annoncees par DevFrontend -- `cd frontend && npm run typecheck` : OK -- `cd frontend && npx vitest run src/features/plugins/usePluginMenus.test.tsx src/features/plugins/menus.test.ts src/plugins/runtime/loader.test.ts src/features/projects/projects.test.tsx src/features/projects/pluginGitRepository.test.tsx src/shared/ui/FloatingWindow.test.tsx` : OK, 48 tests -- `cd frontend && npm test` : OK, 114 fichiers, 1046 tests +## Validation QA du 2026-08-01 -## Prochaine etape +- Branche validee: `feature/ticket120-plugin-menu-crash-isolation` +- HEAD valide: `5a30ec8b9c4758602cc96e72ffd69e415422cd85` +- Verdict QA courant: bug `INTERFACE INTERROMPUE` non reproduit par les validations reelles executees ici. -- QA doit valider sur le flux reel d'installation du plugin si l'UI reste vivante et si les menus natifs sont conserves en fallback au lieu de tomber sur `INTERFACE INTERROMPUE`. +### Commandes executees +- `git -C /home/anthony/Documents/Projects/IdeA rev-parse HEAD` +- `npm --prefix /home/anthony/Documents/Projects/IdeA/sdk/IdeaSDK run package:hello-plugin` +- `cd /home/anthony/Documents/Projects/IdeA/frontend && npx vitest run src/features/plugins/menus.test.ts src/features/plugins/usePluginMenus.test.tsx src/features/plugins/plugins.test.tsx src/plugins/runtime/loader.test.ts` +- `cargo test -p infrastructure --test plugin_install_load -- --nocapture` +- `cargo test -p infrastructure extracts_archive_without_path_escape -- --nocapture` +- `cd /home/anthony/Documents/Projects/IdeA/frontend && npm run test:bundle-transport` +- `cd /home/anthony/Documents/Projects/IdeA/crates/app-tauri && NO_STRIP=true ../../frontend/node_modules/.bin/tauri build --bundles appimage` + +### Resultats utiles +- archive SDK regeneree: `sdk/IdeaSDK/examples/hello-plugin/build/hello-plugin-0.1.0.zip` +- tests frontend cibles: OK (4 fichiers, 29 tests) +- tests backend d'installation/chargement plugin: OK (3 tests) +- AppImage rebuild: `target/release/bundle/appimage/IdeA_0.3.0_amd64.AppImage` + +### Limite de preuve restante +- Pas de harness e2e UI automatise ici pour cliquer le parcours Tauri/AppImage "Installer depuis une archive..." de bout en bout. +- La validation est donc reelle sur archive SDK, backend d'installation, non-regression frontend, et artefact packagé reconstruit, mais pas sur un clic UI automatise observable. + +## Requalification Architect du 2026-08-01 (rechute post-rebuild) + +### Fait determinant trouve par inspection directe des artefacts + +Deux binaires AppImage distincts coexistent sur la machine, avec un ecart temporel et de contenu net: + +| Fichier | mtime | sha256 (8 premiers car.) | +|---|---|---| +| `/home/anthony/Documents/IdeA_0.3.0_amd64.AppImage` (celui qu'IdeA fait tourner — cf. memoire `mcp-bridge-and-delegation-runtime-notes`) | 2026-07-24 15:09 | `61d499f2` | +| `target/release/bundle/appimage/IdeA_0.3.0_amd64.AppImage` (rebuild QA du jour) | 2026-08-01 16:37 | `9ad50c21` | + +Le commit du correctif (`5a30ec8`, isolation `usePluginMenus`/`ProjectsView`) date du **2026-08-01 16:23:56**, soit **apres** le mtime du binaire `~/Documents`. Le binaire que l'utilisateur execute au quotidien (`~/Documents/IdeA_0.3.0_amd64.AppImage`) est donc anterieur de plusieurs jours au correctif et ne peut structurellement pas le contenir. + +### Requalification de cause racine + +- La rechute rapportee le 2026-08-01 par l'utilisateur est tres vraisemblablement un **artefact de deploiement**, pas une regression de code: le rebuild QA a produit un binaire correct dans `target/release/bundle/appimage/`, mais ce binaire n'a jamais remplace celui reellement lance par l'utilisateur (`~/Documents/IdeA_0.3.0_amd64.AppImage`). +- C'est exactement le piege deja documente en memoire projet (`mcp-bridge-and-delegation-runtime-notes`, section « Le binaire qui tourne = AppImage installee, pas les sources ») applique cette fois au correctif plugin plutot qu'au pont MCP. +- Le carnet QA ci-dessus ne mentionne a aucun moment le remplacement du binaire `~/Documents` ni le redemarrage d'IdeA sur ce binaire remplace — seule la production de l'artefact dans `target/release/bundle/` est tracee. + +### Borne de correction attendue + +- **Aucun nouveau code frontend ou backend n'est requis a ce stade.** Le correctif `5a30ec8` (isolation menus plugin) est deja en place et deja valide par tests reels (114 fichiers / 1046 tests vitest, tests backend d'installation/chargement). +- Action requise: deploiement, pas developpement — remplacer `~/Documents/IdeA_0.3.0_amd64.AppImage` par `target/release/bundle/appimage/IdeA_0.3.0_amd64.AppImage` (backup de l'ancien conseille, cf. convention memoire `*.old-fix`), relancer IdeA depuis ce binaire, puis reproduire exactement le parcours Parametres > Plugins > Installer depuis une archive > hello-plugin. +- Si la rechute persiste APRES ce remplacement effectif et un redemarrage complet d'IdeA, alors l'hypothese frontend doit etre rouverte avec un perimetre elargi au-dela de `ProjectsView -> usePluginMenus -> MenuBar`, en verifiant en priorite (deja inspectes le 2026-08-01, RAS a la lecture statique mais non exerces en e2e reel): + - `frontend/src/features/plugins/PluginsPanel.tsx` (flux `startInstallFromArchive` / `reviewArchive` / dialog de confirmation) — surface active au moment precis du clic « Installer » + - `frontend/src/features/plugins/PluginConfirmDialog.tsx` + - `frontend/src/features/plugins/PluginLayoutCellView.tsx` (isolation deja posee en amont de ce ticket, a re-verifier qu'elle couvre bien le layout du hello-plugin reconstruit) + - la place de `RootErrorBoundary` par rapport a ces surfaces, pour confirmer qu'aucun chemin ne la contourne + +### Prochaine etape (remplace la precedente) + +- Ne pas rouvrir de chantier de code avant d'avoir confirme que l'utilisateur reproduit sur le binaire effectivement a jour. +- Remplacement de binaire + retest = action Git/deploiement, a executer avant toute nouvelle investigation frontend. diff --git a/.ideai/tickets/120/issue.md b/.ideai/tickets/120/issue.md index da7d496..08b7818 100644 --- a/.ideai/tickets/120/issue.md +++ b/.ideai/tickets/120/issue.md @@ -5,14 +5,14 @@ title: "Réinvestiguer l’installation de hello-plugin: écran noir / perte d status: "inProgress" priority: "critical" sprint: null -links: [{"target":"#116","kind":"relatesTo"}] +links: [{"target":"#116","kind":"relatesTo"},{"target":"#43","kind":"relatesTo"}] agentRefs: [] attachments: [] createdBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"} -updatedBy: {"kind":"agent","agent_id":"a6ced819-b893-4213-b003-9e9dc79b9641"} +updatedBy: {"kind":"agent","agent_id":"dce19c75-9669-4e45-b8de-9950025157da"} createdAt: 1785534496259 -updatedAt: 1785592705452 -version: 5 +updatedAt: 1785596006134 +version: 8 --- ## Constat utilisateur diff --git a/.ideai/tickets/122/carnet.md b/.ideai/tickets/122/carnet.md new file mode 100644 index 0000000..1254a05 --- /dev/null +++ b/.ideai/tickets/122/carnet.md @@ -0,0 +1,6 @@ +--- +issueRef: "#122" +version: 3 +updatedBy: {"kind":"user"} +updatedAt: 1785592528432 +--- diff --git a/.ideai/tickets/122/issue.md b/.ideai/tickets/122/issue.md new file mode 100644 index 0000000..8538665 --- /dev/null +++ b/.ideai/tickets/122/issue.md @@ -0,0 +1,17 @@ +--- +id: "fa083793-48ae-417a-ab16-3813e22df2e3" +number: 122 +title: "[Bug] Override des permissions defaut qui ne marche pas" +status: "open" +priority: "medium" +sprint: null +links: [] +agentRefs: [{"agentId":"a6ced819-b893-4213-b003-9e9dc79b9641","role":"assigned"}] +attachments: [] +createdBy: {"kind":"user"} +updatedBy: {"kind":"user"} +createdAt: 1785592422173 +updatedAt: 1785592528432 +version: 3 +--- +J'ai l'impression que l'override des permissions systeme ne fonctionne pas. J'avais les permissions par defaut qui ne donnait pas les droits bash, et meme après avoir override ce parametre sur un de mes agents, il n'avait aps acces aux tools bash. Il y a eu acces une fois qu'avais mis le droit dans la config defaut \ No newline at end of file diff --git a/.ideai/tickets/counter.json b/.ideai/tickets/counter.json index 878fe4e..c248bef 100644 --- a/.ideai/tickets/counter.json +++ b/.ideai/tickets/counter.json @@ -1,3 +1,3 @@ { - "nextNumber": 122 + "nextNumber": 123 } \ No newline at end of file diff --git a/.ideai/tickets/index.json b/.ideai/tickets/index.json index c9bc00b..edba004 100644 --- a/.ideai/tickets/index.json +++ b/.ideai/tickets/index.json @@ -1556,7 +1556,7 @@ "issueRef": "#120", "path": "120", "title": "Réinvestiguer l’installation de hello-plugin: écran noir / perte d’affichage IdeA", - "status": "open", + "status": "inProgress", "priority": "critical", "sprint": null, "assignedAgentIds": [], @@ -1564,7 +1564,7 @@ "kind": "agent", "agent_id": "a6ced819-b893-4213-b003-9e9dc79b9641" }, - "updatedAt": 1785534496259 + "updatedAt": 1785596006134 }, { "issueRef": "#121", @@ -1579,6 +1579,21 @@ "agent_id": "dce19c75-9669-4e45-b8de-9950025157da" }, "updatedAt": 1785534534027 + }, + { + "issueRef": "#122", + "path": "122", + "title": "[Bug] Override des permissions defaut qui ne marche pas", + "status": "open", + "priority": "medium", + "sprint": null, + "assignedAgentIds": [ + "a6ced819-b893-4213-b003-9e9dc79b9641" + ], + "createdBy": { + "kind": "user" + }, + "updatedAt": 1785592528432 } ] } \ No newline at end of file