fix: 统一项目过程仓库命名 repos/{项目名}_pc(修复与 project-directory-spec 的路径错位)

- 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 驳回
This commit is contained in:
ymq 2026-08-21 23:35:57 +08:00
parent 78b84c710e
commit 3c34eedb04
2 changed files with 39 additions and 18 deletions

View File

@ -39,7 +39,8 @@ ROLE_ALIASES = {
TASK_REVIEW = 'review' TASK_REVIEW = 'review'
TASK_APPROVED = 'approved' TASK_APPROVED = 'approved'
# 项目过程仓库名(repos/ 下):阶段文档、QC 审计文档、项目管理文档放这里;应用仓库/模块仓库各自独立 # 项目过程仓库名(repos/ 下):阶段文档、QC 审计文档、项目管理文档放这里;应用仓库/模块仓库各自独立。
# 实际仓库名 = {项目名}_pc(见 project-directory-spec 规范),此常量仅为查不到项目名时的回退默认值。
PROJECT_REPO_NAME = 'project' PROJECT_REPO_NAME = 'project'
# 允许的 shell 工作目录前缀(安全限制) # 允许的 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 [])] '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审计/项目管理文档放这里)。 """确保项目过程仓库存在并 git init(阶段文档/QC审计/项目管理文档放这里)。
仓库名 = {项目名}_pc(见 project-directory-spec 规范),查不到项目名时回退 PROJECT_REPO_NAME。
幂等:已存在则跳过。项目过程仓库是本地仓库,无远程,只 commit 不 push。""" 幂等:已存在则跳过。项目过程仓库是本地仓库,无远程,只 commit 不 push。"""
repos_dir = os.path.join(workspace_dir, 'repos') repos_dir = os.path.join(workspace_dir, 'repos')
os.makedirs(repos_dir, exist_ok=True) 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) os.makedirs(repo_dir, exist_ok=True)
if os.path.isdir(os.path.join(repo_dir, '.git')): if os.path.isdir(os.path.join(repo_dir, '.git')):
return {'rc': 0, 'message': '项目过程仓库已存在'} return {'rc': 0, 'message': '项目过程仓库已存在'}
@ -656,7 +673,7 @@ async def _ensure_project_repo(workspace_dir):
async def _commit_repos_after_approve(workspace_dir, title=''): async def _commit_repos_after_approve(workspace_dir, title=''):
"""审核通过后统一提交:项目过程仓库 repos/project/(阶段/QC/PM 文档)+ repos/ 下应用/模块仓库(代码)。 """审核通过后统一提交:项目过程仓库 repos/{项目名}_pc/(阶段/QC/PM 文档)+ repos/ 下应用/模块仓库(代码)。
不在 agent 每次产出时提交,减少 git 并发锁与远端 push 频率。""" 不在 agent 每次产出时提交,减少 git 并发锁与远端 push 频率。"""
msg = f"approve: {title[:80]}" if title else "approve: 审核通过" msg = f"approve: {title[:80]}" if title else "approve: 审核通过"
repos_dir = os.path.join(workspace_dir, 'repos') 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): async def _setup_repos(sor, workspace_dir, project_id):
"""PM:clone 所有项目关联仓库到 workspace/repos/。""" """PM:clone 所有项目关联仓库到 workspace/repos/。"""
# 先确保项目过程仓库存在(阶段文档/QC审计/PM文档放这里) # 先确保项目过程仓库存在(阶段文档/QC审计/PM文档放这里),仓库名 = {项目名}_pc
await _ensure_project_repo(workspace_dir) 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) repos = await _get_project_repos(sor, project_id)
results = [] results = []
repos_dir = os.path.join(workspace_dir, 'repos') 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 目录层,优先级 角色>项目>产线>组织>通用) # 注入角色技能(角色专属技能全量 + 其余 scope 目录层,优先级 角色>项目>产线>组织>通用)
role_skills = await _build_role_skills_block(sor, project_id, role, org_id) 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 system = (AGENT_SYSTEM_PROMPT
.replace('__ROLE__', role) .replace('__ROLE__', role)
.replace('__TITLE__', title) .replace('__TITLE__', title)
.replace('__QNA__', qna_section) .replace('__QNA__', qna_section)
.replace('__WORKSPACE__', workspace_dir) .replace('__WORKSPACE__', workspace_dir)
.replace('__PROJECT_NAME__', project_name)
.replace('__ROLE_SPECIFIC__', role_specific) .replace('__ROLE_SPECIFIC__', role_specific)
.replace('__ROLE_SKILLS__', role_skills) .replace('__ROLE_SKILLS__', role_skills)
.replace('__TOOLS__', tools_text)) .replace('__TOOLS__', tools_text))

View File

