📦 deps(thirdparty): update snapshots
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env python3
|
||||
"""update_flow.py — `cangjie.py update` 的编排逻辑(Phase 2B,路线 C)。
|
||||
|
||||
CLI 只做确定性部分:登记来源 → 切块 → diff → change-set → 影响分析。
|
||||
需要语义判断的节点(增量候选提取、correction/contradiction 定性、合并规则应用)
|
||||
生成待处理 Agent 任务清单,由 Agent 按 methodology 完成后再交回 CLI 校验与重编译。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import shutil
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).parent))
|
||||
from build_chunks import build as build_chunks_for # noqa: E402
|
||||
from cangjie_common import create_run_workdir, load_yaml, new_run_id, sha256_file # noqa: E402
|
||||
from diff_sources import diff as diff_chunks, load_chunks # noqa: E402
|
||||
from impact_analysis import analyze, build_graph # noqa: E402
|
||||
from cangjie_common import dump_json # noqa: E402
|
||||
|
||||
|
||||
def ensure_manifest(pack: Path) -> dict:
|
||||
manifest_path = pack / ".cangjie" / "manifest.yaml"
|
||||
if manifest_path.exists():
|
||||
return load_yaml(manifest_path)
|
||||
manifest = {"schema_version": 1, "content_pack": pack.name, "sources": []}
|
||||
manifest_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
manifest_path.write_text(yaml.safe_dump(manifest, allow_unicode=True, sort_keys=False), encoding="utf-8")
|
||||
return manifest
|
||||
|
||||
|
||||
def run_update(pack: Path, new_source: Path) -> int:
|
||||
sidecar = pack / ".cangjie"
|
||||
bundle_dir = sidecar / "capabilities"
|
||||
if not (bundle_dir / "verified.yaml").exists():
|
||||
raise SystemExit(f"未找到 Capability Bundle: {bundle_dir}/verified.yaml(旧 pack 先运行 migrate-legacy)")
|
||||
|
||||
run_id = new_run_id()
|
||||
workdir = create_run_workdir(sidecar, run_id)
|
||||
|
||||
# 1. 登记来源版本
|
||||
manifest_path = sidecar / "manifest.yaml"
|
||||
manifest = ensure_manifest(pack)
|
||||
source_id = f"src-{new_source.stem.lower().replace(' ', '-')[:32]}"
|
||||
version_id = f"sha256:{sha256_file(new_source)}"
|
||||
entry = next((s for s in manifest["sources"] if s["source_id"] == source_id), None)
|
||||
if entry is None:
|
||||
entry = {"source_id": source_id, "kind": "other", "title": new_source.stem,
|
||||
"uri": new_source.resolve().as_uri(), "rights": "user-provided", "trust": "primary",
|
||||
"versions": []}
|
||||
manifest["sources"].append(entry)
|
||||
if any(v["version_id"] == version_id for v in entry["versions"]):
|
||||
print(f"[skip] 该来源版本已登记(exact duplicate): {version_id[:23]}…")
|
||||
return 0
|
||||
for v in entry["versions"]:
|
||||
if v["status"] == "active":
|
||||
v["status"] = "superseded"
|
||||
entry["versions"].append({"version_id": version_id, "added_at": time.strftime("%Y-%m-%dT%H:%M:%S%z"),
|
||||
"parser": "build_chunks v1.0", "status": "active"})
|
||||
manifest_path.write_text(yaml.safe_dump(manifest, allow_unicode=True, sort_keys=False), encoding="utf-8")
|
||||
|
||||
# 2. 切块(旧版本块先备份用于 diff)
|
||||
chunks_path = sidecar / "chunks" / "chunks.jsonl"
|
||||
old_chunks_backup = None
|
||||
if chunks_path.exists():
|
||||
old_chunks_backup = workdir / "old-chunks.jsonl"
|
||||
shutil.copyfile(chunks_path, old_chunks_backup)
|
||||
build_chunks_for(new_source, sidecar, source_id, 4000)
|
||||
|
||||
# 3. diff → change-set
|
||||
old = load_chunks(old_chunks_backup) if old_chunks_backup else []
|
||||
new = load_chunks(chunks_path)
|
||||
changes = diff_chunks(old, new)
|
||||
change_set = {
|
||||
"schema_version": 1,
|
||||
"change_id": f"chg-{run_id}",
|
||||
"content_pack": pack.name,
|
||||
"created_at": time.strftime("%Y-%m-%dT%H:%M:%S%z"),
|
||||
"base_version": old[0]["version_id"] if old else None,
|
||||
"new_version": version_id,
|
||||
"changes": changes,
|
||||
"summary": {
|
||||
"added": sum(1 for c in changes if c["change_type"] == "additive"),
|
||||
"removed": sum(1 for c in changes if c["change_type"] == "deletion"),
|
||||
"modified": sum(1 for c in changes if c["change_type"] == "modified"),
|
||||
"unchanged": len({c["content_hash"] for c in old} & {c["content_hash"] for c in new}),
|
||||
},
|
||||
}
|
||||
cs_path = sidecar / "changes" / f"{change_set['change_id']}.json"
|
||||
dump_json(cs_path, change_set)
|
||||
|
||||
# 4. 影响分析
|
||||
graph = build_graph(bundle_dir, chunks_path)
|
||||
dump_json(sidecar / "graph" / "dependencies.json", graph)
|
||||
report = analyze(graph, change_set)
|
||||
(workdir / "impact-report.md").write_text(report, encoding="utf-8")
|
||||
|
||||
# 5. 生成待处理 Agent 任务(语义节点不由 CLI 伪造)
|
||||
pending = [f"# update 待处理任务(run: {run_id})", "",
|
||||
f"change-set: `{cs_path}`;影响分析: `{workdir / 'impact-report.md'}`", "",
|
||||
"按 `methodology/` 合并规则逐项处理(CLI 不做语义判断):", ""]
|
||||
need_confirm = [c for c in changes if c.get("requires_human_confirmation")]
|
||||
additive = [c for c in changes if c["change_type"] == "additive"]
|
||||
if additive:
|
||||
pending.append(f"1. **增量候选提取**:对 {len(additive)} 个新增块跑阶段 1(可用检索式取块),"
|
||||
"新候选走阶段 1.5 三重验证 → 阶段 1.6 晋级门 → 更新 Bundle;")
|
||||
if need_confirm:
|
||||
pending.append(f"2. **人工确认项({len(need_confirm)})**:modified/deletion 块需定性 "
|
||||
"correction / contradiction / near_duplicate,冲突不得静默综合(§6.4);")
|
||||
pending += ["3. Bundle 更新后运行 `cangjie.py compile`(沿用原输出策略)重编译受影响入口;",
|
||||
"4. 运行受影响能力 + 邻居能力的回归评测(见影响分析报告)。", "",
|
||||
"> 未受影响的能力/入口不重编译,文件哈希保持不变。"]
|
||||
(workdir / "pending-tasks.md").write_text("\n".join(pending) + "\n", encoding="utf-8")
|
||||
|
||||
print(report)
|
||||
print(f"待处理任务: {workdir / 'pending-tasks.md'}")
|
||||
return 0
|
||||
Reference in New Issue
Block a user