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 流程。建议:

  1. cp -r units/*/code/ /services/
  2. 整理目录结构、合并 package.json
  3. 跑 lint / 格式化(DevLoop 不强制风格)
  4. 自己开 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 复现整套