plan-code-lifecycle.md
4.8 KB
生成代码的去向
Coder 生成的
units/{id}/code/**shipped 后去哪?继续在沙箱里?合到主仓库?开 PR?本页给出 v1 决策与升级路径。
① 三种归宿
| 方案 | 位置 | 优 | 劣 |
|---|---|---|---|
| A · 留沙箱(v1 默认) | data/companies/{cid}/projects/{pid}/units/** |
零集成成本;可被复现脚本读;隔离强 | 不能直接运行在 LemonBoss 主进程;需手动导出 |
| B · 手动 export 导出 | 人类点「导出」按钮 → 下载 zip | 简单;人类可控;适合外部交付 | 没有 git 历史;不接 CI/CD |
| C · 自动开 GitHub PR | 主仓库的 feature branch | 真集成;CI 自动跑;review 流程 | 需 GitHub token / 权限;branch 命名冲突;merge 策略复杂 |
v1 决策:A + B。C 留到 v2 视真实需要再说。本套文档对外宣称"生成代码",但 v1 不承诺自动合并到生产仓库。
② 沙箱代码的生命周期
③ Export API · v1 实现
// server/routes/devloop.js · 新增
router.post('/projects/:pid/export', requireAuth, async (req, res) => {
const { pid } = req.params;
const { include = 'code' } = req.body; // code / code+tests / all
const archiver = require('archiver');
res.setHeader('Content-Type', 'application/zip');
res.setHeader('Content-Disposition', `attachment; filename="${pid}.zip"`);
const zip = archiver('zip');
zip.pipe(res);
const root = projectsDir(pid);
if (include.includes('code')) zip.directory(path.join(root, 'units'), 'units');
if (include.includes('tests')) zip.directory(path.join(root, 'integration'),'integration');
if (include.includes('docs')) {
zip.directory(path.join(root, 'prd'), 'prd');
zip.directory(path.join(root, 'sdd'), 'sdd');
}
// 附 README 说明项目结构
zip.append(buildReadme(pid), { name: 'README.md' });
await zip.finalize();
});
archiver 在 LemonBoss 既有依赖(
"archiver": "^7.0.1"),零新增包。
④ 导出包里的 README 模板
# Project {pid}
由 LemonBoss DevLoop v1 生成 · {timestamp}
## 结构
units/ ├── todo-be/code/ 后端代码 ├── todo-be/tests/ Tester 写的 vitest ├── todo-be/contract.json 接口契约 ├── todo-fe/... integration/spec.json 端到端用例 prd/ 原始需求文档 (HTML 站点) sdd/ 架构设计文档 (HTML 站点)
## 跑起来
```bash
cd units/todo-be
npm install # 各 Unit 独立装包
PORT=3010 node code/server.js
# 另起前端 (如有)
cd units/todo-fe
npm install
npm run dev
测试
cd units/todo-be
vitest run # 跑 Tester 写的 spec
集成
# 在项目根
node integration/runner.js # 启动所有 be + 跑 spec.json
合到主仓库(手动)
没有自动 PR 流程。建议:
- cp -r units/*/code/ /services/
- 整理目录结构、合并 package.json
- 跑 lint / 格式化(DevLoop 不强制风格)
- 自己开 PR
License
继承 LemonBoss 主仓库。
## ⑤ 沙箱代码的保留期
shipped 项目的 `units/` 默认**永久保留**,因为:
- 占用极小(中项目 ~30MB 含日志)
- 反推决策需要原始代码 + coder.log
- memory 系统会引用具体 Unit 实现做风格参考
清理策略(写在 `project.json`):
| 字段 | 默认 | 含义 |
| --- | --- | --- |
| `compressOldRuns` | false | 14 天前的 runs/*/stdout.txt 自动 gzip |
| `keepCodeMonths` | 12 | shipped 12 个月后归档 code/ 到 history/archived-units/ |
| `autoExportOnShip` | false | shipped 时自动生成 export.zip 放项目目录 |
## ⑥ v2 路径 · 自动 PR
v2 会加 `POST .../export-to-github`,参数:
```js
{
"repo": "yibo/lemonboss-services",
"branch": "devloop/p-731042",
"target_path": "services/todo/",
"commit_message": "feat: add TODO API + UI (via DevLoop)",
"open_pr": true,
"github_token": "${secret}"
}
逻辑:调 gh CLI / @octokit/rest 创建 branch + 提交 + 开 PR。v1 不做。
⑦ 跨项目共享 utils
常见担忧:5 个项目都写一遍 JWT 中间件,沙箱内重复实现。v1 接受这个浪费;v2 视情况引入 data/companies/{cid}/shared/,约定:
- Architect 检测多 Unit 共享 util 时,建议拆
shared-*Unit - shared Unit 的 contract.json 跨项目稳定
- Coder 读 shared 时只读 contract,不复制实现
v1 简化:每个项目重复实现 utils。memory 系统会记"这次写了 JWT mw, 下次可以照样",但不会自动拆 shared。
⑧ 关联
- data-layout · units/ 在文件系统里的位置
- plan-migration · 各 Phase 何时开始关心代码归宿
- 复现指南 · 外部 Claude Code 怎么从沙箱代码 + docs 复现整套