docs: integrate unified plugin workspace

This commit is contained in:
2026-09-03 15:55:58 +08:00
parent d7058e6383
commit fcdc1b2f6e
10 changed files with 120 additions and 1222 deletions

View File

@@ -1,576 +0,0 @@
# MakeLore 统一插件工作台实施规范
## 0. 文档信息
| 字段 | 值 |
| --- | --- |
| Spec ID | `ML-PLUGIN-NAV-001` |
| 状态 | 产品方向已获用户确认;待实施 |
| 日期 | 2026-09-03 |
| Task | `20260903-plugin-navigation-design-7c4e2a91` |
| 客户端基线 | `e9875145b41a2cb1827de10d27a4fc6a352704ea` |
| 影响仓库 | MakeLore 客户端 |
| 服务端影响 | 无新接口、无 DTO 变化、无迁移 |
| 来源设计 | 将“插件中心 / 我的插件 / 项目插件”合并为一个 Codex 风格插件入口 |
本文把已确认的产品方向收敛为可实施、可验证的客户端合同。关键词含义:
- **MUST / 必须**:不满足即本次改造未完成。
- **MUST NOT / 禁止**:实现不得出现。
- **SHOULD / 应当**:默认实现方式;偏离时须在任务记录中说明理由。
- **MAY / 可以**:不影响合同的实现选择。
## 1. 已确认事实与独立判断
### 1.1 当前事实
客户端目前存在三个独立页面和三个侧栏入口:
- `/plugin-marketplace`:运营发布的官方目录、搜索、详情和免费获取。
- `/my-plugins`:账号插件库、官方设备包状态和通过对话安装的本机 Device Package。
- `/project-plugins`:当前项目启用状态、伙伴分配投影、计费能力与插件设置。
这些页面实际投影的是同一插件在不同阶段的状态,但底层权威并不相同:
1. 官方目录与详情;
2. Account Library 免费获取状态;
3. 官方设备包的 Package Store 状态;
4. 本机 Device Package 状态;
5. 当前项目启用状态;
6. Agent Skill 分配状态;
7. runtime admission、后端与计费状态。
当前原生 Web Search 已是所选模型的核心工具,不再是 Marketplace Plugin。通过对话安装的
第三方 Web Search、Skill 或 Pi extension 仍属于本机 Device Package。
### 1.2 结论
三个导航入口必须合并,但只能合并用户界面和只读投影,不能合并上述权威状态机。
若只是把三个旧页面放进三个 Tab用户仍需理解“去哪里发现、去哪里下载、去哪里启用”的
旧流程,且新插件类型会继续制造第四个页面。因此本规范采用:
- 一个侧栏入口;
- 一个 canonical route
- 一份统一列表;
- 范围、来源和状态筛选;
- 一个详情面板;
- 各 mutation 仍发送给原有 owner。
## 2. 目标结果
完成后必须实现以下产品结果:
1. Code 侧栏只出现一个“插件”入口。
2. `/plugins` 是唯一 canonical 页面。
3. 官方目录、账号已获取插件、本机包和当前项目状态可以在同一列表中理解和操作。
4. 用户无需先进入“我的插件”再跳转“项目插件”。
5. 免费获取、设备交付、项目启用和 Agent 分配仍是显式且互不自动推进的步骤。
6. 本机 Skill/extension 仍只能通过对话安装;页面只管理已安装内容。
7. 任一远端投影失败时,其他来源仍可独立显示和操作。
8. 旧书签和旧页面链接通过确定性 redirect 进入新的等价筛选状态。
9. 原生模型 Web Search 不作为插件卡片出现。
## 3. 范围
### 3.1 包含
- Code 侧栏插件导航合并。
- `/plugins` route 与旧 route redirects。
- Renderer 统一插件只读投影 Module。
- 统一搜索、范围、来源、状态筛选。
- 官方、本机、项目保留项的统一卡片与详情面板。
- 现有获取、移除、官方设备包、项目启用、本机启停/移除和 Data Service 设置入口。
- 部分失败、缓存、账号切换和项目切换行为。
- 单元测试、页面测试、路由测试和 Electron E2E 更新。
- README 与 task-scoped 项目文档更新。
### 3.2 不包含
- 服务端 Marketplace、Library、Admission、Policy、Token Point 或 Provider 接口变化。
- 新的 Renderer 持久化状态或第四份插件数据库。
- 可见的 npm、Git、文件夹、ZIP 或 `SKILL.md` 安装入口。
- 将本机 Device Package 改为项目级启用。
- 将原生模型 Web Search 重新注册为 Marketplace Plugin。
- 自动获取、自动下载、自动启用项目或自动分配 Agent。
- 插件发布、运营端管理或 Release 生命周期改造。
- 通用第三方插件审核或权限沙箱。
## 4. 不可变产品合同
### 4.1 导航
- `NAV-001`:侧栏 MUST 只有一个 `插件` 按钮,测试标识为
`sidebar-nav-plugins`
- `NAV-002`:按钮在存在当前项目时 MUST 打开
`/plugins?scope=project`;没有当前项目时 MUST 打开
`/plugins?scope=all`
- `NAV-003``/plugins` MUST 是 Code 模块路由且是项目初始化安全路由。
- `NAV-004``/plugins` MUST NOT 成为全页 Provider gate。目录和本机包不能因当前项目
Provider 未配置而不可见。
- `NAV-005`:旧路由 MUST 使用 replace redirect不得继续挂载旧页面。
旧路由映射固定为:
| 旧路由 | 新路由 |
| --- | --- |
| `/plugin-marketplace` | `/plugins?scope=all&source=official` |
| `/my-plugins` | `/plugins?scope=all&state=mine` |
| `/project-plugins` | `/plugins?scope=project` |
### 4.2 状态推进
- `STATE-001`:免费获取只改变 Account Library。
- `STATE-002`:免费获取 MUST NOT 自动下载、启用项目或分配 Agent。
- `STATE-003`:项目启用 MUST 使用当前项目的显式 ID项目切换后旧确认框不得作用于
新项目。
- `STATE-004`Agent 分配仍由项目配置拥有;统一页面只展示投影并跳转到现有分配入口。
- `STATE-005`:本机包启停是设备全局行为,文案必须写明“所有项目”或“本机全局”,
不得显示为“当前项目已启用”。
- `STATE-006`:本机包安装仍是 prepare → 用户确认 → commit 的对话流程;页面不得提供
install picker。
- `STATE-007`system-included 和 code-owned bundled 插件不得显示不适用的下载、更新、
Beta、签名或设备删除动作。
- `STATE-008`:项目中保留但当前无法解析的 plugin ID 必须继续显示,并只提供明确的
“从项目禁用”动作。
### 4.3 Web Search
- `WEB-001`:所选模型的原生 `makelore_web_search` MUST NOT 进入统一插件投影。
- `WEB-002`:原生 Web Search 的可用性属于模型/Agent capability UI。
- `WEB-003`:若用户通过对话安装第三方 Web Search package它只以“本机”来源显示
并遵守 Device Package 的全局启停与新会话加载合同。
## 5. 页面信息架构
### 5.1 页面头部
页面标题固定为“插件”,说明文案必须同时表达:
- 官方插件由 MakeLore 运营发布;
- 本机 Skill/extension 通过对话安装;
- 获取、项目启用和 Agent 分配是独立步骤。
页面提供一个刷新按钮。刷新 MUST 独立触发可用的数据源,不得因为一个 Promise reject
而跳过其他数据源。
### 5.2 筛选
筛选参数是 URL query 的 canonical 状态:
```ts
type PluginWorkspaceScope = 'all' | 'project';
type PluginWorkspaceSource = 'all' | 'official' | 'local';
type PluginWorkspaceState =
| 'all'
| 'available'
| 'mine'
| 'enabled'
| 'update'
| 'unavailable';
```
`/plugins` 的默认 `scope` 与侧栏一致:存在当前项目时为 `project`,否则为 `all`
实现等待 workspace hydration 后只规范化一次 URL禁止因后续异步投影反复改写用户选择。
详情可以使用可选的 `plugin=<source-qualified-key>` query无效或已消失的 key 只关闭详情,
不影响其余筛选。
用户可见控件:
- 范围:`全部插件` / `当前项目`
- 来源:`全部来源` / `官方` / `本机`
- 状态:`全部状态` / `可获取` / `我的` / `已启用` / `可更新` / `不可用`
- 搜索名称、简介、标签、package ID。
要求:
- `FILTER-001`:未知 query 值 MUST 归一为默认值,不得导致白屏。
- `FILTER-002``scope=project` 且没有当前项目时 MUST 回到 `scope=all`,并显示一次
非阻断说明。
- `FILTER-003``state=mine` 表示官方 system-included/当前已获取项与全部本机安装项;
不等同于“已下载到设备”。
- `FILTER-004`:官方搜索词 MUST 发送给现有目录搜索;同一搜索词 MUST 同时在本地过滤
已知 Library、项目投影和 Device Package。
- `FILTER-005`:远端搜索失败不得清空符合条件的本机结果。
- `FILTER-006`:筛选只影响展示,不得触发 acquisition、install 或 enable mutation。
范围语义固定为:
- `scope=all`:官方 catalog/Library/project 已知条目的并集、全部本机包,以及必要的
project retained 条目;
- `scope=project`:当前 project projection 的官方条目、全部本机包和 retained IDs。
本机包必须放在“本机全局生效”分组,不能伪装成项目 assignment
- `state=available`:当前可免费获取且尚未获取的官方条目;
- `state=mine`system-included、当前已获取的官方条目及全部本机包
- `state=enabled`:当前项目已启用的官方条目及本机全局已启用条目;
- `state=update`:现有官方设备包明确存在同频道更新的条目;
- `state=unavailable`暂停、退役后不可重新获取、client incompatible、投影 unavailable
或 retained 的条目。
默认排序不得依赖异步完成顺序:官方 catalog 项保持服务端目录顺序,随后是 Library-only、
project-only、按显示名排序的本机包最后是 retained IDs`scope=project` 时先保持 project
projection 顺序,再列本机包和 retained IDs。
### 5.3 列表与卡片
每张卡片必须在一个位置展示适用的状态维度:
- 来源:`官方` / `本机` / `配置保留`
- 交付:`随 MakeLore 提供` / `账号已获取` / `本机已安装` / `尚未获取`
- 当前项目:`已启用` / `未启用` / `暂不可用`
- 本机包:`本机全局已启用` / `本机全局已停用`
- Agent已分配伙伴数量或“尚未分配”
- 计费:`包含` / `按 Token Point` / `混合` / `无平台插件计费投影`
- 更新、暂停、退役、缓存或不可用提示。
卡片不得用一个“已安装”标签混淆 Account Library、官方设备包和本机包。
### 5.4 详情面板
选择卡片后打开一个统一详情抽屉或同页详情面板,内容顺序固定为:
1. 名称、来源、发布者和版本;
2. 介绍;
3. 当前账号/设备/项目状态;
4. 主动作;
5. 能力与权限;
6. Token Point 说明;
7. Agent 分配;
8. 插件专属设置。
官方详情按需调用现有 `loadDetail(pluginId)`。本机详情只能使用 Device Package 的安全
Renderer 投影,不得读取包目录、任意 manifest 文件或绝对安装路径。
Data Service 设置 Surface 必须迁移到新详情面板,行为和 destructive confirmation 保持
不变。
## 6. 统一投影 Module
### 6.1 Seam
在 Renderer 增加一个纯计算的 `PluginWorkspaceProjection` Module。它是页面唯一学习的
聚合 Interface它不发网络请求、不写 store、不持久化数据。
建议位置:
```text
src/pages/Plugins/
index.tsx
plugin-workspace-model.ts
PluginDetails.tsx
```
外部 Interface
```ts
interface PluginWorkspaceInputs {
catalog: MarketplaceCatalogPage | null;
details: Readonly<Record<string, MarketplacePluginDetail>>;
library: MarketplaceLibrarySnapshot | null;
marketplaceInstallations: Readonly<Record<string, MarketplaceInstallation>>;
devicePackages: DevicePackageIndexV1 | null;
project: CodingPluginProject | null;
activeProject: { id: string; name: string } | null;
agentNames: Readonly<Record<string, string>>;
filters: PluginWorkspaceFilters;
}
interface PluginWorkspaceProjection {
items: readonly PluginWorkspaceItem[];
selected: PluginWorkspaceItem | null;
counts: Readonly<Record<PluginWorkspaceState, number>>;
notices: readonly PluginWorkspaceNotice[];
}
function buildPluginWorkspaceProjection(
input: PluginWorkspaceInputs,
): PluginWorkspaceProjection;
```
页面可以保留短暂的 selected key 与 filter form state不得新增第二个持久 Zustand authority。
### 6.2 稳定身份
统一条目 key 必须带来源,禁止按裸 ID 把本机包和官方插件合并:
```ts
type PluginWorkspaceKey =
| `official:${string}`
| `local:${string}`
| `retained:${string}`;
```
投影算法:
1.`pluginId` 合并 catalog、detail、Library、官方设备包和 project item
2. catalog 不含但 Library 或 project 仍存在的官方条目不得丢失;
3. 每个 Device Package 始终生成独立的 `local:` 条目;
4. `unknownPluginIds` 中仍未被官方条目解释的 ID 生成 `retained:` 条目;
5. 不得根据相同 Skill ID、显示名或 package ID 推断二者是同一插件。
### 6.3 Action union
投影条目只暴露当前合法动作:
```ts
type PluginWorkspaceCommand =
| { kind: 'acquire'; pluginId: string }
| { kind: 'reacquire'; pluginId: string }
| { kind: 'remove_from_library'; pluginId: string }
| { kind: 'install_stable'; pluginId: string }
| { kind: 'install_beta'; pluginId: string }
| { kind: 'update_official'; pluginId: string }
| { kind: 'remove_official_device_package'; pluginId: string }
| { kind: 'enable_project'; projectId: string; pluginId: string }
| { kind: 'disable_project'; projectId: string; pluginId: string }
| { kind: 'enable_local'; packageId: string }
| { kind: 'disable_local'; packageId: string }
| { kind: 'remove_local'; packageId: string }
| { kind: 'open_agent_assignment'; projectId: string; pluginId: string }
| { kind: 'open_settings'; projectId: string; pluginId: string };
```
页面使用单一局部 dispatcher 将 command 交给现有三个 store。dispatcher 不是状态 authority
不得复制 generation、pending 或 retry 逻辑。
### 6.4 Action matrix
| 条目类型 | 账号动作 | 设备动作 | 项目动作 | Agent 动作 |
| --- | --- | --- | --- | --- |
| system-included 官方插件 | 无 | 无 | 启用/禁用 | 分配 |
| code-owned bundled、已获取 | 移除 | 无 | 启用/禁用 | 分配 |
| code-owned bundled、未获取 | 免费获取 | 无 | 无 | 无 |
| downloadable 官方插件、已获取 | 移除 | 下载/更新/Beta/删除设备包 | 交付就绪后启用/禁用 | 分配 |
| downloadable 官方插件、未获取 | 免费获取 | 无 | 无 | 无 |
| 本机 Device Package | 无 | 本机全局启用/停用/移除 | 无 | 无;自动进入符合条件的新/空闲 parent |
| retained project ID | 无 | 无 | 仅从项目禁用 | 无 |
暂停、退役、removed、client-incompatible 或 unavailable 状态继续遵守现有 store/DTO 的
fail-closed 语义;统一页面不得为了显示按钮而自行放宽。
## 7. 数据加载与错误隔离
### 7.1 首次加载
页面挂载时独立启动:
1. `pluginMarketplaceStore.loadCatalog({ limit: 24 })`
2. 登录时 `activateAccount(accountKey)` + `loadLibrary()`
3. `devicePackageStore.load()`
4. 存在当前项目时 `codingPluginsStore.load(projectId)`
实现 MUST 使用独立 catch 或 `Promise.allSettled` 等价行为。禁止一个请求失败阻止其他请求。
### 7.2 部分失败
| 失败来源 | 必须保留的内容 |
| --- | --- |
| catalog | 可信缓存、Library 项、本机包、项目投影 |
| Library | 官方目录、本机包、项目保留配置;账号状态显示未知 |
| official Package Store | Library 和项目配置;保留旧设备版本与错误原因 |
| Device Packages | 官方目录、Library 和项目插件 |
| project projection | 官方目录、Library、本机包当前项目区域显示独立错误 |
- `ERR-001`:错误必须靠近对应来源显示,禁止整页 error boundary。
- `ERR-002`:已有可信缓存时继续展示并标记 stale。
- `ERR-003`:没有权威值时显示未知,不得从另一来源推断 acquisition、pricing 或 enablement。
- `ERR-004`:账号或项目切换必须使旧 generation 结果失去提交资格;复用现有 store 保护,
统一层不得另建竞态较弱的缓存。
- `ERR-005`:选择项在新投影中消失时关闭详情;不得把 A 项详情显示到 B 项。
## 8. 计费与文案
- `BILL-001`:“免费获取”只描述加入账号插件库,不能写成“免费使用”。
- `BILL-002`:列表只显示 `included``token_point``mixed` 的简洁摘要。
- `BILL-003`:详情中的 operation 级价格只来自 Marketplace detail 或当前 project policy
projection不得由客户端计算、缓存拼接或从 manifest 推断。
- `BILL-004`stale/unavailable pricing 必须显示对应状态,不作为新的 runtime admission 依据。
- `BILL-005`:本机包显示“无 MakeLore 平台插件计费投影”,不得承诺其外部服务或模型调用
一定免费。
## 9. 交互与可访问性
- `A11Y-001`:范围、来源、状态必须有可读 label并可用键盘完成选择。
- `A11Y-002`:当前筛选状态必须同时体现在 URL 与控件状态中。
- `A11Y-003`:状态不得只靠颜色表达,必须有文本。
- `A11Y-004`:详情抽屉使用 dialog 语义、初始焦点、Esc 关闭,并在关闭后把焦点还给原卡片。
- `A11Y-005`loading 用 `role=status`,阻断错误用 `role=alert`
- `A11Y-006`destructive action 必须继续使用确认对话框;确认文案包含具体插件名和作用域。
- `A11Y-007`:按钮文字必须区分“从账号移除”“删除设备包”“从项目禁用”“移除本机包”。
- `A11Y-008`:窄窗口中筛选可以换行,卡片主动作仍保持至少 40 px 点击高度。
## 10. 文件级改造建议
### 10.1 新增
| 文件 | 责任 |
| --- | --- |
| `src/pages/Plugins/index.tsx` | route orchestration、独立加载、query state、command dispatch |
| `src/pages/Plugins/plugin-workspace-model.ts` | 纯统一投影、identity、筛选、排序、actions、notices |
| `src/pages/Plugins/PluginDetails.tsx` | 详情、能力、计费、Agent 与 Data Service settings surface |
| `tests/unit/plugin-workspace-model.test.ts` | 深 Module Interface 测试 |
| `tests/unit/plugins-page.test.tsx` | 页面、部分失败、动作与可访问性测试 |
文件名可以按仓库命名习惯微调,但 Module 责任不得重新散回三个页面。
### 10.2 修改
| 文件 | 改造 |
| --- | --- |
| `src/App.tsx` | 注册 `/plugins`;旧 route replace redirect移除三个 lazy page |
| `src/components/layout/Sidebar.tsx` | 三入口收敛为 `sidebar-nav-plugins` |
| `src/components/layout/MainLayout.tsx` | `/plugins` 为 initialization-safe route |
| `src/lib/ai-modules.ts` | 新 route 加入 Code module不加入全页 Provider gate |
| `tests/unit/plugin-marketplace-pages.test.tsx` | 迁移到统一页面行为或删除被替代测试 |
| `tests/unit/project-plugins-page.test.tsx` | 迁移项目投影/settings/unknown ID 行为 |
| `tests/unit/main-layout-module-gate.test.tsx` | 新 route 与 redirects |
| `tests/e2e/plugin-marketplace.spec.ts` | 统一导航、发现、我的、本机和部分失败 |
| `tests/e2e/project-plugins.spec.ts` | 当前项目筛选、启停、Agent 跳转与 settings |
| artifact proof tests | 更新 canonical route/marker保持 Main authority 检查 |
### 10.3 删除
完成行为迁移后删除:
```text
src/pages/PluginMarketplace/
src/pages/MyPlugins/
src/pages/ProjectPlugins/
```
禁止保留旧页面作为 hidden fallback 或让旧、新页面同时拥有产品行为。
### 10.4 保持不变
以下 Module 继续拥有现有 Interface
```text
src/stores/plugin-marketplace.ts
src/stores/device-packages.ts
src/stores/coding-plugins.ts
src/lib/plugin-marketplace.ts
src/lib/device-packages.ts
src/lib/coding-plugins.ts
electron/api/routes/plugin-marketplace.ts
electron/api/routes/device-packages.ts
electron/coding-plugins/**
electron/coding-packages/**
```
若实施证据显示必须改变这些 Interface应先停止并修订本 Spec不能静默扩大范围。
## 11. 验证合同
### 11.1 统一投影单元测试
至少覆盖:
1. 同一官方 ID 从 catalog/Library/device/project 正确合并为一个条目;
2. 同名或同 ID 的本机 package 与官方插件保持两个来源 key
3. Library-only retired/removed 条目不会因当前 catalog query 缺失而消失;
4. project-only unknown ID 生成 disable-only retained 条目;
5. system-included 无获取、下载、更新或移除动作;
6. code-owned bundled 无设备包动作;
7. generic downloadable 插件保留现有 stable/Beta/update/remove 行为;
8. 本机包只有全局启停和移除动作;
9. `mine``project`、source、state 与 search 组合筛选;
10. 原生模型 Web Search 不进入投影;
11. Token Point 摘要不把免费获取误写为免费使用;
12. 任一输入来源为 null/error 时其他条目仍存在。
### 11.2 Renderer 页面测试
至少覆盖:
1. 仅一个页面标题和一组筛选控件;
2. catalog 失败时本机包仍显示;
3. Device Package 失败时官方条目仍显示;
4. 未登录时目录和本机包可见,账号动作要求登录;
5. 项目切换后旧 enable/disable confirmation 不得操作新项目;
6. 详情选择 A→B 时 A 的迟到 detail 不覆盖 B
7. Data Service settings surface 行为迁移无回归;
8. local package 页面没有安装按钮、文件选择器或 source 输入框;
9. destructive action 的 label 与 confirmation 精确区分作用域;
10. keyboard、focus return、status/alert 语义。
### 11.3 路由与侧栏测试
- 侧栏只存在 `sidebar-nav-plugins`
- active project 与 no-project 点击目标正确。
- 三个旧地址按第 4.1 节映射并使用 replace。
- `/plugins` 受 Code module access 管理,但不被项目初始化或 Provider 全页 gate 阻断。
- 登录回跳使用 `/plugins` canonical query不再写旧 route。
### 11.4 Electron E2E
至少覆盖四条真实 Renderer → Main Host API 流程:
1. 官方目录 → 免费获取 → `state=mine` 可见,但项目仍未启用;
2. 当前项目启用/禁用插件Agent 分配跳转仍正确;
3. catalog 503 时已安装本机 Skill 仍可见并可停用/启用;
4. system-included、code-owned bundled、本机包三类动作不会互相串线。
### 11.5 必跑命令
实施任务至少运行:
```text
pnpm run typecheck
pnpm run lint:check
pnpm test
pnpm run build:vite
pnpm run test:e2e -- tests/e2e/plugin-marketplace.spec.ts tests/e2e/project-plugins.spec.ts
```
若仓库脚本不接受上述 E2E 过滤语法,可使用项目已有的等价精确命令并在任务记录中写明。
任何失败必须区分本次回归、既有基线和环境阻塞,不得只报告总数。
## 12. 实施顺序
### `PN-01`:统一投影 Module
所有权:`src/pages/Plugins/plugin-workspace-model.ts` 与其测试。
交付identity、merge、filter、action matrix、partial-input 行为。此票据不改 route 或旧页面。
### `PN-02`:统一页面与详情
所有权:`src/pages/Plugins/**`、必要页面测试。
交付加载协调、列表、详情、commands、Data Service settings、可访问性。调用现有 stores
不改 Main contracts。
### `PN-03`:导航硬切换
所有权:`src/App.tsx`、Sidebar、MainLayout、`ai-modules.ts`、route/module tests。
交付唯一侧栏入口、canonical route、legacy redirects、旧页面删除。依赖 `PN-02`
### `PN-04`:回归与交付验证
所有权:插件 E2E、artifact markers、README 和 task-scoped evidence。
交付:全量静态/单元/build/Electron 验证确认没有旧入口、hidden fallback 或安装 picker。
建议单仓串行实施 `PN-01 → PN-02 → PN-03 → PN-04`,避免多个任务同时改页面测试和路由。
## 13. Definition of Done
只有同时满足以下条件才可宣称完成:
1. 侧栏与 route 只剩一个 canonical 插件入口。
2. 三个旧页面实现已删除,旧地址只做 redirect。
3. 统一投影有独立 Interface 测试,页面不直接散落跨 store 合并判断。
4. Catalog、Library、官方设备包、本机包、项目和 Agent 状态仍各自归原 owner。
5. 官方、本机和 retained 项的动作矩阵全部通过测试。
6. catalog 或 project 任一失败不会遮蔽本机包Device Package 失败不会遮蔽官方目录。
7. 没有可见本机安装入口。
8. 原生模型 Web Search 不出现在插件列表;第三方本机包仍可出现。
9. Data Service 设置、Game Resource 获取/项目启用和本机 Skill 启停均无回归。
10. typecheck、lint、unit、Vite build 和目标 Electron E2E 通过。
11. 实施任务完成项目文档门禁canonical 架构更新只在 Integration Gate 进行。
## 14. 后续但不属于本次
若未来要让本机 Skill 按项目或 Agent 单独启用,必须另立领域设计:它会改变 Device Package
当前“本机全局、所有符合条件 parent 自动加载”的合同,不能作为本次导航合并的顺手功能。

