CI/CD 中的知识管理:Terrain 如何实现自动文档更新

Terrain --- prepares the ground so agents don't have to guess where to stand.

🔗 GitHub:https://github.com/sopaco/terrain


团队在 CI 流水线中经常遇到:

  • 每次合并都要重新生成文档------但其实只有几个文件变了
  • 知识资产与代码脱节却无人察觉------直到 AI 助手基于过时信息给出了错误建议
  • 每个 CI 环境都要手动安装工具链------CodeGraph、RTK、Skills 反复配置
  • 流水线输出难以集成到 Agent 工作流------需要把信息转换成 Agent 能理解的格式

Terrain 的设计哲学就是为自动化而生:JSON 输出、增量刷新、无界面运行、工具链一键部署。


核心能力:CLI 优先,JSON 贯穿始终

Terrain 的所有命令都设计为可在脚本和流水线中直接调用:

  • JSON 标准输出 --- 每条 terrain tools 命令都输出 JSON,无需解析定制格式
  • NDJSON 事件流 --- terrain ask query --stream 输出逐行 JSON 事件,可实时流式消费
  • 无界面运行 --- CLI 不依赖任何显示服务,可在纯终端环境运行

#mermaid-svg-iapg7xK6czwi5iIC{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-iapg7xK6czwi5iIC .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-iapg7xK6czwi5iIC .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-iapg7xK6czwi5iIC .error-icon{fill:#552222;}#mermaid-svg-iapg7xK6czwi5iIC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-iapg7xK6czwi5iIC .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-iapg7xK6czwi5iIC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-iapg7xK6czwi5iIC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-iapg7xK6czwi5iIC .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-iapg7xK6czwi5iIC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-iapg7xK6czwi5iIC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-iapg7xK6czwi5iIC .marker{fill:#333333;stroke:#333333;}#mermaid-svg-iapg7xK6czwi5iIC .marker.cross{stroke:#333333;}#mermaid-svg-iapg7xK6czwi5iIC svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-iapg7xK6czwi5iIC p{margin:0;}#mermaid-svg-iapg7xK6czwi5iIC .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-iapg7xK6czwi5iIC .cluster-label text{fill:#333;}#mermaid-svg-iapg7xK6czwi5iIC .cluster-label span{color:#333;}#mermaid-svg-iapg7xK6czwi5iIC .cluster-label span p{background-color:transparent;}#mermaid-svg-iapg7xK6czwi5iIC .label text,#mermaid-svg-iapg7xK6czwi5iIC span{fill:#333;color:#333;}#mermaid-svg-iapg7xK6czwi5iIC .node rect,#mermaid-svg-iapg7xK6czwi5iIC .node circle,#mermaid-svg-iapg7xK6czwi5iIC .node ellipse,#mermaid-svg-iapg7xK6czwi5iIC .node polygon,#mermaid-svg-iapg7xK6czwi5iIC .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-iapg7xK6czwi5iIC .rough-node .label text,#mermaid-svg-iapg7xK6czwi5iIC .node .label text,#mermaid-svg-iapg7xK6czwi5iIC .image-shape .label,#mermaid-svg-iapg7xK6czwi5iIC .icon-shape .label{text-anchor:middle;}#mermaid-svg-iapg7xK6czwi5iIC .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-iapg7xK6czwi5iIC .rough-node .label,#mermaid-svg-iapg7xK6czwi5iIC .node .label,#mermaid-svg-iapg7xK6czwi5iIC .image-shape .label,#mermaid-svg-iapg7xK6czwi5iIC .icon-shape .label{text-align:center;}#mermaid-svg-iapg7xK6czwi5iIC .node.clickable{cursor:pointer;}#mermaid-svg-iapg7xK6czwi5iIC .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-iapg7xK6czwi5iIC .arrowheadPath{fill:#333333;}#mermaid-svg-iapg7xK6czwi5iIC .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-iapg7xK6czwi5iIC .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-iapg7xK6czwi5iIC .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iapg7xK6czwi5iIC .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-iapg7xK6czwi5iIC .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iapg7xK6czwi5iIC .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-iapg7xK6czwi5iIC .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-iapg7xK6czwi5iIC .cluster text{fill:#333;}#mermaid-svg-iapg7xK6czwi5iIC .cluster span{color:#333;}#mermaid-svg-iapg7xK6czwi5iIC div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-iapg7xK6czwi5iIC .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-iapg7xK6czwi5iIC rect.text{fill:none;stroke-width:0;}#mermaid-svg-iapg7xK6czwi5iIC .icon-shape,#mermaid-svg-iapg7xK6czwi5iIC .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iapg7xK6czwi5iIC .icon-shape p,#mermaid-svg-iapg7xK6czwi5iIC .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-iapg7xK6czwi5iIC .icon-shape .label rect,#mermaid-svg-iapg7xK6czwi5iIC .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iapg7xK6czwi5iIC .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-iapg7xK6czwi5iIC .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-iapg7xK6czwi5iIC :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 流水线集成
JSON 输出
NDJSON 流
增量刷新
CI 流水线
terrain tools
terrain ask query --stream
terrain refresh
terrain-core

