229 Commits

Author SHA1 Message Date
ymq
5ffbf94b72 feat: 生产部署需人工指令——test 通过后不自动派发 deploy_prod
test 的 next_role 从 agent.deploy_prod 改为空,test 通过后流程即止,
生产部署(deploy_prod)不再自动执行,由用户明确指令触发派发。
2026-08-22 20:14:32 +08:00
ymq
69a0b50f76 refactor: SDL_ROLES 各角色 system_prompt 精简为角色定位+引导加载技能
不再写死职责/流程/产出路径/审核方式/部署方案(这些都在角色技能 role/SKILL.md
和规范技能里,通过技能目录注入+load_skill 加载)。system_prompt 只保留:
'你是XX工程师。先 load_skill 加载 role 技能,按其中的职责与应遵守规范执行任务。'
同时删除了 deploy_test/deploy_prod 写死的 Dockerfile/docker-compose 错误部署方案。
2026-08-22 18:51:57 +08:00
ymq
145024506b revert: 回退 develop system_prompt 的「应用级/模块级任务」规范
规范不应写在 system_prompt(SDL_ROLES),应只写在角色技能 agent.develop/role/SKILL.md
(已含应用级/模块级职责区分)。回退 system_prompt 到原样。
2026-08-22 18:42:06 +08:00
ymq
84b2e83213 fix: 切迭代时自动关闭旧迭代 pending 问题(status=answered)
_cancel_active_tasks 作废任务时,一并把该迭代的 pending 问题置 answered(随迭代作废)。
否则旧迭代问题持续 pending 冒泡、阻塞诊断视图,需手动 SQL 清理。
2026-08-22 18:38:56 +08:00
ymq
a9145ee3a4 feat: develop 角色区分应用级/模块级两类任务——应用级产出应用脚手架
应用级任务(标题含应用架构/应用脚手架)产出 repos/{应用名}_app:app/{应用名}.py
(唯一入口+get_module_dbname挂ServerEnv+load模块)、conf/config.json、build.sh。
模块级任务产出 Python 包(无独立 app.py,取库名用 ServerEnv().get_module_dbname())。
修复应用脚手架无人产出、导致应用级 deploy_test 部署失败(找不到 app.py)的缺口。
2026-08-22 18:35:22 +08:00
ymq
ec0a0936d3 fix: 部署以应用为单位——模块级 develop(PM派发)approved 后不创建 deploy_test
模块级 develop(params 含 pm_assigned)是 PM 按模块派发的开发任务,模块不独立部署,
approved 后不应创建模块级 deploy_test(否则每个模块一个 deploy_test = 部署以模块为单位,
即多端口问题的部署侧根源)。deploy_test 是应用级,只由应用脚手架 develop 触发。
2026-08-22 18:21:08 +08:00
ymq
191d28547b fix: paused 生命周期三处修复——切迭代自动 resume + 三 poller 统一排除 paused
1. start_next_iteration 启动新迭代后自动 resume_project:旧迭代遗留的 paused
   (任务达上限触发 failed_poller 自动 pause)随任务作废消除,新迭代恢复 active,
   否则 PM poller 跳过 review 任务导致新迭代卡在 PM 审核(2026-08 实测卡 27 分钟)
2. agent poller / qc poller 也排除 paused 项目,与 PM poller 语义统一:
   paused = 完全暂停推进(不派发/不审查/不审核),消除「任务照常派发却卡审核」半吊子状态
2026-08-22 17:39:13 +08:00
ymq
ea6df9c7c6 fix: configure_env 按 (project_id, env_type) upsert + sudo_enabled 归一化 VARCHAR(1)
- 修复反复 INSERT Duplicate entry(1062):先查 (project_id, env_type) 已存在则 UPDATE
- 修复 DataError(1406):'false' 字符串超长,归一化为 'Y'/'N' 单字符
2026-08-22 11:48:47 +08:00
ymq
0af4faff21 feat: LLM 机构隔离——机构没配 llm 时角色/PM/QC 冒泡问题暂停
- _check_org_llm 检测机构 llm 配置(严格本机构隔离,不含系统级兜底)
- role_agent_run/pm_review_run/qc_review_run 在 LLM 调用前检测,机构没配 llm
  则 raise_problem(need_info) 冒泡问题暂停,等机构配置模型后恢复