View File

@@ -10,7 +10,7 @@
| `electron/coding-runtime/pi/model-tools/**` and `shared/model-tools.ts` | Closed selected-model tool registry and provider-specific Web Search request shaping | The frozen selected model capability controls whether `makelore_web_search` exists. The tool uses that model/provider/credential and normal model billing; no Hosted Plugin adapter, Admission, Plugin Charge, or browser fallback exists. |
| `electron/coding-packages/**`, `electron/api/routes/device-packages.ts`, `shared/device-packages.ts`, and `src/stores/device-packages.ts` | Main-owned conversation install preview/confirmation/commit, immutable local package generations, safe Renderer projection, and parent-worker refresh | Sources are npm, Git, absolute local Plugin directories, or loose `SKILL.md`. Lifecycle scripts are disabled; executable extensions run with desktop-user authority after explicit confirmation. Every generation projects all explicitly installed and currently enabled Skills/extensions; Device Packages never join Account Library, Marketplace Package Store, Release, Channel, or Admission state. |
| `electron/coding-plugins/adapters/game-resource.ts` and `electron/services/game-resource-client.ts` | Provider-neutral `makelore.game-resource` hosted tool adapter and Main-owned Works Square transport | Tools materialize only from an eligible frozen `platform_hosted` parent snapshot. Metered mutations require explicit confirmation and stable logical operation identity; Renderer/Pi never receive Provider URLs, credentials, balances, raw responses, or Provider job IDs. |
| `electron/api/routes/plugin-marketplace.ts`, `src/stores/plugin-marketplace.ts`, `src/pages/PluginMarketplace/`, `src/pages/MyPlugins/`, and `src/pages/ProjectPlugins/` | Bounded Main routes and Renderer projections for Marketplace catalog, Account Library, official package-device state, local Device Packages, and project actions | Renderer receives no Account token, filesystem path, Admission, package bytes, signed download URL, or install-source picker. My Plugins separates Official Plugins from Device Installed. Catalog/Library/device/project generations prevent stale A/B or cross-action results from replacing current state. |
| `electron/api/routes/plugin-marketplace.ts`, `src/stores/{plugin-marketplace,device-packages,coding-plugins}.ts`, and `src/pages/Plugins/` | Existing Main/store authorities plus the pure unified Renderer projection for official catalog, Account Library, official package-device state, local Device Packages, retained IDs, and current-project actions | `/plugins` is the sole canonical surface; legacy Plugin routes only replace-redirect into deterministic filters. `official:`, `local:`, and `retained:` identities stay separate, source failures are isolated, and no Account token, filesystem path, Admission, package bytes, signed URL, or visible install-source picker enters Renderer. |
| `src/components/works/ProjectPublishAction.tsx` | 可发布项目的一键提交、云构建轮询与用户可理解状态 | 只通过 Renderer API 提交非敏感元数据;绑定告警不终止轮询 |
| `src/lib/works-square.ts` | Renderer 侧 Works Square Host API 契约与安全错误映射 | 不接触 Token、ZIP、本地绝对路径或自动部署状态 |
| `electron/api/routes/works.ts` | Works Host API、Renderer capability 门禁、上游安全投影 | 发布凭据、打包、上传与本地绑定均在 Main 内完成 |
@@ -88,4 +88,4 @@
## Last Updated
2026-08-31
2026-09-03

