diff --git a/.project-docs/10-decisions/proposals/20260906-move-plugins-project-settings-7c91a4e2__project-settings-plugin-navigation.md b/.project-docs/10-decisions/proposals/20260906-move-plugins-project-settings-7c91a4e2__project-settings-plugin-navigation.md
new file mode 100644
index 0000000..1258205
--- /dev/null
+++ b/.project-docs/10-decisions/proposals/20260906-move-plugins-project-settings-7c91a4e2__project-settings-plugin-navigation.md
@@ -0,0 +1,86 @@
+# Project Configuration owns Plugin navigation
+
+## Status
+
+Proposed for integration; implemented and verified in task
+`20260906-move-plugins-project-settings-7c91a4e2`.
+
+## Date
+
+2026-09-06
+
+## Context
+
+The integrated product exposed one reviewed unified Plugin workspace at
+`/plugins` through a standalone Code sidebar entry. Project Configuration no
+longer contained its predecessor Plugin Services sheet. The user first directed
+that Plugins belong in Project Settings, then clarified that the workspace must
+live on the same project page used to configure Agents and Skills rather than
+replace that page after navigation.
+
+The navigation change must not collapse the existing independent lifecycles for
+Marketplace acquisition, device installation, project enablement, Agent Skill
+assignment, runtime authorization, and billing. It also must not restore the
+retired duplicate sheet or move Main-owned Plugin authority into Renderer code.
+
+## Decision
+
+- The Agent/Skill Project Configuration page is the visible owner of the single
+ unified Plugin workspace.
+- Its `插件` resource card opens the workspace in a wide same-page drawer. The
+ Project Configuration page remains mounted behind it.
+- `/project-config/plugins` is the canonical deep link for the drawer-open state;
+ it renders Project Configuration rather than a standalone Plugin page.
+- `/plugins` preserves query and navigation state while redirecting to the
+ canonical URL. `/plugin-marketplace`, `/my-plugins`, and `/project-plugins`
+ remain deterministic filtered compatibility redirects.
+- The Code sidebar has no standalone Plugin entry.
+- The canonical workspace remains accessible before Code Provider initialization
+ and when no project is active, so Marketplace and account/device views do not
+ incorrectly depend on local project selection.
+- The existing unified controller, data sources, mutation semantics,
+ authentication, and lifecycle separation remain unchanged.
+
+## Rationale
+
+Plugin installation and activation configure resources that projects may use, so
+Project Configuration is the clearer navigation owner. Reusing the unified
+workspace avoids competing product surfaces and preserves one authoritative view
+across Marketplace, Account Library, device packages, and project status.
+Compatibility redirects protect existing deep links and authenticated return
+flows while establishing an unambiguous canonical location.
+
+## Consequences
+
+- Project Configuration gains a Plugin card beside models, Skills, and knowledge,
+ with access retained in the no-active-project state.
+- Closing the Plugin drawer returns to the already-mounted Project Configuration
+ page; Agent assignment actions close the drawer to expose that same page.
+- Existing bookmarks continue to work, but tests and new product links should use
+ `/project-config/plugins`.
+- Canonical project memory that names the Code sidebar or `/plugins` as the sole
+ current entry must be superseded during Integration Mode.
+- No backend contract, package trust boundary, runtime permission, billing rule,
+ or native Web Search behavior changes.
+
+## Supersedes
+
+- The navigation-only claim that the Code sidebar owns the single `插件` entry and
+ `/plugins` is the canonical product route.
+- It does not supersede the retirement of the duplicate Project Configuration
+ Plugin Services sheet; that implementation remains retired.
+
+## Evidence
+
+- User direction: “插件应该在项目设置中”, clarified as “是放在配置agent、skill那个项目页”.
+- Focused unit verification: 62/62 passed.
+- Electron Plugin journeys: 4/4 passed.
+- Full unit, typecheck, lint, and Vite production build passed.
+
+## Related
+
+- `.project-docs/10-decisions/adr-008-interactive-ai-app-scaffold.md`
+- `.project-docs/30-worklog/tasks/20260906-move-plugins-project-settings-7c91a4e2.md`
+- `src/pages/ProjectConfiguration/index.tsx`
+- `src/pages/Plugins/index.tsx`
+- `src/pages/Plugins/legacy-plugin-redirect.tsx`
diff --git a/.project-docs/30-worklog/tasks/20260906-move-plugins-project-settings-7c91a4e2.md b/.project-docs/30-worklog/tasks/20260906-move-plugins-project-settings-7c91a4e2.md
new file mode 100644
index 0000000..7b110b5
--- /dev/null
+++ b/.project-docs/30-worklog/tasks/20260906-move-plugins-project-settings-7c91a4e2.md
@@ -0,0 +1,100 @@
+# Task: Move plugins into project settings
+
+## Identity
+
+- Task ID: 20260906-move-plugins-project-settings-7c91a4e2
+- Mode: Feature
+- Branch: codex/20260906-move-plugins-project-settings-7c91a4e2-move-plugins-project-settings
+- Worktree: /Users/inmanx/Documents/makelore-task-move-plugins-project-settings-7c91a4e2
+- Base commit: f8eee430f4f4167dc2ecc682ece96c652cdde14b
+- Owner: codex
+- Status: Ready for integration
+
+## Scope
+
+- Move the single user-visible Plugin workspace from the Code sidebar directly
+ into the same Project Configuration page used to configure Agents, Skills,
+ models, and knowledge.
+- Make `/project-config/plugins` the canonical Plugin URL while retaining
+ deterministic compatibility redirects from `/plugins`, `/plugin-marketplace`,
+ `/my-plugins`, and `/project-plugins`.
+- Update focused unit and Electron E2E coverage, the packaged-product marker, and
+ README current-state wording for the navigation change.
+
+## Intent And Constraints
+
+- Preserve the existing unified Plugin workspace and its projections of
+ Marketplace, Account Library, official-device state, Device Packages, current
+ project state, and retained IDs; do not restore the retired duplicate Plugin
+ Services sheet.
+- Keep acquisition, device installation, project enablement, Agent Skill
+ assignment, runtime authorization, and billing as separate lifecycles.
+- Preserve Main-owned Host API, authentication, package verification, and runtime
+ authority. Renderer navigation must not introduce direct IPC or local-runtime
+ HTTP access.
+- Keep Project Configuration and its nested Plugin route available before Code
+ Provider initialization, including the no-active-project state.
+- Render the nested route as a same-page Project Configuration drawer, not as a
+ replacement standalone Plugin page.
+- Preserve legacy deep-link query/state and authenticated return paths.
+- Keep the single Makelore light visual system and Chinese product copy.
+
+## Outcome
+
+- Added a `插件` ResourceCard alongside models, Skills, and knowledge in Project
+ Configuration, retained access in the no-active-project state, and removed the
+ standalone Code sidebar Plugin entry.
+- Changed `/project-config/plugins` to render the Project Configuration page with
+ its wide Plugin drawer open. The Agent/Skill project page remains mounted behind
+ the drawer; closing it returns to the same page. Query/state-preserving
+ `/plugins` compatibility and existing filtered legacy redirects remain intact.
+- Reused the unified Plugin controller and view inside the drawer without
+ restoring the retired duplicate Plugin Services implementation.
+- Kept the unified Plugin controller, data sources, mutations, authentication,
+ and lifecycle semantics unchanged.
+- Updated initialization gates, login return path, README, packaged Marketplace
+ artifact assertion, focused unit tests, and Electron E2E journeys.
+
+## Verification
+
+- Focused navigation, layout, embedded Plugin, controller, login, and artifact
+ verification — 6 files, 62 tests passed; the embedded-view regression failed
+ before implementation and passed afterward.
+- `corepack pnpm run typecheck` — passed.
+- Scoped ESLint across all changed source and test files — passed with no output.
+- `corepack pnpm run build:vite` — Renderer, Main, Preload, and utility builds passed;
+ only existing Browserslist, mixed-import, and chunk-size warnings remained.
+- `node ./node_modules/@playwright/test/cli.js test tests/e2e/project-plugins.spec.ts tests/e2e/plugin-marketplace.spec.ts` — 4/4 passed, including assertions that the Project Configuration page remains mounted behind the Plugin drawer.
+- `corepack pnpm test` — 221 regular files (1861 passed, 3 skipped) and the pressure suite (1 passed).
+- `corepack pnpm run lint:check` — passed with 0 errors and 5 pre-existing warnings.
+- `git diff --check` — passed.
+
+## Follow-ups
+
+- Integration should reconcile the navigation wording in canonical project memory
+ and review overlap with planning task `20260906-remove-project-gate-7c31` before
+ merging. No product-semantic conflict was found in the current peer-task audit.
+
+## Promotion Candidates
+
+- Target: `.project-docs/30-worklog/current-state.md`,
+ `.project-docs/20-architecture/system-overview.md`, and
+ `.project-docs/40-domain/business-rules.md`.
+- Proposal: record the Agent/Skill Project Configuration page as the visible
+ owner of the single unified Plugin workspace. Its `插件` card opens a same-page
+ wide drawer; `/project-config/plugins` is the canonical deep link for that
+ state, and old public URLs remain deterministic compatibility redirects. This
+ rehomes the reviewed unified workspace and does not restore the superseded
+ duplicate Plugin Services implementation.
+- Evidence: explicit user direction in this task, focused unit coverage, 4/4
+ Electron E2E, full unit/typecheck/lint/build verification, and the task-owned
+ proposal `20260906-move-plugins-project-settings-7c91a4e2__project-settings-plugin-navigation.md`.
+- Future impact: new Plugin navigation must originate in Project Configuration,
+ while Plugin lifecycle boundaries, Web Search exclusion, and Main-owned
+ authority remain unchanged.
+- Semantic conflict: this supersedes canonical statements that the Code sidebar
+ owns the only Plugin entry and `/plugins` is canonical; it does not conflict
+ with ADR-008 or the Plugin lifecycle boundaries.
+- Human confirmation: already supplied and clarified by the user: Plugins belong
+ on the same project page used to configure Agents and Skills, not on a separate
+ page. No additional product-direction approval is required during integration.
diff --git a/README.md b/README.md
index 75e6478..edd61ab 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ Makelore 是一个面向软件、视觉创作与智能机器人的 AI 桌面工
- AI 绘画生成:服务端从已确认规格编译专业图片或视频指令并返回不可变 Quote;客户端只展示媒介、画幅、数量、格式、时长、警告和设计点,不展示或改写供应商 Prompt、模型、价格原子或存储地址。确认时只提交 Quote 身份。图片可使用当前 Workspace 的上传素材或生成作品,视频可绑定已审核首帧;任务与资产始终属于 Workspace。
- AI 绘画健壮性:Renderer 为每次命令生成稳定 operation id,网络结果未知时保留原命令供原样重试,不把未知写入当失败或创建第二次生成。Main 负责 Token 刷新、Agent Gateway REST 提交和有界 Run 查询,并将可恢复事件流投影为 Host API SSE;断线后按事件游标续接并重新读取权威 Workspace。Canvas 只使用 Works Square 云端 V2 契约,没有本地语义适配器或降级路径,上游不可用时明确报错。
- AI 绘画项目栏只展示 Workspace,不再在项目下创建独立设计会话。删除时必须完整输入项目名称;删除后项目、Living Form、任务、参考图和生成作品会从账户中隐藏且无法访问,不影响用户已另存到磁盘的副本。删除当前项目后自动打开最近更新的剩余项目,删除最后一个项目后进入空状态。
-- 插件工作台:Code 侧栏只有一个“插件”入口,`/plugins` 在同一列表中投影官方目录、账号 Library、本机 Device Packages 与当前项目状态;旧 Marketplace、My Plugins、Project Plugins URL 只做确定性筛选重定向。来源身份保持 `official:`、`local:`、`retained:` 分离;“免费获取”、官方设备交付、项目启用和伙伴分配仍分别写入既有 authority,不会自动推进下一步。任一来源失败不会清空其他来源;本机 Skill/Pi 插件仍只能通过对话安装,页面只管理已安装包并明确其本机全局生效范围。
+- 项目插件设置:Code 侧栏不再单列“插件”;配置 Agent、Skill、模型与知识的项目配置页内提供“插件”卡片,并在同页宽抽屉中投影官方目录、账号 Library、本机 Device Packages 与当前项目状态。深链使用 `/project-config/plugins` 打开该项目页抽屉;旧 `/plugins`、Marketplace、My Plugins、Project Plugins URL 只做保留查询条件的确定性重定向。来源身份保持 `official:`、`local:`、`retained:` 分离;“免费获取”、官方设备交付、项目启用和伙伴分配仍分别写入既有 authority,不会自动推进下一步。任一来源失败不会清空其他来源;本机 Skill/Pi 插件仍只能通过对话安装,页面只管理已安装包并明确其本机全局生效范围。
- 官方插件运行架构:Renderer 只调用 Main-owned Marketplace facade;Main 负责账号、请求 deadline、签名/摘要校验、不可变 Release、current selection 与原子回滚。Pi parent worker 使用冻结的 effective snapshot,将每个有效 Skill 与已验证 Package Store root 成对传给 resource loader、Extension Host 和 CLI;普通 `skill_only` 下载包不依赖运行时 Policy,也不得携带可执行脚本。Project Scaffold 的 `.mjs` 是代码所有的 bundled 例外,只能从签名客户端固定资源根通过应用自带 Node 执行,不能扩展为 Marketplace 下载 artifact 的脚本权限。正式激活仍等待官方 Ed25519 公钥(production key activation HOLD);生产私钥只能来自部署 secret,测试使用注入的临时密钥。
- 原生 Web Search 是冻结 selected model/provider/credential 的 parent-only 模型工具;只有 Works `model_capabilities` 明确声明支持时才出现,使用当前模型的正常计费链,不依赖 Marketplace 获取、Release、Admission、Hosted Provider 或 `agent_browser` 回退。
- 本机 Device Packages 只由 Conversation 工具发起安装,支持 npm、Git、绝对本地 Plugin 目录和 loose `SKILL.md`。Main 在预览和独立确认后提交不可变本机 generation,禁用生命周期脚本;确认界面明确提示 Pi extension 以桌面当前用户权限执行。新建/空闲 parent 会同时加载所有显式安装且当前启用的 Skill,以及必需 Makelore 扩展之外的全部 Pi extension,active parent 在 turn settled 后切换,child 不继承这些资源,也不会扫描 ambient 项目或用户目录;Renderer 不提供安装源选择器。
diff --git a/scripts/lib/pi-product-artifact.mjs b/scripts/lib/pi-product-artifact.mjs
index 021e2fd..4c2977e 100644
--- a/scripts/lib/pi-product-artifact.mjs
+++ b/scripts/lib/pi-product-artifact.mjs
@@ -69,7 +69,7 @@ const MARKETPLACE_ARTIFACT_MARKERS = Object.freeze({
'/api/coding/plugin-marketplace/library',
'免费获取',
'获取、项目启用与伙伴分配彼此独立',
- '/plugins',
+ '/project-config/plugins',
]),
});
const FORBIDDEN_PROVIDER_AUTHORITY_MARKERS = Object.freeze([
diff --git a/src/App.tsx b/src/App.tsx
index f1cd4a1..6c520ec 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -26,14 +26,17 @@ import { subscribeHostEvent } from '@/lib/host-events';
import { reportDesktopActivity, type DesktopActivityModule } from '@/lib/host-api';
import { installRendererPerformanceDiagnostics } from '@/lib/performance-diagnostics';
import { resolveSupportedLanguage } from '../shared/language';
-import { LegacyPluginRedirect } from './pages/Plugins/legacy-plugin-redirect';
+import {
+ LegacyPluginRedirect,
+ PluginWorkspaceRedirect,
+ PROJECT_SETTINGS_PLUGINS_PATH,
+} from './pages/Plugins/legacy-plugin-redirect';
const Models = lazy(() => import('./pages/Models').then(({ Models: component }) => ({ default: component })));
const Chat = lazy(() => import('./pages/Chat').then(({ Chat: component }) => ({ default: component })));
const Home = lazy(() => import('./pages/Home').then(({ Home: component }) => ({ default: component })));
const PreviewScene = lazy(() => import('./pages/Makelore').then(({ PreviewScene: component }) => ({ default: component })));
const ProjectConfiguration = lazy(() => import('./pages/ProjectConfiguration').then(({ ProjectConfiguration: component }) => ({ default: component })));
-const Plugins = lazy(() => import('./pages/Plugins').then(({ Plugins: component }) => ({ default: component })));
const Workbench = lazy(() => import('./pages/Workbench').then(({ Workbench: component }) => ({ default: component })));
const ImageCanvas = lazy(() => import('./pages/ImageCanvas').then(({ ImageCanvas: component }) => ({ default: component })));
const ImagePromptMuseum = lazy(() => import('./pages/ImagePromptMuseum').then(({ ImagePromptMuseum: component }) => ({ default: component })));
@@ -442,7 +445,8 @@ function App() {
)}
>