feat(mindspace): add SEO/GEO delivery, page template catalog, and admin hooks
Memind CI / Test, build, and release guards (push) Has been cancelled
Memind CI / Test, build, and release guards (push) Has been cancelled
Enable optional SEO/GEO injection and discovery routes for confirmed public pages while keeping private pages noindex. Add premium page template skills, portal catalog API, template shop UI, and Baidu push gated by memind_adm config. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,521 @@
|
||||
# 页面模板 Skill 设计(Agent 可调用 + 授权勾选 + 二期购买)
|
||||
|
||||
日期: 2026-08-04
|
||||
|
||||
状态: **已实现(Phase 1 + 余额购买)** — 见 `page-template-catalog.mjs`、三个 `page-template-*` skill、Portal/Admin API。
|
||||
|
||||
## 1. 背景与目标
|
||||
|
||||
当前 H5 页面由 Goose Agent 按 `static-page-publish` 规范**从零生成 HTML**,平台只提供约束(cover 元数据、CSP、页脚标记等),没有可复用的 HTML 骨架库。导致:
|
||||
|
||||
- 样式与结构不稳定,同类页面差异大
|
||||
- 易漏写 `mindspace-cover`、平台页脚、Page Data 脚本引用
|
||||
- 用户无法选择「旅游 Hero / 商品促销 / 问卷壳」等固定视觉风格
|
||||
|
||||
**目标:**
|
||||
|
||||
1. 提供一套平台维护的 HTML 模板,Agent 通过 skill 读取并填充后落盘 `public/*.html`
|
||||
2. **不影响**现有 `static-page-publish` → `write_file` → finish guard 主链路
|
||||
3. 一期:管理员在 memind_adm 授权,用户在 H5 聊天勾选模板 skill
|
||||
4. 二期:用户可在模板商城购买,支付成功后自动写 skill grant
|
||||
|
||||
---
|
||||
|
||||
## 2. 核心结论
|
||||
|
||||
| 层级 | 负责方 | 说明 |
|
||||
|------|--------|------|
|
||||
| HTML 骨架 | Memind 平台 `skills/page-template-*` | 预置合规 HTML + 占位符 |
|
||||
| 文案 / 章节内容 | Goose + LLM(常见 DeepSeek) | 填占位符,不发明骨架 |
|
||||
| 授权(谁能用) | `h5_user_skill_grants` | 与现有 skill 体系一致 |
|
||||
| 使用(这次用哪个) | H5 聊天 skill 芯片 / 模板选择器 | 注入 `templateId` 到 prompt |
|
||||
| 发布与守卫 | 不变 | finish guard、cover 检查、Page Data bind |
|
||||
|
||||
一句话:
|
||||
|
||||
```text
|
||||
模板是可选 skill 资产;未授权 = 行为与今天完全一致;授权且勾选 = Agent 读模板再 write_file。
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 对现有链路的影响(硬约束)
|
||||
|
||||
### 3.1 不变的部分
|
||||
|
||||
- `static-page-publish` 仍是默认发布 skill(creator 角色或 `static_publish` 能力)
|
||||
- finish guard、`mindspace-cover` 检查、Page Data finish sync、sandbox MCP 路径规则
|
||||
- `syncSkillsToWorkspace` 只同步已授权 skill;未授权模板不会出现在工作区
|
||||
- 意图路由:`coercePageGenerationSkill` / `page-data-collect` 优先级不变
|
||||
|
||||
### 3.2 增量部分
|
||||
|
||||
- 新增若干 `page-template-*` platform skill(默认 **关闭**)
|
||||
- 可选:`page-templates` 聚合 skill(目录索引 + 共用 SKILL.md),或每个模板独立 skill 便于单独定价
|
||||
- `CHAT_SKILL_DEFINITIONS` 增加模板入口(仅 `grantedSkills` 包含时可见)
|
||||
- Agent 工作流多一步:`read_file` 模板 → 替换占位符 → `write_file`
|
||||
|
||||
### 3.3 禁止事项
|
||||
|
||||
- 禁止把 `static-page-publish` 改为「必须选模板」
|
||||
- 禁止模板 skill 绕过 `page-data-collect` 的 bind / policy 流程
|
||||
- 禁止在模板 HTML 内写 `localStorage` / 外链 `<script src="https://...">`
|
||||
- Page Data 类模板必须预置 `/assets/page-data-client.js` 引用位,Agent 只填 dataset 相关占位符
|
||||
|
||||
---
|
||||
|
||||
## 4. 目录结构
|
||||
|
||||
### 4.1 推荐:一模板一 skill(便于授权与定价)
|
||||
|
||||
```text
|
||||
skills/
|
||||
├── page-template-travel/
|
||||
│ ├── SKILL.md
|
||||
│ ├── skill.yaml
|
||||
│ └── templates/
|
||||
│ └── travel-hero.html
|
||||
├── page-template-campaign/
|
||||
│ ├── SKILL.md
|
||||
│ ├── skill.yaml
|
||||
│ └── templates/
|
||||
│ └── campaign-cta.html
|
||||
├── page-template-report/
|
||||
│ ├── SKILL.md
|
||||
│ ├── skill.yaml
|
||||
│ └── templates/
|
||||
│ └── report-editorial.html
|
||||
└── page-template-survey/
|
||||
├── SKILL.md
|
||||
├── skill.yaml
|
||||
└── templates/
|
||||
├── survey-basic.html # 前台问卷壳
|
||||
└── survey-admin-read.html # 后台只读壳(password read)
|
||||
```
|
||||
|
||||
同步后位于用户工作区:
|
||||
|
||||
```text
|
||||
MindSpace/<userId>/.agents/skills/page-template-travel/templates/travel-hero.html
|
||||
```
|
||||
|
||||
### 4.2 可选:聚合 skill(一期快速试点)
|
||||
|
||||
```text
|
||||
skills/page-templates/
|
||||
├── SKILL.md # 索引:templateId → 文件路径 + 适用场景
|
||||
├── skill.yaml
|
||||
└── templates/
|
||||
├── travel-hero.html
|
||||
├── campaign-cta.html
|
||||
└── ...
|
||||
```
|
||||
|
||||
**权衡:**
|
||||
|
||||
| 方案 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| 一模板一 skill | 单独 grant/定价;商城 SKU 一一对应 | skill 数量多 |
|
||||
| 聚合 skill | 实现快,一个 grant 全开 | 无法按模板单独售卖 |
|
||||
|
||||
**建议:** 一期用聚合 `page-templates` 试点;二期拆成 `page-template-*` 便于商城。
|
||||
|
||||
---
|
||||
|
||||
## 5. 模板文件规范
|
||||
|
||||
### 5.1 占位符约定
|
||||
|
||||
使用 Mustache 风格,Agent 替换后不得残留 `{{`:
|
||||
|
||||
```html
|
||||
<title>{{PAGE_TITLE}}</title>
|
||||
<meta name="description" content="{{PAGE_DESCRIPTION}}">
|
||||
<meta name="mindspace-cover" content='{{MINDSPACE_COVER_JSON}}'>
|
||||
<h1>{{HERO_HEADLINE}}</h1>
|
||||
<div class="content">{{MAIN_CONTENT_HTML}}</div>
|
||||
```
|
||||
|
||||
| 占位符 | 必填 | 说明 |
|
||||
|--------|------|------|
|
||||
| `PAGE_TITLE` | 是 | 浏览器标题 |
|
||||
| `PAGE_DESCRIPTION` | 是 | description + cover subtitle 来源 |
|
||||
| `MINDSPACE_COVER_JSON` | 是 | 合法 JSON 字符串(tag/accent/cover 等) |
|
||||
| `HERO_HEADLINE` | 视模板 | 首屏标题 |
|
||||
| `MAIN_CONTENT_HTML` | 是 | Agent 生成的正文 HTML 片段(已 escape 或由 Agent 保证安全) |
|
||||
| `ACCENT` / `ACCENT2` | 推荐 | 与 CSS 主色一致 |
|
||||
|
||||
Page Data 问卷模板额外占位符:
|
||||
|
||||
| 占位符 | 说明 |
|
||||
|--------|------|
|
||||
| `DATASET_ID` | 注册后的 dataset id |
|
||||
| `FORM_FIELDS_HTML` | 表单字段块 |
|
||||
| `ADMIN_PAGE_FILENAME` | 后台页相对路径 hint |
|
||||
|
||||
### 5.2 模板自检清单(入库前)
|
||||
|
||||
- [ ] 完整 `<!DOCTYPE html>`,`lang="zh-CN"`,viewport
|
||||
- [ ] `<meta name="mindspace-cover">` 占位符或示例结构
|
||||
- [ ] 页脚含 `data-mindspace-page-tag="platform-brand"` → `TKMind · 智趣`
|
||||
- [ ] 无 CDN script;Chart 等用 `/assets/chart.umd.min.js` 或相对路径
|
||||
- [ ] 问卷类含 `<script src="/assets/page-data-client.js">`
|
||||
- [ ] 运行 `npm run check:mindspace-cover` 对填充样例通过
|
||||
|
||||
### 5.3 SKILL.md 工作流摘要(Agent 必读)
|
||||
|
||||
```markdown
|
||||
## 何时使用
|
||||
|
||||
- 用户在本轮对话中**明确选择**了「旅游模板 / 促销模板 / …」
|
||||
- 或 prompt 前缀含 `templateId=travel-hero`
|
||||
|
||||
## 工作流
|
||||
|
||||
1. 确认用户已授权本 skill(load_skill 成功)
|
||||
2. read_file → `.agents/skills/page-template-travel/templates/travel-hero.html`
|
||||
3. 根据用户需求生成文案与 MAIN_CONTENT_HTML
|
||||
4. 替换全部占位符,自检无残留 `{{`
|
||||
5. write_file → public/<slug>.html
|
||||
6. 若需 Page Data:仍走 page-data-collect(建表 → register → bind),不得跳过
|
||||
7. 按 static-page-publish 回复 Markdown 链接
|
||||
|
||||
## 何时不用
|
||||
|
||||
- 用户未选模板 → 继续 static-page-publish 从零写 HTML
|
||||
- 用户要求完全自定义版式且与模板冲突 → 从零写,说明原因
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. skill.yaml 示例
|
||||
|
||||
```yaml
|
||||
# skills/page-template-travel/skill.yaml
|
||||
name: page-template-travel
|
||||
version: 1.0.0
|
||||
label: 旅游 Hero 模板
|
||||
description: 深色沉浸 + Hero 图 + 卡片区块,适用于旅游/美食/城市攻略
|
||||
catalog:
|
||||
previewImage: /assets/template-previews/travel-hero.png
|
||||
priceCents: 990 # 二期商城展示;一期忽略
|
||||
category: page-template
|
||||
trigger:
|
||||
keywords:
|
||||
- 旅游模板
|
||||
- 攻略模板
|
||||
- travel-hero
|
||||
router:
|
||||
promptKey: page-template-travel
|
||||
priority: 25
|
||||
requires:
|
||||
- static-page-publish # 文档约定;运行时仍靠 grant 控制
|
||||
executors:
|
||||
- goose
|
||||
```
|
||||
|
||||
`skills-registry.mjs` 的 `parseSkillManifest` 已支持扩展字段;`catalog` / `requires` 为二期预留,一期 parser 可忽略未知键。
|
||||
|
||||
---
|
||||
|
||||
## 7. 授权模型(复用现有 skill grant)
|
||||
|
||||
### 7.1 现有表(无需改 schema — 一期)
|
||||
|
||||
```sql
|
||||
-- 已有:h5_user_skill_grants
|
||||
-- subject_type: 'role' | 'user'
|
||||
-- subject_id: 'user' | <userId>
|
||||
-- skill_name: 如 'page-templates' 或 'page-template-travel'
|
||||
-- enabled: 0 | 1
|
||||
```
|
||||
|
||||
解析链(已实现):
|
||||
|
||||
```text
|
||||
listSkillGrants('role','user') + listSkillGrants('user', userId)
|
||||
→ resolveSkillMap()
|
||||
→ grantedSkillNames()
|
||||
→ syncSkillsToWorkspace() // 仅 enabled skill 复制到 .agents/skills/
|
||||
→ filterChatSkills() // H5 聊天入口过滤
|
||||
→ resolveSkillPrompt() // 意图路由不注入未授权 skill
|
||||
```
|
||||
|
||||
### 7.2 默认策略(一期)
|
||||
|
||||
在 `skills-registry.mjs` 的 `DEFAULT_USER_SKILLS` 中:
|
||||
|
||||
```javascript
|
||||
'page-templates': false, // 聚合 skill,试点
|
||||
'page-template-travel': false, // 拆分后逐项默认关
|
||||
'page-template-campaign': false,
|
||||
'page-template-survey': false,
|
||||
```
|
||||
|
||||
creator 预设可选开启:
|
||||
|
||||
```javascript
|
||||
creator: {
|
||||
...DEFAULT_USER_SKILLS,
|
||||
'page-templates': true,
|
||||
},
|
||||
```
|
||||
|
||||
### 7.3 memind_adm 操作(一期)
|
||||
|
||||
复用已有 Admin API(Memind `admin-routes.mjs`):
|
||||
|
||||
| 方法 | 路径 | 用途 |
|
||||
|------|------|------|
|
||||
| GET | `/admin-api/skills/catalog` | 列出含新 template skill |
|
||||
| GET | `/admin-api/users/:userId/skills` | 查看用户有效 skill |
|
||||
| PUT | `/admin-api/users/:userId/skills` | `{ "skills": { "page-templates": true } }` |
|
||||
| PUT | `/admin-api/skills/role/user` | 角色默认批量开启 |
|
||||
|
||||
`setUserSkills` 成功后已调用 `syncUserSkillsForUser`,**下次会话**工作区即有模板文件。
|
||||
|
||||
---
|
||||
|
||||
## 8. H5 聊天勾选(复用 skill 芯片)
|
||||
|
||||
### 8.1 扩展 CHAT_SKILL_DEFINITIONS
|
||||
|
||||
在 `chat-skills.mjs` 增加(示例):
|
||||
|
||||
```javascript
|
||||
{
|
||||
id: 'page-template-travel',
|
||||
label: '旅游模板',
|
||||
icon: 'page',
|
||||
skillName: 'page-template-travel',
|
||||
requiresSkill: 'page-template-travel',
|
||||
requiresPublish: true,
|
||||
promptKey: 'page-template-travel',
|
||||
},
|
||||
```
|
||||
|
||||
`filterChatSkills` 逻辑已满足:
|
||||
|
||||
- `requiresSkill` → 必须在 `grantedSkills`
|
||||
- `requiresPublish` → 需 `canPublish` 或已 grant `page-data-collect`(页面类统一规则)
|
||||
|
||||
### 8.2 Prompt 前缀
|
||||
|
||||
在 `buildChatSkillPrompt` 增加:
|
||||
|
||||
```javascript
|
||||
case 'page-template-travel':
|
||||
return (
|
||||
'请使用 page-template-travel 技能:先 load_skill,再 read_file 读取 templates/travel-hero.html,' +
|
||||
'按模板占位符填充内容(templateId=travel-hero),write_file 到 public/页面.html,' +
|
||||
'并遵守 static-page-publish 的 mindspace-cover 与链接格式。页面主题:'
|
||||
);
|
||||
```
|
||||
|
||||
用户点击芯片 → `pendingSkillRef` → 发送带前缀的消息 → Agent 走模板流程。
|
||||
|
||||
### 8.3 二期:独立模板选择器(可选 UI)
|
||||
|
||||
在「生成页面」芯片点击后展开二级面板:
|
||||
|
||||
- 展示 `GET /api/mindspace/v1/template-catalog` 返回的已购模板列表
|
||||
- 单选 templateId → 合并进 prompt
|
||||
|
||||
一期可仅用聊天芯片,不做二级 UI。
|
||||
|
||||
---
|
||||
|
||||
## 9. Agent 执行时序
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as 用户
|
||||
participant H5 as H5 Chat
|
||||
participant P as Portal
|
||||
participant G as Goose
|
||||
participant WS as 用户工作区
|
||||
|
||||
U->>H5: 点击「旅游模板」+ 输入主题
|
||||
H5->>P: POST /agent/run (含 skill 前缀)
|
||||
P->>P: grantedSkills 含 page-template-travel?
|
||||
P->>G: 会话 constraints + 用户消息
|
||||
G->>G: load_skill(page-template-travel)
|
||||
G->>WS: read_file templates/travel-hero.html
|
||||
G->>G: LLM 生成文案 + 填占位符
|
||||
G->>WS: write_file public/xxx.html
|
||||
G->>P: Finish + 链接
|
||||
P->>P: finish guard / cover 检查
|
||||
P->>U: 可点击公网链接
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 二期:购买与商城(新增)
|
||||
|
||||
### 10.1 新增表(建议)
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS h5_template_catalog (
|
||||
skill_name VARCHAR(64) PRIMARY KEY COMMENT '与 platform skill name 一致',
|
||||
label VARCHAR(128) NOT NULL,
|
||||
description TEXT,
|
||||
preview_url VARCHAR(512) NULL,
|
||||
price_cents INT NOT NULL DEFAULT 0,
|
||||
currency VARCHAR(8) NOT NULL DEFAULT 'CNY',
|
||||
billing_mode ENUM('free','one_time','subscription') NOT NULL DEFAULT 'one_time',
|
||||
status ENUM('draft','active','archived') NOT NULL DEFAULT 'draft',
|
||||
sort_order INT NOT NULL DEFAULT 0,
|
||||
created_at BIGINT NOT NULL,
|
||||
updated_at BIGINT NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS h5_template_purchases (
|
||||
id CHAR(36) PRIMARY KEY,
|
||||
user_id CHAR(36) NOT NULL,
|
||||
skill_name VARCHAR(64) NOT NULL,
|
||||
order_id VARCHAR(64) NULL COMMENT '关联支付单',
|
||||
source ENUM('purchase','admin_grant','promo') NOT NULL,
|
||||
purchased_at BIGINT NOT NULL,
|
||||
expires_at BIGINT NULL COMMENT '订阅型模板到期;NULL=永久',
|
||||
UNIQUE KEY uq_user_template (user_id, skill_name),
|
||||
KEY idx_template_user (user_id),
|
||||
CONSTRAINT fk_template_purchase_user FOREIGN KEY (user_id) REFERENCES h5_users(id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
```
|
||||
|
||||
**与 skill grant 关系:**
|
||||
|
||||
- 购买成功 / 管理员赠送 → 写 `h5_template_purchases` + `h5_user_skill_grants(enabled=1)`
|
||||
- 退款 / 到期 → `enabled=0` + 可选删除工作区 `.agents/skills/page-template-*`
|
||||
- `resolveUserSkillMap` 可扩展:有效 purchase 视为 grant(即使无 user override 行)
|
||||
|
||||
### 10.2 Portal 用户 API(草案)
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| GET | `/api/mindspace/v1/template-catalog` | 商城列表(含是否已购) |
|
||||
| GET | `/api/mindspace/v1/template-catalog/mine` | 当前用户已购/已授权模板 |
|
||||
| POST | `/api/mindspace/v1/template-catalog/:skillName/checkout` | 创建支付单(对接现有 billing) |
|
||||
| POST | `/api/mindspace/v1/template-catalog/:skillName/activate` | 支付回调内部:写 purchase + grant |
|
||||
|
||||
响应示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"skillName": "page-template-travel",
|
||||
"label": "旅游 Hero 模板",
|
||||
"description": "深色沉浸 + Hero 图",
|
||||
"previewUrl": "https://m.tkmind.cn/assets/template-previews/travel-hero.png",
|
||||
"priceCents": 990,
|
||||
"owned": true,
|
||||
"chatSkillId": "page-template-travel"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 10.3 memind_adm 商城管理(UI 边界)
|
||||
|
||||
按 `AGENTS.md`:**商城配置页在 memind_adm(5174)**,Memind 本仓只实现 API 与 skill 资产。
|
||||
|
||||
memind_adm 需新增:
|
||||
|
||||
- 模板 SKU 配置(映射 `h5_template_catalog`)
|
||||
- 用户已购模板查询
|
||||
- 手动赠送 / 撤销(调 Memind admin API 或直接写 grant)
|
||||
|
||||
### 10.4 支付回调伪代码
|
||||
|
||||
```javascript
|
||||
async function onTemplatePaymentSuccess({ userId, skillName, orderId }) {
|
||||
await pool.query(
|
||||
`INSERT INTO h5_template_purchases (id, user_id, skill_name, order_id, source, purchased_at)
|
||||
VALUES (?, ?, ?, ?, 'purchase', ?)
|
||||
ON DUPLICATE KEY UPDATE order_id = VALUES(order_id), purchased_at = VALUES(purchased_at)`,
|
||||
[uuid(), userId, skillName, orderId, Date.now()],
|
||||
);
|
||||
await userAuth.setUserSkills(userId, { [skillName]: true });
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. 代码改动清单(实施顺序)
|
||||
|
||||
### Phase 1 — 试点(无购买)
|
||||
|
||||
| # | 仓库 | 文件 / 模块 | 改动 |
|
||||
|---|------|-------------|------|
|
||||
| 1 | Memind | `skills/page-templates/` | 新增 SKILL.md + 2~3 个 HTML 模板 |
|
||||
| 2 | Memind | `skills-registry.mjs` | `DEFAULT_USER_SKILLS['page-templates']=false` |
|
||||
| 3 | Memind | `chat-skills.mjs` | `CHAT_SKILL_DEFINITIONS` + `buildChatSkillPrompt` |
|
||||
| 4 | Memind | `chat-skills.test.mjs` | filterChatSkills / prompt 单测 |
|
||||
| 5 | memind_adm | 用户技能页 | 勾选 `page-templates`(若尚未暴露 catalog 新项,刷新 catalog 即可) |
|
||||
| 6 | Memind | `scripts/verify-page-template-samples.mjs` | 可选:占位符填充样例 + cover 检查 |
|
||||
|
||||
**验收:**
|
||||
|
||||
1. 未授权用户:聊天无模板芯片,Agent 行为与现网一致
|
||||
2. 管理员授权后:出现「页面模板」芯片,生成页使用模板骨架且 cover 检查通过
|
||||
3. `npm run verify:mindspace-publish-guards` 仍通过
|
||||
|
||||
### Phase 2 — 商城与购买
|
||||
|
||||
| # | 模块 | 改动 |
|
||||
|---|------|------|
|
||||
| 1 | `schema.sql` + migration | `h5_template_catalog` / `h5_template_purchases` |
|
||||
| 2 | Portal routes | template-catalog API + checkout |
|
||||
| 3 | billing 集成 | 模板 SKU 入账 |
|
||||
| 4 | memind_adm | 商城 UI + 赠送 |
|
||||
| 5 | 拆分 skill | `page-templates` → `page-template-*` 独立定价 |
|
||||
|
||||
---
|
||||
|
||||
## 12. 测试计划
|
||||
|
||||
| 场景 | 预期 |
|
||||
|------|------|
|
||||
| 无 grant | 无芯片;自然语言「做旅游页」仍走 static-page-publish |
|
||||
| 有 grant,未点芯片 | 可走模板或从零(SKILL 约定优先响应用户明确指定) |
|
||||
| 有 grant,点芯片 | read_file 模板 → write_file;链接可访问 |
|
||||
| Page Data 模板 | 仍完成 bind;verify:page-data 通过 |
|
||||
| 撤销 grant | 下次 sync 删除 `.agents/skills/page-template-*` |
|
||||
| 购买回调 | purchase 行 + grant;芯片即时可见(需 refresh capabilities) |
|
||||
|
||||
---
|
||||
|
||||
## 13. 风险与缓解
|
||||
|
||||
| 风险 | 缓解 |
|
||||
|------|------|
|
||||
| Agent 占位符漏替换 | SKILL 强调自检;verify 脚本 grep `{{` |
|
||||
| 模板与 Page Data 流程脱节 | survey 模板仅提供壳;bind 步骤写入 SKILL 强制清单 |
|
||||
| skill 过多难维护 | 一期聚合;二期按销量拆包 |
|
||||
| 购买与 grant 不一致 | purchase 表为 source of truth;定时 reconcile job |
|
||||
|
||||
---
|
||||
|
||||
## 14. 相关文档与代码
|
||||
|
||||
| 主题 | 位置 |
|
||||
|------|------|
|
||||
| 静态页发布规范 | `skills/static-page-publish/SKILL.md` |
|
||||
| Skill 同步 | `skills-registry.mjs` → `syncSkillsToWorkspace` |
|
||||
| Skill grant | `user-auth.mjs` → `resolveUserSkillMap` |
|
||||
| 聊天 skill 芯片 | `chat-skills.mjs` → `CHAT_SKILL_DEFINITIONS` |
|
||||
| Admin skill API | `admin-routes.mjs` `/skills/*` |
|
||||
| Page Data 交付 | `docs/regression-guards/page-data-delivery-contract.md` |
|
||||
| 管理后台 UI 边界 | `AGENTS.md` → memind_adm 5174 |
|
||||
|
||||
---
|
||||
|
||||
## 15. 开放问题(产品确认)
|
||||
|
||||
1. 一期聚合 skill 还是直接按模板拆 skill?
|
||||
2. 模板定价:买断 vs 订阅 vs 套餐捆绑?
|
||||
3. 是否在「生成页面」芯片下做二级模板预览 UI,还是仅聊天芯片?
|
||||
4. creator 角色是否默认赠送全部模板?
|
||||
|
||||
确认后可按 Phase 1 清单开分支实现。
|
||||
+26
-3
@@ -151,16 +151,17 @@ npm run trace:mindspace-artifact -- --public-url http://127.0.0.1:5173/MindSpace
|
||||
|
||||
### H5 Session 架构本地全量联调(`0706-bug干净` 分支)
|
||||
|
||||
在 **本机 `.env`**(勿提交 Git)打开下列开关后重启 `pnpm dev`:
|
||||
在 **本机 `.env`**(勿提交 Git)可额外打开下列开关后重启 `pnpm dev`:
|
||||
|
||||
```bash
|
||||
MEMIND_SESSION_BROKER_ENABLED=1
|
||||
MEMIND_ROUTER_NORMALIZED_DECISION=1
|
||||
MEMIND_SSE_EVENT_TAXONOMY=1
|
||||
MEMIND_RUN_STREAM_REPLAY=1
|
||||
MEMIND_H5_HTML_FINISH_GUARD=1
|
||||
```
|
||||
|
||||
`pnpm dev`(`local` / `split-service` profile)**默认已开启** `MEMIND_H5_HTML_FINISH_GUARD=1`(页面假交付 + 模板合规自动 repair)。若要关闭,在 `.env` 写 `MEMIND_H5_HTML_FINISH_GUARD=0`。
|
||||
|
||||
| 开关 | 验证点 |
|
||||
|------|--------|
|
||||
| `MEMIND_SESSION_BROKER_ENABLED` | Portal 启动日志、`sessionAccess` 路径 |
|
||||
@@ -169,7 +170,7 @@ MEMIND_H5_HTML_FINISH_GUARD=1
|
||||
| `MEMIND_SSE_EVENT_TAXONOMY` | SSE payload 多 `taxonomy` 字段 |
|
||||
| `MEMIND_RUN_STREAM_REPLAY` | run SSE 含 `id:`,断线重连补发 |
|
||||
| `MEMIND_SESSION_STREAM_REPLAY` | session SSE 持久化 + Last-Event-ID 重连补发(4c) |
|
||||
| `MEMIND_H5_HTML_FINISH_GUARD` | Finish 后假交付检测 / 自动 repair |
|
||||
| `MEMIND_H5_HTML_FINISH_GUARD` | Finish 后假交付 / 模板漂移检测与自动 repair(`pnpm dev` 默认开) |
|
||||
|
||||
启动后应看到类似:
|
||||
|
||||
@@ -202,6 +203,28 @@ Plaza 本地开发说明见 [plaza-local.md](./plaza-local.md)。生产发布、
|
||||
|
||||
硬规则:不要把 103 的 `.env`、密钥、RDS 连接串复制进仓库;`.env.example` 只记录变量名与本地示例值。
|
||||
|
||||
## MindSpace SEO / GEO(本地联调)
|
||||
|
||||
默认关闭,与生产一致。在 **memind_adm**(见上表)打开 **MindSpace 配置**,保存 **SEO / GEO** 卡片中的总开关与子开关。
|
||||
|
||||
| 开关 | 作用 |
|
||||
|------|------|
|
||||
| 总开关 `seoGeo.enabled` | 关闭时交付链与改前一致;开启后按收录策略注入 meta / JSON-LD |
|
||||
| `seo.sitemap` / `seo.robots` / `geo.llms` | 控制 `GET /sitemap.xml`、`/robots.txt`、`/llms.txt` |
|
||||
| `seo.baiduPush` | 用户确认公开 MindSpace 页或 Plaza 发帖后推送百度 |
|
||||
|
||||
可索引页条件:`public` + `online` + `user_confirmed_at` 非空。私有页、未确认公开、embed 预览一律 `noindex`。
|
||||
|
||||
本地验证:
|
||||
|
||||
```bash
|
||||
npm run verify:seo-geo
|
||||
npm run verify:seo-discovery
|
||||
npm run verify:portal-access-policy
|
||||
```
|
||||
|
||||
详见 [MindSpace SEO / GEO 回归守卫](./regression-guards/mindspace-seo-geo.md)。
|
||||
|
||||
## 公众号 Agent 调试
|
||||
|
||||
服务号消息转发到专属 Agent 这条链路默认关闭,只有显式设置下面这些变量后才会启用:
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
| [h5-session-stream-replay.md](./h5-session-stream-replay.md) | Portal/Goose SSE 游标映射、断线续播与 Finish 终态恢复 |
|
||||
| [memory-v2-candidate-and-lifecycle.md](./memory-v2-candidate-and-lifecycle.md) | 候选记忆表幂等初始化、Portal fail-open、生命周期 off/canary/active 作用域 |
|
||||
| [episodic-history-recall.md](./episodic-history-recall.md) | 历史会话召回、用户隔离、旧快照回退、提示注入与 off/canary/active 灰度 |
|
||||
| [mindspace-seo-geo.md](./mindspace-seo-geo.md) | 公开页 SEO/GEO 注入、私有页 noindex、sitemap/llms.txt 与百度推送开关 |
|
||||
|
||||
## 自动化
|
||||
|
||||
@@ -21,6 +22,8 @@
|
||||
npm run verify:mindspace-publish-guards # 推荐:改相关代码后
|
||||
npm run verify:mindspace-publish-guards:full # 发 Portal runtime 后
|
||||
npm run verify:h5-session-patches # H5 会话、Agent Run 与 SSE 续播
|
||||
npm run verify:seo-geo # SEO/GEO 单测
|
||||
npm run verify:seo-discovery # robots/sitemap/llms 路由
|
||||
```
|
||||
|
||||
## 新增守卫时
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# MindSpace SEO / GEO 回归守卫
|
||||
|
||||
日期: 2026-08-07
|
||||
|
||||
## 保护内容
|
||||
|
||||
1. **收录策略硬规则**:仅 `access_mode=public` 且 `status=online` 且 `user_confirmed_at` 非空的发布页允许 SEO/GEO 注入与 sitemap/llms 收录。
|
||||
2. **私有页强制 noindex**:密码、登录可见、owner_only、未确认公开、工作区预览直链等必须注入 `noindex, nofollow` 并设置 `X-Robots-Tag`。
|
||||
3. **总开关默认关闭**:`mindspace_config.seo_geo_config.enabled=false` 时,交付链行为与未上线前一致。
|
||||
4. **配置来源**:memind_adm MindSpace 配置页 → `PATCH /admin-api/mindspace/config` → Portal `loadMindSpaceConfigCached()`。
|
||||
5. **百度推送**:仅在 admin 开启 `seo.baiduPush` 且页面可索引时触发;MindSpace 确认公开与 Plaza 发帖共用该开关。
|
||||
|
||||
## 必跑验证
|
||||
|
||||
```bash
|
||||
npm run verify:seo-geo
|
||||
npm run verify:seo-discovery
|
||||
npm run verify:portal-access-policy
|
||||
```
|
||||
|
||||
改以下路径前必须跑上述命令:
|
||||
|
||||
- `mindspace-index-policy.mjs`
|
||||
- `mindspace-seo-tags.mjs` / `mindspace-geo-tags.mjs` / `mindspace-seo-geo-delivery.mjs`
|
||||
- `mindspace-seo-discovery-service.mjs` / `mindspace-seo-notify.mjs`
|
||||
- `mindspace-public-delivery.mjs`
|
||||
- `server/portal-published-page-delivery.mjs`
|
||||
- `server/portal-workspace-publication-delivery.mjs`
|
||||
- `server/portal-seo-discovery-routes.mjs`
|
||||
- `mindspace-config.mjs`
|
||||
- `mindspace-publications.mjs`(确认公开 + 百度推送)
|
||||
|
||||
## 禁止回退
|
||||
|
||||
- 禁止让非 public 页面进入 `/sitemap.xml` 或 `/llms.txt`
|
||||
- 禁止在 embed 模式注入 SEO/GEO
|
||||
- 禁止绕过 `resolveIndexPolicy` 直接注入 canonical / JSON-LD
|
||||
- 禁止删除私有页的 `noindex` 保护以“提升收录”
|
||||
Reference in New Issue
Block a user