View File

@@ -4,6 +4,20 @@ This file is the integrated default-branch snapshot. Feature tasks record progre
## Integrated Through
- Unified Plugin workspace product head
`d7058e6383f1e9dd72c32570cf83b9f439d91033` is integrated on local `main` by
task `20260903-plugin-navigation-integration-4f7c2a96` after fixed-range R4
Standards and Spec review passed with zero findings. Code now has one canonical
`/plugins` route and one `插件` sidebar entry; the former Marketplace, My Plugins,
and Project Plugins routes are replace-only redirects into deterministic filters.
A pure Renderer projection composes official catalog/Library/device state, local
Device Packages, current-project state, and retained IDs while preserving their
existing owners and source-qualified identities. Local Skill/extension installation
remains conversation-only, native selected-model Web Search remains outside the
Plugin list, and partial source failures do not erase other sources. Focused 83-test,
typecheck, full-unit, lint, Vite, and targeted 4/4 Electron evidence passed across
implementation, remediation, and final acceptance. No server contract, runtime,
billing, package, deployment, publication, or user-machine installation changed.
- Packaged Device Package preparation source
`5a2f0eb6785b59d8b455ed5cb1d9773351ff895a` from task
`20260902-local-skill-install-fix-6b3e91a4` and installed-resource activation
@@ -53,8 +67,9 @@ This file is the integrated default-branch snapshot. Feature tasks record progre
loose `SKILL.md` sources. Preview and a distinct confirmation turn precede immutable
local commit; lifecycle scripts stay disabled; new and idle parent workers refresh
automatically while active workers switch after settlement; child workers remain
empty. My Plugins now separates Official Plugins from Device Installed packages and
exposes no visible install picker. The later packaged prepare and multi-extension
empty. At that frontier My Plugins separated Official Plugins from Device Installed
packages and exposed no visible install picker; the unified `/plugins` workspace
recorded above now presents those sources together without merging authority. The later packaged prepare and multi-extension
activation corrections are recorded above; rebuilt exact-main installed-client
acceptance and real selected-model search remain external gates. No paid Provider
request, production install, publish, push, or PR is claimed.
@@ -261,8 +276,9 @@ This file is the integrated default-branch snapshot. Feature tasks record progre
`20260830-integrate-plugin-marketplace-client-6e3b9d82`. Electron Main now owns
the authenticated Marketplace/Library client, immutable Package Store, trusted
release verification, effective installed-plugin resolution, and frozen Pi worker
materialization; Renderer exposes Marketplace, My Plugins, and Project Plugins
projections without receiving credentials, paths, Admissions, or signed URLs.
materialization. Its original Marketplace, My Plugins, and Project Plugins Renderer
surfaces are superseded by the unified `/plugins` projection recorded above;
Renderer still receives no credentials, paths, Admissions, or signed URLs.
Data Service remains system-included and consumes zero Token Points. R7 Standards
and Spec reviews passed with zero findings, and XMA-01 passed all twelve live groups
against real PostgreSQL and a signed-in packaged Windows client. The later
@@ -530,4 +546,4 @@ Robot 绑定设备默认先显示“引导配网 / 已有激活码”路径选
## Last Updated
2026-09-02
2026-09-03

