AI 资产工作流从零部署与运维

AI 资产工作流从零部署与运维

这份文档是给“以后从零重装一遍也不慌”的自己看的。它不追求把博客改造成平台,只把 Hugo + GitHub Pages + AI 助手接成一个稳定的小循环:AI 开发时先查博客里的经验,工作结束后把新的经验脱敏沉淀回博客。

这套东西负责什么

当前博客有两条线:

  1. 正常博客线:生活、旅行、随想、传统文章继续按原来的方式写。
  2. AI 资产线:技术协作经验默认写成短资产,给未来的 Codex、Claude Code 或其他 AI 助手按需读取。

AI 资产线的核心文件是:

  • static/ai/registry.json:公开机器索引。
  • static/ai/assets/**:公开的脱敏资产镜像。
  • ai/sessions/**:脱敏会话摘要,不保存原始 transcript。
  • ai/tips/**:短问题、短原因、短修复、短验证。
  • ai/playbooks/**:多步骤流程。
  • .agents/skills/**:Codex 项目技能。
  • .claude/skills/**:Claude Code 兼容技能。
  • .codex/hooks.json.claude/settings.json:本地安全 hook。
  • .github/workflows/ai-collab-assets.yml:自动接收 digest、生成资产、更新索引、创建 PR。

从零部署

1. 准备本机环境

Windows / PowerShell 下建议准备:

1
2
3
4
git --version
python --version
hugo version
dart-sass --version

建议版本:

  • Python 3.11 或更新。
  • Hugo Extended,尽量和 GitHub Actions 里的 HUGO_VERSION 对齐。
  • Dart Sass,用于主题构建。
  • Git,能正常访问 GitHub。

如果是全新机器,先克隆仓库并拉主题子模块:

1
2
3
git clone --recursive https://github.com/lihan3238/lihan3238.github.io.git
cd lihan3238.github.io
git submodule update --init --recursive

本地构建验证:

1
hugo --minify

Hugo 有时会改 hugo_stats.json。如果只是构建检查,不想保留这类构建噪声:

1
git restore --worktree -- hugo_stats.json

2. 配置 GitHub Pages

在 GitHub 仓库页面进入:

1
Settings -> Pages

确认:

1
Build and deployment -> Source -> GitHub Actions

这个博客已经有 .github/workflows/hugo.yml,它会在 main 分支 push、手动触发、或收到 hugo_deploy_requested 事件后部署到 GitHub Pages。

3. 配置 Actions 权限

进入:

1
Settings -> Actions -> General -> Workflow permissions

建议选择:

1
2
Read and write permissions
Allow GitHub Actions to create and approve pull requests

工作流文件里已经显式声明了所需权限。仓库设置这里是总开关,别让它把工作流的写权限卡掉。

Token 配置

这里有两个 token,别混着记。

1. 本机提交 digest:BLOG_REPO_DISPATCH_TOKEN

用途:在任意本地项目里,把 AI 写好的 digest 提交给博客仓库的 ai_collab_digest_submitted workflow。

创建方式:

  1. 打开 GitHub 的 fine-grained personal access token 页面。
  2. Repository access 只选择 lihan3238/lihan3238.github.io
  3. Repository permissions 给:
1
Contents: Read and write
  1. 生成 token 后,只保存在本机环境变量,不写进仓库。

PowerShell 永久写入用户环境变量:

1
2
3
4
5
6
$token = Read-Host "GitHub token" -AsSecureString
$ptr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($token)
$plain = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($ptr)
[Environment]::SetEnvironmentVariable("BLOG_REPO_DISPATCH_TOKEN", $plain, "User")
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ptr)
Remove-Variable token, plain, ptr

重启 Codex / Claude Code / PowerShell 后检查:

1
[Environment]::GetEnvironmentVariable("BLOG_REPO_DISPATCH_TOKEN", "User") -ne $null

不要把 token 打印出来,不要放进 .env 后提交。

2. 仓库自动合并:BLOG_REPO_AUTOMATION_TOKEN

用途:GitHub Actions 创建 AI 资产 PR 后,自动 approve、squash merge,并触发 Hugo 部署。

进入:

1
Settings -> Secrets and variables -> Actions -> New repository secret

Secret 名字:

1
BLOG_REPO_AUTOMATION_TOKEN

建议仍然使用 fine-grained token,只绑定 lihan3238/lihan3238.github.io,权限给:

1
2
Contents: Read and write
Pull requests: Read and write

如果不配置这个 secret,自动化不会彻底失效:workflow 仍可生成 PR,只是需要你手动 review 和 merge。

启用本地 hooks

Codex 侧:

  • .codex/config.toml 里开启了 codex_hooks = true
  • .codex/hooks.json 配置了 UserPromptSubmitPreToolUse

Claude Code 侧:

  • .claude/settings.json 配置了等价 hooks。
  • 本机私有设置放 .claude/settings.local.json,它已被 .gitignore 忽略。

当前默认 hook 策略:

  • UserPromptSubmit:提交给 AI 前,只硬拦高置信密钥和 token;邮箱、普通路径、password=demo 只提醒。
  • PreToolUse:工具执行前,硬拦真实密钥、危险 shell、更新或删除旧 content/post/**
  • Stop:默认没有启用,不自动截取 transcript。

第一次运行时,Codex / Claude Code 可能会提示 review / trust hooks。要 trust 的是项目内这两个配置文件,它们最终调用:

1
python scripts/ai/hook_policy.py

日常使用

1. 正常写博客

你还是可以直接说:

1
帮我写一篇博文

生活、旅行、随想、计划类内容继续走传统博文。旧博文默认只读,除非你明确说要改某一篇旧文。

2. AI 开发前读取经验

在博客仓库内:

1
2
python scripts/ai/blog_ai.py search "blog style"
python scripts/ai/blog_ai.py get keep-old-blog-posts-read-only-during-v4-work

在其他本地项目里:

1
2
python C:\lihan_work\github_repos\lihan3238.github.io\scripts\ai\blog_ai.py --remote search "registry"
python C:\lihan_work\github_repos\lihan3238.github.io\scripts\ai\blog_ai.py --remote get explain-usage-after-feature-updates

规则是:先搜 registry,命中后只读取单个资产。不要一上来把所有 tips、playbooks、skills 都塞进上下文。

3. AI 开发后沉淀经验

当某次工作真的有复用价值时,让 AI 写一个短 digest JSON。它应该只包含事实摘要、可复用模式、tips、验证方式,不包含原始 transcript、密钥、邮箱、私人路径。

先 dry-run:

1
python C:\lihan_work\github_repos\lihan3238.github.io\scripts\ai\blog_ai.py submit .\digest.json --dry-run

没有 token 或 dry-run 时,脚本会写入博客仓库的 ai/outbox/。这个目录被 .gitignore 忽略,是本地暂存箱。

确认没问题后提交到 GitHub:

1
python C:\lihan_work\github_repos\lihan3238.github.io\scripts\ai\blog_ai.py submit .\digest.json

成功后 GitHub 会触发:

1
Publish AI Collaboration Assets

它会依次做:

  1. 接收 payload。
  2. 脱敏并写入 ai/sessions/
  3. 生成候选 tip / playbook
  4. 更新 static/ai/registry.jsonstatic/ai/assets/**
  5. 校验资产、校验 registry、校验路径 allowlist。
  6. Hugo build。
  7. 创建 PR。
  8. 如果有 BLOG_REPO_AUTOMATION_TOKEN,自动 approve、merge、触发 Pages 部署。

运维检查

本地改完 AI 工作流、hook、资产或公开页面后,至少跑:

1
2
3
4
5
6
7
python -m unittest discover -s tests
python scripts/ai/redact.py --self-test
python scripts/ai/validate_assets.py
python scripts/ai/build_registry.py --check
python scripts/ai/blog_ai.py search usage
python scripts/ai/blog_ai.py get explain-usage-after-feature-updates
hugo --minify

如果 Hugo 改了 hugo_stats.json 且你没有刻意更新它:

1
git restore --worktree -- hugo_stats.json

自动化路径检查:

1
python scripts/ai/guard_changed_paths.py ai/sessions/demo.json ai/tips/demo.json ai/playbooks/demo.md static/ai/registry.json static/ai/assets/tips/demo.json .github/workflows/ai-collab-assets.yml

注意:guard_changed_paths.py --from-git 是给 AI 自动化 PR 用的严格闸门。如果你本轮明确要求新增传统博文,它可能会因为 content/post/** 报错,这是预期保护,不是 Hugo 坏了。

本地 E2E

这个 E2E 不触发 GitHub、不污染博客仓库,适合验证脚本是否还能闭环:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$root = Join-Path $env:TEMP ("lihan-ai-e2e-" + (Get-Date -Format "yyyyMMddHHmmss"))
New-Item -ItemType Directory -Path $root | Out-Null

python scripts/ai/redact.py --self-test
$sessionPath = python scripts/ai/ingest_session.py --input tests\fixtures\ai\session-draft.json --root $root
python scripts/ai/session_to_assets.py --input (Join-Path $root $sessionPath) --root $root --write
python scripts/ai/build_registry.py --root $root
python scripts/ai/validate_assets.py --root $root
python scripts/ai/blog_ai.py --root $root search registry
python scripts/ai/blog_ai.py --root $root get use-registry-before-loading-full-skills
python scripts/ai/blog_ai.py --root $root submit tests\fixtures\ai\session-draft.json --dry-run

看到这些结果就说明链路通了:

  • redaction self-test passed
  • AI assets valid
  • search 能找到 use-registry-before-loading-full-skills
  • get 只读取了单个 tip
  • dry-run 在临时目录写出 ai/outbox/*.json

常见故障

submit 写到了 outbox,没有触发 GitHub

通常是本机没有 BLOG_REPO_DISPATCH_TOKEN

检查:

1
[Environment]::GetEnvironmentVariable("BLOG_REPO_DISPATCH_TOKEN", "User") -ne $null

配置后重启终端,再重新 submit。

GitHub Action 说 payload 为空

ai-collab-assets.yml 明确禁止空 payload。重新检查 digest JSON,或者手动 workflow dispatch 时填入完整 JSON。

PR 创建了,但没有自动合并

通常是没有配置 BLOG_REPO_AUTOMATION_TOKEN,或者 token 权限不够。手动 merge 也可以,不影响资产发布;只是少了自动合并。

registry check 失败

说明资产文件和 static/ai/registry.json 不一致。重新生成:

1
2
python scripts/ai/build_registry.py
python scripts/ai/build_registry.py --check

Hugo build 失败

先本地跑:

1
hugo --minify

如果是主题子模块缺失:

1
git submodule update --init --recursive

hook 误拦

先确认拦截原因。如果只是邮箱、普通路径、password=demo,当前策略应该只提醒不拦截。如果真实误杀,改 scripts/ai/hook_policy.py,再跑:

1
python -m unittest discover -s tests

不要为了省事直接关掉全部 hooks;这几个 hook 是保护旧博文和密钥的门闩。

安全和回滚

Token 维护:

  • token 只给单个仓库,不给全账号。
  • 优先设置 90 天左右过期时间。
  • 过期后重新生成,更新本机环境变量或 GitHub secret。
  • 怀疑泄露时立刻 revoke,并重新生成。

资产安全:

  • 不保存原始 transcript。
  • digest 只写公开可接受的事实摘要。
  • 默认 privacy 必须是 public_redacted
  • ai/outbox/*.json 本地忽略,不提交。

回滚方式:

  1. 如果只是某个 AI 资产写坏了,提交一个修复 PR,删除或改正对应 ai/** 文件。
  2. 重新运行 python scripts/ai/build_registry.py 更新公开索引和镜像。
  3. 如果已经部署,merge 修复 PR 后 Pages 会重新发布。
  4. 如果涉及泄密,先撤销相关 token,再处理仓库历史和公开页面缓存。

什么时候需要迁服务器

现在不需要。GitHub Pages + Actions 已经够用。

只有出现这些需求时,再考虑服务器:

  • 需要私有资产鉴权,而不是公开 public_redacted
  • 需要复杂搜索、权限分组、使用统计。
  • 需要长时间后台任务,超过 GitHub Actions 适合承担的范围。
  • 需要把多个仓库的私有上下文集中管理。

在那之前,保持轻量是优势。这个系统的目标不是多一个要维护的平台,而是让博客继续像自己的小窝,同时让 AI 少走弯路。

参考

Licensed under CC BY-NC-SA 4.0
潇洒人间一键仙
使用 Hugo 构建
主题 StackJimmy 设计