2026-08-22 11:36:27 +08:00
ymq
2eb70a3480 feat: 模型配置菜单入口(⚙️ 模型配置 → sd_project_role_models/index.ui) 2026-08-22 11:18:14 +08:00
ymq
14dca0cc43 feat: 项目-角色-模型配置 + 角色agent模型解析链
- sd_projects 加 default_model 字段(项目缺省模型=创建时的会话模型)
- _t_create_project 记录 created_by + default_model
- _resolve_llm_context 解析链:显式→项目-角色-模型(sd_project_role_models)
  →项目缺省模型(default_model)→RoleSpec→pipelines.default_model→deepseek-v4-pro
- 新增工具 list_role_models / set_role_model(项目设置界面后端)
2026-08-22 10:19:50 +08:00
ymq
c50a5b9914 fix: load_skill 工具归一化 role(裸名 qc/pm → agent.qc/agent.pm)
根因:qc_review_run/pm_review_run 调用 _load_skill_by_name 传裸名 'qc'/'pm',
get_merged(role='qc') 加载不到 roles/agent.qc/ 目录,导致 QC 审查 design 时
load_skill(review-design) 失败 → 退回 3 次达上限 → 任务 waiting → 项目 paused。

修复:_load_skill_by_name 内部 _normalize_role(role),覆盖所有调用点。
2026-08-22 08:16:28 +08:00
ymq
be1fd06ef7 feat: 补充细分能力工具的 schema(reopen_feature/start_fix/fix_bug/verify_bug/close_bug) 2026-08-22 01:31:54 +08:00
ymq
6e82493c20 feat: 能力工具按 capability 动态注入(根治纸面落库)
- 新增 capability_tools.py:TOOL_SCHEMAS 工具 schema + 从产线状态机规范 frontmatter
  读取 capability→tools 映射(可配置)+ exec_capability_tool 分发
- agent_loop 加 _collect_capability_tools:角色技能(scope=role)声明 capability,
  匹配产线状态机规范(scope=pipeline)的 tools 声明,注入对应能力工具
- role_agent_run 注入能力工具(AGENT_TOOLS+capability_tools) + capability_ctx
  (project_id/iteration_id/who/agent_id 自动注入,LLM 不可见)
- _exec_agent_tool 分发能力工具到对应 capability 函数
- 根治:requirement 无法 propose_feature、test 无法 create_case/report_bug
  只能写文档假装落库(sd_features 表=0)的问题
