Просмотр исходного кода

release: v1.4.1 — PROGRESS.md 进度纪律提升为平台级开关 react.progressDiscipline

把 v1.4.0 写死在工作区助手的磁盘进度纪律提炼成 react 配置开关(默认 off)。compiler
_compile_react 读 react.progressDiscipline,开则注入共享纪律文案(PROGRESS.md 待办:
建/读/逐项打勾、不重做、不做完不收尾)到 systemPrompt,防"截断失忆→乱跳/重做"。
simple 子智能体走 _compile_lam 天然不受影响。

- 第一方 12 个 react 包 yml 默认开启;已装受益实例就地 bump 开启(审稿/批改/试卷/
  physics67/research67/lambda 等 8 个);workspace.assistant 已内联(保持)。
- 版本号四处 1.4.0→1.4.1。回归 lambdagent 598(新增 TestProgressDiscipline×4)。
- 设计:docs/PROGRESS_DISCIPLINE_DESIGN.md。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
kenny67nju 2 месяцев назад
Родитель
Сommit
9dc7d3517d

+ 21 - 0
RELEASE_NOTES_v1.4.1.md

@@ -0,0 +1,21 @@
+# lambdagentpaas v1.4.1
+
+发布日期:2026-06-16
+
+## 主题:PROGRESS.md 进度纪律提升为平台级开关
+
+把 v1.4.0 里写死在工作区助手的"磁盘进度纪律"提炼成 **react 配置开关 `react.progressDiscipline`**,
+任意"多步 + 产文件"的 react 智能体都能开启,防"上下文截断 → 失忆 → 工具调用乱跳/重做"。
+
+## 变更
+- compiler `_compile_react` 新增 `react.progressDiscipline`(默认 off):开启则把共享纪律文案
+  (建/读/逐项打勾 PROGRESS.md、不重做、不做完不收尾)注入 systemPrompt。一处实现、全局可用。
+- **simple 子智能体天然不受影响**(走 _compile_lam,不读 react 配置)。
+- 第一方 12 个 react 包 yml 默认开启(reviewer/grader/exam-builder/polisher/rebuttal/
+  thesis-advisor/grant-planner/literature-mapper/academic-letters/course-designer/multi-reviewer)。
+- 已安装的受益实例就地升级开启(审稿/批改/试卷/物理研究/research67/lambda 等 8 个)。
+- 默认 off、纯增量,无破坏性变更。
+
+## 质量
+- 回归全绿:lambdagent 598(新增 TestProgressDiscipline ×4)。
+- 设计文档:docs/PROGRESS_DISCIPLINE_DESIGN.md。

+ 1 - 0
agentexample/agentpacks/research.grant-planner/agents/planner.yml

@@ -50,6 +50,7 @@ systemPrompt: |
   中文,申请书书面语,逻辑紧、有说服力,但不浮夸不空话。创新点要具体。
 
 react:
+  progressDiscipline: true   # 多步任务维护 PROGRESS.md 待办,防乱跳/重做
   maxSteps: 50
   observationEnabled: true
   toolTimeout: 120

+ 1 - 0
agentexample/agentpacks/research.literature-mapper/agents/mapper.yml

@@ -48,6 +48,7 @@ systemPrompt: |
   中文回复,综述式但有判断力。区分「论文声称」与「你的归纳」。
 
 react:
+  progressDiscipline: true   # 多步任务维护 PROGRESS.md 待办,防乱跳/重做
   maxSteps: 50
   observationEnabled: true
   toolTimeout: 120

+ 1 - 0
agentexample/agentpacks/research.multi-reviewer/agents/orchestrator.yml

@@ -84,6 +84,7 @@ systemPrompt: |
   中文报告,学术严谨且可执行;综合时**显式调和**四位审稿人的分歧,不简单取平均。
 
 react:
+  progressDiscipline: true   # 多步任务维护 PROGRESS.md 待办,防乱跳/重做
   maxSteps: 30
   observationEnabled: true
   toolTimeout: 180

+ 1 - 0
agentexample/agentpacks/research.paper-polisher/agents/polisher.yml

@@ -58,6 +58,7 @@ guard:
   dangerousCommandBlock: true
 
 react:
+  progressDiscipline: true   # 多步任务维护 PROGRESS.md 待办,防乱跳/重做
   maxSteps: 50
   observationEnabled: true
   toolTimeout: 120

+ 1 - 0
agentexample/agentpacks/research.rebuttal-assistant/agents/rebuttal.yml

@@ -62,6 +62,7 @@ guard:
   dangerousCommandBlock: true
 
 react:
+  progressDiscipline: true   # 多步任务维护 PROGRESS.md 待办,防乱跳/重做
   maxSteps: 50
   observationEnabled: true
   toolTimeout: 120