无 LLM 调用
terrain-agent

知识检索 + LLM


典型 CI 用法:合并时自动刷新知识

bash 复制代码
# 在 CI 脚本中:合并后自动刷新知识资产
terrain refresh .

# 输出项目新鲜度到日志
terrain project freshness-cached --project my-repo

# 如果新鲜度低于阈值,标记为警告
terrain tools freshness --project my-repo | jq '.score'

这意味着每次代码合并后,知识资产自动更新,无需人工干预。 新成员 clone 仓库后看到的一切知识都是最新的。


环境标准化:terrain env apply 一键部署

在 CI 或新环境中,一条命令安装所有 Agent 工具链:

bash 复制代码
# 预览将要安装的组件
terrain env plan

# 一键安装:Skills、CodeGraph、RTK、AGENTS.md 片段
terrain env apply

# 验证安装状态
terrain env status
组件 说明
Skills 标准化工作流程指令(知识查询、SDD、Ask、架构分析)
CodeGraph 符号调用关系图谱
RTK 压缩 Shell 输出,节省 Token
AGENTS.md 统一项目约定片段

Terrain 的环境配置界面,一键为所有 Agent 部署标准化工具链。


跨平台分发:npm + 预编译安装包

方式 适用场景 安装方式
npm 包 CI/CD、无头服务器、Agent 流水线 npm install -g @terrain-ai/cli
预编译安装包 本地开发、桌面使用 GitHub Releases 下载
Node.js shim npm 环境中的工具调用 自动安装
  • macOS(Apple Silicon)Windows x64 均有预编译二进制
  • @terrain-ai/cli@terrain-ai/rtk 均可通过 npm 全局安装
  • 桌面应用通过 Tauri 打包,内置 CLI,无需额外安装

核心技术:为什么适合流水线?

Rust 原生核心,离线可运行

所有核心计算由 terrain-core(纯 Rust)完成:

  • 无运行时依赖 --- 单一二进制,不依赖 Node.js/Python/数据库
  • 离线执行 --- scan、pack、search、freshness 不调用 LLM
  • 确定性输出 --- 相同输入产生相同 JSON 输出,适合自动化断言

增量刷新引擎

#mermaid-svg-o2YkNgt772FHn7RD{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-o2YkNgt772FHn7RD .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-o2YkNgt772FHn7RD .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-o2YkNgt772FHn7RD .error-icon{fill:#552222;}#mermaid-svg-o2YkNgt772FHn7RD .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-o2YkNgt772FHn7RD .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-o2YkNgt772FHn7RD .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-o2YkNgt772FHn7RD .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-o2YkNgt772FHn7RD .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-o2YkNgt772FHn7RD .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-o2YkNgt772FHn7RD .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-o2YkNgt772FHn7RD .marker{fill:#333333;stroke:#333333;}#mermaid-svg-o2YkNgt772FHn7RD .marker.cross{stroke:#333333;}#mermaid-svg-o2YkNgt772FHn7RD svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-o2YkNgt772FHn7RD p{margin:0;}#mermaid-svg-o2YkNgt772FHn7RD .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-o2YkNgt772FHn7RD .cluster-label text{fill:#333;}#mermaid-svg-o2YkNgt772FHn7RD .cluster-label span{color:#333;}#mermaid-svg-o2YkNgt772FHn7RD .cluster-label span p{background-color:transparent;}#mermaid-svg-o2YkNgt772FHn7RD .label text,#mermaid-svg-o2YkNgt772FHn7RD span{fill:#333;color:#333;}#mermaid-svg-o2YkNgt772FHn7RD .node rect,#mermaid-svg-o2YkNgt772FHn7RD .node circle,#mermaid-svg-o2YkNgt772FHn7RD .node ellipse,#mermaid-svg-o2YkNgt772FHn7RD .node polygon,#mermaid-svg-o2YkNgt772FHn7RD .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-o2YkNgt772FHn7RD .rough-node .label text,#mermaid-svg-o2YkNgt772FHn7RD .node .label text,#mermaid-svg-o2YkNgt772FHn7RD .image-shape .label,#mermaid-svg-o2YkNgt772FHn7RD .icon-shape .label{text-anchor:middle;}#mermaid-svg-o2YkNgt772FHn7RD .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-o2YkNgt772FHn7RD .rough-node .label,#mermaid-svg-o2YkNgt772FHn7RD .node .label,#mermaid-svg-o2YkNgt772FHn7RD .image-shape .label,#mermaid-svg-o2YkNgt772FHn7RD .icon-shape .label{text-align:center;}#mermaid-svg-o2YkNgt772FHn7RD .node.clickable{cursor:pointer;}#mermaid-svg-o2YkNgt772FHn7RD .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-o2YkNgt772FHn7RD .arrowheadPath{fill:#333333;}#mermaid-svg-o2YkNgt772FHn7RD .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-o2YkNgt772FHn7RD .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-o2YkNgt772FHn7RD .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-o2YkNgt772FHn7RD .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-o2YkNgt772FHn7RD .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-o2YkNgt772FHn7RD .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-o2YkNgt772FHn7RD .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-o2YkNgt772FHn7RD .cluster text{fill:#333;}#mermaid-svg-o2YkNgt772FHn7RD .cluster span{color:#333;}#mermaid-svg-o2YkNgt772FHn7RD div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-o2YkNgt772FHn7RD .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-o2YkNgt772FHn7RD rect.text{fill:none;stroke-width:0;}#mermaid-svg-o2YkNgt772FHn7RD .icon-shape,#mermaid-svg-o2YkNgt772FHn7RD .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-o2YkNgt772FHn7RD .icon-shape p,#mermaid-svg-o2YkNgt772FHn7RD .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-o2YkNgt772FHn7RD .icon-shape .label rect,#mermaid-svg-o2YkNgt772FHn7RD .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-o2YkNgt772FHn7RD .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-o2YkNgt772FHn7RD .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-o2YkNgt772FHn7RD :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 变更文件
变更模块
无变更
Git 代码仓库
ProjectScanner

