Files
WorkBuddy df56c2c137 初始化提交:contentm_agent 工作区全量快照
内容分四块:
1、产品规划产出 —— MCN 短视频整合营销工作台的①段五份(1a 需求/1b 竞品/1c 画像/1d 策略/1e 场景)、②段两份(2a 功能/2b 布局)、③段界面(DESIGN.md 契约与令牌表 + mcn-workbench.html 原型 + 实测/会诊/审查三份 + 23 张闸门截图)。
2、开源竞品调研 —— 5 个内容工作台项目的取证原始件与 1b 系列分析文档。
3、参考资料 —— 竞品视频抽帧 1145 张 + 2 个源视频 + 功能点截图。
4、机制侧 —— 协作脚本与状态台账、工作区记忆日志、抽帧/OCR 脚本。

.gitignore 只排运行时日志、脚本备份副本与一次性探针输出,其余按原样入库。
2026-10-08 08:13:02 +08:00

85 lines
4.5 KiB
Python

# -*- coding: utf-8 -*-
"""取证脚本(第 2 棒专用):为「Postiz + PostSider 同源双形态分析」补拉增量面证据。
只读 GitHub 公开 raw / API;产物落本目录 api/fork/ 下,逐件带取证时间。
⛔ 不重复拉第 1 棒已有的 repo.json / README / tree(那些直接复用 api/ 下的)。
"""
import json, os, sys, time, urllib.request, urllib.error
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
HERE = os.path.dirname(os.path.abspath(__file__))
OUT = os.path.join(HERE, "api", "fork")
os.makedirs(OUT, exist_ok=True)
HDRS = {"User-Agent": "wb-research/1.0"}
# (落盘名, raw 路径, 仓库)
RAW = "https://raw.githubusercontent.com/%s/%s/%s" # owner/repo/branch/path
ITEMS = [
("postsider.apps_mcp.README.md", "lumizone/postsider", "main", "apps/mcp/README.md"),
("postsider.apps_mcp.server.json", "lumizone/postsider", "main", "apps/mcp/server.json"),
("postsider.apps_mcp.package.json", "lumizone/postsider", "main", "apps/mcp/package.json"),
("postsider.apps_mcp.CHANGELOG.md", "lumizone/postsider", "main", "apps/mcp/CHANGELOG.md"),
("postsider.mcp.tool-inventory.ts", "lumizone/postsider", "main", "apps/mcp/src/__tests__/tool-inventory.ts"),
("postsider.mcp.server.ts", "lumizone/postsider", "main", "apps/mcp/src/server.ts"),
("postsider.sdk.README.md", "lumizone/postsider", "main", "apps/sdk/README.md"),
("postsider.sdk.index.ts", "lumizone/postsider", "main", "apps/sdk/src/index.ts"),
("postsider.sdk.package.json", "lumizone/postsider", "main", "apps/sdk/package.json"),
("postsider.package.json", "lumizone/postsider", "main", "package.json"),
("postsider.ATTRIBUTION.md", "lumizone/postsider", "main", "ATTRIBUTION.md"),
("postsider.DEPLOYMENT.md", "lumizone/postsider", "main", "DEPLOYMENT.md"),
("postsider.skill.calendar-review.md", "lumizone/postsider", "main", "apps/mcp/skills/postsider-calendar-review/SKILL.md"),
("postsider.skill.content-publishing.md", "lumizone/postsider", "main", "apps/mcp/skills/postsider-content-publishing/SKILL.md"),
("postiz.package.json", "gitroomhq/postiz-app", "main", "package.json"),
("postiz.version.txt", "gitroomhq/postiz-app", "main", "version.txt"),
("postiz.sdk.README.md", "gitroomhq/postiz-app", "main", "apps/sdk/README.md"),
("postiz.sdk.package.json", "gitroomhq/postiz-app", "main", "apps/sdk/package.json"),
]
log = {"fetched_at": time.strftime("%Y-%m-%dT%H:%M:%S"), "items": {}}
for name, repo, branch, path in ITEMS:
url = RAW % (repo, branch, path)
rec = {"repo": repo, "branch": branch, "path": path, "url": url}
try:
req = urllib.request.Request(url, headers=HDRS)
with urllib.request.urlopen(req, timeout=40) as r:
body = r.read()
with open(os.path.join(OUT, name), "wb") as f:
f.write(body)
rec["bytes"] = len(body)
rec["ok"] = True
except urllib.error.HTTPError as e:
rec["ok"] = False
rec["error"] = "HTTP %s" % e.code
except Exception as e:
rec["ok"] = False
rec["error"] = repr(e)
log["items"][name] = rec
print("[%s] %s" % ("OK " if rec.get("ok") else "FAIL", name), rec.get("error", rec.get("bytes")))
time.sleep(0.3)
# 版本差异:取两个仓库的 releases(最近 10 条)与 tags
def api(url):
req = urllib.request.Request(url, headers={**HDRS, "Accept": "application/vnd.github+json"})
with urllib.request.urlopen(req, timeout=40) as r:
return json.loads(r.read().decode("utf-8"))
for slug, full in (("postiz", "gitroomhq/postiz-app"), ("postsider", "lumizone/postsider")):
try:
rl = api("https://api.github.com/repos/%s/releases?per_page=10" % full)
save = [{"tag_name": x.get("tag_name"), "name": x.get("name"),
"published_at": x.get("published_at"), "prerelease": x.get("prerelease")} for x in rl]
with open(os.path.join(OUT, slug + ".releases.json"), "w", encoding="utf-8") as f:
json.dump(save, f, ensure_ascii=False, indent=1)
log["items"][slug + ".releases"] = {"ok": True, "count": len(save)}
print("[releases]", slug, len(save))
except Exception as e:
log["items"][slug + ".releases"] = {"ok": False, "error": repr(e)}
print("[releases]", slug, "FAIL", repr(e))
with open(os.path.join(OUT, "_fetch_log.json"), "w", encoding="utf-8") as f:
json.dump(log, f, ensure_ascii=False, indent=1)
print("\nDONE -> " + OUT)