feat: rename prototype workspace and document versioning

This commit is contained in:
2026-10-19 10:54:02 +08:00
parent 49cd594233
commit 181cce6bfe
8 changed files with 33 additions and 12 deletions
+14 -4
View File
@@ -13,7 +13,7 @@ pouch add product-prototype -g # 全局
Skill 安装后,从 Skill 目录运行初始化脚本。使用仓库 checkout 时命令如下: Skill 安装后,从 Skill 目录运行初始化脚本。使用仓库 checkout 时命令如下:
```bash ```bash
python3 skills/product-prototype/scripts/init.py ./prototype-studio python3 skills/product-prototype/scripts/init.py ./prototype
``` ```
全局安装后可使用 `~/.pouch/skills/product-prototype/scripts/init.py`。初始化脚本是安全的 全局安装后可使用 `~/.pouch/skills/product-prototype/scripts/init.py`。初始化脚本是安全的
@@ -32,7 +32,7 @@ mock。四类源数据仍是唯一事实来源;浏览器产物和构建目录
## 初始化后的目录 ## 初始化后的目录
```text ```text
prototype-studio/ prototype/
├── prototype/ # 源数据:requirements/flow/layout/review ├── prototype/ # 源数据:requirements/flow/layout/review
├── src/ ├── src/
│ ├── App.tsx # React Flow Studio 与 runtime preview │ ├── App.tsx # React Flow Studio 与 runtime preview
@@ -65,7 +65,7 @@ prototype-studio/
初始化后: 初始化后:
```bash ```bash
cd prototype-studio cd prototype
npm install # 安装 package-lock 锁定的依赖 npm install # 安装 package-lock 锁定的依赖
npm run init # 幂等补齐当前项目;已有文件只报告 skip npm run init # 幂等补齐当前项目;已有文件只报告 skip
npm run dev # 启动 Vite(加载/依赖错误原样可见) npm run dev # 启动 Vite(加载/依赖错误原样可见)
@@ -107,13 +107,23 @@ npm test # 离线合约 + mock + Playwright 关键交互与
模板提供可离线复核的 fixture 检查: 模板提供可离线复核的 fixture 检查:
```bash ```bash
cd prototype-studio cd prototype
npm run test:incremental npm run test:incremental
``` ```
它同时比较 flow、layout、review 的 add/change/delete 结果,并断言 `page.keep`、无关坐标和 它同时比较 flow、layout、review 的 add/change/delete 结果,并断言 `page.keep`、无关坐标和
`comment.keep` 等未受影响记录保持不变;该检查是边界回归,不替代真实浏览器回归。 `comment.keep` 等未受影响记录保持不变;该检查是边界回归,不替代真实浏览器回归。
## 版本策略
原型默认是持续演进的:新增功能直接在当前 `prototype/` 上增量修改,保持稳定 ID,并同步
更新 flow、layout、review、实现和相关截图。每轮变更用 Git 提交保留历史;达到评审通过或
需要冻结时,再打 `prototype-v1` 这类 tag 作为基线。
只有需要并行比较多个方案、重做导航/信息架构,或必须保留不可变评审基线时才新开版本分支
或目录。新版本应记录基于哪个版本、变更范围和受影响的稳定 ID,避免复制出两套长期漂移的
原型数据。
## 如何判断完成 ## 如何判断完成
至少应完成:`init` 幂等、`validate` 通过合法 fixture 且拒绝非法 fixture、增量检查通过、 至少应完成:`init` 幂等、`validate` 通过合法 fixture 且拒绝非法 fixture、增量检查通过、
+11
View File
@@ -55,6 +55,17 @@ description: >-
的截图/测试产物。 的截图/测试产物。
- 生成物:截图、报告和测试输出只能写入项目约定的 artifacts 目录;它们不是源数据。 - 生成物:截图、报告和测试输出只能写入项目约定的 artifacts 目录;它们不是源数据。
## 命名与版本策略
- 初始化生成的工作区目录和 npm package 名称统一为 `prototype`;界面标题仍可使用
`Prototype Studio`。
- 后续添加功能默认在当前 `prototype` 上增量修改:保留已有稳定 ID,只新增或局部修改
flow/layout/review 和对应实现,并用 Git 提交记录每轮变更。
- 当一轮原型被评审通过或需要冻结时,用 Git tag/分支保存基线,例如
`prototype-v1`;新需求默认从当前基线继续,不复制一套容易漂移的四类源数据。
- 只有需要并行比较方案、导航/信息架构大幅重做,或必须长期保留不可变评审基线时,才新开
版本分支/目录。新版本必须记录 `based on`、变更范围和受影响的稳定 ID。
## 路由 ## 路由
- **初始化**:读取 `references/commands.md`,运行 `python3 scripts/init.py <target>`;先检查目标, - **初始化**:读取 `references/commands.md`,运行 `python3 scripts/init.py <target>`;先检查目标,
@@ -1,11 +1,11 @@
{ {
"name": "prototype-studio-template", "name": "prototype",
"version": "0.1.0", "version": "0.1.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "prototype-studio-template", "name": "prototype",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@xyflow/react": "12.3.1", "@xyflow/react": "12.3.1",
@@ -1,5 +1,5 @@
{ {
"name": "prototype-studio-template", "name": "prototype",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"packageManager": "npm@10", "packageManager": "npm@10",
@@ -16,7 +16,7 @@ try { fs.mkdirSync(target, { recursive: true }); } catch (error) { fail("INIT_WR
const created = []; const created = [];
const skipped = []; const skipped = [];
copyTree(root, target, root); copyTree(root, target, root);
console.log(`Prototype Studio init: ${target}`); console.log(`Prototype init: ${target}`);
console.log(`created: ${created.length}`); console.log(`created: ${created.length}`);
for (const item of created) console.log(` create ${item}`); for (const item of created) console.log(` create ${item}`);
console.log(`skipped: ${skipped.length}`); console.log(`skipped: ${skipped.length}`);
@@ -21,8 +21,8 @@
python3 skills/product-prototype/scripts/check_structure.py python3 skills/product-prototype/scripts/check_structure.py
python3 skills/product-prototype/scripts/check_docs.py python3 skills/product-prototype/scripts/check_docs.py
tmp_dir="$(mktemp -d)" tmp_dir="$(mktemp -d)"
python3 skills/product-prototype/scripts/init.py "$tmp_dir/studio" python3 skills/product-prototype/scripts/init.py "$tmp_dir/prototype"
python3 skills/product-prototype/scripts/init.py "$tmp_dir/studio" python3 skills/product-prototype/scripts/init.py "$tmp_dir/prototype"
``` ```
第二次输出应只有 `skip`,并且第一次创建的源数据不会被覆盖。`validate` 使用无第三方依赖的 第二次输出应只有 `skip`,并且第一次创建的源数据不会被覆盖。`validate` 使用无第三方依赖的
@@ -94,7 +94,7 @@ def main() -> int:
root = lock.get("packages", {}).get("") root = lock.get("packages", {}).get("")
if lock.get("lockfileVersion") != 3 or not isinstance(root, dict): if lock.get("lockfileVersion") != 3 or not isinstance(root, dict):
errors.append("package-lock.json: expected lockfileVersion 3 with root package") errors.append("package-lock.json: expected lockfileVersion 3 with root package")
elif root.get("name") != "prototype-studio-template": elif root.get("name") != "prototype":
errors.append("package-lock.json: root package name mismatch") errors.append("package-lock.json: root package name mismatch")
except json.JSONDecodeError as exc: except json.JSONDecodeError as exc:
errors.append(f"package-lock.json: invalid JSON ({exc})") errors.append(f"package-lock.json: invalid JSON ({exc})")
+1 -1
View File
@@ -49,7 +49,7 @@ def main() -> int:
parser.error("target must not be the template directory or one of its children") parser.error("target must not be the template directory or one of its children")
target.mkdir(parents=True, exist_ok=True) target.mkdir(parents=True, exist_ok=True)
created, skipped = copy_missing(source, target) created, skipped = copy_missing(source, target)
print(f"Prototype Studio init: {target}") print(f"Prototype init: {target}")
print(f"created: {len(created)}") print(f"created: {len(created)}")
for path in created: for path in created:
print(f" create {path}") print(f" create {path}")