308 Commits

Author SHA1 Message Date
ymq
75cfd52c21 feat(platform_ability): 平台内部agent能力包
- 5工具: 模型治理状态/抓取文档/提取规格/写入配置(幂等)/模块清单
- 权限: 代码层硬门禁仅owner.superuser|admin,不依赖prompt
- 模型自动配置: 通读API文档→生成供应商端点/适配模板/模型四价
- 定价只来自文档原文,禁止编造;单位统一元/千tokens
2026-09-02 15:07:23 +08:00
ymq
0ef3dec4db feat: create_task加产线角色守卫(角色必须属当前产线角色集否则拒绝+返回可用角色清单); 新增list_roles共享工具(各产线自动继承); 工具描述去掉硬编码开发角色名——根治投标产线PM用requirement/design/develop建章节任务的死循环(2026-09-02) 2026-09-02 12:00:39 +08:00
ymq
77477c6caf fix: 项目输出文件必须落项目空间——项目名缺失时project_dir用project_id兜底,不再落到产线空间根/复盘报告落projects/根 2026-09-02 11:46:07 +08:00
ymq
ae213b2f91 fix(零消耗): paused项目两个tokens漏点
- failed_poller→handle_failed_task: paused项目跳过LLM决策(原每轮白烧)
- bug_poller→pm_bug_confirm_run: JOIN sd_projects排除paused(原只看迭代状态)
三主poller(role/pm/qc)已排除paused;retrospective由pm_poller触发无漏点
2026-09-02 11:07:39 +08:00
ymq
36537b3297 feat: 删除/停止/归档项目后清空项目全部待办——新增_clear_project_todos(human_tasks三条关联链+agent_questions),接入pause/archive/delete三操作 2026-09-01 18:01:21 +08:00
ymq
6953a27937 feat(llm-govern): llm_bridge/llm_proxy 挂治理钩子——门禁前置解析+成功/失败结算
- _resolve_cfg_with_govern: 机构有策略→门禁链(限流/限额/主备容错/端点选择/预授权);
  无策略→__LEGACY__走旧llm表(向后兼容);治理真实失败抛错禁止静默回退
- llm_call/llm_call_msgs/llm_call_msgs_native 三处接入;失败结算释放预授权写failed流水
- proxy_chat_completion(运行环境token路径)同样接入,按上游真实usage结算
2026-09-01 17:27:51 +08:00
ymq
4fffee78c0 fix(项目管理): 工具描述同步状态兼容+去确认循环——能力层是实际分发入口,描述必须与代码一致 2026-09-01 15:31:50 +08:00
ymq
7bb18d8839 fix(项目管理): 确认死循环根治四件套
- fix1 _load_history: ASC LIMIT取最旧N条→DESC LIMIT取最新N条再倒回正序(会话超历史上限后LLM看不到用户刚答的确认,复读旧回复)
- fix2 delete_project描述: 去掉'先复述确认再调用'指令(平台确认门已弹窗给用户,LLM再问=死循环),改为直接confirm=true调用
- fix3 pause/resume跨产线状态兼容: 进行中不硬编码active(S_ACTIVE_LIKE含in_progress);暂停前原状态记审计detail,恢复时还原原状态(投标项目不会被改成状态机外的active)
- fix4 owner门禁降级: created_by='agent.*'的项目无人类字面owner→降级同机构人类可操作(否则永久拒绝)
2026-09-01 15:29:59 +08:00
ymq
493732e062 fix(workspace): 工作空间树挂载项目关联仓库——apps/modules数据源增加sd_project_repos(按实际目录归类),根治元景项目无spec.json时看不到模块/应用仓库 2026-09-01 14:14:53 +08:00
ymq
8993a10106 feat(todo-form): 人类任务通道接form_schema——两条待办通道(问题/人类任务)全产线通用动态表单 2026-09-01 13:47:31 +08:00
ymq
14cbf208b7 feat(todo-form): 冒泡待办支持form_schema动态表单——ask_question可声明上传/填写字段,人类在待办里直接完成 2026-09-01 12:38:54 +08:00
ymq
52550c9e69 fix(workspace): 项目目录统一机制——创建时定死目录写库,解析只读库不推导
根因:4个创建入口只有1个写workspace_dir,其余靠解析时推导且口径不一
(上传落盘走旧平铺{space}/{名},角色agent走新结构{space}/projects/{名}),
导致AgentIO上传文件与项目工作目录错位,文件在工作控件里找不到。