收集 Git 元数据
哪些文件变了?
repomix 重新打包
更新对应 C4 文档
跳过文档生成
更新 context.md
重新计算新鲜度评分
输出 JSON 结果

只处理变化的部分------这是增量刷新与传统全量重新生成的核心区别。一个 10 万行代码的项目,如果只修改了几个文件,刷新可能只需几秒。

流水线友好的输出格式

bash 复制代码
# JSON 输出可直接被 jq/脚本处理
terrain tools read-context --project my-repo | jq '.modules[].name'

# NDJSON 流可实时消费
terrain ask query "系统如何处理请求?" --project my-repo --stream | while read line; do
    echo "$line" | jq '.type'
done

# 适合 CI 日志和断言
terrain project freshness-cached --project my-repo > freshness.json

完整 CI 示例

bash 复制代码
#!/bin/bash
# .github/workflows/terrain-knowledge.yml

name: Update Knowledge Assets
on: [push, pull_request]

jobs:
  refresh-knowledge:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Install Terrain CLI
        run: npm install -g @terrain-ai/cli
      
      - name: Refresh knowledge assets
        run: |
          terrain refresh .
          terrain project freshness-cached --project my-repo
          
      - name: Check freshness threshold
        run: |
          SCORE=$(terrain project overview --project my-repo | jq '.freshness_score')
          if [ "$SCORE" -lt 50 ]; then
            echo "::warning::Knowledge assets are stale (score: $SCORE)"
          fi

适合谁?

  • DevOps 工程师 --- 将知识资产更新纳入 CI 流水线
  • 平台团队 --- 标准化所有项目的 Agent 环境
  • 大规模团队 --- 新仓库自动获得知识资产,无需手动配置
  • ACP 集成者 --- 将 terrain tools JSON API 接入自动化 Agent 循环
  • 开源项目维护者 --- 让贡献者 clone 后立刻拥有完整的项目知识

"JSON 输出、增量刷新、一键部署------为自动化而生的知识流水线。"

相关推荐
11路没有终点8 小时前
GitLab CI/CD 高级模式实战:include 模板库 / trigger 子流水线 / matrix 并行
ci/cd·gitlab
11路没有终点8 小时前
GitLab CE CI/CD 入门指引手册:从零搭建第一条流水线
ci/cd·gitlab
chens12312310 小时前
自建三节点 K3s 集群搭建 Drone CI/CD 流水线
ci/cd
虎王物联2 天前
Docker BuildKit多阶段构建:IoT固件交叉编译流水线实战
运维·物联网·ci/cd·docker·容器·物联网嵌入式
LlmCraft|大模型工程实践2 天前
14. CI/CD 流水线中集成 Docker:GitHub Actions 自动构建部署
ci/cd·docker·github
秦渝兴3 天前
GitLab CI/CD 流水线实战
ci/cd·gitlab
gs801403 天前
告别 CI/CD 误伤与红条:Docker 镜像智能清理与优雅防冲突实战
ci/cd·docker·容器
leeyi3 天前
DDD 六条铁律:让 CI 替你骂人——go-arch-lint 门禁实战(第104篇)
ci/cd·agent·领域驱动设计
算法大模型备案干货咪3 天前
《把内容安全做成CI卡点:AIGC合规的工程化落地》
安全·ci/cd·aigc