codebee 0.1.79 → 0.1.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,10 @@ README 元数据带回,供老版本在「发现新版本」时展示新版更
6
6
 
7
7
  ## 未发布
8
8
 
9
+ ## v0.1.80(2026-10-04)
10
+
11
+ - **翻译任务交稿前自查「翻译腔」**:翻译起草要求在术语表之外新增一条交稿自查——欧化句式/逐词直译当面清(长句拆短、被动改主动,清掉「被……所」「……性」「……的存在」这类直译腔标记),译文读感应是「用目标语写出来的」、不是「翻出来的」。此前翻译腔只能靠评审 rubric「流畅度」事后抓,现在起草侧先过一遍,少一轮返工。
12
+
9
13
  ## v0.1.79(2026-10-04)
10
14
 
11
15
  - **周报起草补上「本周提交素材」取材半边**:交付契约一直承诺取材清单第一项「合并的提交(git log)」,但此前只有禅道素材半边落地、git log 全仓无实现——模型写周报时提交记录缺源,容易凭印象编。现在起草提示词在禅道素材旁并列注入最近 7 天提交摘要(40 条封顶);非 git 仓/空仓/命令失败一律静默跳过,绝不阻塞起草。
package/README.md CHANGED
@@ -33,9 +33,9 @@ Trae Agent、OpenClaw……),提供
33
33
  ---
34
34
 
35
35
  <!-- relnotes:start -->
36
- ### 最新版更新内容(v0.1.79)
36
+ ### 最新版更新内容(v0.1.80)
37
37
 
38
- - 周报起草补上「本周提交素材」取材半边:交付契约承诺的 git log 取材(最近 7 天提交摘要,40 条封顶)现在与禅道素材并列注入起草提示词——非 git 仓/空仓/命令失败静默跳过,绝不阻塞起草,周报不再凭印象编提交记录
38
+ - 翻译任务交稿前自查「翻译腔」:翻译起草要求在术语表之外新增交稿自查——欧化句式/逐词直译当面清(长句拆短、被动改主动、清「被……所/……性/……的存在」直译腔标记),译文读感是「用目标语写出来的」;翻译腔起草侧先过一遍,不再只靠评审事后抓
39
39
  <!-- relnotes:end -->
40
40
 
41
41
 
@@ -2313,7 +2313,9 @@ RESEARCH_APPENDIX = """
2313
2313
  # 翻译类稿件的追加要求(借鉴 andrewyng/translation-agent 三步法 translate→reflect→improve
2314
2314
  # 的 glossary 机制):动笔前先提炼术语表、全篇译名以表为准——术语一致性此前只靠
2315
2315
  # 评审 rubric「术语一致性」事后抓,起草侧无约定,长文译名漂移只能靠修订轮返工。
2316
- # TransAgents(多智能体文学翻译)的出版社角色分工不借鉴:评审链已有对应物。
2316
+ # 翻译腔自查条借鉴 yomiyasu(翻译腔检查器):欧化句式/逐词直译前置到起草侧自查,
2317
+ # 不再只靠评审 rubric「流畅度」事后抓。TransAgents(多智能体文学翻译)的出版社
2318
+ # 角色分工不借鉴:评审链已有对应物。
2317
2319
  TRANSLATION_APPENDIX = """
2318
2320
 
2319
2321
  ## 翻译要求(术语表先行)
@@ -2321,7 +2323,10 @@ TRANSLATION_APPENDIX = """
2321
2323
  作品名/产品名/机构名)与反复出现的领域术语,逐条给出「源文 → 译名」。
2322
2324
  - 全篇译名以术语表为准:同一源文术语从头到尾一个译法,不随上下文漂移;业界已有
2323
2325
  通用译名的从通用,没有的定一个贴切的并全篇保持一致。
2324
- - 无术语可提炼的短文可省略术语表,译名一致性要求不变。"""
2326
+ - 无术语可提炼的短文可省略术语表,译名一致性要求不变。
2327
+ - 交稿前自查翻译腔(欧化句式/逐词直译):长句拆短、被动改主动,清掉「被……所」
2328
+ 「……性」「……的存在」这类直译腔标记;译文读感应是「用目标语写出来的」,
2329
+ 不是「翻出来的」。"""
2325
2330
 
2326
2331
  NOVEL_REVISE_PROMPT = """你是__ROLE__。请根据下方汇总评审意见修订稿件文件:`__FILE__`(直接写入该文件)。文件必须以 UTF-8 编码保存(PowerShell 写文件显式加 -Encoding UTF8,禁止依赖默认编码)。
