diff --git a/.hlpd-protocol b/.hlpd-protocol new file mode 100644 index 0000000..c723815 --- /dev/null +++ b/.hlpd-protocol @@ -0,0 +1,30 @@ +# HLDP执行协议 · D146 +# HLDP不是文档格式——是铸渊→工具系统的指令协议 + +## 新增字段 + +@exec: 可执行命令。用编号引用工具和参数。一行一条。 + 编号查 .code-map 翻译成实际路径后执行。 + 格式: <编号> <参数...> + 例: VA-050 /tmp/new.jpg /tmp/ref.jpg + +@check: 执行后校验。返回0=通过,非0=不通过。 + 格式: <编号> <参数...> + 例: TL-CHECK qwen-vision 风格一致性 85 + +@rollback: 失败回滚。可选。 + +## 工具系统收到HLDP后的操作 + +1. 解析 @exec 行 → 提取编号和参数 +2. 编号 → 查 .code-map → 拿到路径/指令 +3. 替换参数 → 组成完整命令 +4. 执行 → 返回输出 +5. 解析 @check → 校验 → 通过/不通过 + +## 工具系统不需要知道 +- HLDP里写了什么背景故事 +- trigger/lock/why 是什么意思 +- 为什么要执行这个命令 + +工具系统只做: 解析 @exec → 查表 → 执行 → 返回。 diff --git a/scripts/hldp-exec b/scripts/hldp-exec new file mode 100755 index 0000000..3e706b5 --- /dev/null +++ b/scripts/hldp-exec @@ -0,0 +1,174 @@ +#!/usr/bin/env python3 +"""HLDP执行器 +收到HLDP文件 → 解析@exec/@check → 查.code-map → 执行 → 返回 + +用法: + hldp-exec 执行HLDP文件中的@exec指令 + hldp-exec --dry-run 只翻译不执行 + hldp-exec --code-map 显示当前.code-map内容 +""" + +import sys, os, subprocess, re, json + +REPO = os.path.expanduser("~/guanghulab") +CODE_MAP_PATH = os.path.join(REPO, ".code-map") + +def load_code_map(): + """加载 .code-map → {编号: 路径}""" + cm = {} + if not os.path.exists(CODE_MAP_PATH): + return cm + with open(CODE_MAP_PATH) as f: + for line in f: + line = line.strip() + if not line or line.startswith("#"): + continue + if "=" in line: + k, v = line.split("=", 1) + cm[k.strip()] = v.strip() + return cm + +def resolve(code, code_map): + """编号 → 实际命令""" + if code in code_map: + return code_map[code] + # 尝试模糊匹配 + for k, v in code_map.items(): + if code in k: + return v + return None + +def parse_hldp(path): + """解析HLDP文件,提取@exec和@check字段""" + execs = [] + checks = [] + in_exec = False + in_check = False + + with open(path) as f: + for line in f: + line = line.strip() + if line.startswith("@exec:"): + in_exec = True + in_check = False + cmd = line.split(":", 1)[1].strip() + if cmd: + execs.append(cmd) + elif line.startswith("@check:"): + in_exec = False + in_check = True + cmd = line.split(":", 1)[1].strip() + if cmd: + checks.append(cmd) + elif line.startswith("@"): + in_exec = False + in_check = False + elif in_exec and line.strip(): + execs.append(line.strip()) + elif in_check and line.strip(): + checks.append(line.strip()) + + return execs, checks + +def translate(commands, code_map): + """翻译编号→真实命令""" + result = [] + for cmd in commands: + parts = cmd.split() + if not parts: + continue + code = parts[0] + resolved = resolve(code, code_map) + if not resolved: + result.append(("UNKNOWN", f"未知编号: {code}", cmd)) + continue + + # 密钥类: 返回加载指令 + if code.startswith("SC-"): + result.append(("SECRET", resolved, cmd)) + continue + + # 脚本/文件类: 组成完整命令 + full_path = os.path.join(REPO, resolved) + args = parts[1:] + + if resolved.endswith(".py"): + full_cmd = f"python3 {full_path} " + " ".join(args) + elif resolved.endswith(".js"): + full_cmd = f"node {full_path} " + " ".join(args) + else: + full_cmd = f"{full_path} " + " ".join(args) + + result.append(("EXEC", full_cmd, cmd)) + + return result + +def run(translated, dry_run=False): + """执行翻译后的命令""" + for i, (typ, cmd, original) in enumerate(translated): + print(f"[{i+1}] {original}") + print(f" → {cmd}") + + if typ == "UNKNOWN": + print(f" ✗ 无法执行: 编号未注册") + continue + if typ == "SECRET": + print(f" ✓ 密钥指令已就绪(不在此处执行)") + continue + + if dry_run: + print(f" (dry-run, 未实际执行)") + continue + + try: + proc = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=300) + if proc.returncode == 0: + print(f" ✓ 执行成功") + if proc.stdout.strip(): + # 截取前500字符 + out = proc.stdout.strip()[:500] + print(f" {out}") + else: + print(f" ✗ 执行失败 (code={proc.returncode})") + if proc.stderr.strip(): + print(f" {proc.stderr.strip()[:300]}") + except Exception as e: + print(f" ✗ 异常: {e}") + +if __name__ == "__main__": + if len(sys.argv) < 2: + print(__doc__) + sys.exit(1) + + arg = sys.argv[1] + + if arg == "--code-map": + cm = load_code_map() + for k, v in sorted(cm.items()): + print(f" {k:<12} = {v}") + sys.exit(0) + + filepath = arg + dry_run = "--dry-run" in sys.argv + + if not os.path.exists(filepath): + print(f"✗ 文件不存在: {filepath}") + sys.exit(1) + + cm = load_code_map() + execs, checks = parse_hldp(filepath) + + if not execs and not checks: + print("⚠ 该HLDP文件中没有 @exec 或 @check 字段") + sys.exit(0) + + print(f"=== 执行 {filepath} ===") + + if execs: + translated = translate(execs, cm) + run(translated, dry_run) + + if checks: + print(f"\n--- @check 校验 ---") + translated = translate(checks, cm) + run(translated, dry_run) diff --git a/video-ai-system/tasks/vision-check.hldp b/video-ai-system/tasks/vision-check.hldp new file mode 100644 index 0000000..9733d77 --- /dev/null +++ b/video-ai-system/tasks/vision-check.hldp @@ -0,0 +1,23 @@ +# 视觉分析 · 出图品控任务 +# 每次WorkRally或Seedance出图后,跑这个HLDP + +> HLDP://video-ai-system/tasks/D146-vision-check +> D146 · 2026-06-26 +> 铸渊 ICE-GL-ZY001 + +--- + +@trigger: 新图生成完毕 +@context: 对比新图和参考图,确认风格一致 +@lock: ⊢ 出图后必跑·不跑不提交 + +@exec: VA-050 /tmp/new_shot.jpg /tmp/ref_plaque.jpg + +@check: style_match 必须为 true +@check: color_consistency 必须 > 70 + +@rollback: 如果 style_match=false → 读取 recommendation → 修正提示词 → 重新出图 → 再跑本HLDP + +--- + +@why: D146踩坑3——闭眼出图不审查导致风格跑偏。冰朔说"别像个瞎子"。现在每出一张图,跑这个HLDP,qwen-vl-max当眼睛。