diff --git a/.claude/skills/d8d-dev/journey-mode.md b/.claude/skills/d8d-dev/journey-mode.md
index 4f1b714..e26a98f 100644
--- a/.claude/skills/d8d-dev/journey-mode.md
+++ b/.claude/skills/d8d-dev/journey-mode.md
@@ -394,14 +394,7 @@ Story 验证全部通过 ≠ 用户能正常使用系统。旅程模式弥补这
3. 证据阶段(⛔ 强制,不得跳过):
- browser_take_screenshot → 保存最终截图到 tests/e2e/screenshots/journey-epic{N}-{M}-final.png
- - browser_network_requests(static=false) → 检查无 localhost API 调用
- - ⛔ **资源加载状态检查**(新增 — 每条旅程必须执行):
- - `browser_network_requests(static=true, filter="\\.(jpg|jpeg|png|gif|webp|svg|mp4|webm|mov)$")`
- - 过滤图片/视频资源请求,检查 HTTP 状态码
- - 任何 403/404 → 标记 `resource_status_check.found = FOUND` + 触发修复
- - 常见 403 原因:MinIO 私有 bucket 未用 presigned URL、防盗链、CORS
- - 常见 404 原因:资源路径错误、文件未上传
- - 记录到 pipeline-state.yaml 的 `verification_detail.resource_status_check`
+ - browser_network_requests → 检查无 localhost API 调用
4. 修复阶段(⛔ 以下任一条件满足时必须执行,不得跳过):
diff --git a/.claude/skills/d8d-dev/phase-00-setup.md b/.claude/skills/d8d-dev/phase-00-setup.md
index 31712c5..82b0edc 100644
--- a/.claude/skills/d8d-dev/phase-00-setup.md
+++ b/.claude/skills/d8d-dev/phase-00-setup.md
@@ -68,6 +68,9 @@
- 标记:Epic 0 完成后此文件才可生效(项目目录需先存在)
4.5. **外网域名发现与连通性验证(NPM MCP)**
+ - project-slug 推导规则:取项目根目录名(basename of pwd),追加 `-group` 后缀
+ - 示例:目录 `/mnt/code/231-251-template-6` → slug = `231-251-template-6-group`
+ - ⛔ 禁止从项目描述或 PRD 内容猜测 slug
- 通过 NPM MCP 工具查询已配置的代理主机:
- 使用 `get_host_report` 快速确认代理数量
- ⚠️ `list_proxy_hosts` 有已知 bug(locations 字段解析失败),用 `get_proxy_host` 逐个查询更可靠
@@ -79,9 +82,10 @@
```
- 缺失的域名通过 `create_proxy_host` 创建(⛔ 参数要求见 `reference/platform-nextjs.md` §7 或 `reference/platform-uni-app.md`)
- `block_exploits: false`(默认 true 阻断 WebSocket)
- - 创建后 `update_proxy_host` 启用 WebSocket Support
- SSL 由 K8S ingress 处理,不需要在 NPM 中配置
- - 创建后验证:`get_proxy_host` 确认 `block_exploits: false` 且 `allow_websocket_upgrade: true`
+ - ⛔ 对每个 proxy host(无论已有还是新建),必须验证并修复(此步骤不可跳过):
+ - `get_proxy_host` 检查 `block_exploits: false` 且 `allow_websocket_upgrade: true`
+ - 如不满足 → `update_proxy_host` 修正(MCP 工具不直接支持 allow_websocket_upgrade 时,用 NPM API:`PUT /api/nginx/proxy-hosts/{id}` 传 `{"allow_websocket_upgrade": true}`)
- 将外网域名写入 `pipeline-context.md` 的"外网域名"部分
- **E2E 测试优先使用外网域名**,localhost 作为最后 fallback
@@ -177,26 +181,6 @@
- 此步骤创建的 .env.local 不应提交到 git(应在 .gitignore 中排除)
- 更新 pipeline-context.md 记录注入状态
-4.8. **MinIO 外网地址注入(⛔ 强制)**
-
- 检测容器环境变量 `MINIO_HOST`,将外网地址注入到 `.env` 中的 `S3_PUBLIC_URL`:
-
- a. 检测 MINIO_HOST:
- ```bash
- echo $MINIO_HOST
- ```
- b. 探测 HTTPS 是否可用:
- ```bash
- curl -sf --max-time 5 https://$MINIO_HOST/minio/health/live && echo "HTTPS" || echo "NO-HTTPS"
- ```
- c. 注入到 `.env`(⚠️ 注意 K8S ingress 会将 HTTP 升级为 HTTPS,必须使用 HTTPS):
- ```
- S3_PUBLIC_URL="https://{MINIO_HOST}"
- ```
- d. 代码中对外暴露的 URL(presigned URL、封面图 URL)必须使用 `S3_PUBLIC_URL`
- e. 内部连接(S3Client endpoint)保持 `S3_ENDPOINT`(localhost:9000)
- f. 详见 `reference/platform-nextjs.md` §8
-
5. **初始化管道状态**
- 创建 `{implementation_artifacts}/pipeline-state.yaml`:
```yaml
diff --git a/.claude/skills/d8d-dev/reference/platform-nextjs.md b/.claude/skills/d8d-dev/reference/platform-nextjs.md
index 6026419..6285b41 100644
--- a/.claude/skills/d8d-dev/reference/platform-nextjs.md
+++ b/.claude/skills/d8d-dev/reference/platform-nextjs.md
@@ -230,89 +230,3 @@ NPM 代理主机默认配置会阻断 WebSocket,导致:
### 验证
`get_proxy_host` 确认:`block_exploits: false` + `allow_websocket_upgrade: true`
-
----
-
-## 8. MinIO 外网地址配置(⛔ 强制)
-
-### 问题描述
-
-`S3_ENDPOINT` 默认为 `http://localhost:9000`(容器内部连接)。但对外暴露的 URL(presigned URL、封面图 URL)
-如果使用 `localhost:9000`,外网用户无法访问。
-
-容器环境提供 `MINIO_HOST` 环境变量(外网 MinIO 域名),需要注入为 `S3_PUBLIC_URL`。
-
-### 关键区分
-
-| 变量 | 用途 | 值 |
-|------|------|------|
-| `S3_ENDPOINT` | S3Client 内部连接 | `http://localhost:9000` |
-| `S3_PUBLIC_URL` | 对外暴露的 URL(presigned、封面) | `https://{MINIO_HOST}` |
-
-### Dual S3Client 模式(⛔ 强制)
-
-AWS SDK `getSignedUrl()` 生成的 presigned URL 签名包含 `X-Amz-SignedHeaders=host`,
-即签名绑定了 S3Client 的 endpoint host。**不能用字符串替换域名**(签名会失效返回 403)。
-
-必须创建两个 S3Client 实例:
-
-```typescript
-// 内部 S3Client(worker 下载、上传等)
-const s3 = new S3Client({ endpoint: "http://localhost:9000", ... });
-
-// 外网 S3Client(生成外网 presigned URL)
-const s3Public = new S3Client({ endpoint: "https://minio-xxx.dev.d8d.fun", ... });
-
-// 内部 presigned URL(worker 用)
-getDownloadUrl(key) → getSignedUrl(s3, ...) // host=localhost:9000
-
-// 外网 presigned URL(浏览器/stream 路由用)
-getPublicDownloadUrl(key) → getSignedUrl(s3Public, ...) // host=minio-xxx.dev.d8d.fun
-```
-
-### 代码规则
-
-- **`getDownloadUrl()`**:用内部 `s3`,返回 localhost presigned URL(worker 下载用)
-- **`getPublicDownloadUrl()`**:用 `s3Public`,返回外网 presigned URL(stream 路由用)
-- **`uploadFile()` 返回值**:使用 `S3_PUBLIC_URL`(公开访问 URL)
-- **worker 中的封面 URL**:使用 `S3_PUBLIC_URL`
-- **禁止字符串替换域名**:`url.replace(localhost, publicUrl)` 会导致 403
-
-### ⚠️ HTTPS 注意
-
-K8S ingress 会将 HTTP 升级为 HTTPS。`S3_PUBLIC_URL` 必须使用 `https://`,
-否则 presigned URL 签名会因重定向而失效。
-
----
-
-## 9. 资源 URL 可访问性检查(⛔ 强制)
-
-### 问题描述
-
-MinIO bucket 默认私有,所有通过 URL 直接访问的资源(图片、视频)都会返回 403。
-前端 `
` 或 `