- workspace.py: 新增 alloc_project_dir(统一分配,用名字不用id,重名加短id避让)
- workspace.py: get_project_dir_by_id/get_workspace_dir 兜底改新结构口径
- project_capability.create_project: 创建时写 workspace_dir+directory_name
- agent_loop_v2.create_project: 改用 alloc_project_dir(原自拼slug逻辑收敛)
2026-09-01 11:54:58 +08:00
ymq
2dcd771533 feat(项目管理): 会话agent项目终止/删除能力+人类owner代码层门禁
- agent_loop_v2: GENERAL_TOOLS新增project_info/list_my_projects/pause/resume/delete_project 5工具+handler(_resolve_owned_project代码层校验owner, 不靠prompt)
- sdlc_ability: 8个项目生命周期handler(start/complete/archive/reopen/pause/resume/backup/delete)全加_require_project_owner门禁——能力层优先于通用层分发,不加则绕过校验;审计who记登录用户
- 别名归一化防LLM编造工具名;_needs_confirmation同步归一防别名绕过确认门
- pause/resume/delete标requires_confirmation(会话确认→代码校验双重门)
2026-09-01 11:51:48 +08:00
ymq
6f72e777da fix(agent): 角色 agent 实例 id——created_by 存真实 id 不再拼字符串
- pipeline_agent_instances 表(项目×角色→稳定实例 ag.xxxx), 幂等注册
- agent/pm/qc 三 poller 派单改用实例 id(原 poller-{role} 拼接, 33字符撞32列宽→1406)
- DDL: 新表 + pipeline_deliverables.created_by 加宽64兜底
2026-09-01 09:26:46 +08:00
ymq
a7d522b15f fix(session): 跨产线会话串扰根治——历史/项目上下文按产线隔离
根因: 各产线页面默认tab共用session_id='default', 对话历史只按session_id过滤
(写入未存pipeline_id), 投标页加载了开发页历史导致LLM答错产线。
- _save_turn: 写入pipeline_id(generic存空串防污染开发产线)
- _load_history: session级读取加pipeline_id过滤
- get_session_project_id: 加pipeline_id参数, 跨产线项目不生效(不删记录)
2026-08-31 22:03:46 +08:00
ymq
2d913c1d12 fix(read_file): 截断显式告知+offset分段读——根治静默截断同类病 2026-08-31 22:01:26 +08:00
ymq
06130bcbef fix(workspace): switch_project后刷新工作目录——根治切项目后list_files仍列旧目录 2026-08-31 19:31:48 +08:00
ymq
947398c9ef fix(upload): get_project_dir_by_id+copy_uploads_to_project;agent工作目录对空workspace_dir项目兜底解析(与落盘同一函数) 2026-08-31 17:54:29 +08:00
ymq
0d64b48271 fix(captools): dict列表序列化用item[k]——getattr(dict,k)永远落空值导致list_features等能力工具返回全空(测试机实测) 2026-08-31 16:45:00 +08:00
ymq
97c7d2f368 fix(retro): _rows_to_dicts用dict(rec)——sqlor行是DictObject,vars()只取内部属性导致复盘素材全空壳(测试机冒烟实测) 2026-08-31 16:37:18 +08:00
ymq
38d9897a78 fix(skills): load_skill走resolve_skill容错匹配+未命中提示裸名规范(根治'技能[产线]bid-workflow不存在') 2026-08-31 16:24:05 +08:00
ymq
65db2dddc3 review修复:复盘认领校验补claimed_by比对、LLM硬超时兜底、报告落盘以write_file完整版为准 2026-08-31 16:15:00 +08:00
ymq
0547c37302 QC契合度门禁+复盘机制:删需求/设计人工确认、PM三阶段禁内容否决(代码兜底修正)、复盘任务+执行器+技能提议工具、QC工具链补ctx 2026-08-31 16:02:03 +08:00
ymq
7023742880 fix(llm): 模型不可用报真实错误+name/model_id双匹配+org语义对齐
- _no_llm_error: 错误写明模型名/原因/行动指引,禁止笼统No LLM API configured
- _get_model_config: name/model_id 双匹配(与gateway解析语义一致),org过滤含系统级共享
- agent_loop_v2 run(): LLM调用异常捕获→yield error事件,前端显示真实错误不再卡死思考中
2026-08-30 15:07:34 +08:00
ymq
519b4bfcf4 fix(parse): DSML双竖线变体+叙述内嵌json代码块解析——实测两种新失败形态,兼容竖线数量任意变化 2026-08-29 16:51:48 +08:00
ymq
cb0a87e65e fix(models): pipeline_pm_notices.fingerprint 64→255——缺口指纹含任务ID列表常超64字符,INSERT DataError(1406) 致编排告警丢失 2026-08-29 15:11:09 +08:00
ymq
31eff0757e feat: get_project_dir_pl产线隔离版——跨产线项目视为无项目(商机空间不显示开发项目) 2026-08-29 15:00:20 +08:00
ymq
eaebca297d fix: 产线隔离——会话项目跨产线时清空,防元景项目劫持商机/投标产线会话 2026-08-29 09:21:34 +08:00
ymq
05e740d662 fix: list_projects严格产线隔离——删除all=true出口(模型会主动跨产线) 2026-08-29 09:02:37 +08:00
ymq
c510ef14a9 fix: list_projects产线隔离——产线会话只列本产线项目(投标不串开发产线);all=true可跨产线 2026-08-29 08:33:54 +08:00
ymq
ffe19ab95b refactor(remote_env): 依赖安装改远程分离式——nohup逐包安装+进度文件,轮询无状态 2026-08-28 21:46:27 +08:00
ymq
023d4a67fa fix(remote_env): 批量pip失败时降级逐包安装(部分成功优于全败) 2026-08-28 21:15:58 +08:00
ymq
ea17307a6c fix(role): agent.deploy 前缀形态也加入 aliases——存量脏数据可解析 2026-08-28 21:13:41 +08:00
ymq
1bdc90f7f0 fix(role): deploy别名归一到agent.deploy_test——LLM写deploy导致approve后任务链断裂(_get_next_role查不到spec) 2026-08-28 21:12:21 +08:00
ymq
e3917e681c feat(work_env): 远程模式自动初始化——技能同步+依赖软件自动安装;agent_loop deploy别名归测试环境 2026-08-28 21:10:36 +08:00
ymq
8fafe18d91 fix(parse): _parse_agent_action 支持 deepseek v4 DSML 原生工具调用格式——长上下文多轮时不解析会5轮耗尽 2026-08-28 18:17:46 +08:00
ymq
c9d914b9ff security(agent): _run_shell 接入 bwrap 沙箱——命令隔离落地
- agent 的 run_shell/run_command 从裸 create_subprocess_shell 改为 bwrap 沙箱
- user/pid/ipc/uts namespace 隔离,网络保留(git push/ssh 部署依赖)
- 系统目录+/d/pipeline+/d/doit 只读(平台代码/配置/其他机构工作区不可写)
- 当前机构工作空间目录可写(跨机构写隔离);/tmp 会话私有
- DNS 兼容 systemd-resolved(/etc/resolv.conf 软链→/run 只读挂载)
- 无 bwrap 降级为原目录隔离并标 sandbox: false(不阻断现有功能)
2026-08-28 14:26:32 +08:00
ymq
9ec38df6b4 feat(gateway): 会话模型选择持久化到项目——设置后持续生效直到再次选择
问题:项目选择模型后不持久化,每次进入会话都回退固定缺省值。
根因:前端模型下拉的 model_id 后端不消费;无项目级模型存储;
     会话只读用户全局 default_llm_id,sd_projects.default_model 无写入路径。