@ -269,7 +269,7 @@ SDL_ROLES = [
aliases=["requirements", "requirement_analysis"], aliases=["requirements", "requirement_analysis"],
system_prompt="""你是需求分析师。按 SDLC 仓库标准产出文档。 system_prompt="""你是需求分析师。按 SDLC 仓库标准产出文档。
产出路径(项目过程仓库 repos/project/ 下): 产出路径(项目过程仓库 repos/__PROJECT_NAME___pc/ 下):
- docs/00-requirement/requirement-spec.md - docs/00-requirement/requirement-spec.md
- apps/<应用名>.md(应用 = 部署单元,至少一个,含端口/环境) - apps/<应用名>.md(应用 = 部署单元,至少一个,含端口/环境)
内容: 项目概述、用户角色及权限、功能列表(每个功能:输入/处理/输出/验收标准)、非功能需求、业务流程。 内容: 项目概述、用户角色及权限、功能列表(每个功能:输入/处理/输出/验收标准)、非功能需求、业务流程。
@ -287,11 +287,11 @@ SDL_ROLES = [
aliases=["designer", "ui", "ux"], aliases=["designer", "ui", "ux"],
system_prompt="""你是系统设计师。按 SDLC 仓库标准产出文档(结构参考 sdlc-repo-standard 技能;模块设计用 templates/module-design.md 模板,模块技能用 templates/module-skill.md 模板,保证 develop 读到一致结构)。 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: 系统架构、技术选型理由、模块划分、模块间依赖关系、开发顺序 - architecture.md: 系统架构、技术选型理由、模块划分、模块间依赖关系、开发顺序
- ui-design.md: 视觉风格(配色/字体/间距)、主页面布局、用户交互模式、弹窗/表单规范 - ui-design.md: 视觉风格(配色/字体/间距)、主页面布局、用户交互模式、弹窗/表单规范
模块级设计(每个模块自包含、可复用,产出到 repos/project/modules/): 模块级设计(每个模块自包含、可复用,产出到 repos/__PROJECT_NAME___pc/modules/):
- modules/<模块名>.md: 模块功能、仓库目录(本地 git 仓库 repos/<模块名>,无真实远端)、技术栈、依赖、开发顺序 - modules/<模块名>.md: 模块功能、仓库目录(本地 git 仓库 repos/<模块名>,无真实远端)、技术栈、依赖、开发顺序
- modules/<模块名>/design.md: 该模块的数据设计(表结构DDL) + CRUD 定义 + 处理逻辑(接口) - modules/<模块名>/design.md: 该模块的数据设计(表结构DDL) + CRUD 定义 + 处理逻辑(接口)
- modules/<模块名>/skill/SKILL.md: 该模块技能文档 - modules/<模块名>/skill/SKILL.md: 该模块技能文档
@ -310,15 +310,15 @@ SDL_ROLES = [
基础模块复用(必读): apppublic、sqlor、ahserver、accounting、appbase、rbac 等基础模块已存在、可直接引用,**不必再开发**——需要权限走 rbac、需要数据访问走 sqlor、需要 HTTP 框架走 ahserver、需要配置走 appbase、需要工具函数走 apppublic。 基础模块复用(必读): apppublic、sqlor、ahserver、accounting、appbase、rbac 等基础模块已存在、可直接引用,**不必再开发**——需要权限走 rbac、需要数据访问走 sqlor、需要 HTTP 框架走 ahserver、需要配置走 appbase、需要工具函数走 apppublic。
准备工作: 准备工作:
1. read_file 读 repos/project/docs/01-design/ 下架构与 UI 设计文档 1. read_file 读 repos/__PROJECT_NAME___pc/docs/01-design/ 下架构与 UI 设计文档
2. read_file 读 repos/project/modules/<模块名>.md 获取模块仓库 URL,读 repos/project/modules/<模块名>/design.md 获取数据设计/CRUD/处理逻辑 2. read_file 读 repos/__PROJECT_NAME___pc/modules/<模块名>.md 获取模块仓库 URL,读 repos/__PROJECT_NAME___pc/modules/<模块名>/design.md 获取数据设计/CRUD/处理逻辑
3. 模块仓库是本地 git 仓库 repos/<模块名>/(设计里的仓库URL是规划占位地址、无真实远端,不要 git_clone) 3. 模块仓库是本地 git 仓库 repos/<模块名>/(设计里的仓库URL是规划占位地址、无真实远端,不要 git_clone)
开发流程: 开发流程:
4. write_file 写代码到模块仓库目录 4. write_file 写代码到模块仓库目录
5. run_shell 编译/运行验证 5. run_shell 编译/运行验证
6. git_commit_push 提交模块仓库代码(本地提交,无远程只 commit 不 push,非 git 目录自动 init;这是 QC 核验「实际产出」的硬证据,务必执行) 6. git_commit_push 提交模块仓库代码(本地提交,无远程只 commit 不 push,非 git 目录自动 init;这是 QC 核验「实际产出」的硬证据,务必执行)
7. write_file 更新 repos/project/modules/<模块名>.md 状态为已完成 7. write_file 更新 repos/__PROJECT_NAME___pc/modules/<模块名>.md 状态为已完成
8. write_file 写 repos/project/docs/02-develop/dev-notes.md 记录开发内容 8. write_file 写 repos/__PROJECT_NAME___pc/docs/02-develop/dev-notes.md 记录开发内容
9. deliver 交付,files 列出所有产出文件路径 9. deliver 交付,files 列出所有产出文件路径
PM审核: list_files/read_file 检查代码文件实际产出 + 模块仓库本地 git log 有提交。""", PM审核: list_files/read_file 检查代码文件实际产出 + 模块仓库本地 git log 有提交。""",
next_role="agent.deploy_test", next_role="agent.deploy_test",
@ -329,11 +329,11 @@ PM审核: list_files/read_file 检查代码文件实际产出 + 模块仓库本
aliases=["deploy_staging", "staging"], aliases=["deploy_staging", "staging"],
system_prompt="""你是测试环境部署工程师。把开发完成的代码部署到测试环境,供测试工程师验证。 system_prompt="""你是测试环境部署工程师。把开发完成的代码部署到测试环境,供测试工程师验证。
产出路径(项目过程仓库 repos/project/ 下): 产出路径(项目过程仓库 repos/__PROJECT_NAME___pc/ 下):
- config/test/ 下: 测试环境 Dockerfile、docker-compose.yml、nginx 配置、部署脚本 - config/test/ 下: 测试环境 Dockerfile、docker-compose.yml、nginx 配置、部署脚本
- docs/04-deploy/deploy-test-env.md: 测试环境部署步骤、环境配置、访问地址 - 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. 准备测试环境部署配置(容器/依赖服务/端口/环境变量) 2. 准备测试环境部署配置(容器/依赖服务/端口/环境变量)
3. 部署到测试环境,run_shell 验证服务可访问 3. 部署到测试环境,run_shell 验证服务可访问
4. 产出部署文档,deliver 交付,files 列出配置文件路径(git 提交由 PM 审核通过后系统统一执行) 4. 产出部署文档,deliver 交付,files 列出配置文件路径(git 提交由 PM 审核通过后系统统一执行)
@ -346,7 +346,7 @@ PM审核: 检查测试环境部署配置完整、服务可访问。""",
aliases=["testing", "qa", "tester"], aliases=["testing", "qa", "tester"],
system_prompt="""你是测试工程师。在测试环境上执行测试,按 SDLC 仓库标准产出文档。 system_prompt="""你是测试工程师。在测试环境上执行测试,按 SDLC 仓库标准产出文档。
产出路径(项目过程仓库 repos/project/docs/03-test/): 产出路径(项目过程仓库 repos/__PROJECT_NAME___pc/docs/03-test/):
- test-plan.md: 测试策略(单元/集成/端到端) - test-plan.md: 测试策略(单元/集成/端到端)
- test-cases.md: 用例清单(编号/前置条件/步骤/预期结果) - test-cases.md: 用例清单(编号/前置条件/步骤/预期结果)
- test-report.md: 执行结果、Bug清单、覆盖率 - test-report.md: 执行结果、Bug清单、覆盖率
@ -359,12 +359,12 @@ PM审核: 检查测试环境部署配置完整、服务可访问。""",
aliases=["deploy_production", "production", "release"], aliases=["deploy_production", "production", "release"],
system_prompt="""你是生产环境部署工程师。测试通过后,把代码部署到生产环境。 system_prompt="""你是生产环境部署工程师。测试通过后,把代码部署到生产环境。
产出路径(项目过程仓库 repos/project/ 下): 产出路径(项目过程仓库 repos/__PROJECT_NAME___pc/ 下):
- config/prod/ 下: 生产环境 Dockerfile、docker-compose.yml、nginx 配置 - config/prod/ 下: 生产环境 Dockerfile、docker-compose.yml、nginx 配置
- docs/04-deploy/deploy-prod-env.md: 生产部署步骤、回滚方案 - docs/04-deploy/deploy-prod-env.md: 生产部署步骤、回滚方案
- docs/04-deploy/release-notes.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. 准备生产配置(高可用、备份、监控告警、域名证书) 2. 准备生产配置(高可用、备份、监控告警、域名证书)
3. 部署到生产环境,验证服务可用 3. 部署到生产环境,验证服务可用
4. 产出部署文档 + 发布说明,deliver 交付,files 列出配置文件(git 提交由 PM 审核通过后系统统一执行) 4. 产出部署文档 + 发布说明,deliver 交付,files 列出配置文件(git 提交由 PM 审核通过后系统统一执行)