🔄 卡若AI 同步 2026-03-31 19:29 | 更新:Cursor规则、水溪整理归档、卡木、运营中枢工作台 | 排除 >20MB: 14 个

This commit is contained in:
2026-03-31 19:29:21 +08:00
parent 0ef13c589c
commit 2b8b5952c1
9 changed files with 407 additions and 8 deletions

View File

@@ -46,6 +46,7 @@ alwaysApply: true
- **卡若**:仅接手 **Agent 物理上不能代劳** 的动作:短信/支付/人脸/企业 SSO、不可逆删除的最终确认、需本人法律意思表示的操作、以及 **第三方强人机校验**(如 Turnstile、必须逐格输入的 OTP、仅人类可过的风控
- **当用户明确说「方案定了我能百分百完成」**Agent 必须交付 **可勾选清单**(步骤序、每步做什么、成功长什么样、失败改走哪条 B 方案),**不得**用空话代替步骤。
- **浏览器 / 注册类**Agent 仍须完成 **收信mail.tm/IMAP、解析邮件链接、打开正确 URL、轮询验证码**;若页面因多输入框/人机验证拒绝自动化,须在清单中写清 **为何** 需卡若手动及 **具体操作**例如「6 位验证码逐格输入,勿整段粘贴」)。
- **Vercel / v0 + mail.tm 取码循环****不要跟单邮箱死磕**。本轮收不到「Sign-up Verification」或明显走错登录页时**放弃该 mail.tm、换新邮箱再注册**;可执行 `03_卡木/木根_逆向分析/全网AI自动注册/脚本/vercel_mailtm_signup_loop.py`(见该目录 `SKILL.md` 与 `水溪_整理归档/经验库/待沉淀/2026-03-31_Vercel与v0_mail.tm注册_OTP与团队创建.md`)。
### 经验沉淀(出了问题要入账 · 可复用)

View File

