353 Commits

Author SHA1 Message Date
ymq
4d2b3aa848 feat(models): 孤儿表归籍——pipeline_agent_instances/agent_settings/project_agents 三表补models定义(此前m0002建表未进models,新库部署缺表);project_capability清除sd_conversations全部4处引用(死表,m0027 DROP);README表清单补归籍说明 2026-09-10 19:05:27 +08:00
ymq
cc63f8822c docs: README 补第二批能力对齐(五级工具作用域接线/patch_file/原生视觉多模态链) 2026-09-10 18:53:49 +08:00
ymq
7dda635c9a feat(agent): 五级作用域工具门禁接线+patch_file+原生视觉多模态
1. _init_components 加第8步 _resolve_tool_scopes: 调 core.tool_sources 五级解析,
   registry 重建为解析后工具集 + capability 工具合成注册(路由 exec_capability_tool)
2. _execute_tool 加作用域执行门禁: LLM 幻觉调用作用域外工具名(generic喊create_task/
   A产线喊B产线工具)直接拒绝并回可行动提示,不只 schema 不给看;解析失败降级不拦截
3. patch_file handler(_t_patch_file): 唯一性校验+replace_all+原子写+越界防护+二进制拒绝
4. 原生视觉: run(image_parts) 构造多模态用户消息; _call_llm 含图失败剥离重试一次
   (_degrade_images_if_needed)+注入如实告知说明(绝不假装看过图); _estimate_tokens/
   _summarize 兼容 list content(_content_as_text); gateway.run_message 加 image_paths
   透传+build_image_parts+超限notes注入
2026-09-10 18:36:54 +08:00
ymq
057fbfc05c docs: README 补 Hermes 能力对齐四项(memory/manage_skill/后台进程/并行委派)实现说明 2026-09-10 17:43:34 +08:00
ymq
d8bc29de29 fix(agent): 撤销误带入的 llm_call project_id 参数(并行会话未完成改动)
上个提交 git add agent_loop_v2.py 时连带提交了并行会话「按项目记账」的
3 处 llm_call_msgs/native(project_id=...) 调用,但配套的 llm_bridge.py 签名
改动仍在对方工作树 dirty、未提交未部署——已部署的 llm_bridge 不认 project_id
→ 通用会话 llm_call_msgs() got unexpected keyword project_id 崩溃。

修复原则:只回退我自己提交的文件到与已部署 llm_bridge 一致,不替对方合并
未完成的记账工作。撤销 _llm_select_skills / _call_llm(native+fallback) 三处
project_id 实参;保留本任务的记忆注入 build_prompt_block(project_id=...) 等。
2026-09-10 17:27:06 +08:00
ymq
1c04efe1be feat(agent): 会话agent四项Hermes能力对齐(记忆写入/技能管理/后台进程/并行委派)
1. memory 工具(add/list/remove): 多租户写入门禁——org_id/user_id强制注入、
   scope白名单user/project/pipeline(global/org种子域禁写)、无身份拒写、
   remove仅本人条目; 记忆注入改可见性过滤版(修跨机构泄漏)
2. manage_skill(create/patch/write_file/remove_file/delete): skill_live扩展,
   只落本租户orgs/users目录, global原版fork-on-write(校验通过才fork,失败零残留),
   org+user双副本同步改, 产线层拒改, delete只删本租户副本+审计留痕
3. run_command background=true + process工具(poll/log/wait/kill): bg_jobs.py
   状态文件化(workspace/.bg/,跨worker可见), 沙箱档位与前台一致(generic强制
   strict+无bwrap拒绝), 超时SIGTERM进程组+stale心跳判活
4. delegate_subtask background + subagent工具(list/steer/stop/result):
   subagents.py 并行上限3/workspace, 深度限制1(子agent禁再委派),
   子会话session_isolation=none(不读父历史不写会话表), steer/stop文件传递
   每轮tool-loop边界消费, 结果流式落盘(stop即部分结果)