修复(通用层,所有产线共用):
- resolve_project 读出 sd_projects.default_model(项目级、跨会话持久)
- run_message 新增 model_id 参数:_resolve_and_persist_model 校验
  (兼容 llm.id/llm.model_id 两种取值 + 多租户隔离)后持久化到项目
- 模型优先级:本次显式选择 > 项目已设 > 个人全局 > 产线默认
  (个人全局从压过一切降为兜底,项目设置不再被全局覆盖)
2026-08-28 12:26:18 +08:00
ymq
d9827c391b fix(orchestration): 元景三问题根治——task_title归位+问题通道统一冒泡+依赖启动策略+确认去重
问题1(部署早于开发启动):
- _check_orchestration_gaps 重构为结构化缺口(kind/fingerprint/task_id/fix_ids)
- 缺口不再只打日志:派发后当场回给PM + 持久化pipeline_pm_notices注入PM下回合上下文
- 新增 update_task_deps 原语:PM核实缺口后补依赖(修正是LLM决策,代码只查漏)

问题2(env补齐后waiting不唤醒):
- _bubble_deploy_env_missing 从自建人工任务死胡同迁移到统一问题通道(raise_problem)
- owner在待办回答→resolve_problem自动唤醒任务→QA注入agent prompt,信息真正交给LLM