2026-08-22 01:19:27 +08:00
ymq
b31cb6c816 fix: pm/qc 角色技能加载归一化 role(agent.pm/agent.qc)
pm_review_run/qc_review_run 传裸名 'pm'/'qc' 给 _build_role_skills_block,
get_merged 按 role_key 精确匹配目录,裸名匹配不上 agent.pm/agent.qc 目录,
导致 pm/qc 角色技能永远不注入。改为 _normalize_role('pm'/'qc')。
2026-08-22 00:12:41 +08:00
ymq
8eedff7af9 feat(sdlc): approve_task/complete_task 对齐 PM 行为推进任务链
- approve_task: 解决 pending review_reject + git 提交 + _get_next_role→迭代边界→_create_next_task 推进链
- complete_task: 同步交付件 review_status 标记 approved,避免任务 completed 但交付件仍 pending 不一致
- 会话 agent 手动 approve 不再断链(下一角色任务照常自动创建)
2026-08-21 23:39:15 +08:00
ymq
3c34eedb04 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 驳回
2026-08-21 23:35:57 +08:00
ymq
78b84c710e feat(sdlc): 会话agent加任务流转工具 approve_task/complete_task/cancel_task(PM权限)
- task_capability 新增 cancel_task 原语(CAS+审计+终态守护)
- sdlc_ability 加 3 个 ToolDefinition + handler,who=agent.pm 记录 PM 权限操作
- _resolve_task_id 租户隔离前缀兜底
- SDL_PROMPT 补任务流转典型场景
- _pm_cancel_task 委托新原语,去掉重复 SQL
2026-08-21 22:43:11 +08:00
ymq
6dbb574862 refactor(sdlc): 技能 base_dir 改全局 skills/(单一技能树,去掉机构副本路径)
- agent_loop: _build_role_skills_block/_load_skill_by_name 改 get_skills_base()
- agent_loop_v2: _resolve_skills_base_dir 改返回 get_skills_base()
2026-08-21 19:18:51 +08:00
ymq
6b4acaff13 fix(sdlc): 目录层 essential 基础规范优先排序——project-directory-spec 等 essential 技能排最前,不被 60 个截断 2026-08-21 18:41:15 +08:00
ymq
71d30e6d45 feat(sdlc): 技能分层导入统一——所有角色技能只注目录层 + load_skill 按需加载全文/子文件(含 PM/QC),对齐 Hermes 分层机制
- _build_role_skills_block: 删除 role scope 全量注入正文特例,所有技能统一目录层
- 新增 _load_skill_by_name: load_skill 工具后端,支持 name 加载全文 + file_path 加载 references/scripts/templates 子文件
- AGENT_TOOLS/PM_SYSTEM_PROMPT/QC_SYSTEM_PROMPT: 加 load_skill 工具 + 技能使用引导
- role/pm/qc 三个 run 的 tool-loop 加 load_skill 拦截
- QC 检查维度改为先 load_skill 加载 project-directory-spec 再检查路径
2026-08-21 18:36:18 +08:00
ymq
f17f745ac6 fix(sdlc): pm_poller 队列饥饿——paused 项目僵尸 review 任务卡队头饿死 active 项目
根因:pm_poller SELECT state='review' AND claimed_by IS NULL ORDER BY created_at ASC LIMIT 5,
只取最老 5 个 review 任务,但暂停门控在 pm_review_run 认领后才检查。paused 项目(人事系统/人事系统1)
的 8 个 develop/deploy_test 僵尸任务永远占住队头,每 15s dispatch 后暂停门控 return idle、claimed_by 恒 NULL,
active 项目(人事项目2)的 requirement/design 任务排在后面对、永远进不了 LIMIT 5 窗口 → PM 无法推进项目。

修复(对齐 agent_poller 队列饥饿修复三件套):
1. SELECT 加 NOT EXISTS paused 项目过滤(暂停门控提前到筛选阶段)
2. LIMIT 5 → 200 容纳僵尸任务
3. 项目轮询 round-robin 保证项目间公平
2026-08-21 13:20:32 +08:00
ymq
9c4f3deea6 feat(sdlc): 判断粒度落到迭代——create_task 迭代级查重 + diagnose_project 迭代级诊断 + prompt 迭代约束
1. _h_create_task:创建 requirement 任务前查「当前迭代」是否已有非 cancelled 的
   requirement 任务(迭代的初始任务),有则拒绝重复创建,避免人事项目2 那种
   需求分析完成后又重复启动需求分析。
2. _h_diagnose_project:诊断单位从「项目」改为「当前迭代」(in_progress),
   按 iteration_id 过滤统计/列出任务,避免多迭代并存时诊断结果混在一起。
3. SDL_PROMPT:加「迭代粒度」约束——每个迭代独立初始任务+任务链,
   创建 requirement 前先查重、诊断/派发/推进都以当前迭代为单位。
2026-08-21 13:04:58 +08:00
ymq
ca0cfc29de feat(sdlc): 迭代级 requirement 任务查重——同一迭代不重复创建需求分析任务 2026-08-21 13:03:17 +08:00
ymq
9f8534bc4e fix(skill): 回退 description 截断缩短,保留优先级顺序+目录60 2026-08-21 12:07:20 +08:00
ymq
3ecb4f755c fix(skill): 角色技能目录 30→60 + 描述精简 + 优先级顺序同步 2026-08-21 12:05:27 +08:00
ymq
8a2d462382 fix: TimeoutError 治理——缩小 read_file 上下文 + 放宽 LLM 外层硬超时给足重试
根因:develop agent 的 LLM 调用(deepseek-v4-pro→qwen3.8-max 经 llmage 网关)在
大上下文多轮累积时偶发挂起/返回 FAILED,llm_bridge 300s×3 重试被外层 420s 硬超时
提前掐断(只够 ~1.4 轮),可自愈的瞬时故障也 TimeoutError 超限暂停任务链。