View File

@@ -1,88 +0,0 @@
# Task: Design unified MakeLore plugin navigation
## Identity
- Task ID: 20260903-plugin-navigation-design-7c4e2a91
- Mode: Feature
- Branch: codex/20260903-plugin-navigation-design-7c4e2a91-plugin-navigation-design
- Worktree: D:\Datas\OthersProjects\makelore-plugin-navigation-design-7c4e2a91
- Base commit: e9875145b41a2cb1827de10d27a4fc6a352704ea
- Owner: codex-root-plugin-nav
- Status: Ready for Integration
## Scope
- Product and architecture assessment of the current Plugin Marketplace, My Plugins,
Project Plugins, local Device Package, and sidebar/router surfaces.
- Compare the current navigation model with OpenAI's documented Codex Plugins
directory and propose one unified MakeLore Plugin surface.
- Write the task-owned implementation proposal
`10-decisions/proposals/20260903-plugin-navigation-design-7c4e2a91__unified-plugin-workspace-spec.md`.
- No product, route, state, server contract, package, or canonical shared-memory
changes.
## Intent And Constraints
- Preserve the independent authorities for catalog, Account Library, device bytes,
project enablement, Agent assignment, runtime admission, and billing even though
their user interface is consolidated.
- Keep local npm/Git/Plugin/loose-Skill installation conversation-only; the unified
page may manage installed Device Packages but must not add an install picker.
- Treat selected-model Web Search as a model tool, not a Marketplace Plugin.
- Avoid semantic overlap with concurrent task
`20260903-design-message-send-client-8d3f2a71`, whose owner confirmed it does not
touch Plugin navigation, pages, sidebar, or router.
## Outcome
- Recommend one sidebar entry and canonical `/plugins` page.
- The page should use one searchable list with source/status/scope filters rather
than three destination tabs: official catalog and locally installed packages are
source projections; acquired/installed/enabled are status filters; the active
project is a scope filter.
- One Plugin detail panel should compose description, capabilities, Token Point
summary, account/device state, current-project enablement, Agent assignments, and
plugin-specific settings while dispatching each mutation to its existing owner.
- Legacy `/plugin-marketplace`, `/my-plugins`, and `/project-plugins` routes should
redirect to deterministic `/plugins` query states during the navigation cutover.
- Official Data Service and Game Resource remain Plugin entries. Model Web Search
belongs in selected-model capabilities and should not appear as a Plugin card.
- A unified projection must tolerate partial backend failure: cached official data
and local Device Packages remain visible independently.
- The accepted direction is now frozen as Spec `ML-PLUGIN-NAV-001`, including the
pure Renderer projection Interface, source-qualified item identity, action matrix,
exact legacy redirects, partial-failure behavior, accessibility contract, file
ownership, tests, four implementation stages, and Definition of Done.
## Verification
- Concurrent Task Gate PASS after the peer owner confirmed disjoint scope.
- Planning Gate PASS after reading the required project memory, architecture,
domain rules, and current integrated state.
- Inspected current sidebar/router and all three Renderer Plugin pages on exact base
`e9875145b41a2cb1827de10d27a4fc6a352704ea`.
- Reviewed official OpenAI Plugins documentation for the single directory,
marketplace-source grouping, Installed projection, enable/disable behavior, and
new-session activation semantics.
- Re-ran the Concurrent and Planning Gates before writing the implementation Spec;
the AI Design peer still has disjoint file and semantic ownership.
- Re-inspected current Renderer stores, DTO projections, page actions, route/module
guards, sidebar entries, unit tests, E2E seams, and canonical Device Package/model
tool rules on the recorded base.
- No executable tests were run because this task makes no product changes; tests
would not alter the design conclusion.
## Follow-ups
- Implement `PN-01` through `PN-04` serially in an isolated client task after explicit
implementation authorization.
- Run fresh Standards and Spec review over the implementation range before promotion
to `main`.
## Promotion Candidates
- If accepted, promote the single-Plugin-surface navigation and state-as-filter
distinction into the architecture/module map during the later Integration Gate.
- Promote the explicit distinction between native selected-model tools and Plugin
entries into the user-facing glossary if future UI work makes that distinction
visible outside Code.