问题3(task_title错位+重复确认):
- SDL_ROLES task_title 各归其位(需求分析/架构设计/脚手架开发/部署测试/功能测试)
- 确认去重:同迭代已确认且非回退重做→跳过重复确认直接派发
- _create_next_task 单例阶段幂等:requirement/design复用同迭代任意活跃任务

机制增强:
- 依赖启动策略 params.dep_policy: all(默认)/any/at_least{n},纯函数_eval_deps_policy
- init.py poller 手写依赖求值收敛到同一纯函数(消除两处语义漂移)
2026-08-27 22:52:27 +08:00
ymq
98b90d4f21 fix(workspace): 悬空项目引用防护——解析层校验+自愈清理+删除时清指针
根因:删除项目后不清理 pipeline_session_settings/pipeline_agent_settings 里的
当前项目指针;解析逻辑(会话级优先)又不校验项目是否存在,悬空引用遮蔽有效
的全局设置,导致工作空间报「请先在会话中切换项目」(实测复现:孤儿项目
0x0EISBKAOsvHzW09dIOS 卡死会话级解析)。

修复(根治,三层):
1. get_session_project_id 加存在性校验:悬空记录自愈清理并回退全局,
   查询异常保守放行不误伤
2. get_session_context 收敛为复用前者,消除重复实现的语义漂移
3. delete_project 删项目时清空两张设置表的指针;孤儿清扫清单纳入这两表
2026-08-27 17:44:37 +08:00
ymq
58d773b6ad fix(workspace): 会话创建项目改用新结构目录 + 写入 directory_name
根因:_t_create_project 用旧结构 build_workspace_path({space}/{项目名}),不写
directory_name;而工作空间读取端已迁到新结构 {space}/projects/{英文slug},
导致会话新建的项目显示「项目目录(不可用)」。

修复:
- 改用 build_space_path 拼 {space}/projects/{slug} 并 os.makedirs
- slug 保留 [A-Za-z0-9_-],须含字母(避免纯数字如'7'),否则兑底 proj_{短ID}
- 写入 directory_name 字段(工作空间读路径依据)
- 同 slug 冲突追加短 ID
2026-08-27 16:11:43 +08:00
ymq
09f8b85f66 feat(gateway): run_message/AgentExecutor 支持 default_pipeline_id
无当前项目时按入口指定产线装载能力(替代硬回退 sdlc_general)。
投标产线会话入口传 bidding_general 即可复用通用 agent 多 session 界面。
2026-08-27 13:12:34 +08:00
ymq
981238b401 feat: capability 工具分发支持全路径模块 + 通用工具聚合层
- exec_capability_tool:module 支持裸名(=pipeline_service.*)或全路径,
  产线自有能力包(如 pipeline_bidding.*)可注册角色工具而宿主零接触
- shared_ability:聚合 SDLC 能力包里的通用任务/交付件/问答/项目工具,
  供新产线能力包复用,不重复实现、不反向依赖具体产线
