| name | RendererProcess | ||||||
|---|---|---|---|---|---|---|---|
| description | Governs renderer-process routes, navigation registry, bootstrap tasks, API wrappers, and store ownership. | ||||||
| keywords |
|
- 覆盖:
src/renderer/src/下的 renderer 应用启动、文件系统路由、活动导航、renderer bootstrap 任务、renderer API wrapper 和 Pinia store 所有权。 - 不覆盖:主进程 IPC handler、preload 暴露和跨进程契约细节;见
guidelines/MainProcess.md。Renderer 测试位置和 stub 由guidelines/Testing.md覆盖。UI/UX 视觉规范见guidelines/UiDesign.md。
- MUST 将 renderer 页面定义为
src/renderer/src/pages/下的 Vue SFC,并让vue-router/auto-routes生成 route records。Router 在src/renderer/src/config/auto-routes.ts中创建,并使用createWebHashHistory()适配 Electron renderer 导航。证据:electron.vite.config.ts、src/renderer/src/config/auto-routes.ts、src/renderer/src/pages/。 - MUST 通过
src/renderer/src/config/activity-bar.ts中的activityBarItems添加主应用导航,不要在组件里硬编码侧边栏入口。ActivityBar.vue渲染该注册表,并根据 route path 计算 active 状态。证据:src/renderer/src/config/activity-bar.ts、src/renderer/src/components/layout/ActivityBar.vue。 - MUST 保持且仅保持一个默认 activity item,并保持 activity item 的 id 和 path 唯一。该注册表会在 dev/test 中强制默认项数量,renderer 测试会断言注册表形状。证据:
src/renderer/src/config/activity-bar.ts、test/renderer/src/config/activity-bar.spec.ts。 - MUST 使用
ActivityBarItem.requiresWorkspace表达 Workspace 门控导航。当useWorkspaceStore().hasCurrentWorkspace为 false 时,ActivityBar.vue会禁用 Workspace 作用域的 item。证据:src/renderer/src/config/activity-bar.ts、src/renderer/src/components/layout/ActivityBar.vue。 - MUST 通过
evaluateWorkspaceNavigation()统一 activity bar 与 route guard 的 Workspace capability 判断;阶段性不支持 Collection Chat 时,两处必须显示/执行同一禁用结果,不得向 Main 发送 primary-only fallback 请求。证据:src/renderer/src/config/navigation-gate.ts、src/renderer/src/components/layout/ActivityBar.vue、src/renderer/src/pages/index.vue。
- MUST 将 renderer 对 preload API 的访问封装在
src/renderer/src/api/<domain>/<area>.tswrapper 中。组件、composable 和 store 应导入这些 wrapper,而不是直接调用window.api;除src/renderer/src/api/**外,renderer 代码不得直接访问window.api。证据:src/renderer/src/api/platform/settings.ts、src/renderer/src/api/session/chat.ts、eslint.config.mjs。 - MUST 让 renderer API wrapper 对齐
window.api.<domain>.<area>,并在可用时基于 shared 契约或 preload API 类型进行类型约束,保留 preload API 返回的标准IpcResponse<T>流程。证据:src/preload/index.ts、src/preload/index.d.ts、src/renderer/src/api/automation/workflow-run.ts、src/shared/types/ipc.ts。 - SHOULD 将可复用异步状态和跨组件 UI 状态放在
src/renderer/src/stores/<domain>/下的 Pinia setup store 中。store 的形状应服务 renderer 状态和页面用例,不需要强制镜像 main services 的 area 或文件名。证据:src/renderer/src/stores/platform/settings.ts、src/renderer/src/stores/session/session.ts、src/renderer/src/stores/automation/workflow-run.ts。 - MUST 让每个 store domain 通过
src/renderer/src/stores/<domain>/index.ts暴露本 domain 的 public store entry points;根级src/renderer/src/stores/index.ts只 re-export domain barrel,不逐文件 re-export store。renderer 非 store 代码应从@renderer/storesroot barrel 导入 store,不要从@renderer/stores/<domain>深路径导入。store 模块内部不得导入 root barrel,跨 store 组合时使用目标 domain barrel 或直接 store module,避免stores/index.ts形成循环依赖。证据:src/renderer/src/stores/platform/index.ts、src/renderer/src/stores/session/index.ts、src/renderer/src/stores/index.ts、src/renderer/src/pages/task.vue、eslint.config.mjs。 - MUST 让每个 renderer store 只直接导入本 domain 的 API wrapper;如果需要组合其他 domain 的能力,应导入其他 domain 的 store 或由本 domain store 提供更高层 action。不得在
src/renderer/src/stores/<domain>/**直接导入src/renderer/src/api/<other-domain>/**。该规则由eslint.config.mjs强制。证据:src/renderer/src/stores/session/session.ts、src/renderer/src/stores/automation/task.ts、eslint.config.mjs。 - SHOULD 让页面和组件通过所属流程的 store/composable 取数和提交动作,避免直接导入无关 domain 的 API wrapper。需要跨 domain 组合时,优先把组合逻辑收敛到拥有该页面流程的 store。证据:
src/renderer/src/pages/task.vue、src/renderer/src/stores/automation/task.ts。 - SHOULD 让页面、组件和关键 composable 的跨 domain store 组合保持流程所有权清晰;当组合逻辑开始承载业务流程,应收敛到 owner store action,而不是在页面里长期堆叠多个领域的细节。该约束通过 review 判断,不再由文件级 lint 白名单维护。证据:
src/renderer/src/pages/task.vue、src/renderer/src/stores/automation/task.ts。 - MUST 通过
src/renderer/src/api/workspace/window.ts和useWorkspaceStore().bootstrapWindowWorkspace()绑定当前窗口的 Workspace 上下文。当前 Workspace 只能来自 main 返回的WindowContext;组件打开 Workspace 或文件夹时调用 Workspace store 的openWorkspaceWindow()/openFolderWindow(),不要在组件中直接替换currentWorkspace。证据:src/renderer/src/stores/workspace/workspace.ts、src/renderer/src/bootstrap/tasks/workspaces.ts、src/renderer/src/components/welcome/WelcomeView.vue。 - MUST 在 launcher context 中保持
currentWorkspace为空;在 Workspace context 不可用、Workspace 不存在或 primary Folder path 缺失时展示页面级错误状态并清空 session state。Workspace bootstrap 必须在同一任务中按 context、Workspace list、当前 Workspace、session list 的顺序完成。证据:src/renderer/src/stores/workspace/workspace.ts、test/renderer/src/stores/workspace/workspace.spec.ts、src/renderer/src/pages/index.vue。 - MUST 让 launcher 使用 active/deleted
WorkspaceLauncherItem投影管理 Folder 与 Collection Workspace;创建、成员编辑、重定位、soft delete、restore 和永久清理只通过 Workspace store action 进入,组件不得直接调用 preload API。证据:src/renderer/src/stores/workspace/workspace.ts、src/renderer/src/components/welcome/WorkspaceList.vue、src/renderer/src/components/welcome/DeletedWorkspaceManager.vue。 - MUST 让 Workspace-scoped 异步结果绑定请求发起时的
workspaceId和请求世代;切换 Workspace 后的迟到 list/detail 响应不得覆盖新 Workspace state,确认式删除和 Action 执行也必须拒绝 scope 已变化的操作。证据:src/renderer/src/stores/session/session.ts、src/renderer/src/stores/insight/knowledge.ts、src/renderer/src/features/fyllo-action/application/use-fyllo-action-dispatcher.ts、src/renderer/src/pages/knowledge.vue。 - MUST 让 proposal list key、detail selection、status update 和 EventRail item 使用完整
ProposalRef { folderId, changeId };不得用裸changeId在不同 Folder 的同名 proposal 之间查找、更新或取消 watcher。Proposal 列表和会话卡片必须展示 owner Folder,linked target 通过worktreeMode与worktreePath呈现;Apply/Archive 入口只发送包含该 ProposalRef 的 Chat 文字消息,不得重新引入 Proposal stage-stream 或 run store。证据:src/renderer/src/stores/proposal/browser.ts、src/renderer/src/stores/session/session.ts、src/renderer/src/components/proposal/ProposalDetailSlideover.vue、src/renderer/src/components/chat/event/ChatProposalPanel.vue、src/renderer/src/pages/proposal.vue。 - MUST 让 Specs、Guidelines、Proposal 与 Overview store 保留 Main 返回的 per-Folder aggregate 和 completeness,列表 key、选择及详情调用分别使用完整
SpecRef、GuidelineRef、ProposalRef;Folder filter 只能改变可见集合,不得重写 owner。页面必须区分 ready-empty、missing、error 与 partial,并让请求绑定发起时的workspaceId和 generation,拒绝前一 Workspace 的迟到响应。证据:src/renderer/src/stores/insight/specs.ts、src/renderer/src/stores/insight/guidelines.ts、src/renderer/src/stores/proposal/browser.ts、src/renderer/src/stores/insight/overview.ts、src/renderer/src/pages/specs.vue、src/renderer/src/pages/guidelines.vue、src/renderer/src/pages/proposal.vue、src/renderer/src/pages/overview.vue。 - MUST 让 Task、Workflow definition/Run 与 Workspace Integration renderer 流程显式携带当前
workspaceId。Task target 与 repository-bound integration binding 必须显示 current/stale 或 unbound 状态;从 Task 建议 proposal owner 时,仅当原始去重 target 集合恰好一个且仍为当前成员才可预选,多 target 降级后不得猜测 owner。Workflow Editor 只负责 v2 definition CRUD;Workflow Run 使用独立 owner-keyed store 和automation:workflow-run:*API,不得把 Run 状态并入 definition store。window.api.automation.workspaceIntegration是 Integration 唯一公开入口,不保留 Project 命名 alias。证据:src/renderer/src/stores/automation/task.ts、src/renderer/src/stores/automation/workflow.ts、src/renderer/src/stores/automation/workflow-run.ts、src/renderer/src/stores/automation/workspace-integration.ts、src/renderer/src/features/workflow-editor/README.md、src/preload/index.ts。 - MUST 让 Lineage Browser 仅以当前 Workspace subjects 作为列表来源,并让每个 proposal node 携带完整
ProposalRef、owner Folder metadata 与 composite key;详情入口必须按该ProposalRef打开正确 repository owner,不得按裸changeId匹配。Workspace 切换后的迟到 lineage 响应必须丢弃,共享 Folder 的 proposal 只能使用当前 Workspace subject/reference 补充 task/session 信息,不得读取其他 Workspace 的 subject 内容。证据:src/renderer/src/stores/insight/lineage.ts、src/renderer/src/pages/lineage.vue、src/renderer/src/composables/useProposalDetailSlideover.ts、src/main/services/insight/lineage/browser.ts。 - MUST 让 spawned completion wake 保持 level-triggered:事件只表示当前 Workspace outbox 可能变化,renderer 每次启动和 wake 都通过 typed API 重新 list,不把事件 payload 或内存队列当作事实来源。
useChatStore()必须按 parent sessionId 仲裁用户 turn 与 notification dispatch,用户提交意图优先,目标 Session submitted/streaming 时保留 pending;非 active Session 的消息刷新只能更新该 Session,不得切换activeSessionId、清空当前 composer 或导航。窗口关闭可丢弃 UI 投影,重开后继续通过既有 Session list/loadMessages恢复 Main 已持久化的 user reminder 与 assistant terminal。证据:src/renderer/src/bootstrap/tasks/spawn-notifications.ts、src/renderer/src/stores/session/chat.ts、src/renderer/src/stores/session/session.ts、src/renderer/src/api/session/chat.ts。
- MUST 将 Workflow definition 与 Workflow Run 视为两个 renderer 状态边界:
src/renderer/src/stores/automation/workflow.ts只负责 Workspace-owned v2 YAML definition CRUD,src/renderer/src/stores/automation/workflow-run.ts负责以workspaceId + parentSessionId + runId为 key 的 list/detail/decide;Workflow Editor 不读取或写入 Run snapshot,也不触发执行。证据:src/renderer/src/features/workflow-editor/README.md、src/renderer/src/stores/automation/workflow.ts、src/renderer/src/stores/automation/workflow-run.ts。 - MUST 让 Workflow Run 使用 wake + interest-gated pull:Main wake 只表示
{ workspaceId, runId }可能失效,只有 ActivityEntry/detail view 持有 active interest 时才能调用getDetail;无 observer 时不得因 wake 发起查询,Workspace/parent/interest generation 改变后的迟到响应必须丢弃。证据:src/renderer/src/features/workflow-run-inspector/integration/wake.ts、src/renderer/src/stores/automation/workflow-run.ts、src/renderer/src/features/workflow-run-inspector/application/use-workflow-run-inspector.ts、test/renderer/src/stores/automation/workflow-run.spec.ts。 - MUST 让
WorkflowRunActivityEntry与SpawnedSessionActivityEntry在ChatBackgroundActivityBar中保持平级;Workflow entry 只能从 workflow-run store、自己的 interest/wake 和 Run projection 派生,不得读取 spawned store、spawn count 或 notification。fresh Agent transcript 入口必须使用 Engine 返回的 workflow session identity,不得把 session 加入 spawned list/count。证据:src/renderer/src/components/chat/ChatBackgroundActivityBar.vue、src/renderer/src/features/workflow-run-inspector/**、test/renderer/src/components/chat-background-activity-bar.spec.ts、test/renderer/src/features/workflow-run-inspector/**。
- MUST 通过
registerBootstrapTasks()和onFylloBootstrap()注册 renderer 启动副作用,而不是在 layout 组件中临时启动;每个 task 必须显式声明phase: "critical" | "background"。src/renderer/src/main.ts在 mount 后使用共享{ pinia, router }context 运行已注册任务。证据:src/renderer/src/main.ts、src/renderer/src/bootstrap/core.ts、src/renderer/src/bootstrap/register.ts。 - MUST 先并行结算全部 critical task,再启动 background task,并保持每个 task 的失败隔离和 name/phase/duration 结果。Workspace bootstrap 属于 critical,且其内部 context → list → current Workspace → sessions 顺序不变;ACP renderer cache 属于 background,不得阻塞应用可交互。证据:
src/renderer/src/bootstrap/core.ts、src/renderer/src/bootstrap/tasks/workspaces.ts、src/renderer/src/bootstrap/tasks/acp-agents.ts、test/renderer/src/bootstrap/fyllo-bootstrap.spec.ts。 - MUST 在 critical 未结算时只渲染
StartupLoading.vue,不得提前挂载 Welcome、WorkspaceRouterView或页面级业务错误;critical 成功或失败结算并在下一nextTick()后,通过window.api.platform.lifecycle.markInteractive()通知 main。Background task 状态只能影响其局部 UI。证据:src/renderer/src/App.vue、src/renderer/src/main.ts、test/renderer/src/app-startup.spec.ts。 - MUST 让 bootstrap task 注册保持幂等;新增任务注册应通过
registerBootstrapTasks()接入,该函数会防止重复注册。证据:src/renderer/src/bootstrap/register.ts。 - MUST 将 Workflow Run wake listener 作为
backgroundbootstrap task 注册,并在 Workspace 变化时清理旧 scope;task 只能订阅 Main 的 typed wake API,不能在页面 mount 时创建全局 listener。证据:src/renderer/src/bootstrap/tasks/workflow-runs.ts、src/renderer/src/bootstrap/register.ts、test/renderer/src/bootstrap/fyllo-bootstrap.spec.ts。 - MUST 在 Workspace critical bootstrap 结算后以 background task 注册 spawned notification listener并执行首次 pull;listener 重建时必须销毁旧订阅,旧 Workspace wake 不得触发当前 scope 的 drain。证据:
src/renderer/src/bootstrap/tasks/spawn-notifications.ts、test/renderer/src/bootstrap/spawn-notifications.spec.ts。 - MUST 让 spawned Session inspection 使用
useSpawnedSessionStore()保存 owner-scoped 查询状态:list key 为完整workspaceId + parentSessionId,detail key 还必须包含sessionId,同 key 请求合并并以 generation 拒绝 Workspace/父 Session 切换后的迟到结果。list interest 与 detail interest 必须分别引用计数;详情只在 Slideover 打开期间持有 detail interest,关闭后不得因缓存存在而继续读取。interest 范围内的 view wake 只触发 typed API 重新查询,不直接写 status/content,也不得触发 completion notification drain;in-flight 收到 wake 时必须合并为至多一个 queued post-refresh,terminal wake 不得丢失。历史spawn.session使用消息所属父 Session host context;当前 Chat footer 的活动宿主位于 Prompt 外部,展示同一父 Session 的 active 与 terminal 全部 list summary,并通过 spawned-session-inspector 根公共入口打开详情。证据:src/renderer/src/stores/session/spawned-session.ts、src/renderer/src/bootstrap/tasks/spawned-sessions.ts、src/renderer/src/features/fyllo-signal/**、src/renderer/src/features/spawned-session-inspector/**、src/renderer/src/components/chat/ChatContainer.vue、src/renderer/src/components/chat/ChatBackgroundActivityBar.vue。
pnpm exec vitest run --project renderer
pnpm typecheck:web- 当
electron.vite.config.ts、src/renderer/src/main.ts、src/renderer/src/config/auto-routes.ts、src/renderer/src/config/activity-bar.ts、src/renderer/src/bootstrap/**、src/renderer/src/api/**或src/renderer/src/stores/**发生变化时,重新检查本文档。