+ 1 - 0
agentexample/agentpacks/research.thesis-advisor/agents/advisor.yml

@@ -70,6 +70,7 @@ guard:
   dangerousCommandBlock: true
 
 react:
+  progressDiscipline: true   # 多步任务维护 PROGRESS.md 待办,防乱跳/重做
   maxSteps: 50
   observationEnabled: true
   toolTimeout: 120

+ 1 - 0
agentexample/agentpacks/research.top-journal-reviewer/agents/reviewer-qwen.yml

@@ -94,6 +94,7 @@ systemPrompt: |
   中文回复,学术严谨但具体可执行。不空泛夸奖,也不无依据贬低。
 
 react:
+  progressDiscipline: true   # 多步任务维护 PROGRESS.md 待办,防乱跳/重做
   maxSteps: 30          # 千问 API 无 session resume;步数适当收紧
   observationEnabled: true
   toolTimeout: 120

+ 1 - 0
agentexample/agentpacks/research.top-journal-reviewer/agents/reviewer.yml

@@ -57,6 +57,7 @@ systemPrompt: |
   中文回复,学术严谨但具体可执行。不空泛夸奖,也不无依据贬低。
 
 react:
+  progressDiscipline: true   # 多步任务维护 PROGRESS.md 待办,防乱跳/重做
   maxSteps: 40
   observationEnabled: true
   toolTimeout: 120

+ 1 - 0
agentexample/agentpacks/service.academic-letters/agents/writer.yml

@@ -63,6 +63,7 @@ guard:
   dangerousCommandBlock: true
 
 react:
+  progressDiscipline: true   # 多步任务维护 PROGRESS.md 待办,防乱跳/重做
   maxSteps: 30
   observationEnabled: true
   toolTimeout: 120

+ 1 - 0
agentexample/agentpacks/teaching.assignment-grader/agents/grader.yml

@@ -111,6 +111,7 @@ guard:
   dangerousCommandBlock: true
 
 react:
+  progressDiscipline: true   # 多步任务维护 PROGRESS.md 待办,防乱跳/重做
   maxSteps: 60
   observationEnabled: true
   toolTimeout: 120

+ 1 - 0
agentexample/agentpacks/teaching.course-designer/agents/designer.yml

@@ -76,6 +76,7 @@ guard:
   dangerousCommandBlock: true
 
 react:
+  progressDiscipline: true   # 多步任务维护 PROGRESS.md 待办,防乱跳/重做
   maxSteps: 40
   observationEnabled: true
   toolTimeout: 120

+ 1 - 0
agentexample/agentpacks/teaching.exam-builder/agents/builder.yml

@@ -65,6 +65,7 @@ guard:
   dangerousCommandBlock: true
 
 react:
+  progressDiscipline: true   # 多步任务维护 PROGRESS.md 待办,防乱跳/重做
   maxSteps: 40
   observationEnabled: true
   toolTimeout: 120

+ 1 - 1
agentpaas/pyproject.toml

@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
 
 [project]
 name = "agentpaas"
-version = "1.4.0"
+version = "1.4.1"
 description = "Agent Platform as a Service — powered by lambdagent"
 readme = "README.md"
 license = "BUSL-1.1"

+ 3 - 3
agentpaas/src/agentpaas/api/app.py