View File

@@ -1,162 +0,0 @@
# Task: Implement unified plugin workspace ML-PLUGIN-NAV-001
## Identity
- Task ID: 20260903-plugin-navigation-implementation-a4c7e291
- Mode: Feature
- Branch: codex/20260903-plugin-navigation-implementation-a4c7e291-plugin-navigation-implementation
- Worktree: C:\Users\7brot\.codex\worktrees\1721\makelore
- Base commit: 959e2faf03dfacb3c8e2035e44774436c752d4b0
- Owner: codex
- Status: Ready for Integration
## Scope
- Implement approved Spec `ML-PLUGIN-NAV-001` serially as PN-01 through PN-04:
a pure source-qualified Renderer projection, one `/plugins` workspace and detail
surface, a hard route/sidebar cutover with exact replace redirects, removal of the
three superseded page implementations, and focused/full/Electron verification.
- Own only the Spec-listed Renderer page/navigation/tests/artifact-marker/README
paths plus this task record. Preserve the existing Marketplace, Device Package,
Coding Plugin, Agent assignment, runtime admission, and billing authorities.
## Intent And Constraints
- Concurrent Task Gate passed for the exact identity/base/worktree above. The
superseded exact-overlap task `20260903-plugin-navigation-implementation-6b4d9e21`
was released from the registry after source-thread adjudication; its worktree,
branch, and record were not removed or modified by this task.
- Planning Gate passed after reading repository guidance, the complete Spec, startup
project memory, architecture/domain rules, relevant indexes, and the completed AI
Design peer record. That peer explicitly excludes plugin pages, navigation,
Sidebar, and router, so no semantic overlap remains.
- Confirmed public test seams are `buildPluginWorkspaceProjection`, the unified
Renderer page/local dispatcher/detail dialog, route/sidebar/module guards, and the
targeted Renderer-to-Main Electron flows. Work vertically red -> green at those
seams rather than mocking internal modules.
- Use `official:`, `local:`, and `retained:` identity without inferred cross-source
merging. Keep local installation conversation-only, native selected-model Web
Search out of the projection, system-included actions restricted, and local package
state explicitly device-global.
- Do not change Server, Electron Main/plugin contracts, the three existing stores,
Package Store/runtime/billing authority, app identity/global paths, or add a
persistent Zustand authority, compatibility layer, feature flag, or visible local
installation picker.
- Do not write or clean `D:\\Datas\\OthersProjects\\makelore`; do not push, create a
PR, deploy, publish, install a package, or merge `main`.
## Project Context Loaded
- Project goal: present official, acquired, local-device, project, and Agent Plugin
state through one understandable UI while preserving each existing authority.
- Current integrated focus: curated Marketplace Release A, system-included Data
Service, code-owned bundled Game Resource, conversation-only Device Packages, and
selected-model native Web Search are already integrated contracts.
- Decisions affecting this task: acquisition/device delivery/project enablement/Agent
assignment/runtime admission/billing remain independent; Device Packages are
device-global and child workers remain empty; Renderer access stays behind typed
Host API facades.
- Relevant evidence: the integrated Marketplace and Device Package suites establish
the current DTO/authority behavior; installed-client Device Package activation is a
separate release gate and is not claimed by this UI task.
- Likely modules: `src/pages/{PluginMarketplace,MyPlugins,ProjectPlugins,Plugins}`,
`src/App.tsx`, layout navigation/guards, `src/lib/ai-modules.ts`, their unit/E2E and
artifact marker tests, and `README.md`.
- Unknown to verify before implementation: whether the current public Renderer DTOs
express every Spec field without contract changes. A real interface conflict blocks
that range rather than authorizing a wrapper or compatibility path.
- Non-blocking stale context: canonical `module-map.md` still names the old three-page
UI and must be proposed for later Integration Gate promotion, not edited in feature
mode.
## Outcome
- `PN-01` added the pure `buildPluginWorkspaceProjection` interface, canonical
query parser/serializer, and a local command dispatcher. The projection keeps
`official:`, `local:`, and `retained:` identities separate; preserves
catalog/Library/project-only/local/retained entries under partial failures;
excludes only the native selected-model `makelore_web_search`; and derives the
Spec action matrix without writing a store.
- `PN-02` replaced the three page-specific views with one `/plugins` workspace and
one detail dialog. It independently loads Catalog, Library, Device Packages, and
current-project projection; exposes URL-backed scope/source/state/search/detail
state; keeps source errors local; dispatches every action to its existing owner;
embeds the existing Data Service settings surface; resets project-scoped
confirmation on project change; and provides dialog focus, Escape, focus-return,
status, alert, and destructive-scope semantics.
- `PN-03` reduced the Code sidebar to `sidebar-nav-plugins`, registered the
initialization-safe and non-provider-gated canonical route, added the three exact
replace redirects, and deleted the old Marketplace, My Plugins, and Project
Plugins implementations and their superseded page tests. No hidden fallback
implementation remains.
- `PN-04` updated the targeted Electron flows, product artifact markers, and
`README.md`. The E2E authenticated fixture now starts a fresh Renderer document
against a Main-owned session and `/api/auth/me` identity; this removed a measured
reload/localStorage setup race without changing product authentication code.
- Actual changed scope is limited to `src/pages/Plugins/**`, the listed route/layout
files, deletion of the three old page directories, focused unit/Electron tests,
`scripts/lib/pi-product-artifact.mjs`, `README.md`, and this task record. No
Server, Electron Main, Marketplace/Device/Coding store, Package Store, runtime,
billing, or persistence authority was changed; no fourth Zustand authority was
added.
## Verification
- `corepack pnpm run typecheck` — passed after the final E2E fixture edit.
- `corepack pnpm run lint:check` — passed with 0 errors. Five pre-existing warnings
remain in untouched files: one `react-hooks/exhaustive-deps` warning in
`src/pages/Home/index.tsx` and four `react-refresh/only-export-components`
warnings in `src/pages/Makelore/index.tsx`.
- `corepack pnpm test` — passed: 225 regular test files with 1821 passed and 2
skipped tests, followed by the isolated pressure file with 1 passed test.
- `corepack pnpm run build:vite` — passed for Renderer, Electron Main, Preload, and
utility worker. Existing warnings remain for stale Browserslist data,
static/dynamic imports, and the existing large Renderer chunk.
- `corepack pnpm run test:e2e -- tests/e2e/plugin-marketplace.spec.ts
tests/e2e/project-plugins.spec.ts --reporter=line` — passed after its production
build with all 4 targeted Renderer-to-Main flows.
- `corepack pnpm exec playwright test tests/e2e/plugin-marketplace.spec.ts -g
"keeps system, bundled, and local actions" --repeat-each=10 --workers=1
--reporter=line` — 10/10 passed after stabilizing the authenticated fixture.
- `corepack pnpm exec vitest run tests/unit/pi-product-artifact.test.ts
--maxWorkers=1` — passed: 15/15 artifact proof tests.
- Focused projection/query/controller/page/navigation/Main-layout suites passed;
the final page suite passed 5/5, including project-switch confirmation reset and
dialog initial-focus/Escape/focus-return behavior.
- Existing parent/child/worker lifecycle coverage passed in the full suite through
`coding-plugin-effective-resolver`, `pi-managed-worker-opener`,
`device-package-manager`, and `device-package-routes` tests.
- `check_doc_drift.py --task-id
20260903-plugin-navigation-implementation-a4c7e291` — passed the feature-task
ownership boundary check.
- `git diff --check` passed before Task Documentation Gate finalization.
- One full-suite run transiently failed the untouched Marketplace client temp
Package Store install case; its exact isolated rerun passed 1/1 and the subsequent
full suite passed as recorded above. An earlier targeted E2E run exposed the
test-only auth reload race; trace inspection showed no Library request and a
signed-out persisted fixture, after which the clean-document Main-session fixture
passed 10/10 and the formal targeted command passed 4/4.
## Follow-ups
- No implementation follow-up or product deviation is known. The canonical module
map promotion below remains intentionally deferred to an Integration Gate.
## Promotion Candidates
- Target: `.project-docs/20-architecture/module-map.md`.
- Proposal: replace the three legacy Renderer plugin pages with the pure unified
projection, `/plugins` workspace/detail surface, canonical query state, and exact
legacy redirects; keep Catalog, Library, official Package Store, Device Packages,
project enablement, Agent assignment, admission, and billing under their existing
owners.
- Evidence: approved Spec `ML-PLUGIN-NAV-001`, this task's single implementation
commit, pure projection/action tests, route/page tests, artifact proof, full unit
suite, production build, and 4/4 targeted Electron flows.
- Future impact: architecture readers will use `/plugins` and
`src/pages/Plugins/plugin-workspace-model.ts` as the Renderer aggregation seam and
will not extend the deleted page implementations.
- Semantic conflicts: none known; the concurrent AI Design task owns no plugin
navigation or plugin authority surface.
- Human confirmation: no new product-direction decision is required, but promotion
must still occur only in an exclusively owned Integration Gate.

