Deliver isolated no-project scratch sessions across Backend, Frontend and UI #691
@@ -0,0 +1,61 @@
|
|||||||
|
# 无项目对话(Scratch Session)实施计划
|
||||||
|
|
||||||
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||||
|
|
||||||
|
**Goal:** 任意启用账号可创建彼此隔离的通用智能体会话;无 `project.create` 也能用;不得接入知识树/文档树等项目专属功能。
|
||||||
|
|
||||||
|
**Architecture:** 每个无项目对话 = 带 `settings.host.kind = "scratch"` 的私有空壳 `Project` + 恰好一条 `Conversation`。新建走专用 API(不要求 `project.create`)。列表/侧栏把 scratch 从真项目切换器剔除,归入虚拟分类「无项目对话」。服务端对 scratch 统一 fail-closed 拒绝 RDM/知识发布/成员等。
|
||||||
|
|
||||||
|
**Tech Stack:** Go Backend(store/server/authz)、TypeScript Frontend(store/TaskSidebar)、现有 SQLite projects 表 `settings` JSON。
|
||||||
|
|
||||||
|
**Spec:** [docs/superpowers/specs/2026-10-22-scratch-session-general-agent-design.md](../specs/2026-10-22-scratch-session-general-agent-design.md)
|
||||||
|
|
||||||
|
**实施执行:** agent-per-unit(配置:AGENT-EXECUTION.md);`fallback_to_host: never`。
|
||||||
|
|
||||||
|
## Global Constraints
|
||||||
|
|
||||||
|
- 固有能力不可做成 `role_permissions` 行。
|
||||||
|
- ListProjects 前后端一致过滤 scratch。
|
||||||
|
- RDM 未部署时也须宿主侧拒绝,不能只藏 UI。
|
||||||
|
- 最小充分:不做升级、协作、配额、nullable project_id。
|
||||||
|
|
||||||
|
## Review Focus
|
||||||
|
|
||||||
|
- 无 `project.create` 的创建路径与真项目门禁是否拆开
|
||||||
|
- scratch 上项目专属能力是否服务端 fail-closed
|
||||||
|
- 侧栏是否把 scratch 与真项目分开
|
||||||
|
|
||||||
|
## 文件映射
|
||||||
|
|
||||||
|
| 区域 | 路径 |
|
||||||
|
|------|------|
|
||||||
|
| 标记 helper | Backend store 或 core 小 helper |
|
||||||
|
| 创建 API | `modules/backend/internal/server/server.go` |
|
||||||
|
| 列表过滤 / 1:1 | `modules/backend/internal/store/projects.go`、server createConversation |
|
||||||
|
| 门禁 | `project_lifecycle.go`、cmdbus/RDM、knowledge、跨读 |
|
||||||
|
| 前端 API/store/侧栏 | `api.ts`、`store.ts`、`TaskSidebar.tsx` |
|
||||||
|
|
||||||
|
## Tasks
|
||||||
|
|
||||||
|
### U1 — Backend 创建与固有授权
|
||||||
|
|
||||||
|
- [ ] 实现 `IsScratchProject`;`POST /api/scratch-sessions`
|
||||||
|
- [ ] ListProjects 排除 scratch;禁止 POST /api/projects 伪造 scratch;scratch 下禁止二开会话
|
||||||
|
- [ ] 角色 catalog 不暴露可配置 scratch 动作
|
||||||
|
- [ ] 单测覆盖无/有 project.create、禁用账号、伪造、1:1
|
||||||
|
|
||||||
|
### U2 — Backend 项目专属 fail-closed
|
||||||
|
|
||||||
|
- [ ] `rejectIfScratch` 挂到 projectWork/成员/RDM/knowledge/X1/跨读
|
||||||
|
- [ ] 允许消息/附件/改名置顶归档/级联删除
|
||||||
|
- [ ] 单测正负例
|
||||||
|
|
||||||
|
### U3 — Frontend
|
||||||
|
|
||||||
|
- [ ] `createScratchSession`;sidebarMode;去掉无项目时自动「默认项目」
|
||||||
|
- [ ] TaskSidebar「无项目对话」分类与隐藏项目专属入口
|
||||||
|
- [ ] 前端测试
|
||||||
|
|
||||||
|
### U4 — 验证收口
|
||||||
|
|
||||||
|
- [ ] 最小相关测试通过;task-sync / PR / CI / 独立 Review
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
# 无项目对话(Scratch Session)设计
|
||||||
|
|
||||||
|
- 状态:**已批准**(对话设计第 1–4 节,2026-10-22)。
|
||||||
|
- 日期:2026-10-22;作者:host(设计整理);来源等级:SELF。
|
||||||
|
- 配套计划:[实施计划](../plans/2026-10-22-scratch-session-general-agent-plan.md)。
|
||||||
|
|
||||||
|
## 1. 目标与非目标
|
||||||
|
|
||||||
|
**目标**
|
||||||
|
|
||||||
|
- 任意**启用账号**可创建「无项目对话」,当作通用智能体使用(多轮对话)。
|
||||||
|
- 无 `project.create`(角色「项目访问」)的用户也能完成该路径,不被「默认项目」创建 403 卡住。
|
||||||
|
- 各无项目对话彼此**独立**:不共享文档、上下文、知识等。
|
||||||
|
- **不得**接入知识树、文档树、成员、RDM 等项目专属功能。
|
||||||
|
|
||||||
|
**非目标(本轮)**
|
||||||
|
|
||||||
|
- scratch → 真项目升级 / 事后绑定 RDM
|
||||||
|
- 分享、协作、邀请进空壳项目
|
||||||
|
- 配额、TTL、自动清理
|
||||||
|
- 将 `conversations.project_id` 改为可空等大 schema 重构
|
||||||
|
|
||||||
|
## 2. 已锁定决策
|
||||||
|
|
||||||
|
| 项 | 决策 |
|
||||||
|
|---|---|
|
||||||
|
| 数据模型 | 方案 A:每个无项目对话 = 一个轻量私有空壳 `Project` + 恰好一条 `Conversation` |
|
||||||
|
| UI | 侧栏虚拟分类「无项目对话」下列会话;**不**进入真项目切换器 |
|
||||||
|
| 谁可建 | 所有启用账号(有无 `project.create` 均可) |
|
||||||
|
| 权限 | **固有能力**,不进角色矩阵,**不可被管理员修改**;与可配置的 `project.create` 完全分离 |
|
||||||
|
|
||||||
|
## 3. 数据模型与权限
|
||||||
|
|
||||||
|
### 3.1 空壳项目约定
|
||||||
|
|
||||||
|
- 仍用现有 `projects` 表;`settings` 写入稳定标记:`host.kind = "scratch"`(解析仅经统一 helper,例如 `IsScratchProject`)。
|
||||||
|
- 每个无项目对话 = **一个 scratch 项目 + 恰好一条会话**(创建时原子写入;禁止在 scratch 下再建第二会话)。
|
||||||
|
- 项目 `owner` = 当前账号;不建成员、不共享、不邀请。
|
||||||
|
- 会话默认 `crossPrivate = true`。
|
||||||
|
|
||||||
|
### 3.2 权限
|
||||||
|
|
||||||
|
| 动作 | 门禁 |
|
||||||
|
|------|------|
|
||||||
|
| `POST /api/projects` 创建真项目 | 仍要 `project.create`(不变) |
|
||||||
|
| 创建无项目对话 | 启用账号即可;**不是**角色可配置动作 |
|
||||||
|
| scratch 上读写会话/发消息 | 仅 owner |
|
||||||
|
| scratch 升成真项目 / 绑 RDM | 本轮不做(明确拒绝) |
|
||||||
|
|
||||||
|
角色 catalog、`PUT .../permissions`、角色编辑 UI **不得**出现或改写「无项目对话」能力。关掉 `project.create` 不影响 scratch 创建。
|
||||||
|
|
||||||
|
### 3.3 专用创建 API
|
||||||
|
|
||||||
|
`POST /api/scratch-sessions` → `{ project, conversation }`
|
||||||
|
|
||||||
|
- 内部:插 scratch 项目 → 建唯一会话 → **不**触发 RDM provision。
|
||||||
|
- **禁止**经 `POST /api/projects` 伪造 scratch 标记。
|
||||||
|
|
||||||
|
### 3.4 列表语义
|
||||||
|
|
||||||
|
- 真项目列表 / 侧栏项目切换器:**过滤掉** scratch。
|
||||||
|
- 「无项目对话」分类:按会话列出(标题来自会话名)。
|
||||||
|
|
||||||
|
## 4. 服务端门禁(禁用项目专属能力)
|
||||||
|
|
||||||
|
判定:`IsScratchProject(p)` ≡ `settings.host.kind == "scratch"`。
|
||||||
|
|
||||||
|
**一律拒绝(scratch 上)**
|
||||||
|
|
||||||
|
- RDM 绑定 / provision;`rdm.*` 命令对 scratch 的 projectId → 403/400
|
||||||
|
- 知识树 / 文档树 / 法规树 / 驾驶舱 / 模板实例化
|
||||||
|
- 成员、职责、项目权限矩阵、项目归档协作
|
||||||
|
- 因「拥有 scratch」而授予 `project.create` 联动能力
|
||||||
|
- Project Context(X1)注入(视为未启用,走普通通用智能体组装)
|
||||||
|
- 跨会话读:scratch 会话不可被对端读出,也不可读其他会话
|
||||||
|
- 在已有 scratch 下再建会话
|
||||||
|
- 普通创建项目接口伪装 scratch
|
||||||
|
|
||||||
|
**允许(通用智能体最小集)**
|
||||||
|
|
||||||
|
- 本会话消息、附件(仅挂本 scratch,不进知识发布)
|
||||||
|
- 会话改名 / 置顶 / 归档 / 删除(删除可级联删空壳项目)
|
||||||
|
- 普通 LLM 对话;显式 `@knowledge` 对 scratch **关闭**
|
||||||
|
|
||||||
|
实现:集中 `rejectIfScratch` / `requireNonScratch`,挂在项目工作、RDM 分发、knowledge、成员 API;不能只藏 UI。
|
||||||
|
|
||||||
|
## 5. 前端信息架构
|
||||||
|
|
||||||
|
- 项目切换器:真项目列表 + 虚拟项「无项目对话」。
|
||||||
|
- 选中「无项目对话」:列出本人所有 scratch 会话;「+ 新建对话」调用 scratch API。
|
||||||
|
- 打开 scratch 会话时:隐藏项目设置、模板生成、依赖当前真项目的 RDM 入口。
|
||||||
|
- `createTask`:无真项目时**不再**自动 `createProject('默认项目')`;无建项权或用户在无项目对话视图时走 scratch API。
|
||||||
|
- 无建项权用户主路径:登录 → 默认落在「无项目对话」→ 可直接新建/继续对话。
|
||||||
|
|
||||||
|
## 6. 验收标准
|
||||||
|
|
||||||
|
1. 无建项权账号可进入「无项目对话」并完成多轮通用对话,不因默认项目 403。
|
||||||
|
2. 有建项权账号同样可建无项目对话;真项目创建仍只认 `project.create`。
|
||||||
|
3. 同一用户两个 scratch 会话互不共享附件知识库、上下文条目、跨会话读取。
|
||||||
|
4. scratch 上 RDM/知识树/文档树/成员/项目设置类能力服务端拒绝;UI 无入口。
|
||||||
|
5. 角色权限 UI / API 不能出现或改写该能力。
|
||||||
|
6. scratch 不出现在项目切换器。
|
||||||
|
7. 无法在已有 scratch 项目下再建第二条会话。
|
||||||
|
|
||||||
|
## 7. 最小验证
|
||||||
|
|
||||||
|
- Backend:创建门禁、RDM/knowledge 拒绝、ListProjects 过滤、1:1 约束单测。
|
||||||
|
- Frontend:侧栏分组、无建项权主路径、scratch 视图隐藏项目入口的测试。
|
||||||
Reference in New Issue
Block a user