修复:read_file 30000→12000 缩小上下文;_LLM_HARD_TIMEOUT 420→600 给 llm_bridge
至少 2 轮完整重试机会。
2026-08-21 00:10:38 +08:00
ymq
d97c1442fa fix: 模块仓库本地 git 化——develop git_commit_push 自动 init+本地提交作为产出证据,QC 改查实际文件不再要求远程推送
根因:设计阶段模块仓库URL是规划占位地址(git@code.local),develop 的 git_clone 失败后
代码直接 write_file 到 repos/<模块>/ 但从未 git init,导致模块仓库无 .git;加上上一轮
「审核后统一提交」让 develop 连本地提交都不做,QC 找不到 git 提交证据 → qc_reject 死循环。

修复:_git_commit_push 非 git 目录自动 init;develop 提示词改为本地 git init + git_commit_push
提交模块仓库;QC 提示词改为 list_files/read_file 核验真实文件 + 本地提交,不因无远程推送退回。
2026-08-20 23:44:51 +08:00
ymq
38e47be4db feat: git 提交改为审核通过后统一提交——role agent 不再每次产出提交(移除 auto-commit + 角色提示词 git_commit_push),PM approve 后统一 commit 项目过程仓库+应用/模块仓库,减少并发锁与远端 push 频率 2026-08-20 21:45:07 +08:00
ymq
8bc1b4e571 feat(session): gateway/executor 支持 session_id 多会话隔离
web 多 tab 独立会话:run_message 加 session_id,会话 key 从 channel:user_id
扩展为 channel:user_id:session_id(空则向后兼容单会话);AgentExecutor 历史
加载/保存按 session_id 隔离,空则回退 project 级隔离。
2026-08-20 17:38:18 +08:00
ymq
7b03f37ed3 fix(menus): 产线功能菜单指向真 CRUD 页面而非 xls2crud stub
menus url 原指向 sd_*_list/index.ui(xls2crud 占位页,无数据),改为
sd_projects/sd_bugs/sd_test_cases/sd_iterations(xls2ui 生成的真实 CRUD 页面)。
2026-08-20 15:54:12 +08:00
ymq
ff2179be67 feat(poller): 每项目/租户并发上限 max_agents_per_project,防单项目占满全局并发
agent_poller 项目轮询基础上,新增每项目并发门控:
- 读 appbase params 表 max_agents_per_project(默认 4),改后下一轮(10s)立即生效
- 每轮查各项目 running 计数(GROUP BY tenant_id),达上限的项目跳过不派新任务
- 改小后不强制杀,超出的 running 任务自然跑完即「等其完成」语义
- 与全局 max_concurrent_agents(默认3→预置10) + 项目轮询配套,形成三级并发控制
2026-08-20 15:44:51 +08:00
ymq
7a2175f363 fix(role-agent): LLM 调用加 asyncio.wait_for 硬超时兜底,防挂起无心跳
role_agent_run 的 llm_call_msgs_native 内部 300s×3 重试最坏 15 分钟,
期间心跳不更新(心跳在调用前 touch),观察上像任务挂起/僵尸。
外层 asyncio.wait_for(420s) 硬上限:① 缩短最坏时长到 7 分钟
② 防 aiohttp total 超时因 DNS 等场景失效导致的真正无限挂起。
超时抛异常 → mark_failed → retry+1 → 重新认领,不再无限卡住。
2026-08-20 15:21:14 +08:00
ymq
c848dc1d4c refactor(agent_loop): 删除 v1 硬编码角色定义,统一走能力包
- 删 ROLE_SPECIFICS(角色 prompt 硬编码,已被 sdlc_ability.SDL_ROLES 完整覆盖)
- 删 ROLE_CHAIN(任务链硬编码,已被 RoleSpec.next_role 覆盖)
- _resolve_role/_get_next_role 去掉 fallback,只走 get_role_spec
- 删死代码 PM_PROMPT/_is_safe_workdir/_parse_result(0 引用)
- 保留 ROLE_ALIASES:服务 _normalize_role 的 who 规范化(27 处调用点依赖),
  与能力包角色 prompt 是不同职责