View File

@@ -0,0 +1,92 @@
# Task: Integrate unified plugin workspace into client main
## Identity
- Task ID: 20260903-plugin-navigation-integration-4f7c2a96
- Mode: Integration
- Branch: main
- Worktree: D:\Datas\OthersProjects\makelore
- Base commit: e9875145b41a2cb1827de10d27a4fc6a352704ea
- Owner: codex-root
- Status: Ready for Integration
## Scope
- Fast-forward client `main` from exact base
`e9875145b41a2cb1827de10d27a4fc6a352704ea` through the approved unified Plugin
workspace design and reviewed product head
`d7058e6383f1e9dd72c32570cf83b9f439d91033`.
- Promote only the accepted Integration-Gate memory changes: record the unified
`/plugins` surface in current state and replace the stale three-page entry in the
architecture module map.
- Preserve the three pre-existing untracked task records in the client root exactly;
do not stash, reset, clean, delete, move, or adopt them.
- Run bounded integration verification, complete the task documentation gate, and
release the root integration lock.
## Intent And Constraints
- The fixed product range is
`959e2faf03dfacb3c8e2035e44774436c752d4b0...d7058e6383f1e9dd72c32570cf83b9f439d91033`.
R4 task `20260903-plugin-navigation-acceptance-r4-9c2f6a41` independently passed
Standards and Spec with zero findings.
- Preserve the existing Catalog, Account Library, official Package Store, Device
Package, project enablement, Agent assignment, runtime admission, and billing
authorities. This integration changes only the already-reviewed Renderer product
and canonical project memory.
- Keep local Skill/extension installation conversation-only and keep selected-model
native Web Search outside the Plugin projection.
- Related task `20260903-design-message-send-client-8d3f2a71` is Ready for Integration
and explicitly excludes Plugin pages, navigation, Sidebar, and router code; no
semantic or file ownership conflict exists.
- Do not push, open a PR, deploy, publish, package, or install a client.
## Project Context Loaded
- Startup memory, integrated current state, decisions, system overview, module map,
data flow, business rules, success criteria, glossary, evidence, commitments, and
stale-item registry were read from the exact client base.
- The approved `ML-PLUGIN-NAV-001` specification and the implementation, three
remediation, and final R4 acceptance records were read in full.
- `main` at `e9875145b41a2cb1827de10d27a4fc6a352704ea` is an exact ancestor of the
reviewed product head, so the product integration is eligible for `--ff-only`.
- Concurrent Task Gate: Passed. Planning Gate: Passed.
## Outcome
- Fast-forwarded local client `main` from
`e9875145b41a2cb1827de10d27a4fc6a352704ea` to the exact reviewed product head
`d7058e6383f1e9dd72c32570cf83b9f439d91033`; no merge conflict or product
rewrite occurred.
- The canonical Code Plugin surface is now one sidebar entry and one `/plugins`
workspace. The three old routes remain replace-only redirects and the deleted old
page implementations do not remain as fallbacks.
- Promoted the implementation task's architecture candidate into `module-map.md`,
recorded the integrated product and R4 evidence in `current-state.md`, and corrected
the obsolete My Plugins wording in the durable Device Package rule.
- Preserved all three pre-existing untracked client-root task records exactly. No
push, PR, deployment, publication, package, or user-machine installation occurred.
## Verification
- Pre-integration ancestry check proved the root base is an ancestor of the reviewed
product head; `git merge --ff-only` advanced through exactly five commits (approved
design plus implementation and three remediations).
- Final R4 acceptance record reports Standards PASS and Spec PASS with zero findings
over `959e2faf03dfacb3c8e2035e44774436c752d4b0...d7058e6383f1e9dd72c32570cf83b9f439d91033`.
- Post-merge focused verification passed: 8 files / 83 tests.
- Post-merge `corepack pnpm run typecheck` passed.
- Source evidence retained by R4: full unit 1842 passed / 2 skipped plus pressure 1
passed; lint 0 errors with 5 pre-existing warnings; all Vite targets passed; targeted
Electron Plugin E2E passed 4/4.
- `check_project_docs`, task-aware document drift, staged diff check, exact branch/HEAD,
and final root-status checks are part of the closing gate.
## Follow-ups
- A rebuilt and installed client smoke remains a separate release activity; it was not
authorized or required by this source integration.
## Promotion Candidates
- None recorded.

View File

