Bläddra i källkod

从旧包补齐产物时把包内日志按用户令 2 归位到 logs/build/ (不再落进产物仓)

现象(本次补齐后自检立刻逮到): 用 products_restore_missing.py 从 guanlan-rudong-v2_0.2.0_test_win64.zip
补齐 567 件之后, `guanlan.py check` 的「日志统一」转 FAIL —— rc=5:
  outputs/rudong/m5_cms_tcm/shared_component_bandpower.log: 日志跑到 logs/ 外面了
原因: 历史交付包把 39 件构建日志当产物发过(m5_cms_tcm/ ontology/ sop/ tcm_compatible_replay/ windscada/),
补齐就把它们又搬回了产物仓。这正是用户令 2 要统一掉的那种不一致。

处置(两处, 一次性根治):
· `products_restore_missing.take()`: 补齐时凡 `.log`/`.jsonl` 一律不落产物仓, 直接写
  `logs/build/<场>/<相对路径>`(数据不丢, 但不算产物、不进台账), 并如实打印;
· 已落地的 39 件用 `scripts/log_audit.py --migrate --yes` 归位(logs/build/rudong 现 78 件),
  台账重算: raw-derived 1725 / shipped 567 → **528**, 39 件记 `log-relocated`(报表新增一列)。

复检: 产物仓内 *.log/*.jsonl = 0 件; `guanlan.py check` 三项全绿(页面归口 不一致 0 / 日志统一 无不一致 /
呼应校验正常), 仅剩本机未装 Ollama 一条预期 FAIL。
zhouyang.xie 3 veckor sedan
förälder
incheckning
762d17ebbb
1 ändrade filer med 30 tillägg och 6 borttagningar
  1. 30 6
      scripts/products_restore_missing.py

+ 30 - 6
scripts/products_restore_missing.py

@@ -179,7 +179,25 @@ def main() -> int:
     prov = {}
 
     def take(rel: str, src_path=None, src_bytes=None):
-        """补齐一件 (或在位则只记账)。src_path=目录来源, src_bytes=zip 来源。"""
+        """补齐一件 (或在位则只记账)。src_path=目录来源, src_bytes=zip 来源。
+
+        ★ 日志不补进产物仓 (2026-09-17): 历史交付包里把构建日志也当产物发过 (如
+          `m5_cms_tcm/shared_component_bandpower.log`)。用户令 2 定的是"运行日志只在 logs/",
+          所以这里把它直接落到 `logs/build/<场>/…` —— 数据没丢, 但不再算产物、也不进台账
+          (否则每从旧包补一次, `guanlan.py check` 的「日志统一」就红一次: 日志跑到 logs/ 外面了)。
+        """
+        low = rel.lower()
+        if low.endswith(('.log', '.jsonl')):
+            from src import logfile as _lf
+            dst_log = _lf.build_log(rel, P.farm())
+            prov[rel] = dict(source='log-relocated', why='包内日志: 按用户令 2 落到 logs/build/, 不算产物')
+            if not a.dry_run:
+                dst_log.parent.mkdir(parents=True, exist_ok=True)
+                if src_bytes is not None:
+                    dst_log.write_bytes(src_bytes)
+                elif src_path is not None:
+                    shutil.copy2(src_path, dst_log)
+            return
         dst = dest_root / rel
         if dst.exists():
             # 已存在的件分两类: 我们自己重算的(raw-derived) 与 上轮已补齐的(shipped)。
@@ -244,13 +262,19 @@ def main() -> int:
     by_store = {}
     for rel, m in prov.items():
         store = rel.split('/')[0]
-        d = by_store.setdefault(store, {'raw-derived': 0, 'shipped': 0})
+        d = by_store.setdefault(store, {'raw-derived': 0, 'shipped': 0, 'log-relocated': 0})
+        d.setdefault(m['source'], 0)
         d[m['source']] += 1
-    print(f'{"仓":26s} {"raw 重算":>9s} {"随包补齐":>9s}')
+    moved = sum(d['log-relocated'] for d in by_store.values())
+    print(f'{"仓":26s} {"raw 重算":>9s} {"随包补齐":>9s}' + (f' {"日志归位":>9s}' if moved else ''))
     for store, d in sorted(by_store.items()):
-        print(f'  {store:24s} {d["raw-derived"]:9d} {d["shipped"]:9d}')
-    tot = {k: sum(d[k] for d in by_store.values()) for k in ('raw-derived', 'shipped')}
-    print(f'  {"合计":24s} {tot["raw-derived"]:9d} {tot["shipped"]:9d}')
+        print(f'  {store:24s} {d["raw-derived"]:9d} {d["shipped"]:9d}'
+              + (f' {d["log-relocated"]:9d}' if moved else ''))
+    tot = {k: sum(d[k] for d in by_store.values()) for k in ('raw-derived', 'shipped', 'log-relocated')}
+    print(f'  {"合计":24s} {tot["raw-derived"]:9d} {tot["shipped"]:9d}'
+          + (f' {tot["log-relocated"]:9d}' if moved else ''))
+    if moved:
+        print(f'  (日志不落产物仓: {moved} 件按用户令 2 落到 logs/build/, 不计入产物台账)')
 
     if a.dry_run:
         print('\n(dry-run, 未写盘)')