2026-09-10 17:09:45 +08:00
ymq
736a2dd579 feat(human_task): 待办提供者注册表register_todo_provider——平台待办开放给外部模块注入(工单模块首用)
- _TODO_PROVIDERS注册表: provider签名async fn(user_id, roles, limit)->[todo dict], dict须含source
- list_my_human_todos: db context外遍历providers union(逐个try/except,坏provider不拖垮列表)
- count_my_human_tasks: 仅全局角标(project_id空)计入providers——工单不属于产线项目
- 架构: 待办是平台级机制,各部分(产线任务/冒泡问题/工单)产生待办,本模块聚合;
  外部模块注册钩子注入,不跨模块读表(sage-module-scaffolding 7.3)
2026-09-10 16:14:20 +08:00
ymq
b8a2aeadb7 fix(models): pipeline_conversations 孤儿表归籍本模块——补models定义(13列与活表逐列对齐,唯一写入方agent_loop_v2._save_turn)+README数据表登记;字段顺序含m0003补列session_id在尾;task_id/step_name/attachments/msg_type/org_id为预留列(活表395行实测零写入),保留定义与活表一致 2026-09-10 15:30:40 +08:00
ymq
92cdafdd22 fix(ability): 项目/模型配置弹窗URL改/pipeline_core/**——三表页面迁归属(sdlc→core),旧路径/pipeline-sdlc/sd_projects与sd_project_role_models的index.ui随迁移删除,不改则弹窗404 2026-09-10 12:33:56 +08:00
ymq
ac82d2f32d fix(project): create_project默认project_type去SDLC语义(web_app→general)+补pipeline_id/default_model参数——pipeline_id必须与alloc_project_dir的space一致,此前目录按general建而pipeline_id走DB默认sdlc_general,工作空间解析space=pipeline_id错位;注:本函数当前无调用方(实建项目走agent_loop_v2._t_create_project与bidding直插),此修复为防御性,生效路径是m0018迁移改DB列默认值 2026-09-09 19:15:19 +08:00
ymq
655d50bde8 feat(skill): 技能提议实时生效——写机构技能目录orgs/{org_id}/按scope覆盖global,机构间隔离
用户需求变更(2026-09-08):propose_skill从人工审核链(pending→published)改为实时生效,
但只写提议者所属机构的skills目录,靠org scope(优先级3)同名覆盖global(0),不影响其他机构。

- 新增 skill_live.py: publish_skill_live 路由决策+路径穿越清洗+frontmatter scope剥离+原子写
  * 客户机构(org≠0)→orgs/{org_id}/{name}/实时生效
  * org 0陷阱:get_merged里orgs/0/是全机构共享缺省——org0+有user_id降级users/{uid}/(仅本人);
    org0无人值守(复盘poller)拒绝实时写,保持pending人工审核链(防agent自动影响全平台)
- v2 _t_propose_skill / v1 retrospective.propose_skill 接入:落库照写(成功=published+路径审计)
- v1 poller长进程配套:_reload_skills_throttled(30s TTL)接入_build_role_skills_block/_load_skill_by_name
  (v2每条消息executor init已reload,无需改)
- 工具描述三处同步:core GENERAL_TOOLS/capability_tools TOOL_SCHEMAS/RETRO prompt
2026-09-08 23:59:24 +08:00
ymq
84bef76401 feat(agent): 统一文件读取+联网检索+只读库查询+generic strict沙箱(对齐Hermes信息摄入能力)
- 新增 file_read.py: v1/v2 共用统一读取(分页续读+docx/pdf解析+显式截断告知)
  根治立项书76088字符只读到30000(v2)/12000硬截无提示(v1)的真实翻车
- 新增 web_tools.py: web_search(Bing RSS优先+HTML兜底)/fetch_url(超长落盘webcache+read_file续读)
  SSRF三层防护(公网域名/DNS私址拒绝/重定向逐跳)+不可信数据标注;
  修复 aiohttp content.read(n) 对 chunked 响应提前返回半截的坑(改 resp.read())
- 新增 db_query.py: query_project_data 只读白名单查询(强制project_id参数化+where/order_by注入校验+审计)
- agent_loop.py(v1角色agent): read_file 12000硬截→共享file_read分页; AGENT_TOOLS 加三工具(补required防全参必填);
  _run_shell 加 strict 档(通用会话:不挂平台目录+可写根收窄到用户专属目录); PM/QC/RETRO prompt 工具清单同步
- agent_loop_v2.py(v2会话agent): _t_read_file 改走共享模块; 新增三工具 handler; generic run_command 强制strict+无bwrap拒绝
2026-09-08 23:13:06 +08:00
ymq
0702640aba fix(gate): _gate_plan按(请求能力,模型能力)对规划门禁——显式t2i选中i2i或自动选型落到i2i且无媒体→t2i契约代码表判定;带媒体=真i2i走LLM层;修自动选型路径cap_req空不换算致LLM按i2i契约误拦(2026-09-08实测) 2026-09-08 17:26:46 +08:00
ymq
1fce2ceb03 fix(gate): 降级执行时完备性直接走代码表——LLM/模型技能层按模型自身i2i契约误判,实测拦截合法文生图任务(2026-09-08) 2026-09-08 17:23:32 +08:00
ymq
5bb22fe7df feat(gate): invoke_model完备性门禁接入能力降级换算——i2i/r2v模型无媒体输入时按t2i/t2v契约校验(否则i2i承接文生图被缺输入图误拦)(2026-09-08) 2026-09-08 17:20:40 +08:00
ymq
d8bd88ced7 feat(ws): load_workspace注册generic_workspace_dir到ServerEnv供dspy调用(2026-09-08) 2026-09-08 16:01:15 +08:00
ymq
e0efcfc7db feat(models): add 5 runtime table JSONs + pipeline_tasks retry_count/last_error 2026-09-08 15:24:31 +08:00
ymq
83d11772d5 feat(agent): 完备性判断改LLM裁决(2026-09-08用户定夺:判断归LLM,契约归数据,硬编码降级为兜底)
- judge_completeness:①模型有配套技能(skills/models/{model}/SKILL.md)→LLM按
  技能输入契约vs用户已给内容判断缺什么;②无技能→LLM按能力语义(输入→输出
  模态)判断;③LLM失败→_check_completeness_code能力表兜底(闸门不因裁决故障失效)
- load_model_skill读配套技能;_resolve_capability补返回description供裁决
- 裁决只在invoke_model(贵动作)发生,不是每条消息;宁放行不误拦,可选参数不拦
2026-09-08 12:31:22 +08:00
ymq
ba65d586b1 feat(agent): 完备性硬门禁(2026-09-08用户定夺一C+二A)
意图识别归主循环LLM(system prompt语义引导),完备性硬门禁归代码。
- invoke_model入口check_completeness按能力契约校验必备输入:
  t2i/t2v/tts要描述,i2v/i2i要输入图,asr要音频,r2v要参考媒体
- 缺失返回QUESTION前缀,不调上游零费用(在llm_infer之前)
- v1角色agent+v2会话agent四处工具循环QUESTION硬拦截转
  ask_user/ask_question,禁回填靠LLM自觉(deepseek类会空参硬试烧钱)
- 22例单测全PASS(齐备/缺失/字符串vs数组形态/未登记能力不误伤)
2026-09-08 11:58:39 +08:00
ymq
25c9e7cdb3 fix(gateway): run_message空输入守卫——空/纯空白消息绝不进LLM(2026-09-07实测:空prompt致LLM幻觉delete_project要确认/直接run_command执行python3 heredoc非危险命令绕过确认门);入口拦截覆盖generic+全通道 2026-09-07 18:04:43 +08:00
ymq
bf6cb5b24a feat(agent): 平台模型调用能力——invoke_model/list_platform_models工具(v1角色agent+v2会话agent,唯一实现platform_model_tools);llm_bridge.llm_infer通用推理透传全能力payload+超时参数化;角色prompt加配图节(禁字符画,生成真图嵌正文)(2026-09-07用户需求) 2026-09-07 17:31:29 +08:00
ymq
763e84681f fix(gateway): 项目模型持久化加对话能力守卫——白名单取pipeline_llm.selection.CHAT_CAPS(未装兜底t2t/i2t/m2t),非对话模型选中即无效走回退链(2026-09-06用户定夺) 2026-09-06 19:49:15 +08:00
ymq
2f6b9396e1 feat(agent): _build_ctx注入session_id——能力handler会话级隔离键(extract规格锚定防跨会话串数据) 2026-09-05 21:25:47 +08:00
ymq
83c6d7aa5d docs: README 补通用会话产线隔离 7 层纵深防御说明 2026-09-05 19:51:57 +08:00
ymq
874a14b6bb fix(isolation): session_search 通用会话只搜自身历史(与 _load_history 过滤对称)
第7层泄漏补刀:session_search 原按 iteration_id 过滤,通用会话 iteration_id=''
匹配到的是所有无项目对话;统一改为按 pipeline_id='' 过滤通用会话历史,
防止修复前落库的污染对话被搜出复述。
2026-09-05 15:29:44 +08:00
ymq
b93617feaf fix(isolation): 第7层泄漏——通用会话历史回放不过滤产线,跨产线对话进上下文
实测:工具/文件系统隔离生效后,通用助手仍复述出产线项目ID。
根因:_load_history 无 session_id 分支按 created_by 全量回放该用户
所有产线的最近对话(项目名称/ID 随历史泄漏)。

修复:通用会话只回放 pipeline_id='' 的历史(存库时 store_pl='' 与
此过滤对称);有 session_id 的分支同样加通用会话空产线过滤。
2026-09-05 15:27:00 +08:00
ymq
5c28fed040 fix(isolation): 第6层泄漏——通用会话工作空间总根可枚举所有产线项目
实测发现:工具层隔离生效后,LLM 改用 list_files/run_command 浏览
WORKSPACE_BASE 总根({base}/{org}/{产线}/…全量可见),从目录名
枚举出所有产线的全部项目。

修复:
- workspace.py 新增 generic_workspace_dir():通用会话专属目录 _general/{uid}
- agent_loop_v2: generic 会话文件根改专属目录(_resolve_ws_path 越界保护圈死)
- agent_loop_v2: run_command 对通用会话执行层拒绝(shell 无法圈禁在目录内)
- schema 层剔除 shell 类工具(配合 pipeline-core)
2026-09-05 15:21:35 +08:00
ymq
b99fb4cc13 fix(isolation): 通用助手会话泄漏产线项目工具——5层修复
根因:
1. tool_registry 全局单例跨会话污染:产线会话注册的工具(如 list_projects)
   永久残留,后续通用会话把全部工具塞给 LLM
2. generic 会话 pipeline_id 空被无条件回退 DEFAULT_ABILITY_ID(sdlc_general),
   _execute_ability_tool 拿到产线能力包直接执行
3. _h_list_projects 对 space='general' 不过滤,列出所有产线全部项目
4. GENERAL_TOOLS 本身含项目管理工具,通用会话无条件拿到

修复(纵深防御,schema 层+执行层双保险):
- agent_loop_v2: ToolRegistry 改每 executor 独立实例(禁全局单例)
- agent_loop_v2: generic 会话跳过默认产线回退
- agent_loop_v2: _execute_ability_tool 对 generic 直接返回 None
- agent_loop_v2: _dispatch_sdlc_tool 对 generic 拒绝项目类工具(含别名归一)
- agent_loop_v2: generic 记忆只读 global 域、技能只检索 global 层
- sdlc_ability: _h_list_projects 对 general 空间拒绝列项目

配套:pipeline-core load_agent_config generic 时剔除 category=project 工具
2026-09-05 12:43:33 +08:00
ymq
e88e0bfc37 feat(llm_bridge): llm_call/llm_call_msgs加timeout参数——_timeout经payload透传统一推理端点(提取等长任务超端点默认60秒) 2026-09-05 10:24:55 +08:00
ymq
03c79fe356 fix(rag-client): Authorization前缀被写入侧秘密扫描替换为***致401——运行时拼接 2026-09-04 19:49:39 +08:00
ymq
8a627b34a1 fix(rag-client): dapi返回值类型加固(失败可能返回字符串) 2026-09-04 19:36:13 +08:00
ymq
8a9d0f8294 fix(llm_bridge): 修复purpose碰撞——3个调用函数补purpose参数并塞payload._purpose(上轮重构收敛时丢失,4处调用点传purpose='utility'会TypeError) 2026-09-04 19:32:33 +08:00
ymq
25db66aa61 fix(llm_bridge): 自调用Bearer前缀用拼接构造——字面量被脱敏工具替换成***致Authorization头无效(401同根因) 2026-09-04 18:33:53 +08:00
ymq
f3f82dd448 refactor(llm): agent调用收敛到模型治理统一推理API——llm_bridge改HTTP自调用薄客户端(短期token+本进程端口),删旧llm表直查;llm_proxy委托chat_inference;gateway/agent_loop/bug_flow模型解析与缺省模型改走治理链/统一解析,清除写死模型名 2026-09-04 17:05:42 +08:00
ymq
0aa632dd28 fix(kb-ingest): 待办置完成改用suggestion_id精确匹配(防同名文件误伤) 2026-09-04 16:33:15 +08:00
ymq
ae3967c3b0 fix(rag-access): RC4加解密显式传key(对称约定)+会话agent通道挂检索工具(全产线共享) 2026-09-04 16:12:17 +08:00
ymq
21c8c16daa feat(rag-access): 产线接入知识库——全角色按项目owner权限检索(rag_search/rag_kb_list)+PM建议入库待办闭环+统一API模式 2026-09-04 15:57:41 +08:00
ymq
83ce9c820c feat: list_tasks图标补qc_rejected/cancelled 2026-09-03 17:31:37 +08:00
ymq
03473e8fbb feat: task_io_render 共享渲染——md交付件MdWidget渲染+下载链接,office/pdf下载链接(全产线统一) 2026-09-03 16:41:27 +08:00
ymq
7596f76605 feat(ctx): _build_ctx补org_id——能力工具handler可取当前用户机构(供应商自动归属需要) 2026-09-03 16:22:00 +08:00
ymq
63d9e00a1e fix: 豁免分支先COMMIT认领再迁移——_claim_task的UPDATE未提交,另一连接更新同一行锁等待超时1205(实测豁免路径50秒卡死) 2026-09-03 12:44:22 +08:00
ymq
ae78742479 feat: 通用QC/PM门禁声明式豁免——params.skip_generic_qc任务交付直接approved(qc_review_run/pm_review_run兜底放行存量卡住任务) 2026-09-03 12:28:12 +08:00
ymq
9d40816fac fix: get_session_project_id产线不匹配不再删除项目指针
根因: _valid只返回空串,调用方无法区分'项目已删'(应清理自愈)和
'跨产线合法上下文'(必须保留)。原实现产线不匹配也删全局/会话指针——
平台页点一次「工作空间」就把用户在投标页的当前项目清掉(复现脚本实锤)。
修复: _valid返回(vpid, reason), gone才清理, cross只视为无项目回退
2026-09-02 19:01:18 +08:00
ymq
19c7d05105 fix: load_skill支持file_path子文件加载
v2引擎_t_load_skill只返回主文档,参考文件无法读取(内部agent实测反馈)
- file_path走Skill.read_linked_file(已带路径穿越防护)
- 主文档加载时列出可用子文件
- 子文件加载失败时提示可用子文件清单
2026-09-02 17:56:10 +08:00
ymq
20471a1fda refactor: platform_ability迁出到独立模块pipeline-platform 2026-09-02 15:26:18 +08:00
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