2026-08-26 22:54:00 +08:00
ymq
36c131e348 fix(cleanup_orphans): 补 <> '' 非空守卫(空串=未挂载非孤儿,防误删32会话/23功能);补充无项目/无迭代/无任务全量引用表 2026-08-26 15:22:18 +08:00
ymq
8eeb196515 fix(delete_project)+feat(cleanup_orphans): 删除项目补 task_id 级联(sd_deliverables/artifacts/task_steps/human_tasks)+sd_project_role_models;新增孤儿清扫能力(指向已删项目/迭代/任务的残留,dry_run可先统计) 2026-08-26 15:17:48 +08:00
ymq
ccba6f470e fix(orchestration): 环境信息只卡部署,不卡需求/设计/开发
用户 2026-08-26 定调纠正了我原方案的错误。我原本提议把「env/*.json 无占位符」做成
requirement 阶段的结束条件(把缺陷堵在最便宜的阶段)——这是错的,会把死循环制度化:

主机/SSH账号/密码/部署路径是**外部输入**,requirement agent 根本产不出来。若要求它
填全才能通过,agent 就卡在无法解决的事情上无限重试。正是 2026-08-25 hrs7 的死循环成因:
deploy_test 因 env 占位符失败 → PM 判「根因在 requirement」→ 回退整链并作废 owner 已
人工确认的三模块设计 → 重做需求后 env 依然是占位符 → 再次失败。

实际上 hrs7 的 requirement agent 做得对:填了能确定的(port 9187/dbname hrs7),未知项
标「待明确」并列入 pending 清单 —— 这是正确履职,被回退是冤枉的。

实现:
1. _check_deploy_env_ready 只对 agent.deploy_test/deploy_prod 生效,其余角色一律放行。
   检查 ssh.host/user、deploy.path、db.host/user/dbname + ssh 凭据(password 或 key_file
   二者其一) + requirement 自列的 pending 清单;domain/status 等非必需项不阻断。
2. 认领路径加此进入条件:不齐备 → 不进 running,任务置 waiting(界面可见,不在 submitted
   静默打转) + 冒泡 deploy_env_required 人工任务给 owner,写清缺哪些字段、文件在哪,
   并说明「补齐后自动继续,无需重跑上游阶段」。按 task_id 去重。
3. PM prompt 加硬约束:外部输入缺失禁止回退上游。回退前先自问「这个缺陷是上游 agent
   能做对却做错了,还是本来就产不出?」——前者才回退,后者一律冒泡等人补。

验证:11 例离线用例全过(用 hrs7 线上真实 test.json 结构),覆盖
requirement/design/develop/test 四阶段占位符必须放行、部署阶段必须阻塞并列缺失字段、
补齐后放行、密钥文件替代密码、空密码无密钥阻塞、domain 缺失不阻断。
2026-08-26 12:09:23 +08:00
ymq
31eab89234 fix(orchestration): 多依赖门控 4 处放行漏洞 + description 继承 + 幂等 + 完备性查漏
【1. description 不再继承 + 用 PM 的 next_task_description】
_create_next_task 原实现 new_params={**params} 把上游 description 整个继承,导致
design 派生的「应用脚手架 develop」拿到需求任务的描述(产出需求规格说明书),于是它交付
文档、4 分钟 approved —— 一行代码没写却走完 develop,打破「应用级 develop approved =
编码完成」这个 deploy_test 门控前提,造成 deploy_test 在编码未完成时提前启动。
同时 PM 在 review_approve 里给出的 next_task_title/next_task_description 一直被丢弃
(1935 行采集、2239 行调用时没传) —— 现已接上,流转决策权归 LLM,代码只做兜底。

【2. 多依赖门控 4 处漏洞(用户重点要求)】
D1 _task_deps_satisfied 查「不在终态的依赖」,依赖ID不存在时查出0行 → 误判满足而放行
D2 PM 派发时未知依赖引用只警告、静默丢弃 → 任务以更少依赖落库 → 并行开跑
D3 len>=20 就当有效任务ID收下、不校验存在性,配合 D1 让门控完全失效
D4 依赖处于 cancelled/failed 时依赖方永久 submitted,死锁且无人知晓
修法:逐个比对依赖存在性与状态;missing/dead/self 一律阻塞并冒泡;PM 派发时依赖
无法解析的任务置 waiting 而非静默降级为并行。init.py 的 poller 同步同语义(两处实现
必须一致,否则一处拦住另一处放行)。

【3. 幂等】并发多任务同时 approved 会各自创建下一阶段任务 → 同迭代重复任务(历史上出现
过「同一迭代两个 design 任务」)。按 (迭代, 角色, 系统派生) 先查后建。

【4. 逃逸阀通则】依赖永不可达时冒泡 dependency_blocked 人工任务(按 task_id 去重),
消除静默死锁。对照:failed_poller 自动 pause 项目却无人通知,hrs7 因此卡近 1 小时。

【5. 完备性查漏 _check_orchestration_gaps】代码只查漏、不替 PM 决策:
G1 依赖自引用/成环(DFS 回边) → 必然死锁
G2 应用级 develop 未依赖未完成的模块级 develop → 正是本次故障成因
G3 设计清单 generated_modules 有模块无对应 develop 任务 → PM 漏派

逻辑验证:/tmp 两组离线用例共 30 例全过,并以可执行方式证实原实现 4 处放行漏洞。
2026-08-26 11:49:24 +08:00
ymq
c03469bf7a fix: 阻塞求助不得当缺陷驳回——bug_flow 前置确定性分流转 need_info
回归修复(我引入):人事项目7 实测 deploy_test 两次 report_bug 上报「env/test.json
待确认无法部署」,被 pm_bug_confirm_run 在 9/13 秒内以「属测试环境问题,非代码缺陷」
自动 reject,PM 收不到求助 → 回退 requirement 重做 → requirement 同样拿不到环境信息
→ 再编占位 → QC 再驳,死循环。

根因:prompt 判据写了「reject:测试环境问题导致的假失败」,LLM 严格照做。但
report_bug 在这里承担的是「向上冒泡求助」,不是「报告代码缺陷」。

修复分两层:
1) 代码层确定性分流(主):_is_blocking_help() 按特征词判定阻塞求助,
   命中者不进 LLM,直接 _escalate_blocking_bugs() 转 need_info 冒泡给人,
   bug 保持 open 等信息补齐;幂等(已有 pending need_info 则跳过)。
2) prompt 兜底(次):删除「测试环境问题→reject」判据,加铁律说明外部输入
   缺口不是可 reject 的非缺陷。

实测验证:2 个真实被误驳文本命中分流,3 个真缺陷文本不命中。
2026-08-25 21:27:09 +08:00
ymq
1d743df4e3 feat(approval): 钉钉审批接成产线审批关卡
复用引擎既有 approval_gate 机制,不重造状态机:
- 新增 dingtalk_approval.py:注册 step_type='dingtalk_approval'(interactive),
  进入步骤自动向钉钉发起审批;注册 biz_type='pipeline_approval' 回调钩子,
  审批结果回来调 approval_approve/reject 推进产线(内部已 save_artifact+resume_task)
- executor._handle_interactive_step 加外部通知钩子(按 step_type meta.notifier 分派),
  并把 tenant_id 从 _execute_step 传下来(原 step_info 里无此字段,会永远取空)
- biz_id 编码 tenant_id:task_id:step_name,回调据此定位步骤
- 软依赖 dingdingflow:未加载时步骤仍挂起等人工审批,不推钉钉、不报错
- 通知失败只记日志不改步骤状态,避免外部系统故障导致步骤 FAILED
2026-08-25 18:22:03 +08:00
ymq
8862d72a60 fix(sdlc): 根治任务名继承 bug(design 任务名不再跟需求名一样)
根因:_create_next_task 用 new_title=f'{title}({next_role}阶段)' 直接继承上一任务
title + 追加角色后缀。导致 design 任务名变成「需求规格说明书(agent.design阶段)」
跟需求名混同;回退重做后更叠加成「...(回退重做)(agent.develop阶段)
(agent.deploy_test阶段)」越叠越长。

修:title 改按 next_role 的声明式 task_title 生成语义标题(项目名 + 阶段语义),
阶段模板由 RoleSpec.task_title 声明(design=应用架构与模块设计 / develop=应用脚手架开发 /
deploy_test=部署测试 / test=功能测试),代码不硬编码。
2026-08-25 17:01:19 +08:00