@@ -1,148 +0,0 @@
# Task: Plugin navigation remediation
## Identity
- Task ID: 20260903-plugin-navigation-remediation-c5e8a731
- Mode: Feature
- Branch: codex/20260903-plugin-navigation-remediation-c5e8a731-plugin-navigation-remediation
- Worktree: C:\Users\7brot\.codex\worktrees\plugin-nav-remediation-c5e8a731\makelore
- Base commit: 1b1f206dd8aeb7bf69e61b0cd684f70accce9e26
- Owner: codex-01a0656d
- Status: Ready for Integration
## Scope
- Remediate the five fixed-range Spec failures reported by task
`20260903-plugin-navigation-acceptance-5e8b3c72` on implementation head
`1b1f206dd8aeb7bf69e61b0cd684f70accce9e26`.
- Own only `src/pages/Plugins/**`, their focused unit/page tests, and this task
record. No store, Electron Main, server, runtime, billing authority, sidebar,
module guard, or legacy redirect change is in scope.
- Deliver one remediation commit for a fresh fixed-range Standards + Spec review;
do not merge `main`, push, create a PR, deploy, publish, package, or install.
## Intent And Constraints
- Concurrent Task Gate passed for the exact identity/base/worktree above. The
prior implementation and acceptance tasks are Ready for Integration and are
read-only. The AI Design peer explicitly excludes Plugin pages/navigation, so
no file or semantic ownership overlap exists.
- Planning Gate passed after reading the exact project-memory tree, authoritative
Spec `ML-PLUGIN-NAV-001`, ADR-006, prior implementation/acceptance records, and
the current Renderer projection/page/controller plus Marketplace DTO/store
contracts.
- Confirmed public TDD seams are the pure projection/query resolver, the local
command dispatcher, and `PluginsView`/route composition. Tests must fail before
each production correction and observe URL, commands, copy, and detail output
rather than private implementation calls.
- Continuously canonicalize invalid URL state without a one-shot ref or replace
loop, while preserving one visible no-project fallback notice.
- Preserve a source-qualified `retained:` project selection even when Catalog or
Library recognizes the same ID; it may use those sources only for display
metadata and may dispatch only disable for the projection's original project ID.
- Treat `status=unavailable` plus retained version/channel/reason as an existing
device package for cleanup and same-channel update semantics. Show its reason,
mark retained snapshots stale after refresh failure, and distinguish suspended
from retired without inferring state across sources.
- Render operation-level pricing only from Marketplace detail or current project
policy, deduplicated by capability/operation identity and without client-side
price calculation.
- Distinguish signed-out acquisition from authenticated Library failure. Signed-out
users receive an explicit login command; authenticated unknown Library state
remains fail-closed.
- Existing DTOs already expose every required field, so no authority/interface
conflict is present. If later evidence contradicts that conclusion, stop the
affected range rather than add a compatibility layer or broaden ownership.
- Preserve the root workspace and all peer worktrees; in particular do not write
or clean `D:\\Datas\\OthersProjects\\makelore`.
## Project Context Loaded
- Product goal: one understandable Plugin workspace that composes, but never
merges, Catalog, Library, device package, project, Agent, admission, and billing
authorities.
- Current state: official bundled Plugins, conversation-only Device Packages, and
selected-model native Web Search already have separate delivery/runtime rules;
the unified Renderer implementation is complete but failed five acceptance roots.
- Relevant decisions: Electron Main retains runtime/credential ownership; Device
Packages are device-global and child workers remain empty; account acquisition,
device delivery, project enablement, Agent assignment, admission, and billing do
not advance one another.
- Relevant evidence: the acceptance record identifies unreachable scope fallback,
lost recognized retained IDs, mishandled unavailable installations/stale status,
omitted detail operations/pricing, and missing signed-out action as exact failures.
- Canonical-memory candidate remains the prior implementation task's deferred
module-map promotion; this feature remediation does not edit integrated memory.
- Known documentation drift: `read-before-planning.md` names old locations for
`memory-index.md` and `current-state.md`; the exact existing files were resolved
with `rg --files` and read successfully, so this is non-blocking.
## Outcome
- Replaced one-shot URL normalization with a pure query resolution result and a
Router-location marker that carries the no-project fallback notice across the
canonical replace. Canonical URL and scope controls now remain aligned when the
active project changes or the same mounted route receives a new invalid query,
without a `setSearchParams` loop or effect-owned React state.
- Preserved catalog/Library-recognized `unknownPluginIds` as source-qualified
`retained:` rows in both project and all scopes. They reuse only recognizable
display metadata and expose exactly one mutation: disable against the project
ID recorded by the project projection.
- Treated `MarketplaceInstallation.status=unavailable` with a retained version
and channel as an existing device package for same-channel update and device
removal, while keeping runtime/project actions fail-closed. Cards and details
display the retained version reason, failed retained snapshots show `缓存`, and
suspended/retired states have distinct copy.
- Added a read-only detail operation projection. Marketplace detail operations
render without a project; the current project policy replaces a duplicate
operation as one complete server-owned billing projection, while detail-only
operations remain visible. No pricing is calculated or inferred locally.
- Added an explicit `sign_in` command for signed-out free catalog entries and
dispatch it to the existing `/login` route. Authenticated Library failure still
reports unknown delivery and exposes no acquisition mutation.
- No route, store, Electron Main, server, runtime, billing authority, sidebar, or
E2E file changed. No new authority, fallback, feature flag, compatibility layer,
or visible local-package installation entry was added.
- This task supplies a remediation candidate only. It does not claim the fresh
fixed-range Standards + Spec review has passed.
## Verification
- TDD URL RED: focused query/page tests failed because the production composition
erased `scope=project` before the fallback notice and only normalized the first
URL. GREEN: the final query + page run passed 2 files / 13 tests.
- TDD projection/action RED: focused model/controller/page tests produced the six
expected failures for retained unavailable installation semantics, stale and
lifecycle copy, recognized retained IDs, signed-out action, login dispatch, and
visible status copy. GREEN: the focused five-file suite passed 5 files / 34 tests.
- TDD detail RED: the two new page assertions failed because Marketplace detail
operations were absent without a project and a detail-only operation disappeared
when project policy existed. GREEN: `tests/unit/plugins-page.test.tsx` passed all
9 tests with server pricing output and duplicate identity coverage.
- `corepack pnpm run typecheck`: passed (`tsc --noEmit`).
- `corepack pnpm run lint:check`: passed with zero errors. Five pre-existing
warnings remain in `src/pages/Home/index.tsx` and `src/pages/Makelore/index.tsx`;
neither file is owned or changed by this task.
- `corepack pnpm test`: passed 225 files / 1830 tests with 2 skipped, followed by
the isolated pressure file passing 1 file / 1 test (aggregate 226 files / 1831
passed / 2 skipped).
- `corepack pnpm run build:vite`: passed all Renderer, Electron Main, Preload, and
release utility builds. Existing Browserslist-age, mixed dynamic/static import,
and large-chunk warnings remain non-blocking.
- `corepack pnpm run test:e2e -- tests/e2e/plugin-marketplace.spec.ts tests/e2e/project-plugins.spec.ts --reporter=line`:
passed the existing 4/4 Electron flows. The command also rebuilt all production
targets successfully. The E2E set was not expanded because the remediation is
covered at the production composition/pure projection seams and did not require
a route or Host API change.
- `git diff --check`: passed before documentation closeout.
## Follow-ups
- Run fresh fixed-range Standards + Spec review over
`959e2faf03dfacb3c8e2035e44774436c752d4b0...remediation HEAD`; do not integrate
or merge `main` before that independent acceptance completes.
## Promotion Candidates
- None. This remediation changes no durable authority or architecture decision;
the prior implementation task's module-map candidate remains the correct owner.

View File

@@ -1,125 +0,0 @@
# Task: Plugin navigation R2 remediation
## Identity
- Task ID: 20260903-plugin-navigation-remediation-r2-b8e4d317
- Mode: Feature
- Branch: codex/20260903-plugin-navigation-remediation-r2-b8e4d317-plugin-navigation-remediation-r2
- Worktree: C:\Users\7brot\.codex\worktrees\plugin-nav-remediation-r2-b8e4d317\makelore
- Base commit: c5020ae22c9bef1b5bc8190469998127842c4513
- Owner: codex-01a0656d
- Status: Ready for Integration
## Scope
- Remediate the three R2 Spec findings against product base
`c5020ae22c9bef1b5bc8190469998127842c4513`.
- Preserve the exact canonical `/plugins?...` route through a successful login,
while accepting only safe internal return paths and retaining `/module-select`
as the default.
- Pass device/project refresh-failure provenance into the pure plugin workspace
projection so retained snapshots stay visible and are labelled as cached.
- Surface `CodingPluginProject.policyStatus` (`stale` or `unavailable`) beside
affected project policy/pricing; leave `current` unmarked.
- Add focused projection, page, controller, login/route regressions and run the
required unit, typecheck, lint, Vite, and relevant Electron verification.
- Produce one remediation commit and a clean READY_FOR_INTEGRATION handoff.
## Intent And Constraints
- Follow the authoritative unified plugin workspace Spec and the exact three
findings recorded by R2 review commit
`a698c41b39f11b4ebe15fd0f74b5fb8457ae3514`.
- Work test-first through public projection, page, controller, and router seams.
- Keep Catalog, Library, Package Store, Device Packages, project enablement,
Agent Skill assignment, runtime admission, and billing authorities unchanged.
- Do not modify stores, Electron Main, server/runtime/billing contracts, or add
a new cache/authority, compatibility layer, feature flag, or wrapper layer.
- Limit product edits to `src/pages/Plugins/**` and `src/pages/Login/index.tsx`;
a minimal existing route seam is permitted only if required by the login
regression. Corresponding unit/page/route tests and this task record are owned.
- Keep original R1 fixes covered and unchanged in semantics.
- Do not merge main, push, create a PR, deploy, publish, or install to a user
machine. Do not modify or clean any other worktree or the repository root.
## Project Context Loaded
- Product goal: finish ML-PLUGIN-NAV-001 R2 remediation without merging existing
backend or runtime authorities into the Renderer projection.
- Current state: base `c5020ae22c9bef1b5bc8190469998127842c4513`
contains the initial implementation and R1 remediation; R2 Standards passed
with zero findings and R2 Spec reported exactly three Medium roots.
- Relevant decisions: `/plugins` is the canonical Code-owned, initialization-safe
route; auth return uses router state; source-qualified identities and
fail-closed partial-source behavior remain intact; Renderer displays but does
not calculate or authorize project policy/billing state.
- Evidence: the authoritative Spec, R2 review record, current App/Login/Plugins
composition, device-package and coding-plugin snapshot-preservation stores,
and existing unit/Electron fixtures were inspected.
- Likely modules: `src/pages/Plugins/plugin-workspace-controller.ts`,
`src/pages/Plugins/plugin-workspace-model.ts`, `src/pages/Plugins/index.tsx`,
`src/pages/Plugins/PluginDetails.tsx`, `src/pages/Login/index.tsx`, and focused
tests under `tests/unit` (plus relevant existing Electron coverage if needed).
- Unknowns/risks: dependency availability in the fresh worktree must be checked;
the stable public route unit seam may be more appropriate than expanding the
Electron fixture for the login-return contract.
- Concurrent task assessment: the authoritative task owner exactly matches this
managed worktree, branch, and base. Same-topic implementation/remediation/review
tasks are READY_FOR_INTEGRATION; remaining planning peers declare no overlapping
ownership of the scoped Plugin/Login files or semantics.
- Concurrent Task Gate: Passed.
- Planning Gate: Passed.
## Outcome
- Plugin acquisition sign-in now carries the exact canonical workspace path
(including scope/source/state/search/selected-plugin query) in router state.
Login returns to that same path after successful credential and model sync.
- Login accepts only supported same-app absolute return paths with one leading
slash. Absolute external and protocol-relative targets fall back to
`/module-select`; the existing no-return default is unchanged.
- The pure workspace projection now receives bounded device/project refresh
failure provenance. Preserved local package, project-backed official, and
retained unknown rows stay visible and render as cached; project failure does
not mark catalog-only official rows.
- Project policy status is projected verbatim onto project-associated official
and retained rows. Details explain `stale` and `unavailable` beside billing,
while `current` remains unmarked. No status changes commands, admission, or
client-side pricing.
- No stores, Electron Main, server, runtime, billing authority, dependencies,
legacy routes, or unrelated product files were changed.
## Verification
- TDD login/controller RED: 2 expected failures (bare `/login`, fixed
`/module-select`); GREEN: 2 files, 18 tests passed.
- TDD refresh provenance RED: 2 expected failures (`stale=false` in model/page);
GREEN: 2 files, 26 tests passed.
- TDD policy status RED: 5 expected failures (missing projection and copy);
GREEN: 2 files, 32 tests passed.
- Focused plugin/login/route suite: 6 files, 58 tests passed.
- `pnpm run typecheck`: passed.
- `pnpm run lint:check`: passed with 0 errors and 5 pre-existing warnings in
`src/pages/Home/index.tsx` and `src/pages/Makelore/index.tsx`, outside this diff.
- `pnpm test`: 225 files / 1841 tests passed / 2 skipped, plus the isolated
coding-chat pressure file 1/1 passed.
- `pnpm run build:vite`: passed. Existing Browserslist age, mixed static/dynamic
import, and chunk-size warnings remained non-failing.
- Targeted Electron E2E (`plugin-marketplace.spec.ts` and
`project-plugins.spec.ts`): final combined rerun 4/4 passed. The first combined
run was 3/4: one case timed out waiting for the test fixture to observe
`/api/auth/me` before any plugin assertion. Playwright trace showed successful
Electron launch and reload with no console/renderer crash; the isolated rerun
passed 1/1, then the full targeted rerun passed 4/4.
- Public router Login regression covers exact canonical return plus rejected
external/protocol-relative targets and unchanged default behavior.
## Follow-ups
- Source task will run a fresh fixed-range Standards + Spec acceptance review.
- Do not merge to main before that independent acceptance.
## Promotion Candidates
- None. The changes implement the already-authoritative ML-PLUGIN-NAV-001 Spec
and do not introduce a new shared architecture or product decision.