2327
2332
 
@@ -2870,25 +2875,36 @@ _CH_MENTION_RE = re.compile(r"第\s*(\d{1,4})\s*(?:[—–\-~至到]\s*(\d{1,4})
2870
2875
 
2871
2876
 
2872
2877
  def _archived_preface(workdir, start):
2873
- """前文回退:续写批次的前作章文件被归档成单文件(发布后 chapter-NN.md
2874
- 不在场)时,从「已成稿/」目录找回前文全文,供全书评审与合并成书使用。
2875
- 任一前文章节文件仍在场则视为未归档,返回空串(正常路径零影响)。"""
2878
+ """前文回退:续写批次里从第 1 章起连续归档的前缀(chapter-NN.md 不在场)
2879
+ 从「已成稿/」目录找回,供全书评审与合并成书使用。返回 (文本, 归档覆盖
2880
+ 到的章号):第 1 章仍在场返回 ("", 0)(正常路径零影响);混合态(如
2881
+ 1–20 已归档、21–28 在场)按连续缺失前缀计入——2026-10-04 实案:旧版
2882
+ 见任一章在场就整体放弃,1–20 被静默丢出成书。同题名 .md/.txt 并存只
2883
+ 取一份,不重复计字。"""
2876
2884
  if start <= 1:
2877
- return ""
2885
+ return "", 0
2886
+ covered = 0
2878
2887
  for i in range(1, start):
2879
2888
  if _read_chapter(workdir, i):
2880
- return ""
2889
+ break
2890
+ covered = i
2891
+ if covered < 1:
2892
+ return "", 0
2881
2893
  adir = os.path.join(str(workdir), _ARCHIVE_DIR)
2882
2894
  try:
2883
2895
  names = sorted(os.listdir(adir))
2884
2896
  except OSError:
2885
- return ""
2897
+ return "", 0
2886
2898
  parts = []
2899
+ stems = set()
2887
2900
  for name in names:
2888
2901
  if not name.lower().endswith((".md", ".txt")):
2889
2902
  continue
2890
2903
  if "目录" in name: # 阅读目录/章节目录是索引不是正文
2891
2904
  continue
2905
+ stem = os.path.splitext(name)[0]
2906
+ if stem in stems: # 同题名 .md/.txt 是同一份内容的两种格式
2907
+ continue
2892
2908
  p = os.path.join(adir, name)
2893
2909
  if not os.path.isfile(p):
2894
2910
  continue
@@ -2898,7 +2914,8 @@ def _archived_preface(workdir, start):
2898
2914
  continue
2899
2915
  if t and t.strip():
2900
2916
  parts.append(t.strip())
2901
- return "\n\n".join(parts)
2917
+ stems.add(stem)
2918
+ return "\n\n".join(parts), covered
2902
2919
 
2903
2920
 
2904
2921
  def _full_manuscript(workdir, start, end, cap=60000):
@@ -2910,7 +2927,7 @@ def _full_manuscript(workdir, start, end, cap=60000):
2910
2927
  old_text = "\n\n".join(t for t in (_read_chapter(workdir, i)
2911
2928
  for i in range(1, start)) if t)
2912
2929
  if not old_text and start > 1:
2913
- old_text = _archived_preface(workdir, start)
2930
+ old_text = _archived_preface(workdir, start)[0]
2914
2931
  budget = cap - len(new_text) - 2
2915
2932
  if budget <= 0:
2916
2933
  return new_text[:cap]
@@ -4383,11 +4400,11 @@ def _run_serial_review(run, task, agents, ev, stats, mode, critics, impl, route,
4383
4400
  ms_name = _ms_name(task.get("manuscript"))
4384
4401
  book_title = outline.get("book_title") or task["title"]
4385
4402
  parts = ["# %s" % book_title, ""]
4386
- # 前文归档回退:前作章文件已被归档(chapter-NN.md 不在场)时,合并成品
4387
- # 不能只剩本批——否则续写批次的「成书」会静默丢掉此前全部章节
4388
- arch_preface = _archived_preface(workdir, start) if start > 1 else ""
4403
+ # 前文归档回退:从第 1 章起连续归档的前缀(chapter-NN.md 不在场)时,
4404
+ # 合并成品不能只剩本批——否则续写批次的「成书」会静默丢掉归档前文
4405
+ arch_preface, arch_upto = _archived_preface(workdir, start) if start > 1 else ("", 0)
4389
4406
  if arch_preface:
4390
- parts.append("## 前文(第 1–%d 章 · 归档稿)" % (start - 1))
4407
+ parts.append("## 前文(第 1–%d 章 · 归档稿)" % arch_upto)
4391
4408
  parts.append("")
4392
4409
  parts.append(arch_preface)
4393
4410
  parts.append("")
@@ -4414,7 +4431,7 @@ def _run_serial_review(run, task, agents, ev, stats, mode, critics, impl, route,
4414
4431
  summary="已合并 %d 章为 %s(约 %d 字%s%s)" % (
4415
4432
  n, ms_name, total_words,
4416
4433
  ",分 %d 卷" % len(vol_heads) if vol_heads else "",
4417
- ",前文 1–%d 章取自归档" % (start - 1) if arch_preface else ""),
4434
+ ",前文 1–%d 章取自归档" % arch_upto if arch_preface else ""),
4418
4435
  duration_s=0.1)
4419
4436
 
4420
4437
  chapters_pass = all(c["passed"] for c in chapter_scores)
@@ -530,19 +530,24 @@ def locked_chapter_outline_text(workdir, chapter, cap=3000):
530
530
  return _read_workdir_text(hits[-1], cap)
531
531
 
532
532
 
533
- def locked_serial_outline_block(task, start, end, per_cap=2500, total_cap=16000):
533
+ def locked_serial_outline_block(task, start, end, per_cap=2500, total_cap=None):
534
534
  """续写大纲生成的锁定章纲注入块:本批 [start, end] 逐章汇总章纲全文。
535
- 一份章纲都没有时回退 大纲/*.md(截断兜底,至少锚住卷纲方向);两者皆无
536
- 返回 ""(零噪音)。"""
535
+ 总量上限随批大小缩放(下限 16000、上限 32000)——2026-10-04 实案:12 章
536
+ 批次章纲共 2.4 万字,旧固定 16000 截尾,第 45—48 章被生成成「待核:原
537
+ 章名未提供」。一份章纲都没有时回退 大纲/*.md(截断兜底,至少锚住卷纲
538
+ 方向);两者皆无返回 ""(零噪音)。"""
539
+ n = max(1, int(end) - int(start) + 1)
540
+ if total_cap is None:
541
+ total_cap = max(16000, min(32000, per_cap * n))
537
542
  workdir = str(task.get("workdir") or "")
538
543
  parts, used = [], 0
539
544
  if workdir:
540
- for n in range(int(start), int(end) + 1):
545
+ for num in range(int(start), int(end) + 1):
541
546
  if used >= total_cap:
542
547
  break
543
- t = locked_chapter_outline_text(workdir, n, cap=per_cap)
548
+ t = locked_chapter_outline_text(workdir, num, cap=per_cap)
544
549
  if t:
545
- head = "### 第 %d 章锁定章纲" % n
550
+ head = "### 第 %d 章锁定章纲" % num
546
551
  parts.append(head + "\n" + t)
547
552
  used += len(head) + len(t) + 2
548
553
  if parts:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codebee",
3
- "version": "0.1.79",
3
+ "version": "0.1.80",
4
4
  "description": "CodeBee · 多智能体编排台 — 统一编排本机 AI 编码 CLI(Codex / Claude Code / QwenCode / OpenCode / Aider…):目标→拆解→路由→执行→验证→跨厂商评审→修复→报告。纯 Python 标准库实现,本地 Web UI。",
5
5
  "license": "MIT",
6
6
  "bin": {