2026-08-20 14:37:14 +08:00
ymq
917eb3eda9 feat(role_agent): role_agent_run import role skills 2026-08-20 12:02:49 +08:00
ymq
77f5aa45dc fix(poller): 依赖门控提前到候选筛选 + 项目轮询,修复队列饥饿
agent_poller 原来 SELECT 后 [:avail] 截断只取队列头 avail 个任务,依赖门控却
在认领阶段(_claim_task)才检查——依赖未满足的僵尸 submitted 任务(created_at 最早)
永久占住队头,导致其他项目/新任务饿死(一项目卡死全平台瘫痪)。

改动:
1. 候选 SELECT 带上 depends_on,批量查依赖状态,排除依赖未满足的任务(终态=completed/approved)
2. 项目轮询(round-robin): 按 tenant_id 分组轮流取就绪任务,保证项目间公平
3. SELECT LIMIT 20->200 容纳僵尸任务;批量查依赖替代 N+1
2026-08-20 11:34:49 +08:00
ymq
7f05a3b467 fix: _ensure_project_repo 在 git init 之后才配置仓库级 user(否则 git config 报 not a git repository 导致初始 commit 失败) 2026-08-20 00:45:32 +08:00
ymq
c319cb74df feat: repos目录规范——项目过程仓库(阶段/QC/PM文档)+应用仓库+模块仓库; 阶段文档产出到repos/project并git commit; 临时文件不进仓库 2026-08-20 00:38:50 +08:00
ymq
0702f2570e fix: 同步SDL_ROLES能力包角色提示词——requirement不划模块/design两层产出+模块划分+依赖/develop基础模块复用(此前只改了agent_loop硬编码,能力包会覆盖) 2026-08-19 23:24:15 +08:00
ymq
b4bc1a5d1e feat: 新增模块设计模板(design.md+skill/SKILL.md)——统一模块设计结构,design产出用模板保证develop读到一致结构 2026-08-19 23:14:38 +08:00
ymq
eb861b2c70 refactor: design产出拆两层——应用级(architecture+ui-design风格/主页/交互/弹窗规范),数据设计下沉到各模块(数据/CRUD/处理逻辑/skills)实现模块自包含复用 2026-08-19 23:11:38 +08:00
ymq
f78d327853 refactor: 模块划分下沉到design阶段——设计师定模块+依赖关系+开发顺序,PM按设计师模块清单派发develop任务 2026-08-19 23:02:20 +08:00
ymq
596717a3d6 feat: 模块化拆分原则——概念相近功能独立模块+独立仓库+伞仓库,基础模块(apppublic/sqlor/ahserver/accounting/appbase/rbac)可引用不必再开发 2026-08-19 22:55:52 +08:00
ymq
d84f68dd7e fix: develop不deliver三修——①限制探索轮数+强制产出 ②实际产出兜底(检测write_file/git) ③巨型任务拆小(粒度控制) 2026-08-19 22:46:40 +08:00
ymq
b341a43ad6 Revert "feat(task): 新增 cancel_task 工具,会话 agent 可取消单个任务"
This reverts commit fa5b5dc8e0f6fcd97c9ac72b364d1632d3d1fc67.
2026-08-19 19:53:07 +08:00
ymq
fa5b5dc8e0 feat(task): 新增 cancel_task 工具,会话 agent 可取消单个任务
背景:会话 agent 报告"没有终止运行中任务"的工具,只能靠驳回+附作废意见兜底。
核对:现有工具只有项目级(pause_project)/迭代级(start_next_iteration 的
_cancel_active_tasks、cancel_iteration)的停止能力,task_capability 连 S_CANCELLED
常量都没有,缺"取消单个任务"的任务级工具。