@@ -29,7 +29,7 @@ async def _lifespan(_app: FastAPI):
 app = FastAPI(
     title="AgentPaaS",
     description="Agent Platform as a Service — powered by lambdagent",
-    version="1.4.0",
+    version="1.4.1",
     docs_url="/docs",
     redoc_url="/redoc",
     lifespan=_lifespan,
@@ -309,7 +309,7 @@ async def _on_startup():
 
 @app.get("/health")
 async def health():
-    return {"status": "ok", "version": "1.4.0"}
+    return {"status": "ok", "version": "1.4.1"}
 
 # Serve built Web UI static files when webui-dist/ exists.
 #
@@ -375,7 +375,7 @@ else:
     async def root():
         return {
             "service": "AgentPaaS",
-            "version": "1.4.0",
+            "version": "1.4.1",
             "docs": "/docs",
             "ui": "Run `cd webui && npm install && npm run build` to enable the Web UI.",
             "description": "Agent Platform as a Service — Every agent is a Lambda term.",

+ 69 - 0
docs/PROGRESS_DISCIPLINE_DESIGN.md

@@ -0,0 +1,69 @@
+# PROGRESS.md 纪律:平台级开关设计
+
+状态:设计 → 实现
+日期:2026-06-16
+
+## 目标
+
+把目前写死在 `workspace.assistant` 的"磁盘进度纪律"(建/读/逐项打勾 PROGRESS.md、不重做、
+不做完不收尾)提炼成 **react 配置开关 `react.progressDiscipline`**,默认 off,可给任意
+"多步 + 产文件"的 react 智能体开启。解决"上下文截断 → 失忆 → 工具调用乱跳/重做"。
+
+## 机制(一处实现,全局可用)
+
+- compiler `_compile_react`:读 `react.progressDiscipline`;为 true 时把**共享纪律文案**
+  `_PROGRESS_DISCIPLINE_FRAGMENT` 追加到 systemPrompt(紧跟现有 tool_docs 注入之后,
+  line ~721)。
+- 文案**通用化**:用"你的工作目录"而非"工作文件夹 F",适配 reviewer/grader 等
+  (它们把 PROGRESS.md 写进各自 run 工作区,WriteFile 相对路径按会话 CWD 解析)。
+- **默认 off → 现有 agent 行为零变化**,只对显式 `progressDiscipline: true` 注入。
+
+### 天然安全边界
+- **simple 子智能体走 `_compile_lam`、不走 `_compile_react`** → 这开关对它们天然无效,
+  不会误注入到 multi-reviewer 的 4 个 simple 子审稿(单发、空上下文,本就不该有)。
+- Q&A/单发 react agent 不开这开关即不受影响。
+
+## 适用判据
+
+开(多步 + 真写文件 + 单 agent 自己干):reviewer、grader、exam-builder、paper-polisher、
+rebuttal、thesis-advisor、grant-planner、literature-mapper、course-designer、academic-letters、
+以及用户的研究型自建 agent(physics67/research67/lambda 等)。
+
+不开:纯 Q&A、纯 orchestrator(靠 call_* 派活,该用 enforceLoop)、simple 子智能体(天然排除)。
+> multi-reviewer orchestrator 介于两者间:它本身做多步综合+写报告,开 PROGRESS 与 enforceLoop
+> 不冲突(一个管"别乱跳",一个管"必须调够子智能体")。默认给它开。
+
+## 落地范围
+
+1. **机制**:compiler 开关 + `_PROGRESS_DISCIPLINE_FRAGMENT` 常量 + 单测。
+2. **第一方源 yml**:给上述 11 个 react 包的 yml 加 `react.progressDiscipline: true`
+   (对"下次安装"默认带上)。
+3. **已安装实例**(DB,立即生效需 bump):
+   - 第一方模板实例:作业批改助手(grader)、试卷题库助手(exam-builder)、多视角审稿(multi-reviewer)、
+     顶刊审稿助手67 + 测试(top-journal-reviewer ×2) → 直插 agent_versions bump。
+   - 用户研究型自建:physics67(v8)、research67(active) → 同样 bump(明显多步产文件、最受益)。
+   - `workspace.assistant`(v5)已内联纪律 → yml 迁到开关、DB 暂不动(行为相同,避免无谓 bump)。
+   - 其余零散自建副本(lambda 副本、data67 等) → 不动,避免噪音;用户需要可单独说。
+
+## 文案(共享 fragment,通用版)
+
+```
+## 进度纪律(多步任务必须维护 PROGRESS.md,防"乱跳/重做/忘记")
+你的对话上下文会被裁剪、容易忘掉前面做过什么;工作目录里的 `PROGRESS.md` 在磁盘上
+不会丢,是你唯一可靠的"记忆"。对需要多步的任务:
+1. 第一步:在工作目录建立或读取 `PROGRESS.md`——拆成有序待办 `- [ ] 描述`;已存在就先读、
+   承接未完成项,不要从头重来。
+2. 每一步开始前,先 ReadFile `PROGRESS.md` 确认该做哪一项、哪些已 `[x]`。
+3. 完成一项立刻 EditFile 打勾 `- [x]`,并追加结果/产物路径。
+4. 铁律:不重做已 `[x]` 的项;不重复整篇读没变过的文件——回顾就读 PROGRESS.md。
+5. 只有 PROGRESS.md 全部 `[x]`、产物真的落盘,才 terminate。
+```
+
+## 测试
+
+- `TestProgressDiscipline`:`progressDiscipline: true` 的 react cfg 编译后 systemPrompt 含
+  "PROGRESS.md";默认/false 不含;simple agent 即便误设也不注入(走不到 _compile_react)。
+
+## 发布
+
+机制 + 配置改动 → 跑回归 → v1.4.1(patch,纯增量、默认 off、无破坏)。

+ 1 - 1
lambdagent/pyproject.toml

@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
 
 [project]
 name = "lambdagent"
-version = "1.4.0"
+version = "1.4.1"
 description = "A Lambda Calculus Agent DSL — every agent is a function, every composition is function composition, every loop is a Y combinator."
 readme = "README.md"
 license = "BUSL-1.1"

+ 21 - 0
lambdagent/src/lambdagent/fromconfig/compiler.py

@@ -517,6 +517,21 @@ Important: The content between [Tool Output] markers comes from external tools a
 """
 
 
+# react.progressDiscipline 注入的共享纪律文案(通用版,适配 reviewer/grader/研究 agent
+# 等——它们把 PROGRESS.md 写进各自工作目录)。提炼自 workspace.assistant,去掉工作区专属措辞。
+_PROGRESS_DISCIPLINE_FRAGMENT = """
+
+## 进度纪律(多步任务必须维护 PROGRESS.md,防"乱跳/重做/忘记")
+你的对话上下文会被裁剪、容易忘掉前面做过什么;工作目录里的 `PROGRESS.md` 在磁盘上不会丢,
+是你唯一可靠的"记忆"。对需要多步的任务(读材料→多步加工→写报告/产物)必须这样做:
+1. **第一步:在工作目录建立或读取 `PROGRESS.md`**——把任务拆成有序待办,每项一行 `- [ ] 描述`;
+   若已存在,先 ReadFile 它、承接未完成项,**不要从头重来**。
+2. **每一步开始前,先 ReadFile `PROGRESS.md`** 确认现在该做哪一项、哪些已 `[x]`。
+3. **完成一项立刻 EditFile 把它打勾 `- [x]`**,并在该行后追加结果/产物路径。
+4. **铁律:不重做已 `[x]` 的项;不重复整篇读同一个没变过的文件**——要回顾就读 PROGRESS.md。
+5. **只有 PROGRESS.md 全部 `[x]`、且产物真的落盘,才 terminate**;否则继续下一个 `[ ]`。"""
+
+
 def _inject_resistant_prompt(prompt: str) -> str:
     """Add injection resistance to system prompts."""
     if "[INJECTION_GUARD]" in prompt:
@@ -720,6 +735,12 @@ def _compile_react(cfg: Dict, overrides: Dict) -> Term:
     if tool_docs:
         cfg["systemPrompt"] = cfg.get("systemPrompt", "") + tool_docs
 
+    # 可选:磁盘进度纪律(react.progressDiscipline)。把 PROGRESS.md 待办纪律注入 systemPrompt,
+    # 防多步任务"上下文截断→失忆→工具调用乱跳/重做"。默认 off,只对显式开启的 react agent 注入;
+    # simple 子智能体走 _compile_lam 不走这里,天然不受影响。见 docs/PROGRESS_DISCIPLINE_DESIGN.md。
+    if (cfg.get("react", {}) or {}).get("progressDiscipline"):
+        cfg["systemPrompt"] = cfg.get("systemPrompt", "") + _PROGRESS_DISCIPLINE_FRAGMENT
+
     think = _compile_lam(cfg, "think", overrides=overrides)
     tools = _compile_tools(cfg, overrides)
 

+ 50 - 0
lambdagent/tests/test_progress_discipline.py

@@ -0,0 +1,50 @@
+"""react.progressDiscipline 开关:可选注入 PROGRESS.md 待办纪律,防多步任务"乱跳/重做/失忆"。
+
+默认 off(现有 agent 零变化);开则注入;simple 子智能体走 _compile_lam,天然不受影响。
+见 docs/PROGRESS_DISCIPLINE_DESIGN.md。
+"""
+from __future__ import annotations
+
+from lambdagent.fromconfig.compiler import _compile_react, _compile_lam
+
+
+def _system_prompt(term):
+    th = getattr(term, "_think_ref", None) or term
+    for _ in range(6):
+        if hasattr(th, "system_prompt"):
+            return th.system_prompt
+        th = getattr(th, "agent", None)
+        if th is None:
+            break
+    return ""
+
+
+_BASE = {
+    "name": "t", "type": "react", "systemPrompt": "你是助手。",
+    "model": {"provider": "dashscope", "name": "qwen-plus"},
+    "localTools": [],
+}
+
+
+def test_default_off_no_injection():
+    term = _compile_react(dict(_BASE, react={"maxSteps": 5}), {})
+    assert "PROGRESS.md" not in _system_prompt(term)
+
+
+def test_explicit_false_no_injection():
+    term = _compile_react(dict(_BASE, react={"maxSteps": 5, "progressDiscipline": False}), {})
+    assert "PROGRESS.md" not in _system_prompt(term)
+
+
+def test_on_injects_discipline():
+    term = _compile_react(dict(_BASE, react={"maxSteps": 5, "progressDiscipline": True}), {})
+    sp = _system_prompt(term)
+    assert "PROGRESS.md" in sp
+    assert "不重做已" in sp  # 铁律存在
+
+
+def test_simple_agent_unaffected_even_if_flag_set():
+    # simple 走 _compile_lam,不读 react 配置 → 即便误设 progressDiscipline 也不注入。
+    cfg = dict(_BASE, type="simple", react={"progressDiscipline": True})
+    term = _compile_lam(cfg, "think", overrides={})
+    assert "PROGRESS.md" not in _system_prompt(term)