codebee 0.1.56 → 0.1.57

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.
@@ -83,12 +83,7 @@ def _append_audit(workdir, chapter, branches, pick):
83
83
  if not workdir:
84
84
  return
85
85
  try:
86
- p = os.path.abspath(os.path.join(str(workdir), ".codebee",
87
- "branch-plans.md"))
88
- root = os.path.abspath(str(workdir))
89
- if root not in p.split(os.sep)[:-len([".codebee", "branch-plans.md"])]:
90
- if not p.startswith(root + os.sep):
91
- return
86
+ p = _audit_path(workdir)
92
87
  os.makedirs(os.path.dirname(p), exist_ok=True)
93
88
  with open(p, "a", encoding="utf-8") as f:
94
89
  if f.tell() == 0:
@@ -103,3 +98,33 @@ def _append_audit(workdir, chapter, branches, pick):
103
98
  f.write("\n")
104
99
  except Exception:
105
100
  pass
101
+
102
+
103
+ def _audit_path(workdir):
104
+ """审计文件路径(越界拒绝:workdir 必须存在的目录)。"""
105
+ from pathlib import Path
106
+ root = Path(workdir).resolve()
107
+ if not root.is_dir():
108
+ raise ValueError("workdir 必须是已存在的目录")
109
+ return root / ".codebee" / "branch-plans.md"
110
+
111
+
112
+ def mark_stale(workdir, chapter):
113
+ """正史重写后旧推演标过期(inkos 借鉴:分支计划随正史失效)。
114
+
115
+ 修订步骤改写章稿后,本章的分支计划节头追加「(已过期,正史已重写)」——
116
+ 防止后续翻看审计时把旧推演当成当前正史的来源。失败静默。"""
117
+ if not workdir:
118
+ return
119
+ try:
120
+ p = _audit_path(workdir)
121
+ if not p.is_file():
122
+ return
123
+ txt = p.read_text(encoding="utf-8", errors="replace")
124
+ header = "## 第 %d 章\n" % chapter
125
+ stale_header = "## 第 %d 章(已过期,正史已重写)\n" % chapter
126
+ if header in txt and stale_header not in txt:
127
+ p.write_text(txt.replace(header, stale_header, 1),
128
+ encoding="utf-8")
129
+ except Exception:
130
+ pass
package/app/core/jobs.py CHANGED
@@ -260,10 +260,10 @@ def wait_for_idle(timeout=10):
260
260
 
261
261
 
262
262
  def begin_restart_drain():
263
- """升级任务已退出执行位且没有用户任务时,原子停止接单。"""
263
+ """升级任务已退出执行位且没有用户任务或 direct 对话时,原子停止接单。"""
264
264
  global _restart_drain
265
265
  with _pool_lock:
266
- if _restart_drain or _alive != 0:
266
+ if _restart_drain or _alive != 0 or _chat_alive != 0:
267
267
  return False
268
268
  _restart_drain = True
269
269
  return True
@@ -921,7 +921,7 @@ def _do_selfupgrade(job, ev):
921
921
  if ev.is_set() or (store.get_run(run_id) or {}).get("status") != "running":
922
922
  return
923
923
  store.finish_step(run_id, step["n"], "done" if res["ok"] else "failed",
924
- summary="升级完成,点「重启」生效" if res["ok"]
924
+ summary="升级完成,服务将自动重启生效" if res["ok"]
925
925
  else ("升级失败: " + res["error"][:300]),
926
926
  exit_code=res.get("exit_code"))
927
927
  # expected_status 守卫:用户已强制终止的运行保持 cancelled,不被改写