改动:
- task_capability.py: 加 S_CANCELLED 常量 + cancel_task()(任意非终态→cancelled+清
  claimed_by,CAS 只动非终态,附 audit)
- sdlc_ability.py: 加 cancel_task ToolDefinition + _h_cancel_task handler(前缀解析
  截断ID)+ SDL_HANDLERS 注册
2026-08-19 19:06:22 +08:00
ymq
4d543f529c fix(qa-feedback): raise_problem 归一化 question,修复 QC 改进意见丢失(1241)
根因:QC 审核的决策里 questions 是 list(7 条改进意见数组),qc_review_run 把
decision.get("questions") 直接传给 raise_problem 的 question 参数,而 raise_problem
未做 str 化,导致 INSERT pipeline_agent_questions 时 question 字段是 list,MySQL 报
OperationalError(1241, 'Operand should contain 1 column(s)'),改进意见根本没落库。

后果链:QC 意见丢失 → develop 重做时 _build_qna_section 读不到任何 pending 退回意见
→ 每次裸重做(看不到「为什么被驳回、该怎么改」)→ 反复产出同样的空交付件。

修复:raise_problem 里 question 若为 list/tuple,先 join 成换行字符串再入库。
2026-08-19 18:34:58 +08:00
ymq
3ffe39e885 fix(task-flow): QC/PM 驳回加重试上限,打破「空交付件→驳回→重做」死循环
根因:develop agent 产出空交付件 → QC 驳回(qc_reject)直接 qc_review→submitted,
不递增 retry_count、不检查 task_max_retry 上限 → 无限重做循环;3 个 running 任务
占满 max_concurrent_agents=3 全局名额 → agent poller avail=0 不再派发 6 个 submitted
任务 → 任务整体饿死,只有手动 start_agents(绕过并发限制)才走一步。

修复:
1. task_capability.py 新增 _reject_with_retry_limit:退回时 retry_count+1,超
   task_max_retry(默认3)则转 failed(释放并发名额,交 failed poller 报故障给人工)。
   qc_reject_task / reject_task 统一走它。
2. agent_loop.py qc_review_run 驳回时感知超限转 failed,跳过建 qc_reject 问题
   (failed poller 会报 fault_report),返回 failed 而非 rejected。
2026-08-19 18:15:39 +08:00
ymq
ccc7baafbd feat(iteration): start_next_iteration 二次确认——当前迭代有未完成任务时须 confirm=true 才作废
当前迭代存在活跃任务时,start_next_iteration 不带 confirm 返回 CONFIRM 提示
("还有 N 个未完成任务,确认作废并启动下一迭代?"),用户确认后 agent 传 confirm=true 才执行。
无活跃任务时无需确认直接推进。抽 _active_task_ids 供计数与作废复用。
2026-08-19 17:17:32 +08:00
ymq
d77910ea2e feat(iteration): 迭代状态机改造——显式「当前迭代」+ 序号 seq_no + 启动下一迭代,废除 created_at 推断
背景:用户明确迭代状态机语义——当前迭代唯一(状态 in_progress)、按序号 1,2,3 推进、
需用户指令启动下一迭代、启动下一迭代时若当前未结束则强制完成。

1. iteration_capability.py:
   - create_iteration 自动分配 seq_no = 项目内 max(seq_no)+1
   - 新增 get_current_iteration(sor, pid):当前迭代 = status='in_progress' 唯一迭代
   - 新增 start_next_iteration(pid):强制完成当前迭代 + 作废其活跃任务 + 启动下一个 planning 迭代
   - list_iterations 按 seq_no 排序
2. sdlc_ability.py: 4 处 created_at 推断(默认迭代)收口到 get_current_iteration;
   新增 start_next_iteration 工具;list_iterations 显示 seq_no + 当前迭代标记
3. agent_loop.py: PM 派发任务默认迭代收口到 get_current_iteration
4. agent_loop_v2.py: create_project 初始迭代 status 从非法的 'active' 改为 'in_progress' + seq_no=1
2026-08-19 17:06:31 +08:00