View File

@@ -1,112 +0,0 @@
# Task: Plugin navigation R3 detail retry remediation
## Identity
- Task ID: 20260903-plugin-navigation-remediation-r3-f3a8c4d1
- Mode: Feature
- Branch: codex/20260903-plugin-navigation-remediation-r3-f3a8c4d1-plugin-navigation-remediation-r3
- Worktree: C:\Users\7brot\.codex\worktrees\plugin-nav-remediation-r3-f3a8c4d1\makelore
- Base commit: 0bfabc0df24fdd41c37af498f7a4e49bc00d31db
- Owner: codex-01a0656d
- Status: Ready for Integration
## Scope
- Remediate the R3 detail-loading retry loop against exact product base
`0bfabc0df24fdd41c37af498f7a4e49bc00d31db`.
- Make automatic official-detail loading selection-scoped: at most one automatic
request per detail open, a stable local error after rejection, and one new
attempt after explicitly closing and reopening the same detail.
- Add a public Renderer/page regression for reject/settle and close/reopen, while
preserving the existing A-to-B late-detail protection.
- Produce one remediation commit and a clean READY_FOR_INTEGRATION handoff.
## Intent And Constraints
- Follow the authoritative ML-PLUGIN-NAV-001 Spec, especially section 5.4 and
ERR-001/ERR-005 in section 7.2, plus the exact R3 acceptance finding supplied
by the source task.
- Work test-first through the public `Plugins` Renderer/page seam.
- Limit product edits to `src/pages/Plugins/index.tsx` and the necessary focused
plugin page test. This task record is the only project-document write owned by
the task.
- Do not modify stores, Electron Main, server, runtime, billing, router, Login,
dependencies, or any other worktree/root checkout.
- Do not add a cache, persistent authority, compatibility layer, feature flag,
broad retry framework, or speculative UI.
- Do not merge main, push, create a PR, deploy, publish, or install the app.
## Project Context Loaded
- Product goal: close the R3 P1 finding without changing the unified plugin
workspace's authority boundaries or its existing R1/R2 behavior.
- Current state: exact HEAD and merge-base are
`0bfabc0df24fdd41c37af498f7a4e49bc00d31db`; only this newly created task
record is untracked. Marketplace `loadDetail` sets `loading`, then `error` and
rejects on a supported request failure. The current page effect observes that
error and immediately calls it again.
- Relevant decisions: official detail is loaded on demand; source failures must
remain local and stable; Renderer must not create a second cache or retry
authority; stale A detail must never replace selected B.
- Evidence inspected: the complete ML-PLUGIN-NAV-001 Spec, current project
memory, the R2 task record, `src/pages/Plugins/index.tsx`, the Marketplace
store detail transition, and existing public page/model tests.
- Likely modules: `src/pages/Plugins/index.tsx` and
`tests/unit/plugins-page.test.tsx` only.
- Risks: an already-loading detail must count as the current open's automatic
attempt so a later failure cannot trigger a compensating request; changing or
clearing selection must reset the attempt boundary without weakening store
generation protection.
- Concurrent task assessment: task_context identity, worktree, branch, and base
match exactly. Remaining Planning peers are old Marketplace/ML-07 reviews or
unrelated modules and declare no ownership of this page/test or retry
semantic. Concurrent Task Gate: Passed. Planning Gate: Passed.
## Outcome
- `Plugins` now records the official detail selection's automatic attempt before
observing later `loading` or `error` state. A rejected request therefore
settles as one stable local detail failure instead of immediately starting an
unbounded retry loop.
- Clearing selection resets that local attempt boundary. Closing and reopening
the same official detail permits exactly one new automatic request; changing
A to B likewise establishes B's own attempt without changing Marketplace
store generation or late-result protection.
- The public page regression drives the real route composition, reproduces the
supported store `error` transition, proves one call while open, observes the
existing detail error surface, closes the dialog, and proves one additional
call only after reopening.
- No store, Electron Main, server, runtime, billing, router, Login, dependency,
or unrelated product file was changed.
## Verification
- TDD RED: `tests/unit/plugins-page.test.tsx` reported the new contract failure
exactly: `loadDetail` expected 1 call after the detail error settled but
received 2 (13 existing tests passed, 1 new test failed).
- TDD GREEN: `tests/unit/plugins-page.test.tsx` passed 14/14.
- Focused plugin suite (`plugins-page`, projection model, query, controller):
4 files / 39 tests passed, including the existing A-to-B late-detail model
regression and the prior R1/R2 behavior.
- `pnpm run typecheck`: passed.
- `pnpm run lint:check`: passed with 0 errors and 5 pre-existing warnings in
`src/pages/Home/index.tsx` and `src/pages/Makelore/index.tsx`, outside this
diff.
- `pnpm test`: 225 files / 1842 tests passed / 2 skipped; the separately run
coding-chat pressure test passed 1/1.
- `pnpm run build:vite`: Renderer, Electron Main, Preload, and utility worker
builds passed. Existing Browserslist age, mixed static/dynamic import, and
large-chunk warnings remained non-failing.
- Targeted Electron E2E (`plugin-marketplace.spec.ts` and
`project-plugins.spec.ts`): 4/4 passed after the script's production rebuild.
- `git diff --check`: passed; the product diff is limited to
`src/pages/Plugins/index.tsx` and `tests/unit/plugins-page.test.tsx`.
## Follow-ups
- Source task will run a fresh fixed-range R4 Standards + Spec review. Do not
merge to main before that independent acceptance.
## Promotion Candidates
- None recorded.

View File

@@ -56,9 +56,10 @@
never run. Pi extensions execute with desktop-user authority after that fact is shown
in confirmation. New and idle parent workers refresh automatically, active parents
switch only after settlement, and child workers never inherit Device Package resources.
- Device Packages appear separately from Official Plugins in My Plugins and never enter
Account Library, Marketplace Package Store, Release, Channel, Admission, project
enablement, Agent assignment, or server billing state.
- Device Packages appear as a separate `本机` source beside Official Plugins in the
unified `/plugins` workspace and never enter Account Library, Marketplace Package
Store, Release, Channel, Admission, project enablement, Agent assignment, or server
billing state.
- 面向用户的 AI 编程新建流程必须在 `mini_game``mini_program``custom` 中选择;`ProjectType` 是产品类型,创建后不能通过 UI 或 Host API 修改,未传类型的兼容 API 调用按 `custom` 处理。
- 新建小游戏和小程序会生成平台固定版本的受控 Vite 发布模板,并可使用项目配置中的单一“提交审核”入口;`custom` 和缺少类型字段的旧项目不提供一键发布。
- `ProjectType` 不等于 `BuildPreset`:第一期两个可发布产品类型都映射到内部受控 Vite preset本地 `projectType` 不是授权边界Main-owned 安全打包、Host API 和服务端包体校验仍必须执行。
@@ -138,4 +139,4 @@
## Last Reviewed
2026-08-31
2026-09-03