@@ -23,3 +23,23 @@
- Turnstile / 企业策略可能拦截自动化或一次性域名。
- 客观无法代劳时:向卡若交付 **可勾选清单**(含「逐格 OTP」等符合 `.cursor/rules/karuo-ai.mdc` 问题自治分工。
## 循环策略(取码不行就换邮箱 · 做通)
**原则**:不要跟**同一封收不到码 / 只有 Attempted Sign-in / OTP 总失败**的邮箱死磕——**超时无「Sign-up Verification」→ 放弃该 mail.tm → 脚本自动生成下一邮箱 → 继续注册**。
**脚本(木根)**`03_卡木/木根_逆向分析/全网AI自动注册/脚本/vercel_mailtm_signup_loop.py`
```bash
cd "/Users/karuo/Documents/个人/卡若AI/03_卡木/木根_逆向分析/全网AI自动注册/脚本"
# 每轮打印新邮箱 + 注册链接;你在浏览器点 Continue with Email收不到注册验证码则自动下一轮
python3 vercel_mailtm_signup_loop.py --max-rounds 8 --poll-timeout 180
# 需要先手动点发码再轮询时:
python3 vercel_mailtm_signup_loop.py --pause-enter --poll-timeout 240
# 每轮结果落盘备查:
python3 vercel_mailtm_signup_loop.py --out-jsonl ./vercel_mailtm_rounds.jsonl
```
说明:脚本**忽略**环境变量 `MAILTM_ADDRESS` / `MAILTM_PASSWORD`,每轮都是**全新** mail.tm避免固定邮箱卡死。

View File

@@ -14,6 +14,7 @@
from __future__ import annotations
import argparse
import json
import os
import re
import subprocess
@@ -36,6 +37,10 @@ _BASE_RGB = (26, 28, 34) # 与字同系深灰蓝
_WASH_ALPHA = int(255 * 0.05) # 整屏极淡底雾(约 95% 透)
_TITLE_ALPHA = int(255 * 0.09)
_BODY_ALPHA = int(255 * 0.11)
# 第二页底部「轻行动」略亮于正文,仍属低调(普通人能扫到,不抢 SEO 藏词主责)
_ACTION_ALPHA = int(255 * 0.22)
_STATE_NAME = ".soul_seo_tail_state.json"
def load_keywords(path: Path) -> list[str]:
@@ -114,6 +119,40 @@ def probe_size_rate(main_mp4: Path) -> tuple[int, int, int]:
return width, height, sr
def probe_duration_sec(mp4: Path) -> float:
r = subprocess.run(
[
"ffprobe",
"-v",
"error",
"-show_entries",
"format=duration",
"-of",
"default=noprint_wrappers=1:nokey=1",
str(mp4),
],
capture_output=True,
text=True,
)
try:
return float((r.stdout or "").strip() or 0.0)
except ValueError:
return 0.0
def load_tail_state(state_path: Path) -> dict:
if not state_path.is_file():
return {}
try:
return json.loads(state_path.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError):
return {}
def save_tail_state(state_path: Path, state: dict) -> None:
state_path.write_text(json.dumps(state, ensure_ascii=False, indent=2), encoding="utf-8")
def render_keyword_page_subtle_rgba(
width: int,
height: int,
@@ -121,8 +160,13 @@ def render_keyword_page_subtle_rgba(
png_path: Path,
font_path: Path | None,
page_label: str,
footer_line: str | None = None,
footer_alpha: int | None = None,
) -> None:
"""全透明底 + 极淡同色系雾 + 同色系略亮字(低对比、高透明)。"""
"""全透明底 + 极淡同色系雾 + 同色系略亮字(低对比、高透明)。
footer_line可选多画在底部用于第二页轻引导不替代正片 cta_ending
"""
if Image is None:
raise RuntimeError("需要安装 Pillow: pip install pillow")
img = Image.new("RGBA", (width, height), (0, 0, 0, 0))
@@ -134,8 +178,12 @@ def render_keyword_page_subtle_rgba(
try:
title_font = ImageFont.truetype(str(fp), 26)
body_font = ImageFont.truetype(str(fp), 20)
try:
foot_font = ImageFont.truetype(str(fp), 18)
except OSError:
foot_font = body_font
except OSError:
title_font = body_font = ImageFont.load_default()
title_font = body_font = foot_font = ImageFont.load_default()
# 标题:与底同系,仅略亮 + 极低 alpha
tr, tg, tb = _BASE_RGB
@@ -154,6 +202,15 @@ def render_keyword_page_subtle_rgba(
y += 32
if y > height - 36:
break
fl = (footer_line or "").strip()
if fl:
fa = int(footer_alpha) if footer_alpha is not None else _ACTION_ALPHA
ar, ag, ab = min(tr + 18, 255), min(tg + 20, 255), min(tb + 24, 255)
bbox = draw.textbbox((0, 0), fl, font=foot_font)
tw = bbox[2] - bbox[0]
fx = max(24, (width - tw) // 2)
fy = height - 46
draw.text((fx, fy), fl, fill=(ar, ag, ab, fa), font=foot_font)
img.save(str(png_path), "PNG")
@@ -286,6 +343,21 @@ def main() -> None:
nargs="*",
help="可选:只处理这些文件名(相对于 --dir不填则处理目录下全部 .mp4",
)
ap.add_argument(
"--ignore-state",
action="store_true",
help="忽略状态文件、不做「已含尾帧」跳过(仅当你已换回无尾帧母片时再开,否则会叠双尾帧)",
)
ap.add_argument(
"--action-line",
default="点头像进房 · 每晚派对直播",
help="第二页底部轻引导(略亮于藏词正文);设为空字符串可关",
)
ap.add_argument(
"--no-action-line",
action="store_true",
help="不绘制第二页底部引导(仍保留两页 SEO 藏词)",
)
args = ap.parse_args()
words = load_keywords(args.keywords)
font_try = args.font
@@ -297,6 +369,9 @@ def main() -> None:
break
d = args.dir.resolve()
state_path = d / _STATE_NAME
state: dict = load_tail_state(state_path)
if args.files:
mp4s = []
for f in args.files:
@@ -311,10 +386,22 @@ def main() -> None:
return
dur_each = args.duration / max(1, args.pages)
page2_footer = ""
if not args.no_action_line:
page2_footer = (args.action_line or "").strip()
for main in mp4s:
idx = clip_index_from_name(main.name)
try:
dur_before = probe_duration_sec(main)
if (
not args.ignore_state
and main.name in state
and dur_before > 1.0
and abs(float(state[main.name]) - dur_before) < 1.05
):
print(f"⏭ 已含尾帧(时长与状态一致,跳过防叠双尾): {main.name}")
continue
w, h, sr = probe_size_rate(main)
block_a, block_b = pick_two_blocks(words, idx, args.per_page)
with tempfile.TemporaryDirectory(prefix="seo_tail_") as td:
@@ -329,7 +416,13 @@ def main() -> None:
w, h, block_a, png_a, font_try, "搜索关键词 1/2"
)
render_keyword_page_subtle_rgba(
w, h, block_b, png_b, font_try, "搜索关键词 2/2"
w,
h,
block_b,
png_b,
font_try,
"搜索关键词 2/2",
footer_line=page2_footer or None,
)
make_tail_clip_from_rgba_overlay(
png_a, ta, dur_each, w, h, sr
@@ -352,6 +445,9 @@ def main() -> None:
tails.append(one)
concat_videos_list(main, [main, *tails])
new_d = probe_duration_sec(main)
state[main.name] = round(new_d, 2)
save_tail_state(state_path, state)
nkw = len(block_a) + len(block_b)
print(
f"✅ 已加关键字尾帧×{args.pages}: {main.name}(序号 {idx},共 {nkw} 词,"

View File

@@ -500,8 +500,10 @@ MIN_SILENCE_TRIM_TOTAL_SEC = 0.12
COVER_TITLE_MAX_CJK = 6
# 封面优先用 hook_3sec吸睛高光句可略长于纯标题字数上限
COVER_HOOK_MAX_CJK = 16
CTA_END_MIN_SEC = 2.0
CTA_END_MAX_SEC = 3.8
CTA_END_MIN_SEC = 2.2
CTA_END_MAX_SEC = 4.5
# 最后一条口播字幕后CTA 再停留一小段(多为静音),方便读完 + 过渡到无声 SEO 尾帧
CTA_HOLD_AFTER_VOICE_SEC = 0.32
# ============ 工具函数 ============
@@ -1872,14 +1874,19 @@ def append_cta_ending_subtitle(
if anchor_end < CTA_END_MIN_SEC + float(subtitle_overlay_start) * 0.5:
return sub_images
span = min(CTA_END_MAX_SEC, max(CTA_END_MIN_SEC, anchor_end * 0.08))
span = min(CTA_END_MAX_SEC, max(CTA_END_MIN_SEC, anchor_end * 0.11))
cta_start = max(float(subtitle_overlay_start), anchor_end - span)
if cta_start >= anchor_end - 0.15:
cta_start = max(0.0, anchor_end - CTA_END_MIN_SEC)
# 收口CTA 结束略晚于最后一条语音字幕结束(不超过片长),便于「读完再断声」
cta_end = min(anchor_end + float(CTA_HOLD_AFTER_VOICE_SEC), dur - 0.04)
if cta_end <= cta_start + 0.2:
cta_end = min(anchor_end, dur - 0.02)
img_path = os.path.join(temp_dir, "sub_cta_ending.png")
create_subtitle_image(cta, out_w, out_h, img_path)
sub_images.append({"path": img_path, "start": cta_start, "end": anchor_end})
sub_images.append({"path": img_path, "start": cta_start, "end": cta_end})
sub_images.sort(key=lambda x: (float(x["start"]), float(x["end"])))
return sub_images

View File

@@ -4,7 +4,7 @@
Soul 切片一体化流水线
视频制作(封面/Hook格式+ 视频切片
流程:转录 → 字幕转简体 → 高光识别(AI) → 批量切片 → 增强(封面+字幕+CTA) → 快速混剪(可选)
流程:转录 → 字幕转简体 → 高光识别(AI) → 批量切片 → 增强(封面+字幕+CTA) → [two-folders 默认] SEO 两页尾帧 → 快速混剪(可选)
"""
import argparse
import atexit
@@ -179,6 +179,16 @@ def main():
action="store_true",
help="传给 soul_enhance去静音参数更温和",
)
parser.add_argument(
"--no-seo-tail",
action="store_true",
help="成片后不自动跑 append_seo_keyword_tail默认 --two-folders 且出成片时会拼 SEO 两页)",
)
parser.add_argument(
"--seo-tail-force",
action="store_true",
help="SEO 忽略 .soul_seo_tail_state.json须已换回无尾帧母片否则会叠双尾帧",
)
args = parser.parse_args()
if getattr(args, "ops_short", False):
@@ -412,6 +422,30 @@ def main():
]
run(montage_cmd, "生成快速混剪", timeout=600, check=False)
# 5. 成片 SEO 尾帧(两页藏词 + 第二页轻引导):与 soul_enhance 分离,默认在 two-folders 成片后执行
run_seo_tail = (
use_two_folders
and not getattr(args, "slices_only", False)
and not getattr(args, "no_seo_tail", False)
and enhanced_count > 0
)
kw_file = SKILL_DIR / "参考资料" / "视频尾帧_SEO关键词200.txt"
if run_seo_tail and kw_file.is_file():
seo_cmd = [
sys.executable,
str(SCRIPT_DIR / "append_seo_keyword_tail.py"),
"--dir",
str(enhanced_dir),
"--keywords",
str(kw_file),
]
if getattr(args, "seo_tail_force", False):
seo_cmd.append("--ignore-state")
seo_timeout = max(900, 180 * max(1, enhanced_count))
run(seo_cmd, "成片末尾 SEO 尾帧×2 静帧,无声)", timeout=seo_timeout, check=False)
elif run_seo_tail and not kw_file.is_file():
print(f" ⚠ 跳过 SEO 尾帧:未找到词表 {kw_file}", flush=True)
print()
print("=" * 60)
print("✅ 流水线完成")

View File

@@ -68,6 +68,11 @@ python3 auto_register.py add-key -p cerebras -k csk-xxx # 手动添加
# ====== 网关健康检查 ======
python3 ../../运营中枢/scripts/karuo_ai_gateway/key_health_check.py
# ====== Vercel / v0mail.tm 多轮:取码失败换新邮箱)======
python3 vercel_mailtm_signup_loop.py --max-rounds 8 --poll-timeout 180
python3 vercel_mailtm_signup_loop.py --pause-enter --poll-timeout 240 # 先回车再轮询
python3 vercel_mailtm_signup_loop.py --out-jsonl ./vercel_mailtm_rounds.jsonl
```
### 自动化全链路
@@ -109,6 +114,13 @@ python3 ../../运营中枢/scripts/karuo_ai_gateway/key_health_check.py
6. 验证 Key 可用性 → 存入 key_pool.db
7. 网关下次请求自动读取新 Key
### Vercel / v0 邮箱注册mail.tm 循环)
1. **不要单邮箱死磕**登录页试邮只会收到「Attempted Sign-in」+ signup 链接;**注册页** `Continue with Email` 才会收到 **Sign-up Verification** 六位码。
2. **循环**:本轮 `poll-timeout` 内无注册验证邮件 → **放弃该 mail.tm** → 脚本 `vercel_mailtm_signup_loop.py` 自动生成下一邮箱 → 重复,直到取到码或达 `--max-rounds`
3. OTP 建议**逐格输入**;团队 URL 需全局唯一。
4. 经验与命令见 `水溪_整理归档/经验库/待沉淀/2026-03-31_Vercel与v0_mail.tm注册_OTP与团队创建.md`
### 新增平台支持
1.`providers/` 创建 `平台名_provider.py`,继承 `BaseProvider`

View File

@@ -0,0 +1,227 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Vercel / v0 同账号mail.tm 多轮注册循环。
策略:本轮在超时内拿不到「注册验证码邮件」→ 放弃该邮箱 → 自动再建一个新 mail.tm → 继续下一轮。
不跟单封死磕;与 config 里 fixed mail.tm 无关(脚本内不读 MAILTM_* 固定账号)。
人工配合:每轮打印注册链接后,在浏览器打开并对该邮箱走「注册页 → Continue with Email」。
"""
from __future__ import annotations
import argparse
import json
import os
import random
import re
import string
import sys
import time
import urllib.parse
from datetime import datetime, timezone
from pathlib import Path
import httpx
MAILTM_API = "https://api.mail.tm"
RE_OTP = re.compile(r"(?<!\d)(\d{6})(?!\d)")
def _clear_mailtm_env() -> None:
os.environ.pop("MAILTM_ADDRESS", None)
os.environ.pop("MAILTM_PASSWORD", None)
def create_fresh_mailtm() -> tuple[str, str, str]:
"""返回 (email, password, bearer_token)。"""
t = 30
r = httpx.get(f"{MAILTM_API}/domains", timeout=t)
r.raise_for_status()
domains = r.json().get("hydra:member", [])
if not domains:
raise RuntimeError("mail.tm 无可用域名")
domain = domains[0]["domain"]
prefix = "".join(random.choices(string.ascii_lowercase + string.digits, k=14))
email = f"{prefix}@{domain}"
password = "".join(random.choices(string.ascii_letters + string.digits, k=18))
r = httpx.post(
f"{MAILTM_API}/accounts",
json={"address": email, "password": password},
timeout=t,
)
if r.status_code not in (200, 201):
raise RuntimeError(f"mail.tm 创建失败: {r.status_code} {r.text[:120]}")
tr = httpx.post(
f"{MAILTM_API}/token",
json={"address": email, "password": password},
timeout=t,
)
tr.raise_for_status()
token = tr.json().get("token") or ""
if not token:
raise RuntimeError("mail.tm token 为空")
return email, password, token
def poll_signup_verification_code(
token: str,
timeout_sec: int,
interval_sec: float,
) -> tuple[str | None, str]:
"""
只认「注册验证」类邮件里的 6 位码。
返回 (code, reason)code 为 None 时 reason 为 TIMEOUT / NO_SIGNUP_MAIL。
"""
headers = {"Authorization": f"Bearer {token}"}
deadline = time.time() + timeout_sec
seen_subjects: set[str] = set()
while time.time() < deadline:
try:
r = httpx.get(f"{MAILTM_API}/messages", headers=headers, timeout=20)
r.raise_for_status()
for msg in r.json().get("hydra:member", []):
mid = msg.get("id") or ""
sub = (msg.get("subject") or "").strip()
if not mid or not sub:
continue
key = f"{mid}:{sub}"
if key in seen_subjects:
continue
seen_subjects.add(key)
dr = httpx.get(f"{MAILTM_API}/messages/{mid}", headers=headers, timeout=20)
dr.raise_for_status()
data = dr.json()
text = data.get("text") or ""
html = data.get("html")
if isinstance(html, list) and html:
text = text + "\n" + str(html[0])
elif isinstance(html, str):
text = text + "\n" + html
blob = sub + "\n" + text
sl = sub.lower()
# 仅注册验证;登录试邮 / 无账号说明 不算成功取码
if "attempted" in sl and "sign-in" in sl:
continue
if "sign-up verification" in sl or "signup verification" in sl:
m = RE_OTP.search(blob)
if m and m.group(1) != "666666":
return m.group(1), "OK"
# 主题即「123456 - …」且正文含 sign up / verify your email
if "vercel" in sl and (
"sign up" in blob.lower() or "sign-up" in blob.lower()
):
m = RE_OTP.search(sub) or RE_OTP.search(blob)
if m and m.group(1) != "666666":
return m.group(1), "OK"
except Exception as e:
print(f"[poll] 异常(将重试): {e}", file=sys.stderr)
time.sleep(interval_sec)
return None, "TIMEOUT"
def main() -> int:
ap = argparse.ArgumentParser(description="Vercel 注册 mail.tm 多轮循环(取码失败换新邮箱)")
ap.add_argument("--max-rounds", type=int, default=8, help="最多换几轮邮箱")
ap.add_argument("--poll-timeout", type=int, default=180, help="每轮等待注册验证码秒数")
ap.add_argument("--interval", type=float, default=3.0, help="轮询间隔秒")
ap.add_argument(
"--pause-enter",
action="store_true",
help="打印链接后等待按回车再开始收信(方便你先点 Continue with Email",
)
ap.add_argument(
"--out-jsonl",
type=str,
default="",
help="每轮结果追加写入 JSONL路径",
)
ap.add_argument(
"--ref",
type=str,
default="https://v0.app/ref/WQ9P9N",
help="邀请链接(仅打印参考)",
)
args = ap.parse_args()
out_path = Path(args.out_jsonl).expanduser() if args.out_jsonl else None
print("=== Vercel / v0 · mail.tm 注册循环 ===", flush=True)
print("规则:本轮超时无「注册验证码」→ 放弃该邮箱 → 自动下一邮箱。\n", flush=True)
for rnd in range(1, args.max_rounds + 1):
_clear_mailtm_env()
print(f"--- 第 {rnd}/{args.max_rounds} 轮 ---", flush=True)
try:
email, password, token = create_fresh_mailtm()
except Exception as e:
print(f"[失败] 无法创建 mail.tm: {e}", flush=True)
rec = {
"round": rnd,
"ok": False,
"reason": "MAILTM_CREATE_FAIL",
"error": str(e),
"ts": datetime.now(timezone.utc).isoformat(),
}
if out_path:
out_path.parent.mkdir(parents=True, exist_ok=True)
with open(out_path, "a", encoding="utf-8") as f:
f.write(json.dumps(rec, ensure_ascii=False) + "\n")
continue
enc = urllib.parse.quote(email, safe="")
signup = f"https://vercel.com/signup?email={enc}"
print(f"邮箱: {email}", flush=True)
print(f"mail.tm 密码(查信用): {password}", flush=True)
print(f"注册页: {signup}", flush=True)
print(f"邀请参考: {args.ref}", flush=True)
print(
"请在浏览器打开「注册页」,对该邮箱点 Continue with Email 发码。\n",
flush=True,
)
if args.pause_enter:
input("准备好后按回车开始轮询收信…")
code, reason = poll_signup_verification_code(
token, args.poll_timeout, args.interval
)
rec = {
"round": rnd,
"email": email,
"mailtm_password": password,
"signup_url": signup,
"code": code,
"poll_reason": reason,
"ok": code is not None,
"ts": datetime.now(timezone.utc).isoformat(),
}
if out_path:
out_path.parent.mkdir(parents=True, exist_ok=True)
with open(out_path, "a", encoding="utf-8") as f:
f.write(json.dumps(rec, ensure_ascii=False) + "\n")
if code:
print(f"\n[成功] 注册验证码: {code}", flush=True)
print(
"下一步:在 Vercel 注册页逐格输入 OTP完成团队创建再打开 v0 邀请链接。\n",
flush=True,
)
return 0
print(
f"\n[放弃本轮] 未收到注册验证码({reason}),已丢弃该邮箱,进入下一轮。\n",
flush=True,
)
print("[结束] 已达最大轮数仍未取到注册验证码。", flush=True)
return 2
if __name__ == "__main__":
sys.exit(main())

View File

@@ -500,3 +500,4 @@
| 2026-03-31 18:12:24 | 🔄 卡若AI 同步 2026-03-31 18:12 | 更新:金仓、卡木、运营中枢工作台 | 排除 >20MB: 14 个 |
| 2026-03-31 18:15:25 | 🔄 卡若AI 同步 2026-03-31 18:15 | 更新:金仓、金盾、卡木、总索引与入口、运营中枢工作台 | 排除 >20MB: 14 个 |
| 2026-03-31 19:04:30 | 🔄 卡若AI 同步 2026-03-31 19:04 | 更新:金仓、卡木、总索引与入口、运营中枢工作台 | 排除 >20MB: 14 个 |
| 2026-03-31 19:20:26 | 🔄 卡若AI 同步 2026-03-31 19:20 | 更新Cursor规则、金仓、水溪整理归档、总索引与入口、运营中枢工作台 | 排除 >20MB: 14 个 |

View File

@@ -503,3 +503,4 @@
| 2026-03-31 18:12:24 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-31 18:12 | 更新:金仓、卡木、运营中枢工作台 | 排除 >20MB: 14 个 | [仓库](http://open.quwanzhi.com:13000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:13000/fnvtk/karuo-ai/wiki) |
| 2026-03-31 18:15:25 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-31 18:15 | 更新:金仓、金盾、卡木、总索引与入口、运营中枢工作台 | 排除 >20MB: 14 个 | [仓库](http://open.quwanzhi.com:13000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:13000/fnvtk/karuo-ai/wiki) |
| 2026-03-31 19:04:30 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-31 19:04 | 更新:金仓、卡木、总索引与入口、运营中枢工作台 | 排除 >20MB: 14 个 | [仓库](http://open.quwanzhi.com:13000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:13000/fnvtk/karuo-ai/wiki) |
| 2026-03-31 19:20:26 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-31 19:20 | 更新Cursor规则、金仓、水溪整理归档、总索引与入口、运营中枢工作台 | 排除 >20MB: 14 个 | [仓库](http://open.quwanzhi.com:13000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:13000/fnvtk/karuo-ai/wiki) |