[{"title":"Tongue 舌象分析管理系统","permalink":"/posts/tongue-project/","summary":"访问在线演示\n系统概览 该系统专注于舌象数据的结构化管理，现阶段重点是稳定沉淀结构化训练资产，为后续算法训练与模型接入做准备。\n核心模块 1. 主页 主页展示舌象数据集工作流的全局状态：\n图片总数：已上传的舌象图片数量 待处理：等待预处理的图片数量 已完成预处理：已预处理完成的图片数量 导出数据集数：已导出的训练数据集数量 数据概览包含训练资产沉淀的进度指标：\n指标 说明 预处理完成率 标准图可用于后续标注和训练导出 待处理占比 用于判断当前图片预处理阻塞情况 已导出数据集 沉淀为后续模型训练的基础资产 2. 图片管理 图片管理模块提供完整的图片生命周期管理：\n字段 说明 ID 图片唯一标识 图片名称 文件名 预处理状态 已完成 / 待处理 尺寸 图片分辨率 文件大小 图片文件体积 缩略图预览 预览图 上传时间 上传时间戳 操作功能：\n预处理 - 对图片进行标准化处理 详情 - 查看图片详细信息 标注 - 进行人工标注 报告 - 生成分析报告 删除 - 移除图片 3. 数据导出 数据导出模块支持按多种维度筛选导出训练数据：\n预处理状态 是否标注 是否复核 结构化标签 4. 任务中心 任务中心追踪所有图片预处理和数据集导出任务：\n字段 说明 任务 ID 任务唯一标识 任务类型 如 preprocess 状态 任务执行状态 图片 ID 关联的图片 数据集 ID 关联的数据集 失败原因 任务失败时的错误信息 开始时间 任务开始时间 结束时间 任务结束时间 项目设计：wobushi041\n","content":"访问在线演示\n系统概览 该系统专注于舌象数据的结构化管理，现阶段重点是稳定沉淀结构化训练资产，为后续算法训练与模型接入做准备。\n核心模块 1. 主页 主页展示舌象数据集工作流的全局状态：\n图片总数：已上传的舌象图片数量 待处理：等待预处理的图片数量 已完成预处理：已预处理完成的图片数量 导出数据集数：已导出的训练数据集数量 数据概览包含训练资产沉淀的进度指标：\n指标 说明 预处理完成率 标准图可用于后续标注和训练导出 待处理占比 用于判断当前图片预处理阻塞情况 已导出数据集 沉淀为后续模型训练的基础资产 2. 图片管理 图片管理模块提供完整的图片生命周期管理：\n字段 说明 ID 图片唯一标识 图片名称 文件名 预处理状态 已完成 / 待处理 尺寸 图片分辨率 文件大小 图片文件体积 缩略图预览 预览图 上传时间 上传时间戳 操作功能：\n预处理 - 对图片进行标准化处理 详情 - 查看图片详细信息 标注 - 进行人工标注 报告 - 生成分析报告 删除 - 移除图片 3. 数据导出 数据导出模块支持按多种维度筛选导出训练数据：\n预处理状态 是否标注 是否复核 结构化标签 4. 任务中心 任务中心追踪所有图片预处理和数据集导出任务：\n字段 说明 任务 ID 任务唯一标识 任务类型 如 preprocess 状态 任务执行状态 图片 ID 关联的图片 数据集 ID 关联的数据集 失败原因 任务失败时的错误信息 开始时间 任务开始时间 结束时间 任务结束时间 项目设计：wobushi041\n","date":"2026-06-22","tags":[]},{"title":"Harness Engineering","permalink":"/posts/harness-engineering/","summary":"从架构视角深入解读 Harness 的设计哲学，帮助工程师建立对现代 CI/CD 平台的认知框架\n一、Harness 到底是什么 一句话：Harness 是一个构建在 Kubernetes 之上的、以 Delegate 为核心执行引擎的、SaaS 化的软件交付平台。\n这句话里有三个关键词，每一个都值得展开。\n1. 构建在 Kubernetes 之上 Harness 的控制平面（Control Plane）是一组微服务，运行在 Kubernetes 集群中。这意味着：\n弹性伸缩是天然能力，不是事后补丁 多租户隔离通过 K8s 的 namespace 和资源配额实现 服务治理依赖 K8s 原生的服务发现和负载均衡 这不是什么了不起的事——几乎所有现代 SaaS 产品都跑在 K8s 上。但关键在于，Harness 把 K8s 的能力向下暴露给了用户：你的 Pipeline 可以直接操作 K8s 集群进行部署，而不是通过一层中间转换。\n2. Delegate 是核心执行引擎（重点） 这是理解 Harness 最关键的一个概念。\nDelegate 是一个运行在你基础设施中的进程，负责执行 Pipeline 中的所有任务。它不是 Harness 帮你跑的——它跑在你的环境里。\n为什么要这样设计？因为软件交付涉及的操作，绝大多数都需要访问内网资源：代码仓库、制品库、K8s 集群、数据库、云账号。如果这些操作全部由 Harness 的 SaaS 控制平面来执行，就意味着你的内网资源必须对 Harness 开放——这在安全合规层面几乎不可接受。\nDelegate 的架构解决了这个问题：\n┌─────────────────────────────────────────────────────┐ │ Harness SaaS控制平面 │ │ (Pipeline 编排、状态管理、UI、API) │ └──────────────────────┬──────────────────────────────┘ │ 出站连接（Delegate 主动拉取任务） │ ← 不需要入站端口暴露 ┌──────────────────────▼──────────────────────────────┐ │ 你的基础设施 │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Delegate │ │ Delegate │ │ Delegate │←可部署多个 │ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ │ │ │ │ │ ┌───▼───┐ ┌────▼───┐ ┌────▼───┐ │ │ │K8s集群 │ │代码仓库 │ │云账号 │ │ │ └───────┘ └────────┘ └────────┘ │ └─────────────────────────────────────────────────────┘ 核心设计要点：\n","content":"从架构视角深入解读 Harness 的设计哲学，帮助工程师建立对现代 CI/CD 平台的认知框架\n一、Harness 到底是什么 一句话：Harness 是一个构建在 Kubernetes 之上的、以 Delegate 为核心执行引擎的、SaaS 化的软件交付平台。\n这句话里有三个关键词，每一个都值得展开。\n1. 构建在 Kubernetes 之上 Harness 的控制平面（Control Plane）是一组微服务，运行在 Kubernetes 集群中。这意味着：\n弹性伸缩是天然能力，不是事后补丁 多租户隔离通过 K8s 的 namespace 和资源配额实现 服务治理依赖 K8s 原生的服务发现和负载均衡 这不是什么了不起的事——几乎所有现代 SaaS 产品都跑在 K8s 上。但关键在于，Harness 把 K8s 的能力向下暴露给了用户：你的 Pipeline 可以直接操作 K8s 集群进行部署，而不是通过一层中间转换。\n2. Delegate 是核心执行引擎（重点） 这是理解 Harness 最关键的一个概念。\nDelegate 是一个运行在你基础设施中的进程，负责执行 Pipeline 中的所有任务。它不是 Harness 帮你跑的——它跑在你的环境里。\n为什么要这样设计？因为软件交付涉及的操作，绝大多数都需要访问内网资源：代码仓库、制品库、K8s 集群、数据库、云账号。如果这些操作全部由 Harness 的 SaaS 控制平面来执行，就意味着你的内网资源必须对 Harness 开放——这在安全合规层面几乎不可接受。\nDelegate 的架构解决了这个问题：\n┌─────────────────────────────────────────────────────┐ │ Harness SaaS控制平面 │ │ (Pipeline 编排、状态管理、UI、API) │ └──────────────────────┬──────────────────────────────┘ │ 出站连接（Delegate 主动拉取任务） │ ← 不需要入站端口暴露 ┌──────────────────────▼──────────────────────────────┐ │ 你的基础设施 │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Delegate │ │ Delegate │ │ Delegate │←可部署多个 │ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ │ │ │ │ │ ┌───▼───┐ ┌────▼───┐ ┌────▼───┐ │ │ │K8s集群 │ │代码仓库 │ │云账号 │ │ │ └───────┘ └────────┘ └────────┘ │ └─────────────────────────────────────────────────────┘ 核心设计要点：\n出站连接：Delegate 主动向 Harness 控制平面轮询任务，不需要你开放任何入站端口。你的防火墙规则可以保持严格。 任务执行：Delegate 收到任务后，在你的内网环境中执行——访问你的代码仓库、推送到你的 K8s 集群、调用你的云 API。 无状态设计：Delegate 本身不保存状态，可以水平扩展。多个 Delegate 组成一个 Delegate Group，自动负载均衡。 自动升级：Delegate 定期检查新版本并自动更新，不需要手动运维。 这个设计的精妙之处在于：Harness 看到了你的 Pipeline 定义和执行结果，但从未直接触达你的内网资源。所有敏感操作都在你的边界内完成。这满足了大多数企业的安全合规要求。\n3. SaaS 化的软件交付平台 Harness 的默认形态是 SaaS——控制平面由 Harness 团队运维，你只需要部署 Delegate。当然也有 Self-Managed Platform（即私有化部署），但 SaaS 是其主推模型。\n这意味着：\n你不需要运维 CI/CD 基础设施本身（Jenkins Master 的运维痛点彻底消失） 版本升级对用户透明（对比 Jenkins 的插件兼容性噩梦） 多租户天然支持（团队隔离不需要额外配置） 二、Pipeline 的抽象模型 理解了 Delegate，再来看 Harness 的 Pipeline 是怎么组织的。\nHarness 的 Pipeline 采用四层抽象：\nPipeline（流水线） └── Stage（阶段） └── Step（步骤） └── Step Group（步骤组，可选） 每一层的职责：\nPipeline：一次完整的软件交付流程。通常对应一次代码提交从构建到部署的全过程。 Stage：Pipeline 中的一个逻辑阶段。常见类型有 Build（构建）、Deploy（部署）、Approval（审批）、Custom（自定义）。 Step：Stage 中的一个原子操作。比如\u0026quot;执行 Shell 脚本\u0026quot;、\u0026ldquo;推送镜像\u0026rdquo;、\u0026ldquo;滚动更新 K8s Deployment\u0026rdquo;。 Step Group：一组可复用的 Step 集合，类似于函数封装。 这个模型和 Jenkins Pipeline 的 Stage → Step 模型很像，但有一个关键区别：Harness 的每一层抽象都有独立的失败策略、回滚逻辑和条件执行控制。你可以在 Stage 级别定义\u0026quot;如果失败则回滚到上一个版本\u0026quot;，而不是在每个 Step 里写 try-catch。\nInfrastructure Definition：部署目标的声明式描述 Harness 有一个独特的概念叫 Infrastructure Definition，它声明式地描述\u0026quot;这次部署的目标环境是什么\u0026quot;。\n比如，一个 K8s 部署的 Infrastructure Definition 会声明：\n目标集群是哪个（通过 Cloud Provider Connector 关联） 目标 namespace 是什么 Release Name 的前缀是什么 这个设计的好处是：Pipeline 的逻辑和部署目标解耦了。同一个 Pipeline 可以通过切换 Infrastructure Definition，部署到 dev、staging、prod 三个环境，不需要维护三份 Pipeline 配置。\n三、Connector 机制：如何连接外部世界 Harness 需要和很多外部系统交互：GitHub、Docker Hub、AWS、K8s 集群、Slack……这些连接通过 Connector 统一管理。\nConnector 的核心设计原则是凭证与使用分离：\nConnector 定义：存储在 Harness 控制平面，包含连接 URL、认证方式（SSH Key、Token、IAM Role 等）、连接测试逻辑。 实际连接：由 Delegate 在你的内网环境中执行。Connector 的凭证信息会被传递给 Delegate，但连接动作发生在你的网络边界内。 这意味着：你往 Harness 里存的是\u0026quot;怎么连\u0026quot;的描述，而不是让 Harness 直接连。实际的网络握手在你自己的环境里完成。\n常见的 Connector 类型：\nSource Code Connector：GitHub、GitLab、Bitbucket，用于拉取代码 Artifact Connector：Docker Registry、JFrog Artifactory、Nexus，用于推送/拉取构建产物 Cloud Provider Connector：AWS、GCP、Azure，用于调用云 API Kubernetes Cluster Connector：直接关联 K8s 集群的 kubeconfig 或 Service Account Notification Connector：Slack、Email、PagerDuty，用于发送通知 四、Harness vs Jenkins：架构层面的本质差异 很多对比文章停留在\u0026quot;Jenkins 有 1800+ 插件，Harness 没有\u0026quot;这种层面。这没有意义。我们需要从架构层面理解两者的本质差异。\n4.1 执行模型 Jenkins：Master-Agent 架构。Master 负责调度和状态管理，Agent 负责执行。Master 是单点——它挂了，整个 CI/CD 就停了。即使配置了 HA，本质上也是 Active-Passive，资源利用率低。\nHarness：控制平面是分布式微服务，无单点。执行层是 Delegate，无状态且可水平扩展。不存在\u0026quot;Master 挂了全部停摆\u0026quot;的问题。\n4.2 安全模型 Jenkins：Agent 需要能被 Master 访问（入站连接）。如果 Master 在云上、Agent 在内网，你需要打通网络隧道或暴露端口。Jenkins 凭证存储在 Master 的文件系统上，历史上多次出现凭证泄露漏洞。\nHarness：Delegate 主动出站连接，不需要入站端口。凭证存储在 Harness 控制平面（加密），但实际使用凭证的操作在 Delegate 端完成。攻击面显著更小。\n4.3 配置管理 Jenkins：Pipeline 定义用 Jenkinsfile（Groovy DSL）。Groovy 是一门完整的编程语言，这意味着 Jenkinsfile 可以写得极其灵活，也可以写得极其难以维护。没有 Schema 校验，错误在运行时才发现。\nHarness：Pipeline 定义用 YAML。YAML 是声明式的，有明确的 Schema，可以在提交前校验。灵活性不如 Groovy，但一致性和可审计性更好。\n4.4 插件 vs 原生能力 Jenkins：核心是一个调度引擎，几乎所有能力都靠插件实现。插件质量参差不齐，版本兼容性是噩梦（Jenkins 升级大版本时，插件大面积挂掉是常态）。\nHarness：核心能力（CI、CD、Feature Flags、SLO 管理、云成本管理、安全测试编排、IaC 管理、开发者门户、混沌工程）是平台原生的，不是插件。这意味着版本一致性有保障，但灵活性受限——你不能像 Jenkins 那样写一个自定义插件来扩展能力。\n4.5 可观测性 Jenkins：原生可观测性很弱。你需要额外部署 Prometheus + Grafana 来监控 Jenkins 本身，再用 ELK 来聚合构建日志。\nHarness：内置部署可观测性（Service Reliability Management）。Pipeline 的每次执行都有完整的审计日志、执行时间线、失败分析。和外部 APM 工具（Datadog、New Relic）的集成是原生支持的。\n4.6 总结对比 维度 Jenkins Harness 架构 Master-Agent（中心化） 控制平面 + Delegate（分布式） 安全模型 入站连接，凭证存本地 出站连接，凭证加密存储 配置语言 Groovy DSL（图灵完备） YAML（声明式） 能力扩展 插件生态（1800+） 平台原生能力 可观测性 需要额外搭建 内置 运维成本 高（Master 运维、插件管理） 低（SaaS 托管、Delegate 自动升级） 五、从 Jenkins 迁移到 Harness：你需要知道的事 如果你的团队正在考虑从 Jenkins 迁移到 Harness，以下几个点值得提前了解：\n5.1 迁移不是 1:1 翻译 Jenkinsfile 里的 Groovy 逻辑（条件判断、循环、共享库调用）不能直接翻译成 Harness YAML。你需要重新设计 Pipeline 的抽象层次——哪些是 Stage，哪些是 Step Group，哪些逻辑应该下沉到 Delegate 端的脚本里。\n5.2 Harness 不是免费的 Jenkins 是开源免费的（运维成本除外）。Harness SaaS 是按消费计费的——基于构建分钟数、部署次数、Feature Flag 请求数等维度。你需要评估你的使用量对应的费用，而不是假设\u0026quot;换工具就能省钱\u0026quot;。\n5.3 Delegate 的运维成本 虽然 Delegate 会自动升级，但它仍然跑在你的基础设施上。你需要监控它的资源使用（CPU、内存、网络），确保它不会影响你的业务服务。在大规模场景下，Delegate Group 的容量规划是一个需要认真对待的问题。\n5.4 学习曲线是真实的 Harness 的概念模型（Pipeline/Stage/Step/Infrastructure Definition/Connector/Delegate）比 Jenkins 的概念模型（Job/Stage/Step/Agent）更丰富。团队需要时间来建立新的心智模型。\n六、心理认知准备：面对新范式的正确姿态 6.1 认清范式转移的本质 CI/CD 工具的演进不是线性的功能迭代，而是范式转移：\n第一代：脚本时代。Shell 脚本 + Cron，手动编排。 第二代：自动化服务器。Jenkins 为代表，\u0026ldquo;一切皆可插件\u0026rdquo;。 第三代：软件交付平台。Harness 为代表，\u0026ldquo;一切皆是平台能力\u0026rdquo;。 每一代迁移都不是\u0026quot;旧工具的升级\u0026quot;，而是思维方式的改变。从 Jenkins 到 Harness，你需要放弃\u0026quot;什么都能自定义\u0026quot;的执念，接受\u0026quot;平台已经帮你做好了大多数决策\u0026quot;的现实。\n6.2 工程师的三种认知陷阱 陷阱一：工具熟悉度 = 工具优越性\n用惯了 Jenkins 的工程师会本能地认为 Jenkins \u0026ldquo;更好\u0026rdquo;——因为他们已经踩过坑、建立了心智模型、知道怎么绕过问题。但\u0026quot;我熟悉\u0026quot;和\u0026quot;它更好\u0026quot;是两回事。评估新工具时，需要把熟悉度带来的偏见剥离掉。\n陷阱二：灵活性崇拜\n\u0026ldquo;Jenkins 什么都能做\u0026quot;是真的，但\u0026quot;什么都能做\u0026quot;也意味着\u0026quot;什么都要自己做\u0026rdquo;。Harness 的限制性恰恰是它的优势——它帮你做出了大量架构决策，你不需要在 Groovy 脚本里重新发明轮子。\n陷阱三：迁移恐惧\n\u0026ldquo;迁移太麻烦了，不如继续用 Jenkins。\u0026ldquo;这种想法在短期内是理性的，但长期来看，技术债务会累积。Jenkins 的插件维护成本、Master 的运维成本、安全漏洞的修复成本，这些隐性成本往往被低估。\n6.3 建立正确的评估框架 在决定是否迁移到 Harness 之前，建议从以下维度评估：\n安全合规需求：你的行业对安全合规的要求有多严格？Delegate 的出站连接模型是否能显著降低你的合规风险？ 团队规模：小团队（\u0026lt; 10 人）可能不需要 Harness 的全部能力，Jenkins + 云托管方案可能更经济。大团队（\u0026gt; 50 人）的运维成本和协作复杂度会显著放大 Harness 的价值。 多云/混合云需求：如果你的部署目标跨越多个云平台或混合云环境，Harness 的 Connector 和 Infrastructure Definition 模型会大幅降低管理复杂度。 预算：评估 Harness 的定价模型是否适合你的使用模式。高频率、小规模的 CI 场景可能不划算；低频率、高复杂度的 CD 场景价值更大。 6.4 CNCF 平台工程白皮书的启示 CNCF 平台白皮书对平台工程的定义是：\n平台工程是设计和构建工具链与工作流的学科，为云原生时代的软件工程组织提供自助服务能力。平台工程提供集成产品（通常称为\u0026quot;内部开发者平台\u0026rdquo;），贯穿软件生命周期的每个阶段。\nHarness 的设计哲学与此高度一致：它不是一个 CI 工具或 CD 工具，而是一个平台——它把 CI、CD、Feature Flags、SLO 管理、安全测试、成本管理、开发者门户整合在一起，提供统一的自助服务体验。\n理解这一点很重要：你不是在选一个 Jenkins 的替代品，你是在评估一个平台工程战略是否适合你的组织。\n总结 Harness 的架构设计有三个核心支柱：\nDelegate 模型：把执行引擎放在用户环境中，解决了安全合规的根本问题 声明式 Pipeline：用 YAML 替代 Groovy，用 Schema 校验替代运行时错误 平台化整合：把 CI/CD 之外的能力（安全、成本、可靠性）纳入同一个平台 这三个支柱共同构成了一个和 Jenkins 截然不同的软件交付范式。理解这个范式，比记住 Harness 有哪些产品模块重要得多。\n作为工程师，面对范式转移时最有价值的心态是：不预设结论，但带着框架去评估。 这篇文章给你的框架是架构层面的——Delegate 是怎么工作的、Pipeline 是怎么组织的、安全模型是怎么设计的。带着这些认知去试用 Harness，你会比\u0026quot;看功能清单\u0026quot;更快地判断它是否适合你的团队。\n","date":"2026-06-09","tags":["Harness","CI/CD","平台工程","架构设计","Agent Workflow"]},{"title":"LLM Wiki：面向 Agent 工程的知识编译层","permalink":"/posts/llm-wiki/","summary":"如果只先记住一个结论，那么可以记这句：\nLLM wiki 不是“让 AI 帮你整理笔记”，而是把项目知识从原始资料提升为 Agent 可消费、可引用、可演化的知识中间层。\n这个判断的关键在于，问题并不只是“资料有没有被存下来”，而是“资料是否已经被整理成 Agent 可以稳定工作的形状”。在这件事上，RAG 和 LLM wiki 处理的根本不是同一层问题。Andrej Karpathy 提出的 llm-wiki.md 范式 给出的也不是一个笔记软件教程，而是一种把知识从原始材料编译成可维护工作上下文的思路。\n本文想讨论的是三个问题：\nLLM wiki 到底是什么 它和 RAG 的边界到底在哪里 如果要把它落到工程实践里，最小实现应该长什么样 1. Agent 真正缺的不是“更多文档”，而是知识编译层 很多仓库并不缺文档。\nREADME、ADR、issue、PR、聊天记录、代码注释、发布记录，甚至临时会议纪要，往往已经足够多。问题在于，这些材料大多是围绕“人怎么理解系统”自然长出来的，而不是围绕“Agent 应该如何进入系统、命名概念、定位事实、拼装上下文”组织出来的。\n这会带来几个很典型的摩擦：\n资料很多，但没有稳定入口 术语存在，但定义分散甚至漂移 同一个问题需要每次重新检索和重新拼接上下文 原始资料适合追溯事实，不适合直接充当工作层 所以 LLM wiki 试图解决的，不是“把一堆东西再存一遍”，而是另一件更具体的事：\n它的价值不在存储，而在预编译；不在收集，而在把知识变成可持续复用的中间表示。\nKarpathy 在原始 gist 里把这件事描述得很清楚：系统并不直接依赖原始材料回答问题，而是先把原始材料经过整理，沉淀成持续更新的 wiki 层，并由 schema 约束其结构与工作流，再把它作为后续查询和工作的主上下文层。来源\n2. 与 RAG 的绝对区分：一个是运行时召回，一个是离线知识编译 很多讨论会把 LLM wiki 和 RAG 混在一起，但这两者并不是同义替换。\nRAG 的经典定义来自 Lewis 等人的论文 Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks：模型在生成前，先从外部知识源检索相关内容，再把检索结果并入生成过程。论文链接\n","content":"如果只先记住一个结论，那么可以记这句：\nLLM wiki 不是“让 AI 帮你整理笔记”，而是把项目知识从原始资料提升为 Agent 可消费、可引用、可演化的知识中间层。\n这个判断的关键在于，问题并不只是“资料有没有被存下来”，而是“资料是否已经被整理成 Agent 可以稳定工作的形状”。在这件事上，RAG 和 LLM wiki 处理的根本不是同一层问题。Andrej Karpathy 提出的 llm-wiki.md 范式 给出的也不是一个笔记软件教程，而是一种把知识从原始材料编译成可维护工作上下文的思路。\n本文想讨论的是三个问题：\nLLM wiki 到底是什么 它和 RAG 的边界到底在哪里 如果要把它落到工程实践里，最小实现应该长什么样 1. Agent 真正缺的不是“更多文档”，而是知识编译层 很多仓库并不缺文档。\nREADME、ADR、issue、PR、聊天记录、代码注释、发布记录，甚至临时会议纪要，往往已经足够多。问题在于，这些材料大多是围绕“人怎么理解系统”自然长出来的，而不是围绕“Agent 应该如何进入系统、命名概念、定位事实、拼装上下文”组织出来的。\n这会带来几个很典型的摩擦：\n资料很多，但没有稳定入口 术语存在，但定义分散甚至漂移 同一个问题需要每次重新检索和重新拼接上下文 原始资料适合追溯事实，不适合直接充当工作层 所以 LLM wiki 试图解决的，不是“把一堆东西再存一遍”，而是另一件更具体的事：\n它的价值不在存储，而在预编译；不在收集，而在把知识变成可持续复用的中间表示。\nKarpathy 在原始 gist 里把这件事描述得很清楚：系统并不直接依赖原始材料回答问题，而是先把原始材料经过整理，沉淀成持续更新的 wiki 层，并由 schema 约束其结构与工作流，再把它作为后续查询和工作的主上下文层。来源\n2. 与 RAG 的绝对区分：一个是运行时召回，一个是离线知识编译 很多讨论会把 LLM wiki 和 RAG 混在一起，但这两者并不是同义替换。\nRAG 的经典定义来自 Lewis 等人的论文 Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks：模型在生成前，先从外部知识源检索相关内容，再把检索结果并入生成过程。论文链接\nRAG 的重点天然落在运行时：\n找不找得到 召回的片段准不准 噪音高不高 排序和相关性好不好 而 LLM wiki 的关注点并不在“这一问检索到什么”，而在“平时有没有把知识整理成一个稳定的工作骨架”。\n这里可以直接用一张表来区分说明：\n维度 RAG LLM wiki 主要工作阶段 运行时 离线持续维护 核心目标 找回相关片段 组织成稳定知识骨架 输入形态 原始文档切片 经整理后的主题页、术语页、决策页 主要优化对象 召回率、相关性 可导航性、可引用性、一致性 失败模式 没召回 / 召回噪音 结构陈旧 / 术语漂移 / 入口失效 更像什么 检索系统 知识编译系统 一句话说，RAG 更像是在 query time 做“找”，而 LLM wiki 更像是在 authoring time 做“整理”和“压缩”。\nKarpathy 在 gist 里讲得很直接：不要只在 query time 从 raw documents 里临时捞片段，而是让 LLM 持续维护一个位于你和原始资料之间的 persistent wiki。这个动作本质上就是先把知识整理成稳定结构，再用这层结构服务后续工作，而不是每次都直接在原始材料里临时搜索。来源\n这也是为什么更适合把 LLM wiki 理解成知识层的 build step，而不是检索层的补丁。\n3. 关键不在载体，而在知识形状 LLM wiki 很容易被误解成“用 Obsidian 记笔记”“用 Notion 建文档”“用 Hugo 发布知识库”。这些都可以是载体，但都不是重点。\n哪怕都是 Markdown 文件，面向博客的写法和面向 Agent 的写法也完全不同。\n普通文档更关心的是：\n人类读起来顺不顺 章节结构清不清楚 能不能从头到尾顺着看 而 LLM wiki 还必须满足额外约束：\n页面能不能被独立引用 概念有没有稳定命名 页面之间有没有显式关系 知识能不能被逐步重写，而不是只追加 Obsidian 官方文档一直强调链接、反向链接、图谱和知识库组织能力，例如 internal links、backlinks、graph view 这些能力，本质上都是在增强“知识节点之间的关系可见性”。官方帮助文档 这和 LLM wiki 的思路是相通的，但 LLM wiki 还会再向前一步：它不只要求可读，还要求这些页面天然适合被模型抽取、拼接、引用和重写。\n所以问题不在“你是不是用了 wiki 工具”，而在“你的页面是不是构成了稳定知识节点”。\n4. 一个工程可用的 LLM wiki，最小结构其实只有三层 如果严格按照 Karpathy 的原始范式来看，最小结构应该收缩成三层，而不是先发明一套很重的目录体系。\n最小结构就是：\nraw/ schema wiki/ 这里三层各自的职责非常明确：\nraw/：原始资料层，放文章、论文、图片、数据文件等。它是事实来源层，默认不可变，LLM 只读不改。 schema：规则层，通常就是 AGENTS.md、CLAUDE.md 这类文件。它负责告诉 LLM 这套 wiki 怎么组织、有哪些命名约定、如何 ingest、如何 query、如何 lint。 wiki/：知识层，由 LLM 生成和维护的 markdown 页面集合。摘要页、实体页、概念页、比较页、总览页、综合分析页都在这里。 这是原始 gist 里最重要的架构判断之一：原始资料、知识页、维护规则，必须分层。来源\n继续往下拆，这三层里真正决定上限的，往往反而不是 wiki/，而是 raw/ 和 schema。\n对 raw/，重点应该放在数据清洗和人工审核上。无论是自己总结的随记、技术文档、学习笔记、心得，还是外部文章、PDF、Word、Markdown、截图、数据表，只要准备进入这套系统，都更适合先被视为原始知识材料，而不是直接可用知识。这里最怕的是脏数据、重复信息、低质量摘录、未经确认的引用、格式噪音和上下文残缺。因为 raw/ 作为最底层，决定了后面所有 synthesis 的上界；如果地基层就松，后面的 wiki 写得再漂亮，也只是把偏差结构化。\n所以，raw/ 这一层不是“收集得越多越好”，而是“清洗得越干净越好”。进入 raw/ 的材料，应该尽量经过明确整理和人工审核，至少保证来源可追溯、内容可读、格式可处理、重复可识别、噪音可控。\n而 schema 的重要性，很多时候甚至会被低估。schema 不只是一个说明 LLM 怎么写 wiki 的配置文件，它本质上是在约束 LLM 的边界，控制每一轮循环的误差，规定它如何 ingest、如何建立 cross-references、如何回写、如何做 lint、如何处理冲突、何时该保守、何时可以改写。它真正解决的问题不是“格式统一”，而是“这套系统如何在多轮迭代中维持 cross-reference quality 和整体 consistency”。\n再说得具体一点，schema 要回答的其实是这些问题：\n每一轮 ingest 的标准动作是什么 更新一个 source 时允许触碰哪些页面 新信息和旧结论冲突时应该如何处理 query 产出的分析什么时候允许回写进 wiki 哪些页面必须保守，哪些页面可以积极重构 lint 应该检查哪些一致性问题 如果这些规则不清楚，LLM 每一轮虽然都在“工作”，但系统的熵其实是在增加的。旧结论和新增信息之间的冲突、命名漂移、cross-references 退化、页间不一致，都会慢慢侵蚀整个 wiki 的可信度。可以把 schema 理解成一套控制循环误差和管理新增熵的机制，它的目标不是让 LLM 更自由，而是让它更稳定。\n在这三层之下，index.md 和 log.md 是两个非常关键的特殊文件：\nindex.md 是内容导向的目录，帮助 LLM 和人快速找到相关页面 log.md 是时间导向的追加日志，记录 ingest、query、lint 等动作 再往下扩展成 entities/、concepts/、systems/ 之类的目录，当然可以做，但那已经是某个具体领域的实例化，不是这个范式本身的最小要求。\n所以如果只讲核心，可以把它概括成一句话：\nLLM wiki 的最小骨架不是一堆分类目录，而是 raw、schema、wiki 三层分离。\n5. 页面不是“文档”，而是知识节点 这是 LLM wiki 和普通知识库教程最不一样的地方。\n在普通文档系统里，一页文章写得顺、写得全，通常就已经够用了。但在 LLM wiki 里，一页首先是一个可以被引用、组合和追踪的知识节点，而且这页默认是由 LLM 持续维护的，不是主要靠人手工慢慢改出来的。\n落到写法上，页面最好尽量满足这些原则：\n一页只承载一个稳定主题 页面标题必须是可复用的引用名 先写定义、边界、关系，再写叙述性背景 显式写出相关页、前置概念、依赖系统和常见误解 让页面可以被独立抽出，而不是必须通读整篇才能理解 差页面和好页面的区别通常很直接。\n差页面往往是：\n流水账 混合多个主题 没有链接 没有边界 读完之后仍然不知道它在知识图里属于哪里 好页面通常具备这些特征：\n主题单一 命名稳定 关系显式 可以被独立引用 被抽取进上下文后仍然保留语义完整性 这也是为什么 LLM wiki 里的页面更像“可组合单元”，而不是“仅供线性阅读的章节”。至于 wiki 本身为什么应该是 persistent、compounding、interlinked artifact，Karpathy 在原始 gist 里已经讲得很完整，这里不再重复扩写，重点只放在这套结构真正落地时，哪些地方最容易失真。\n6. Agent 工作流闭环：Ingest、Query、Lint、Rewrite 如果只把 LLM wiki 当成一个静态文件夹，它很快就会失效。真正有用的是把它变成一条持续运行的知识维护流水线。\n一个比较自然的最小闭环是四步：\n6.1 Ingest 从 raw/ 提取事实，更新 wiki 页面，而不是把原始资料直接塞进上下文。\n这一步做的不是复制粘贴，而是：\n抽概念 归术语 拆主题 建链接 标记来源 按照 gist 的描述，一个 source 进来之后，LLM 不只是写一页摘要，还可能同时更新 index.md、相关实体页、概念页，以及 log.md。也就是说，ingest 不是“收录一份文件”，而是“把新知识并入现有 wiki”。来源\n6.2 Query 后续回答、分析、规划，优先基于 wiki 层展开；原始资料只作为追溯证据层。\n这样做的好处是，上下文不再是一次次临时拼装的碎片，而是来自同一套稳定骨架。并且 gist 里另一个很重要的点是，好的 query 结果不该只留在聊天记录里，它本身也可以回写成新的 wiki 页面，让分析结果继续沉淀。来源\n6.3 Lint 定期检查结构健康度，例如：\n断链 重复页 命名冲突 过时页 空入口 孤儿页 已经被新来源推翻但没更新的旧结论 被频繁提到但还没有单独页面的重要概念 Karpathy 在 gist 里专门把 lint 作为一个动作提出，这一点非常关键，因为知识系统和代码系统一样，也会腐化。来源\n6.4 Rewrite 随着任务推进，持续重写结构，让 wiki 跟着系统演化，而不是无限追加新页面。\n真正的维护不是“越写越多”，而是“该折叠的折叠，该合并的合并，该改名的改名”。\n所以这套东西的关键判断应该是：\nLLM wiki 不是静态知识库，而是一条持续运行的知识维护流水线。\n而这条流水线能不能长期稳定运转，最终看的还是两件事：raw/ 有没有把好底层质量关，schema 有没有把好多轮循环的一致性关。\n7. 为什么这套东西在今天才真正可行 如果把时间拉长一点看，LLM wiki 并不是完全凭空冒出来的新想法。\nVannevar Bush 在 1945 年的文章 As We May Think 里提出过著名的 memex 概念，强调通过关联路径组织个人知识，而不是只靠线性归档。原文链接\n这个方向并不新，真正长期卡住的，是维护成本。\n过去的问题不是没人想到链接化知识系统，而是：\n资料整理太费人 命名统一太费人 跨页归并太费人 持续重写太费人 而 LLM 真正改变的一点，不只是“能生成文字”，而是它显著压低了这些知识维护动作的边际成本：摘要、归并、重写、抽术语、补链接、生成索引页、维护跨页一致性，这些以前昂贵的操作，现在终于可以低成本持续执行。\n所以 LLM wiki 不是旧 wiki 的换皮，而是旧知识系统在新维护成本条件下的再成立。Karpathy 的 gist 之所以让人眼前一亮，也正是因为它把这件事从模糊愿景落到了可执行结构上。来源\n8. 失败模式与反模式：它什么时候会退化成垃圾层 任何知识系统只要开始维护，就会面临腐化问题。LLM wiki 也不例外。\n最常见的失败模式大概有这几类：\n8.1 不区分 raw 和 wiki 如果什么都往 wiki/ 里塞，而不是先把原始资料留在 raw/、把整理后的知识放进 wiki/，信息密度很快就会失控，后面所有页面都会变成冗长噪音。\n8.2 没有术语页 同一个概念今天叫 workflow state，明天叫 task context，后天又叫 execution memory，Agent 没法稳定对齐，知识骨架会从内部崩掉。\n8.3 当前任务态和长期知识混写 任务临时结论、调试痕迹、一次性 workaround，如果直接写进稳定概念页，后面会持续污染判断。\n8.4 页面之间没有显式关系 只有孤立页面，没有 related pages、前置概念、依赖系统，这样的知识库看起来很多，实际仍然不可导航。\n8.5 只增不改 知识库一旦只追加、不折叠、不重写，就会像没有重构的代码一样越来越不可用。\n8.6 把 schema 当装饰，把 wiki 当真理源 如果 schema 没有持续演化，LLM 很快就会退化成一个泛化聊天机器人，而不是一个有纪律的 wiki maintainer。更具体地说，一旦没有人去约束每轮循环的动作、更新范围、冲突处理和链接策略，系统表面上看起来还在增长，实际上 cross-reference quality、inbound links 和跨页 consistency 已经在悄悄下降。反过来，如果把 wiki 当成最终事实本身，也会出问题。代码、测试、运行行为、生产数据，依旧是更高优先级的事实源。\n也就是说，LLM wiki 最危险的状态不是“没有写”，而是“写得很多，但结构已经失真”。\n9. 适用场景：它是给长期系统准备的 LLM wiki 并不是任何项目都值得上。\n它更适合这些场景：\n长期维护代码库 多模块系统 研究型或架构型项目 高频使用 Agent 参与设计、编码、调试、审查的工作流 它不太适合这些场景：\n一次性脚本 临时 demo 变化太快且没有沉淀意愿的项目 对上下文一致性没有要求的低复杂度工作 简单说，如果系统还没有复杂到需要知识骨架，那么引入 LLM wiki 只会制造额外维护成本。\n工程基础设施从来都不是越多越好，而是只在复杂度真正出现时再引入。\n10. 把它理解成知识层的 build step 如果要给全文做一个最短总结，可以把 LLM wiki 理解成知识层的 build step。\n它不是文档层的附件，也不是一个“更会记笔记”的工具，而是一层位于原始资料和运行时检索之间的知识编译层：\n原始资料是真实来源 schema 是维护规则 RAG 是运行时检索机制 LLM wiki 是两者之间的知识编译层 真正有区分度的地方，从来不是“也有知识库”，而是是否把知识组织成了 Agent 可以稳定工作的形状。\n当 Agent 开始参与真实工程工作流时，知识库就不再只是备忘录，而会逐渐演化成上下文基础设施。\n参考资料 Andrej Karpathy, LLM Wiki gist Patrick Lewis et al., Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks Vannevar Bush, As We May Think Obsidian, Official Help Yunfan Gao et al., Retrieval-Augmented Generation for Large Language Models: A Survey ","date":"2026-06-01","tags":["wiki","agent","LLM","RAG","knowledge"]},{"title":"Superpowers 使用指南","permalink":"/posts/superpowers-plugin-guide/","summary":"如果只先记住一个结论，那么可以记这句：\nSuperpowers 不是单纯的“代码增强插件”，而是一套把软件开发最佳实践内化为可执行工作流的方法论插件。\n它的价值不在于“帮你多补几行代码”，而在于通过一组技能系统，把设计、计划、执行、测试、审查、调试和收尾这些环节串成一个更稳定的开发闭环。\n本文会系统回答几个问题：\nSuperpowers 到底是什么 它和普通代码辅助工具有什么本质区别 它的完整工作流怎么跑 什么时候该自动触发，什么时候适合手动调用 使用中最容易踩的坑是什么 1. Superpowers 到底是什么 Superpowers 是一个面向 Claude Code 的开发流程插件。它不是把一堆零散命令简单打包，而是把软件工程中的一整套高质量实践，组织成可自动触发、可组合、可审查的工作流。\n和常见“你提需求，我给代码”的工具相比，它有几个明显不同点：\n它会优先帮助你澄清需求，而不是立刻开写 它强调计划拆解，而不是一次性生成大段实现 它默认引入 TDD、代码审查和系统化调试 它允许通过子代理并行处理任务 它把“验证是否真的完成”看得和“写出代码”同样重要 换句话说，Superpowers 关注的不只是产出代码，而是产出一个更可控、更可验证的开发过程。\n2. 核心理念是什么 Superpowers 背后最重要的不是某个命令，而是它坚持的几条工程原则。\n2.1 测试驱动开发优先 它默认推崇 TDD，也就是经典的 RED -\u0026gt; GREEN -\u0026gt; REFACTOR 循环：\n先写一个失败的测试 再写最少的代码让测试通过 最后在测试保护下重构 这会强迫开发从“想当然实现”切换到“先定义预期行为，再补实现”。\n2.2 系统化优于临时应对 遇到问题时，它更倾向于：\n明确定位问题 收集证据 找根因 用流程和验证收束结果 而不是简单地“试一下这个改法能不能过”。\n2.3 简单性优先于复杂炫技 Superpowers 的方法论倾向非常明确：复杂度不是能力的证明，能把问题拆到足够小、足够清楚，才是真正可维护的工程能力。\n2.4 验证优先于宣称 “已经修好了”“应该可以了”“理论上没问题”这类表述，在它的工作流里都不算真正完成。必须通过测试、审查、验证或复现消除，结果才算站得住。\n3. 它和普通代码辅助工具有什么不同 可以用下面这张表快速理解它的定位：\n维度 普通代码辅助工具 Superpowers 主要目标 更快生成代码 更稳地完成完整开发流程 默认行为 直接根据需求写实现 先设计、再计划、再执行 测试态度 可有可无 默认强制引入 TDD 代码审查 往往依赖人工补充 工作流内建审查机制 调试方式 偏经验式试错 强调系统化根因分析 适用对象 单次编码任务 需要流程质量保证的开发任务 所以，Superpowers 更像是“开发过程的组织者”，而不只是“生成代码的助手”。\n","content":"如果只先记住一个结论，那么可以记这句：\nSuperpowers 不是单纯的“代码增强插件”，而是一套把软件开发最佳实践内化为可执行工作流的方法论插件。\n它的价值不在于“帮你多补几行代码”，而在于通过一组技能系统，把设计、计划、执行、测试、审查、调试和收尾这些环节串成一个更稳定的开发闭环。\n本文会系统回答几个问题：\nSuperpowers 到底是什么 它和普通代码辅助工具有什么本质区别 它的完整工作流怎么跑 什么时候该自动触发，什么时候适合手动调用 使用中最容易踩的坑是什么 1. Superpowers 到底是什么 Superpowers 是一个面向 Claude Code 的开发流程插件。它不是把一堆零散命令简单打包，而是把软件工程中的一整套高质量实践，组织成可自动触发、可组合、可审查的工作流。\n和常见“你提需求，我给代码”的工具相比，它有几个明显不同点：\n它会优先帮助你澄清需求，而不是立刻开写 它强调计划拆解，而不是一次性生成大段实现 它默认引入 TDD、代码审查和系统化调试 它允许通过子代理并行处理任务 它把“验证是否真的完成”看得和“写出代码”同样重要 换句话说，Superpowers 关注的不只是产出代码，而是产出一个更可控、更可验证的开发过程。\n2. 核心理念是什么 Superpowers 背后最重要的不是某个命令，而是它坚持的几条工程原则。\n2.1 测试驱动开发优先 它默认推崇 TDD，也就是经典的 RED -\u0026gt; GREEN -\u0026gt; REFACTOR 循环：\n先写一个失败的测试 再写最少的代码让测试通过 最后在测试保护下重构 这会强迫开发从“想当然实现”切换到“先定义预期行为，再补实现”。\n2.2 系统化优于临时应对 遇到问题时，它更倾向于：\n明确定位问题 收集证据 找根因 用流程和验证收束结果 而不是简单地“试一下这个改法能不能过”。\n2.3 简单性优先于复杂炫技 Superpowers 的方法论倾向非常明确：复杂度不是能力的证明，能把问题拆到足够小、足够清楚，才是真正可维护的工程能力。\n2.4 验证优先于宣称 “已经修好了”“应该可以了”“理论上没问题”这类表述，在它的工作流里都不算真正完成。必须通过测试、审查、验证或复现消除，结果才算站得住。\n3. 它和普通代码辅助工具有什么不同 可以用下面这张表快速理解它的定位：\n维度 普通代码辅助工具 Superpowers 主要目标 更快生成代码 更稳地完成完整开发流程 默认行为 直接根据需求写实现 先设计、再计划、再执行 测试态度 可有可无 默认强制引入 TDD 代码审查 往往依赖人工补充 工作流内建审查机制 调试方式 偏经验式试错 强调系统化根因分析 适用对象 单次编码任务 需要流程质量保证的开发任务 所以，Superpowers 更像是“开发过程的组织者”，而不只是“生成代码的助手”。\n4. 它是怎么工作的 当你描述一个开发需求时，Superpowers 的典型反应通常不是直接产出代码，而是先把整个过程带入一个更可控的结构。\n一个标准链路大致如下：\n先澄清需求与边界 基于确认后的设计拆出计划 将计划拆成足够小、足够清晰的任务 在实现过程中引入 TDD 在阶段之间引入代码审查 在遇到问题时使用系统化调试 最后统一验证、合并或清理分支 这意味着它真正自动化的，不只是“代码生成”，而是“工程节奏”。\n5. 完整开发流程：7 个阶段 Superpowers 的主流程可以理解为 7 个阶段。\n5.1 阶段一：头脑风暴（brainstorming） 触发时机 当你开始描述一个新功能、改造需求或 bug 修复目标时，通常会先进入这一阶段。\n这个阶段做什么 通过提问把模糊需求变清楚 探索可能的技术方案 明确实现边界和验收标准 输出一个可被继续规划的设计基础 它为什么重要 很多返工并不是因为写代码太慢，而是因为一开始问题就没有被定义清楚。brainstorming 的价值就在于尽量把“想做什么”说透，而不是一上来就开写。\n示例 用户：我想添加用户认证功能 Claude：先一起把需求细化一下： 1. 认证方式是 JWT、Session，还是 OAuth？ 2. 是否需要第三方登录？ 3. 密码强度和找回流程有什么要求？ ... 5.2 阶段二：使用 Git 工作树（using-git-worktrees） 触发时机 设计被确认之后，就可以进入隔离工作空间的准备阶段。\n这个阶段做什么 创建独立的工作树或分支 在隔离环境中初始化项目 检查当前测试基线是否干净 适合场景 并行开发多个功能 隔离实验性修改 避免直接污染主开发分支 5.3 阶段三：编写计划（writing-plans） 触发时机 当设计已经清晰，并且准备进入实现阶段时，会开始写计划。\n这个阶段做什么 把一个模糊的大目标拆成多个小任务，每个任务通常控制在 2 到 5 分钟可完成的粒度内。\n一个高质量任务通常要包含：\n精确的文件路径 明确的目标 需要补充或修改的代码 具体验证方式 清晰的完成标准 为什么要把任务拆这么细 因为细粒度任务有几个优势：\n更容易验证 更容易回滚 更适合并行执行 更适合做阶段性审查 示例计划结构 ## 任务 1：创建用户模型 - 文件：`src/models/user.py` - 验证：运行 `pytest tests/test_user.py` - 预期：测试通过 ## 任务 2：实现认证端点 - 文件：`src/api/auth.py` - 验证：运行 `pytest tests/test_auth.py` - 预期：测试通过 5.4 阶段四：执行计划（executing-plans / subagent-driven-development） 两种主要执行方式 方式 A：分批执行（executing-plans） 特点是：\n分批推进 每批执行后保留人工检查点 更适合对关键步骤需要持续确认的任务 方式 B：子代理驱动（subagent-driven-development） 特点是：\n为不同任务启动独立子代理 可以并行处理多个小任务 每个任务都可独立审查 如果任务拆得足够清晰，子代理驱动通常能显著提升吞吐量。\n5.5 阶段五：测试驱动开发（test-driven-development） 这是整个流程里最有“纪律感”的一环。\nSuperpowers 倾向强制执行下面这个循环：\nRED：先写失败测试 GREEN：写最少实现让测试通过 REFACTOR：在测试保护下重构 示例 def test_user_authentication(): user = authenticate(\u0026#34;admin\u0026#34;, \u0026#34;password123\u0026#34;) assert user.is_authenticated is True 先运行测试，此时它应该失败，因为实现还不存在。\n然后写最小实现让它通过，最后再进行结构优化。\n为什么这个步骤不能省 因为如果一开始就直接写实现，很容易陷入：\n功能看起来跑通了 但行为边界并没有被明确定义 重构时也没有足够保护 5.6 阶段六：请求代码审查（requesting-code-review） Superpowers 把代码审查看成主流程的一部分，而不是“有空再做”的补充动作。\n审查的几个维度 是否符合最初设计 代码质量是否达标 测试是否足够 是否存在明显安全风险 严重程度划分 Critical：必须修复，否则阻断进度 Major：强烈建议修复 Minor：建议改进 Suggestion：可选优化 这个分级很重要，因为它让“审查反馈”从情绪判断变成了更可执行的工程判断。\n5.7 阶段七：完成开发分支（finishing-a-development-branch） 当所有任务完成后，流程还没有结束。最后一个阶段通常会做：\n验证测试是否全部通过 确认是否创建 Pull Request 选择是否合并到主分支 清理工作树和临时分支 这一步的意义在于：不要把“功能写完了”和“开发任务真正闭环了”混为一谈。\n6. 辅助技能：为什么它不只是主流程 7 步 除了主线流程，Superpowers 还内建了几类辅助技能，用来补足真实开发中常见的中断、调试和修复场景。\n6.1 系统化调试（systematic-debugging） 这是最值得重视的辅助技能之一。它强调四个步骤：\n重现问题 缩小范围 找到根因 修复并验证 这套方法最大的价值是：避免一上来就乱改代码，把调试从“碰运气”变成“可解释的分析过程”。\n6.2 完成前验证（verification-before-completion） 这个技能负责确认：\n问题是否真的修复 测试是否覆盖到了关键路径 是否引入了回归 它的作用是防止“看起来修好了，但其实没有彻底解决”。\n6.3 接收代码审查（receiving-code-review） 当审查反馈回来后，这个技能会帮助处理：\n反馈归类 修改请求响应 修复后的再验证 它让“被审查”不再只是被动挨批，而变成一个结构化的改进流程。\n6.4 调度并行代理（dispatching-parallel-agents） 这个技能适合在任务天然可拆、且互相依赖较少时使用。它会帮助：\n划分并发任务 分配子代理 汇总结果 如果任务足够独立，并行执行确实能省下不少时间；但如果任务边界不清，并发反而会制造更多协调成本。\n7. 手动调用技能时怎么用 虽然 Superpowers 会自动触发，但手动调用也很有价值，尤其是在你想明确控制节奏时。\n开发流程相关 /brainstorming /writing-plans /executing-plans /subagent-driven-development 测试与调试相关 /test-driven-development /systematic-debugging /verification-before-completion 审查与分支管理相关 /requesting-code-review /receiving-code-review /using-git-worktrees /finishing-a-development-branch /dispatching-parallel-agents 什么时候适合手动调用 你已经有成熟设计，只想直接进入计划阶段 你只想单独调试某个问题 你需要强行插入一次代码审查 你想控制并行代理的使用时机 8. 一个典型工作流示例 下面用“添加用户认证功能”举一个更完整的例子。\n第一步：提出需求 我想添加用户认证功能 此时不会立即开写，而是先被引导澄清：\n认证方式是什么 是否需要第三方登录 密码策略如何设计 是否有限流和安全审计要求 第二步：生成设计与计划 在需求明确后，系统可能会生成类似这样的任务拆解：\n任务 1：创建用户模型 任务 2：实现注册接口 任务 3：实现登录接口 任务 4：添加 JWT 中间件 任务 5：补齐测试与错误处理 第三步：执行并审查 每个任务在推进过程中会配套：\n失败测试 最小实现 重构 阶段性审查 第四步：收尾 最后统一做：\n覆盖验证 审查收口 PR 创建或合并 工作树清理 这样一个流程的优点是：它不要求你在脑中同时维护全部复杂度，而是把复杂度分配给了流程本身。\n9. 最常见的误区与陷阱 这类方法论工具最大的风险，不是不会用，而是“自以为在用，实际上一直在绕过核心价值”。\n9.1 误区一：把它当成更强的代码生成器 错误心态通常是：\n直接帮我写完，不用问那么多。\n但这正好绕开了 Superpowers 最值钱的部分：设计澄清、任务拆解、验证与审查。\n9.2 误区二：跳过测试 如果你默认认为“先写代码，测试后面再补”，那实际上已经背离了它的 TDD 核心。\n省掉测试，短期看更快，长期通常意味着：\n更高返工率 更脆弱的重构能力 更容易漏掉边界情况 9.3 误区三：排斥代码审查 很多人会本能地觉得审查拖慢进度，但真正的关键问题如果在这个阶段没被拦住，后面付出的代价往往更大。\nSuperpowers 把审查放进流程，不是为了增加仪式感，而是为了尽量把风险前置。\n9.4 误区四：任务拆得太大 比如下面这种任务描述就很危险：\n任务 1：实现完整用户系统（预计 2 小时） 问题在于它：\n难验证 难回滚 难并行 难清晰审查 更合理的做法，是拆成多个可独立验证的小任务。\n9.5 误区五：对流程缺乏耐心 很多人会觉得“先花 5-10 分钟澄清需求”是在拖节奏，但真实经验往往相反：前面少花这几分钟，后面多返工几十分钟甚至几小时。\n10. 最佳实践建议 如果你想把 Superpowers 用得顺一点，我会建议优先做到下面几件事。\n10.1 尽量把需求描述具体 例如不要只说：\n我想做登录功能 更好的表达是：\n我想做登录功能，要求： - 使用 JWT - 支持邮箱和手机号登录 - 密码加密存储 - 接入 Google 和 GitHub 第三方登录 - 有速率限制 需求越具体，后续设计与计划质量通常越高。\n10.2 接受设计引导 如果工具在设计阶段提出质疑、追问或建议，不要急着把它看成“阻碍”。很多时候这些追问恰恰是在帮你提前暴露模糊点。\n10.3 信任细粒度任务拆解 2 到 5 分钟粒度的小任务，虽然看起来碎，但它通常更适合：\n快速验证 阶段性交付 并行推进 快速回滚 10.4 把审查当成保护机制 越早发现关键问题，越便宜。尤其是安全、边界和测试覆盖问题，越适合前置解决。\n10.5 合理使用并行代理 并行不等于永远更快。只有当任务天然独立时，并发才是收益项；否则，它很可能只是更快地制造混乱。\n11. 它适合什么，不适合什么 更适合的场景 新功能开发 Bug 修复 代码重构 性能优化 技术债治理 不那么适合的场景 一次性小脚本 很短的临时实验 紧急 hotfix 最后这类场景并不是“不能用”，而是完整流程的收益未必大于成本。\n12. 总结 Superpowers 最核心的价值，不在于它提供了多少命令，而在于它把优秀工程实践从“口头原则”变成了“可执行流程”。\n它做的事情可以概括为四点：\n用流程把质量前置 用自动化降低认知负荷 用任务拆解提升执行稳定性 用测试、审查和验证减少返工 如果你本来就重视 TDD、代码审查、系统化调试和分阶段交付，那么 Superpowers 会像一个很顺手的“流程放大器”；如果你习惯跳过设计、跳过测试、跳过审查，那它给你的第一感受可能不会是更轻松，而是更有纪律。\n但也正因为这种纪律，它更有机会把“会写代码”推进成“能稳定地完成开发工作流”。\n","date":"2026-05-30","tags":["AI","Claude Code","Workflow"]},{"title":"Docker 学习笔记","permalink":"/posts/docker-learning-notes/","summary":"这篇文章是一份面向个人工程实践的 Docker 入门整理，重点记录 Docker、Dockerfile、Docker Compose，以及它们在 Windows + WSL2 环境下的实际工作方式。\n文章定位 这不是一篇面向生产环境的完整 Docker 手册，而是一份偏向个人工程实践的入门梳理，目标是把几个最常见但最容易混淆的问题讲清楚：\nDocker 到底是什么 Dockerfile 和 Docker Compose 分别解决什么问题 Windows + WSL2 下 Docker 到底运行在哪里 一个前后端项目如何通过 Compose 完成部署 参考资料 Docker 教程视频 Docker 是什么 Docker 是基于 Linux 内核能力实现的容器技术，核心依赖包括命名空间（Namespaces）和控制组（cgroups）。它的本质不是“轻量虚拟机”，而是运行在宿主机 Linux 内核之上的隔离用户态环境。\n因此，Docker 容器具备这些特征：\n有自己的文件系统视图，例如 /bin、/etc、/usr、/app 可以运行 Linux 用户态程序，例如 sh、java、ls 不拥有独立内核，而是共享宿主机内核 更适合描述为“进程级隔离环境”，而不是真正意义上的虚拟机 一句话理解：\n容器负责隔离运行环境，镜像负责定义运行环境。\nWindows + WSL2 下的 Docker 运行方式 在 Windows 环境中，Docker 并不是“直接跑在 Windows 内核上”。Docker Desktop 实际依赖的是 WSL2 提供的 Linux 内核环境。\n","content":"这篇文章是一份面向个人工程实践的 Docker 入门整理，重点记录 Docker、Dockerfile、Docker Compose，以及它们在 Windows + WSL2 环境下的实际工作方式。\n文章定位 这不是一篇面向生产环境的完整 Docker 手册，而是一份偏向个人工程实践的入门梳理，目标是把几个最常见但最容易混淆的问题讲清楚：\nDocker 到底是什么 Dockerfile 和 Docker Compose 分别解决什么问题 Windows + WSL2 下 Docker 到底运行在哪里 一个前后端项目如何通过 Compose 完成部署 参考资料 Docker 教程视频 Docker 是什么 Docker 是基于 Linux 内核能力实现的容器技术，核心依赖包括命名空间（Namespaces）和控制组（cgroups）。它的本质不是“轻量虚拟机”，而是运行在宿主机 Linux 内核之上的隔离用户态环境。\n因此，Docker 容器具备这些特征：\n有自己的文件系统视图，例如 /bin、/etc、/usr、/app 可以运行 Linux 用户态程序，例如 sh、java、ls 不拥有独立内核，而是共享宿主机内核 更适合描述为“进程级隔离环境”，而不是真正意义上的虚拟机 一句话理解：\n容器负责隔离运行环境，镜像负责定义运行环境。\nWindows + WSL2 下的 Docker 运行方式 在 Windows 环境中，Docker 并不是“直接跑在 Windows 内核上”。Docker Desktop 实际依赖的是 WSL2 提供的 Linux 内核环境。\n你可以这样理解：\nWindows 是宿主操作系统 WSL2 提供真实的 Linux 内核能力 Docker Desktop 运行并管理 Docker 引擎 你在 WSL 终端中执行 docker ps，本质上是在调用 Docker Desktop 暴露给 WSL 的接口 所以，当前这类开发方式最适合的原则通常是：\n代码放在 WSL 的 Linux 文件系统中，例如 /home/lst041/... 容器、镜像和图形化管理交给 Docker Desktop 命令操作在 WSL 或 PowerShell 中完成，但要清楚引擎本身由 Docker Desktop 托管 Dockerfile 与 Docker Compose 的区别 这两个概念经常被混用，但职责完全不同。\nDockerfile：定义“单个镜像如何构建” Dockerfile 用来描述一个镜像的构建过程，例如：\n使用哪个基础镜像 工作目录是什么 需要复制哪些文件 暴露哪个端口 容器启动时执行什么命令 一个最常见的 Spring Boot 示例：\nFROM openjdk:17-jdk-slim WORKDIR /app COPY target/*.jar app.jar EXPOSE 8080 ENTRYPOINT [\u0026#34;java\u0026#34;, \u0026#34;-jar\u0026#34;, \u0026#34;app.jar\u0026#34;] Docker Compose：定义“多个服务如何协同运行” Docker Compose 面向的是系统级编排，而不是单个镜像构建。它主要解决的问题包括：\n多个容器如何一起启动 服务之间如何通信 哪些端口要暴露给宿主机 哪些目录需要挂载 数据如何持久化 如果把 Dockerfile 看成“做一台机器”，那 Docker Compose 更像是“把多台机器和网络一起搭起来”。\n一个基础的 Dockerfile 使用流程 1. 准备应用产物 以 Java 项目为例，先确保已经打出 JAR 包，并且 Dockerfile 能够正确访问它：\nDockerfile 一般放在项目根目录 target/ 目录中需要存在可执行 JAR JDK 版本要与项目构建产物匹配 2. 构建镜像 docker build -t my-app . 说明：\n-t 表示给镜像打标签（tag） . 表示当前目录作为构建上下文 3. 运行容器 docker run -d -p 8080:8080 --name app my-app 说明：\n-d 表示后台运行 -p 8080:8080 表示宿主机端口映射到容器端口 --name app 为容器指定名称 常用 Docker 命令速查 容器与镜像查看 docker ps docker ps -a docker images docker --version docker info 拉取、运行与进入容器 docker pull nginx:alpine docker run -d --name mynginx -p 80:80 nginx:alpine docker logs mynginx docker exec -it mynginx sh 停止、启动与删除 docker stop mynginx docker start mynginx docker restart mynginx docker rm mynginx docker rmi nginx:alpine 清理命令 docker image prune docker system prune 构建与调试 docker build -t my-springboot-app . docker run -it xxx sh docker exec -it xxx sh Docker Compose 部署示例 这里用一个典型的前后端项目部署流程来说明 Compose 的使用方式。\n1. 构建后端镜像 FROM eclipse-temurin:8-jdk-alpine WORKDIR /app COPY target/*.jar app.jar RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \\ \u0026amp;\u0026amp; echo \u0026#34;Asia/Shanghai\u0026#34; \u0026gt; /etc/timezone EXPOSE 8080 ENTRYPOINT [\u0026#34;java\u0026#34;, \u0026#34;-jar\u0026#34;, \u0026#34;app.jar\u0026#34;] 构建命令：\ndocker build -t springboot . docker images 2. 编写 Nginx 配置 这个配置主要负责两件事：\n托管前端静态资源 将 /api 请求反向代理到后端容器 server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html index.htm; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://backend:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } 3. 编写 docker-compose.yml version: \u0026#34;3.8\u0026#34; services: db: image: mysql:8.0 container_name: library-mysql restart: always environment: MYSQL_ROOT_PASSWORD: Llsstt2324 MYSQL_DATABASE: library TZ: Asia/Shanghai volumes: - ./mysql/data:/var/lib/mysql - ./mysql/init:/docker-entrypoint-initdb.d networks: - library-net backend: image: springboot:latest container_name: library-backend restart: always depends_on: - db environment: SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/library?useUnicode=true\u0026amp;characterEncoding=utf-8\u0026amp;allowMultiQueries=true\u0026amp;useSSL=false\u0026amp;serverTimezone=GMT%2B8\u0026amp;allowPublicKeyRetrieval=true SPRING_DATASOURCE_USERNAME: root SPRING_DATASOURCE_PASSWORD: Llsstt2324 networks: - library-net nginx: image: nginx:alpine container_name: library-nginx restart: always ports: - \u0026#34;80:80\u0026#34; volumes: - ./Library-frontend/dist:/usr/share/nginx/html - ./nginx/default.conf:/etc/nginx/conf.d/default.conf depends_on: - backend networks: - library-net networks: library-net: driver: bridge 4. 启动整套服务 docker compose up -d 访问地址：\nhttp://localhost 常用配套命令：\ndocker compose up -d --build backend docker compose ps docker logs -f library-backend Docker Compose 常用命令 生命周期管理 命令 作用 docker compose up -d 后台启动所有服务 docker compose down 停止并删除容器和网络 docker compose stop 停止服务但保留容器 docker compose start 启动已停止的服务 docker compose restart 重启所有服务 状态检查与排错 命令 作用 docker compose ps 查看容器状态 docker compose logs -f 查看全部服务日志 docker compose logs -f backend 查看指定服务日志 docker compose top 查看进程与资源占用 docker compose config 校验并展开配置 重新构建 命令 作用 docker compose up -d --build 重新构建并启动变更服务 docker compose up -d --build backend 只更新指定服务 docker compose build --no-cache 强制无缓存构建 两种常见的 Compose 使用模式 模式一：先手动构建，再交给 Compose 运行 docker build -t springboot:latest . docker compose up -d 对应 Compose 配置：\nbackend: image: springboot:latest 适用场景：\n学习阶段 镜像需要复用 镜像来源于 Docker Hub 模式二：由 Compose 负责构建 backend: build: context: . dockerfile: docker/backend/Dockerfile 启动命令：\ndocker compose up -d --build 这个模式更接近真实工程实践，因为镜像构建与服务编排绑定得更紧。\n端口流向应该怎么理解 以 Spring Boot API 为例，常见有两条访问路径。\n方式一：直接访问后端容器 浏览器 -\u0026gt; 宿主机端口 9090 -\u0026gt; 容器端口 8080 -\u0026gt; Spring Boot 应用\n方式二：通过 Nginx 反向代理 浏览器 -\u0026gt; 宿主机端口 80 -\u0026gt; Nginx 容器 -\u0026gt; 后端容器 8080\n无论走哪条路径，真正提供服务的都是容器内部的应用端口。\n把镜像推送到 Docker Hub 1. 给镜像打标签 docker tag springboot:latest yourname/springboot-library:v1.0 2. 推送镜像 docker push yourname/springboot-library:v1.0 3. 修改 Compose 配置 backend: image: yourname/springboot-library:v1.0 container_name: library-backend restart: always 从 Docker Hub 拉镜像并运行 1. 拉取镜像 docker pull authorname/springboot-library:v1.0 2. 创建目录结构 mkdir -p library-app/nginx library-app/mysql/init library-app/Library-frontend/dist 3. 准备配置文件 nginx/default.conf docker-compose.yml 4. 准备初始化 SQL 与前端产物 cp /mnt/e/Vue-Springboot-Library/mysql/init/springboot-vue.sql /home/lst041/library-app/mysql/init/ cp -r /mnt/e/Vue-Springboot-Library/Library-frontend/dist /home/lst041/library-app/Library-frontend/ 5. 启动 cd ~/library-app docker compose up -d 一个更标准的项目目录结构 project/ ├── docker-compose.yml ├── backend/ │ └── Dockerfile ├── frontend/ │ └── dist/ └── mysql/ └── init/ └── init.sql 多行命令在不同终端中的写法 终端 换行符 Ubuntu / WSL / Bash \\ Windows CMD ^ PowerShell ` 如果没有强需求，我通常更推荐直接写成单行命令，可读性和兼容性都更稳定：\ndocker run -d -p 8080:8080 --name app springboot ","date":"2025-12-19","tags":["Docker"]}]