From 3c34eedb04981fc355d517a6f9b89a3bb5e0e8a4 Mon Sep 17 00:00:00 2001 From: ymq Date: Fri, 21 Aug 2026 23:35:57 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=BB=9F=E4=B8=80=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E8=BF=87=E7=A8=8B=E4=BB=93=E5=BA=93=E5=91=BD=E5=90=8D=20repos/?= =?UTF-8?q?{=E9=A1=B9=E7=9B=AE=E5=90=8D}=5Fpc=EF=BC=88=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E4=B8=8E=20project-directory-spec=20=E7=9A=84=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E9=94=99=E4=BD=8D=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PROJECT_REPO_NAME 保留为回退默认值,_ensure_project_repo 改为按 {项目名}_pc 命名 - _setup_repos/role_agent_run 查项目名并注入 __PROJECT_NAME__ 占位符 - SDL_ROLES 6 个角色 prompt 的 repos/project/ 全部改为 repos/__PROJECT_NAME___pc/ - 根因:角色 prompt 硬编码旧名 repos/project,与 project-directory-spec(权威规范) 要求 {项目名}_pc 不一致,导致首次产出必被 QC 驳回 --- pipeline_service/agent_loop.py | 33 ++++++++++++++++++++++++++------ pipeline_service/sdlc_ability.py | 24 +++++++++++------------ 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/pipeline_service/agent_loop.py b/pipeline_service/agent_loop.py index 06e185e..dff7dbf 100644 --- a/pipeline_service/agent_loop.py +++ b/pipeline_service/agent_loop.py @@ -39,7 +39,8 @@ ROLE_ALIASES = { TASK_REVIEW = 'review' TASK_APPROVED = 'approved' -# 项目过程仓库名(repos/ 下):阶段文档、QC 审计文档、项目管理文档放这里;应用仓库/模块仓库各自独立 +# 项目过程仓库名(repos/ 下):阶段文档、QC 审计文档、项目管理文档放这里;应用仓库/模块仓库各自独立。 +# 实际仓库名 = {项目名}_pc(见 project-directory-spec 规范),此常量仅为查不到项目名时的回退默认值。 PROJECT_REPO_NAME = 'project' # 允许的 shell 工作目录前缀(安全限制) @@ -627,12 +628,28 @@ async def _get_project_repos(sor, project_id): 'local_path': getattr(r, 'local_path', '') or ''} for r in (recs or [])] -async def _ensure_project_repo(workspace_dir): +async def _get_project_name(sor, project_id): + """查项目名(用于命名项目过程仓库 {项目名}_pc)。查不到返回空串。""" + try: + r = await sor.sqlExe( + "SELECT name FROM sd_projects WHERE id=${pid}$ LIMIT 1", + {"pid": project_id}) + await sor.sqlExe("COMMIT", {}) + if r: + return getattr(r[0], 'name', '') or '' + except Exception: + pass + return '' + + +async def _ensure_project_repo(workspace_dir, project_name=''): """确保项目过程仓库存在并 git init(阶段文档/QC审计/项目管理文档放这里)。 + 仓库名 = {项目名}_pc(见 project-directory-spec 规范),查不到项目名时回退 PROJECT_REPO_NAME。 幂等:已存在则跳过。项目过程仓库是本地仓库,无远程,只 commit 不 push。""" repos_dir = os.path.join(workspace_dir, 'repos') os.makedirs(repos_dir, exist_ok=True) - repo_dir = os.path.join(repos_dir, PROJECT_REPO_NAME) + repo_name = f"{project_name}_pc" if project_name else PROJECT_REPO_NAME + repo_dir = os.path.join(repos_dir, repo_name) os.makedirs(repo_dir, exist_ok=True) if os.path.isdir(os.path.join(repo_dir, '.git')): return {'rc': 0, 'message': '项目过程仓库已存在'} @@ -656,7 +673,7 @@ async def _ensure_project_repo(workspace_dir): async def _commit_repos_after_approve(workspace_dir, title=''): - """审核通过后统一提交:项目过程仓库 repos/project/(阶段/QC/PM 文档)+ repos/ 下应用/模块仓库(代码)。 + """审核通过后统一提交:项目过程仓库 repos/{项目名}_pc/(阶段/QC/PM 文档)+ repos/ 下应用/模块仓库(代码)。 不在 agent 每次产出时提交,减少 git 并发锁与远端 push 频率。""" msg = f"approve: {title[:80]}" if title else "approve: 审核通过" repos_dir = os.path.join(workspace_dir, 'repos') @@ -673,8 +690,9 @@ async def _commit_repos_after_approve(workspace_dir, title=''): async def _setup_repos(sor, workspace_dir, project_id): """PM:clone 所有项目关联仓库到 workspace/repos/。""" - # 先确保项目过程仓库存在(阶段文档/QC审计/PM文档放这里) - await _ensure_project_repo(workspace_dir) + # 先确保项目过程仓库存在(阶段文档/QC审计/PM文档放这里),仓库名 = {项目名}_pc + project_name = await _get_project_name(sor, project_id) + await _ensure_project_repo(workspace_dir, project_name) repos = await _get_project_repos(sor, project_id) results = [] repos_dir = os.path.join(workspace_dir, 'repos') @@ -1107,12 +1125,15 @@ async def role_agent_run(project_id, role, agent_id=None, model_name=None): # 注入角色技能(角色专属技能全量 + 其余 scope 目录层,优先级 角色>项目>产线>组织>通用) role_skills = await _build_role_skills_block(sor, project_id, role, org_id) + # 项目名(用于 prompt 里 {项目名}_pc 占位符替换,角色产出路径以 project-directory-spec 为准) + project_name = await _get_project_name(sor, project_id) system = (AGENT_SYSTEM_PROMPT .replace('__ROLE__', role) .replace('__TITLE__', title) .replace('__QNA__', qna_section) .replace('__WORKSPACE__', workspace_dir) + .replace('__PROJECT_NAME__', project_name) .replace('__ROLE_SPECIFIC__', role_specific) .replace('__ROLE_SKILLS__', role_skills) .replace('__TOOLS__', tools_text)) diff --git a/pipeline_service/sdlc_ability.py b/pipeline_service/sdlc_ability.py index 8eebc8a..bc2cab3 100644 --- a/pipeline_service/sdlc_ability.py +++ b/pipeline_service/sdlc_ability.py @@ -269,7 +269,7 @@ SDL_ROLES = [ aliases=["requirements", "requirement_analysis"], system_prompt="""你是需求分析师。按 SDLC 仓库标准产出文档。 -产出路径(项目过程仓库 repos/project/ 下): +产出路径(项目过程仓库 repos/__PROJECT_NAME___pc/ 下): - docs/00-requirement/requirement-spec.md - apps/<应用名>.md(应用 = 部署单元,至少一个,含端口/环境) 内容: 项目概述、用户角色及权限、功能列表(每个功能:输入/处理/输出/验收标准)、非功能需求、业务流程。 @@ -287,11 +287,11 @@ SDL_ROLES = [ aliases=["designer", "ui", "ux"], system_prompt="""你是系统设计师。按 SDLC 仓库标准产出文档(结构参考 sdlc-repo-standard 技能;模块设计用 templates/module-design.md 模板,模块技能用 templates/module-skill.md 模板,保证 develop 读到一致结构)。 -应用级设计(产出到项目过程仓库 repos/project/docs/01-design/): +应用级设计(产出到项目过程仓库 repos/__PROJECT_NAME___pc/docs/01-design/): - architecture.md: 系统架构、技术选型理由、模块划分、模块间依赖关系、开发顺序 - ui-design.md: 视觉风格(配色/字体/间距)、主页面布局、用户交互模式、弹窗/表单规范 -模块级设计(每个模块自包含、可复用,产出到 repos/project/modules/): +模块级设计(每个模块自包含、可复用,产出到 repos/__PROJECT_NAME___pc/modules/): - modules/<模块名>.md: 模块功能、仓库目录(本地 git 仓库 repos/<模块名>,无真实远端)、技术栈、依赖、开发顺序 - modules/<模块名>/design.md: 该模块的数据设计(表结构DDL) + CRUD 定义 + 处理逻辑(接口) - modules/<模块名>/skill/SKILL.md: 该模块技能文档 @@ -310,15 +310,15 @@ SDL_ROLES = [ 基础模块复用(必读): apppublic、sqlor、ahserver、accounting、appbase、rbac 等基础模块已存在、可直接引用,**不必再开发**——需要权限走 rbac、需要数据访问走 sqlor、需要 HTTP 框架走 ahserver、需要配置走 appbase、需要工具函数走 apppublic。 准备工作: - 1. read_file 读 repos/project/docs/01-design/ 下架构与 UI 设计文档 - 2. read_file 读 repos/project/modules/<模块名>.md 获取模块仓库 URL,读 repos/project/modules/<模块名>/design.md 获取数据设计/CRUD/处理逻辑 + 1. read_file 读 repos/__PROJECT_NAME___pc/docs/01-design/ 下架构与 UI 设计文档 + 2. read_file 读 repos/__PROJECT_NAME___pc/modules/<模块名>.md 获取模块仓库 URL,读 repos/__PROJECT_NAME___pc/modules/<模块名>/design.md 获取数据设计/CRUD/处理逻辑 3. 模块仓库是本地 git 仓库 repos/<模块名>/(设计里的仓库URL是规划占位地址、无真实远端,不要 git_clone) 开发流程: 4. write_file 写代码到模块仓库目录 5. run_shell 编译/运行验证 6. git_commit_push 提交模块仓库代码(本地提交,无远程只 commit 不 push,非 git 目录自动 init;这是 QC 核验「实际产出」的硬证据,务必执行) - 7. write_file 更新 repos/project/modules/<模块名>.md 状态为已完成 - 8. write_file 写 repos/project/docs/02-develop/dev-notes.md 记录开发内容 + 7. write_file 更新 repos/__PROJECT_NAME___pc/modules/<模块名>.md 状态为已完成 + 8. write_file 写 repos/__PROJECT_NAME___pc/docs/02-develop/dev-notes.md 记录开发内容 9. deliver 交付,files 列出所有产出文件路径 PM审核: list_files/read_file 检查代码文件实际产出 + 模块仓库本地 git log 有提交。""", next_role="agent.deploy_test", @@ -329,11 +329,11 @@ PM审核: list_files/read_file 检查代码文件实际产出 + 模块仓库本 aliases=["deploy_staging", "staging"], system_prompt="""你是测试环境部署工程师。把开发完成的代码部署到测试环境,供测试工程师验证。 -产出路径(项目过程仓库 repos/project/ 下): +产出路径(项目过程仓库 repos/__PROJECT_NAME___pc/ 下): - config/test/ 下: 测试环境 Dockerfile、docker-compose.yml、nginx 配置、部署脚本 - docs/04-deploy/deploy-test-env.md: 测试环境部署步骤、环境配置、访问地址 流程: - 1. read_file 读 repos/project/docs/00-requirement/ 的部署环境需求 + repos/project/docs/01-design/ 的设计 + 1. read_file 读 repos/__PROJECT_NAME___pc/docs/00-requirement/ 的部署环境需求 + repos/__PROJECT_NAME___pc/docs/01-design/ 的设计 2. 准备测试环境部署配置(容器/依赖服务/端口/环境变量) 3. 部署到测试环境,run_shell 验证服务可访问 4. 产出部署文档,deliver 交付,files 列出配置文件路径(git 提交由 PM 审核通过后系统统一执行) @@ -346,7 +346,7 @@ PM审核: 检查测试环境部署配置完整、服务可访问。""", aliases=["testing", "qa", "tester"], system_prompt="""你是测试工程师。在测试环境上执行测试,按 SDLC 仓库标准产出文档。 -产出路径(项目过程仓库 repos/project/docs/03-test/): +产出路径(项目过程仓库 repos/__PROJECT_NAME___pc/docs/03-test/): - test-plan.md: 测试策略(单元/集成/端到端) - test-cases.md: 用例清单(编号/前置条件/步骤/预期结果) - test-report.md: 执行结果、Bug清单、覆盖率 @@ -359,12 +359,12 @@ PM审核: 检查测试环境部署配置完整、服务可访问。""", aliases=["deploy_production", "production", "release"], system_prompt="""你是生产环境部署工程师。测试通过后,把代码部署到生产环境。 -产出路径(项目过程仓库 repos/project/ 下): +产出路径(项目过程仓库 repos/__PROJECT_NAME___pc/ 下): - config/prod/ 下: 生产环境 Dockerfile、docker-compose.yml、nginx 配置 - docs/04-deploy/deploy-prod-env.md: 生产部署步骤、回滚方案 - docs/04-deploy/release-notes.md: 发布说明 流程: - 1. 确认测试验证通过(read_file 读 repos/project/docs/03-test/test-report.md) + 1. 确认测试验证通过(read_file 读 repos/__PROJECT_NAME___pc/docs/03-test/test-report.md) 2. 准备生产配置(高可用、备份、监控告警、域名证书) 3. 部署到生产环境,验证服务可用 4. 产出部署文档 + 发布说明,deliver 交付,files 列出配置文件(git 提交由 PM 审核通过后系统统一执行)