news 2026/9/7 19:01:21

gstack /document-release 实战指南:发布后文档同步、Diataxis 覆盖度地图与文档债务上报

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
gstack /document-release 实战指南:发布后文档同步、Diataxis 覆盖度地图与文档债务上报

gstack /document-release 实战指南:发布后文档同步、Diataxis 覆盖度地图与文档债务上报

【免费下载链接】gstackUse Garry Tan's exact Claude Code setup: 23 opinionated tools that serve as CEO, Designer, Eng Manager, Release Manager, Doc Engineer, and QA项目地址: https://gitcode.com/GitHub_Trending/gs/gstack

gstack 的/document-release技能是发布流水线中“Technical Writer”角色:它在/ship提交代码之后、PR 合并之前运行,自动读取全部项目文档并与 diff 交叉比对,构建 Diataxis(reference / how-to / tutorial / explanation)覆盖度地图,修补 README、ARCHITECTURE、CONTRIBUTING、CLAUDE.md、TODOS.md 与 CHANGELOG 的漂移,把文档债务写进 PR body。读完本文,你将完整掌握这条“post-ship docs”工作流的每一步命令、判定规则与底层防护机制(redaction 扫描、banner tripwire、标题同步、跨模型复审),并能在自己的项目里复现同样的自动化文档审计。

技能定位:自动为主、风险才停

/document-release的运行时机被明确框定在两个节点之间:after/ship(代码已提交、PR 已存在或即将存在)但before the PR merges。它的工作目标是让项目中每个文档文件都准确、最新、且以“友好、面向用户”的语气撰写(见 document-release/SKILL.md)。

该技能在 gstack 技能表中被定位为“Technical Writer”:Update all project docs to match what you just shipped. Catches stale READMEs automatically.(见 README.md 技能列表)。其 frontmatter 声明了触发词与版本(见 SKILL.md 头部):

  • name: document-releaseversion: 1.0.0preamble-tier: 2
  • triggersupdate docs after shipdocument what changedpost-ship docs
  • allowed-tools:Bash、Read、Write、Edit、Grep、Glob、AskUserQuestion

行为基调是“mostly automated”:明显的 factual 更新直接执行,只在风险性或主观决策上停下来问。技能把“何时停、何时不停、何事绝不干”写成了三张清单,这是理解整套工作流安全边界的关键:

Only stop for(仅以下情况停下来问):

  • 风险性/存疑的文档改动(narrative、philosophy、security、删除、大段重写)
  • VERSION 升级决策(若尚未升级)
  • 需要新增的 TODOS 条目
  • 跨文档的叙事性(非事实性)矛盾

Never stop for(以下情况绝不打断用户):

  • 明显来自 diff 的事实性更正
  • 向表格/列表添加条目
  • 更新路径、计数、版本号
  • 修复过期的交叉引用
  • CHANGELOG 语气润色(轻微措辞调整)
  • 标记 TODOS 完成
  • 跨文档事实性不一致(如版本号不匹配)

NEVER do(三条绝对禁令):

  • 覆写、替换或重新生成 CHANGELOG 条目——只做措辞润色,保留全部内容
  • 未经询问就 bump VERSION——版本变更必须走 AskUserQuestion
  • 对 CHANGELOG.md 使用Write工具——必须用Edit做精确old_string匹配

这三张清单贯穿后续所有 Step,是技能“自动化但不失控”的设计核心。

工程结构:骨架 + 按需加载的 Section

/document-release是 gstack 中典型的“carved skill”:SKILL.md 只是决策树骨架,真正的步骤正文放在按需读取的 section 里。SKILL.md 顶部标注了生成来源:

<!-- AUTO-GENERATED from SKILL.md.tmpl — do not edit directly --> <!-- Regenerate: bun run gen:skill-docs -->

即 SKILL.md 由 SKILL.md.tmpl 经bun run gen:skill-docs渲染生成,{{SECTION_INDEX:document-release}}占位符对应 sections/manifest.json 中的 section 注册表。该 manifest 声明了唯一的 section:

id文件覆盖范围
release-bodyrelease-body.mdSteps 2-9:逐文件审计、自动更新、风险变更询问、CHANGELOG 润色、跨文档一致性、TODOS 清理、VERSION bump、提交与 PR body

骨架中对应的 STOP 指令要求:在进入 Steps 2-9 之前,必须完整读取sections/release-body.md并逐步执行,“Do not work from memory — that section is the source of truth for this step”。这种设计把技能主体保持在 token 预算内,同时保证执行时依据的是完整正文而非模型的“记忆”。

Step 0:检测平台与 base branch

工作流第一步是检测 git 托管平台,因为它决定了后续所有 PR/MR 命令的形态:

git remote get-url origin 2>/dev/null

判定顺序:

  1. URL 含github.comGitHub
  2. URL 含gitlabGitLab
  3. 否则看 CLI 可用性:gh auth status成功 → GitHub(覆盖 GitHub Enterprise);glab auth status成功 → GitLab(覆盖自托管);都失败 →unknown,仅用 git 原生命令

随后确定“base branch”——即该 PR/MR 的目标分支,若无 PR 则用仓库默认分支。按平台分别探测:

GitHub:

  1. gh pr view --json baseRefName -q .baseRefName
  2. gh repo view --json defaultBranchRef -q .defaultBranchRef.name

GitLab:

  1. glab mr view -F json提取target_branch
  2. glab repo view -F json提取default_branch

Git 原生兜底(unknown 平台或 CLI 失败时):

  1. git symbolic-ref refs/remotes/origin/HEAD | sed 's|refs/remotes/origin/||'
  2. 失败则git rev-parse --verify origin/main→ 用main
  3. 再失败则git rev-parse --verify origin/master→ 用master
  4. 全部失败回退到main

检测出的 base 分支名要在后续所有git diffgit loggit fetchgit merge与 PR/MR 创建命令中替换掉指令里的<base>/<default>占位符。

Step 1:Pre-flight 与 Diff 分析

前置检查:若当前正处在 base 分支上,直接中止——“You're on the base branch. Run from a feature branch.”

然后收集变更上下文(三条命令构成审计的输入面):

git diff <base>...HEAD --stat git log <base>..HEAD --oneline git diff <base>...HEAD --name-only

接着发现仓库内所有文档文件(限定 maxdepth 2,排除.gitnode_modules.gstack.context):

find . -maxdepth 2 -name "*.md" -not -path "./.git/*" -not -path "./node_modules/*" -not -path "./.gstack/*" -not -path "./.context/*" | sort

最后把变更归入四类文档相关类别:

  • New features— 新文件、新命令、新技能、新能力
  • Changed behavior— 修改的服务、更新的 API、配置变化
  • Removed functionality— 删除的文件、移除的命令
  • Infrastructure— 构建系统、测试基础设施、CI

输出一句摘要:“Analyzing N files changed across M commits. Found K documentation files to review.”

Step 1.5:Diataxis 覆盖度地图(爆炸半径分析)

这是/document-release最有辨识度的设计:在触碰任何文档文件之前,先构建“已发布内容 vs 已文档化内容”的覆盖度地图。它借用了 Diataxis 框架(tutorial / how-to / reference / explanation)——但作为**审计透镜(audit lens)**而非生成工具。gstack 对 Diataxis 的完整论证见 docs/explanation-diataxis-in-gstack.md,配套的端到端用法见 docs/howto-document-a-shipped-feature.md。

第 1 步:从 diff 提取 public surface 变化。扫描git diff <base>...HEAD中的:

  • 新导出的函数、类、命令、CLI flag、配置项、API 端点
  • 新技能、工作流或用户可见能力
  • 重命名或被移除的 public surface(模块、命令、功能)
  • 新环境变量、feature flag、配置旋钮

第 2 步:对每个新增/变化的 public surface 条目评估四象限覆盖:

Coverage map: [entity] [reference?] [how-to?] [tutorial?] [explanation?] /new-skill ✅ AGENTS.md ❌ ❌ ❌ --new-flag ✅ README ✅ README ❌ ❌ FooProcessor ❌ ❌ ❌ ❌

四个象限的定义(注意 reference 标注的是“在哪”而不是简单打勾):

  • Reference— 事实性描述:它是什么、API、选项(README 表格、AGENTS.md 技能列表、API 文档)
  • How-to— 任务导向:“如何用这个做 X”(README 示例、CONTRIBUTING 工作流)
  • Tutorial— 学习导向:给新手的分步演练(getting started 指南)
  • Explanation— 理解导向:“为什么这样设计”(ARCHITECTURE 决策、设计理据)

第 3 步:输出覆盖度地图并分级。零覆盖条目是critical gaps(进入 Step 3 重点处理);仅有 reference 覆盖的条目是common gaps(记入 PR body)。

第 4 步:架构图漂移检测。若 ARCHITECTURE.md(或任何文档)含 ASCII 图或 Mermaid 块,从中提取实体名(模块、服务、数据流),与 diff 交叉比对,标记出在代码中被重命名、拆分、移除或迁移的图内实体。

覆盖度地图同时喂给 Steps 2-3(审什么、改什么)和 Step 9(PR body 中的文档债务总结)。关键纪律是:Do NOT auto-generate missing documentation pages — flag gaps only(只标记缺口、绝不自动生成缺失文档页);发现显著缺口时,建议用户运行/document-generate补齐。

Steps 2-4:逐文件审计、自动更新与风险变更询问

进入这一段前,技能要求完整读取 sections/release-body.md。以下规则是通用启发式,适用于任何仓库,并非 gstack 专属。

Step 2:Per-File Documentation Audit

逐个读取文档文件并与 diff 交叉比对:

README.md:

  • 是否描述了 diff 中可见的全部功能与能力?
  • 安装/搭建说明与变更是否一致?
  • 示例、demo、用法描述是否仍然有效?
  • 排障步骤是否仍然准确?

ARCHITECTURE.md:

  • ASCII 图与组件描述是否与当前代码一致?
  • 设计决策与“why”解释是否仍然准确?
  • 保持保守——只更新被 diff 明确推翻的内容。架构文档描述的是低频变化物。

CONTRIBUTING.md(新贡献者冒烟测试):

  • 像一个全新贡献者那样走一遍搭建步骤;
  • 列出的命令是否准确?每一步是否会成功?
  • 测试分层描述是否与当前测试基础设施一致?
  • 工作流描述(dev setup、operational learnings 等)是否最新?
  • 标记任何会让首次贡献者失败或困惑的内容。

CLAUDE.md / 项目指令文件:

  • 项目结构章节是否匹配实际文件树?
  • 列出的命令与脚本是否准确?
  • 构建/测试说明是否与 package.json(或等价物)一致?

其他任意 .md 文件:读取文件、判断其目的与受众,与 diff 交叉比对是否矛盾。

对每个文件,把需要的更新分为两类:

  • Auto-update— diff 明确支持的事实性更正:向表格加一行、更新文件路径、修正计数、更新项目结构树
  • Ask user— 叙事性变更、章节删除、安全模型变更、大段重写(单节超过约 10 行)、相关性强歧义、新增整节

Step 3:Apply Auto-Updates

用 Edit 工具直接应用所有清晰、事实性的更新。每个被修改的文件必须输出一行“具体改了什么”的摘要——不是“Updated README.md”,而是“README.md: added /new-skill to skills table, updated skill count from 9 to 10.”

绝不自动更新的内容:

  • README 的开头介绍或项目定位
  • ARCHITECTURE 的哲学或设计理据
  • 安全模型描述
  • 任何文档的整节删除

Step 4:Ask About Risky/Questionable Changes

对 Step 2 识别出的每个风险/存疑更新,走 AskUserQuestion,包含:项目名、分支、哪个文档文件、正在审什么、具体的文档决策、RECOMMENDATION: Choose [X] because [一句话理由],以及包含C) Skip — leave as-is的选项。每次得到回答后立即应用被批准的修改。

Step 5:CHANGELOG Voice Polish(sell-test 评分)

文档中用加粗的 “CRITICAL” 强调:绝不 clobber CHANGELOG 条目。这一步只润色语气,不重写、不替换、不再生成内容。技能还引用了一起真实事故作为约束依据——某次代理把本应保留的 CHANGELOG 条目替换掉了——因此这里把规则写死:

  1. 先通读整个 CHANGELOG.md,理解已有内容
  2. 只修改既有条目内部的措辞;绝不删除、重排、替换条目
  3. 绝不从零再生成条目——条目由/ship基于真实 diff 和提交历史写出,是 source of truth;你在润色散文,不是在重写历史
  4. 某条目看起来错误或残缺时,走 AskUserQuestion,不要悄悄修
  5. 用 Edit 工具做精确old_string匹配——绝不用 Write 覆写 CHANGELOG.md

若本分支未修改 CHANGELOG:跳过本步。若修改了,则用sell-test(Diataxis 评分量规)逐条打分 0-3:

  • 1 分— 回答了“What changed?”(reference:点名了功能/修复)
  • 1 分— 回答了“Why should I care?”(explanation:用户影响、消除了什么痛点)
  • 1 分— 回答了“How do I use it?”(how-to:命令、flag 或文档链接)

低于 2 分的条目需要重写,3 分是 gold。配套语气规则:

  • 以用户“现在能做什么”开头,而不是实现细节
  • “You can now...” 而不是 “Refactored the...”
  • 把读起来像 commit message 的条目标记并重写
  • 内部/贡献者变更归入独立的### For contributors小节
  • 轻微语气调整自动修;若重写会改变语义,走 AskUserQuestion

这一声调标准与仓库的 docs/CHANGELOG_STYLE.md 呼应:后者规定每个## [X.Y.Z]条目的 release-summary 结构(两行粗体标题、3-5 句导语、“The X numbers that matter” 指标表、“What this means for [audience]” 收尾段)与禁用词表(无 em dash、无 AI 词汇、真实数字真实文件真实命令),以及### Itemized changes下必须署名社区贡献者(Contributed by @username)。/document-release的 sell-test 是对同一套声音纪律的“逐条打分”实现。

Step 6:跨文档一致性与可发现性

单文件审计之后做全局一致性 pass,共五项检查:

  1. README 的功能/能力列表是否与 CLAUDE.md(或项目指令)的描述一致?
  2. ARCHITECTURE 的组件列表是否与 CONTRIBUTING 的项目结构描述一致?
  3. CHANGELOG 的最新版本是否与 VERSION 文件一致?
  4. Discoverability(可发现性):每个文档文件是否都能从 README.md 或 CLAUDE.md 到达?若 ARCHITECTURE.md 存在但两个入口文件都没链接到它,标记之——每个文档都应可从两个入口文件之一发现
  5. 标记文档间矛盾:清晰的事实性不一致(如版本号不匹配)自动修;叙事性矛盾走 AskUserQuestion

Step 7:TODOS.md 清理

这是与/shipStep 5.5 互补的第二遍。规范的 TODO 条目格式定义在 review/TODOS-format.md:按 skill/组件分节(## Browse## Ship…),节内按优先级 P0→P4 排序;每个条目是 H3,必填 What / Why / Context / Effort / Priority,可选 Depends on / Blocked by;完成项移入## Completed并附**Completed:** vX.Y.Z.W (YYYY-MM-DD)

若 TODOS.md 不存在,跳过本步。存在则做三件事:

  1. 已完成但未标记的条目:把 diff 与 open TODO 交叉比对。若某 TODO 显然被本分支的变更完成,移入 Completed 区并附**Completed:** vX.Y.Z.W (YYYY-MM-DD)。保持保守——只标记 diff 中有明确证据的条目
  2. 描述需要更新的条目:若某 TODO 引用的文件/组件被大改,其描述可能过期。走 AskUserQuestion 确认该 TODO 应更新、完成还是保持原样
  3. 新的延期工作:检查 diff 中的TODOFIXMEHACKXXX注释,凡代表有意义延期工作(非琐碎内联备注)的,走 AskUserQuestion 询问是否收进 TODOS.md

Step 8:VERSION Bump 决策

标题同样标了CRITICAL — NEVER BUMP VERSION WITHOUT ASKING

  1. VERSION 文件不存在:静默跳过
  2. 先检查本分支是否已改过 VERSION:
git diff <base>...HEAD -- VERSION
  1. 未 bump 时,走 AskUserQuestion,选项:

    • RECOMMENDATION: Choose C (Skip)——纯文档变更很少值得 bump
    • A) Bump PATCH (X.Y.Z+1) —— 文档变更与代码变更一起发布
    • B) Bump MINOR (X.Y+1.0) —— 若这是一次独立的重大发布
    • C) Skip — no version bump needed
  2. 已 bump 时——不要静默跳过,要验证 bump 是否仍覆盖本分支全部变更范围:

    • a. 读当前 VERSION 对应的 CHANGELOG 条目,它描述了哪些功能?
    • b. 读完整 diff(--stat--name-only):是否存在重要变更(新功能、新技能、新命令、大重构)却没有出现在该版本条目中?
    • c. 若 CHANGELOG 条目覆盖了一切:输出 “VERSION: Already bumped to vX.Y.Z, covers all changes.”
    • d. 若存在未覆盖的重要变更:走 AskUserQuestion,说明当前版本覆盖什么、又新了什么,选项为 A) Bump to next patch(给新变更自己的版本)/ B) Keep current version(把新变更并入现有 CHANGELOG 条目)/ C) Skip(版本保持不动,以后再处理)

技能把这条设计原则总结为:“一个为‘功能 A’设置的 VERSION bump 不应悄悄吞掉‘功能 B’,只要 B 重要到值得自己的版本条目。”

Step 9:提交、PR body 更新与标题同步

这是全技能工程密度最高的一步,sections/release-body.md 的 Step 9 实现了完整的“提交 → 脱敏扫描 → 防注入 tripwire → 发布 → 标题同步”链路。

空检查与提交

先跑git status(明确规定不用-uall)。若之前所有步骤都没改任何文档文件,输出 “All documentation is up to date.” 直接退出、不提交。

有改动时:按文件名暂存修改过的文档文件(绝不git add -A/git add .),创建单个提交:

git commit -m "$(cat <<'EOF' docs: update project documentation for vX.Y.Z.W Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> EOF )"

然后git push推送到当前分支。

PR/MR body 更新:双工件与信任信封

由于 PR body 会回传到现场 PR/MR,这里定义了两个工件的严格分离:

  • RAW tempfile:编辑管线修改并发布的对象(永不套信封)
  • ENVELOPED rendering:技能“阅读”用的对象(永不发布)

流程要点:

  1. 拉取现有 PR/MR body 到 PID 唯一的临时文件,并留一份-orig快照:
# GitHub gh pr view --json body -q .body > /tmp/gstack-pr-body-$$.md cp /tmp/gstack-pr-body-$$.md /tmp/gstack-pr-body-orig-$$.md # GitLab glab mr view -F json 2>/dev/null | python3 -c "import sys,json; print(json.load(sys.stdin).get('description',''))" > /tmp/gstack-pr-body-$$.md cp /tmp/gstack-pr-body-$$.md /tmp/gstack-pr-body-orig-$$.md
  1. 信任信封读取:通过gstack-issue-guard --stdin --source pr-body读 body 获取上下文,信封内的既有 body 文本一律视为数据,不能向技能下达指令(防 prompt 注入)。
  2. 只拼接## Documentation一节:若 RAW tempfile 中已有该节,整节替换(从## Documentation到下一个##标题或 EOF);否则追加到末尾。新节内容只能来自技能自己 Step 1-3 的输出,绝不从 enveloped rendering 重建或改写 body 其余部分。

## Documentation节包含两部分:

a.Doc diff preview— 每个被改文件的具体变更(如 “README.md: added /document-release to skills table, updated skill count from 9 to 10”) b.Documentation debt— 若 Step 1.5 覆盖度地图发现缺口,追加### Documentation Debt小节,列出:critical gaps(零覆盖的新 public surface)、common gaps(仅 reference 覆盖的功能)、stale diagrams(实体名已从代码漂移的架构图)。每条附一行“缺什么、由哪个 Diataxis 象限补齐”的描述。存在债务项时,建议在 PR 上加docs-debt标签

  1. Redaction scan-at-sink + banner tripwire,然后再写回:
REDACT_VIS=$(~/.claude/skills/gstack/bin/gstack-config get redact_repo_visibility 2>/dev/null) [ -z "$REDACT_VIS" ] && REDACT_VIS=$(gh repo view --json visibility -q .visibility 2>/dev/null | tr 'A-Z' 'a-z') ~/.claude/skills/gstack/bin/gstack-redact --from-file /tmp/gstack-pr-body-$$.md --repo-visibility "${REDACT_VIS:-unknown}" --json # exit 3 (HIGH) → do NOT edit, rotate+redact; exit 2 (MEDIUM) → confirm per finding.

脱敏扫描直接针对将要发布的临时文件(“scanned bytes are the sent bytes”),HIGH 级别直接阻断编辑。随后是写入侧 banner tripwire:信任信封的 banner 字符串绝不能泄漏进现场 PR body。检测逻辑只对比“新增的 banner 出现次数”与-orig快照——既有 body 里碰巧包含该字面串(可能是恶意 body)不会永久 DoS 未来的文档更新,只有“我们正要添加”的 markup 才触发 ABORT。脚本注释还特意说明了两处工程细节:grep -c无匹配时本身打印 0(追加 fallback echo 会双打印并让-gt比较走进干净分支、恰好在这个防护上 fail open);每个 bash 块在独立 shell 中运行、$$不同,因此 fetch/splice/scan/tripwire/edit 必须在同一个 shell 内完成,tripwire 对缺失文件 fail closed。

  1. 发布:GitHub 用gh pr edit --body-file;GitLab 用 Read 工具读取文件后经 heredoc 传给glab mr update -d,避免 shell 元字符问题。
  2. 清理临时文件;若gh pr view/glab mr view失败(无 PR/MR)则跳过并提示;若 edit 命令失败则警告 “Could not update PR/MR body — documentation changes are in the commit.” 并继续。

PR/MR 标题同步

PR 标题必须始终以v<VERSION>开头——与/ship同规则。若 Step 8 在/ship已建 PR 之后 bump 了 VERSION,标题就过期了,此子步骤负责修正:

V=$(cat VERSION 2>/dev/null | tr -d '[:space:]') CURRENT_TITLE=$(gh pr view --json title -q .title 2>/dev/null || true) # GitHub NEW_TITLE=$(~/.claude/skills/gstack/bin/gstack-pr-title-rewrite.sh "$V" "$CURRENT_TITLE") gh pr edit --title "$NEW_TITLE" # GitLab: glab mr update -t "$NEW_TITLE"

标题重写规则收敛在共享 helper bin/gstack-pr-title-rewrite.sh 中(single source of truth,/ship与 GitHub Action 也调用它),处理三种情况:标题已正确(no-op)、前缀版本不同(替换)、无版本前缀(前置一个)。VERSION 不存在或为空则整段跳过;edit 失败只警告不阻塞。

结构化文档健康摘要

最后输出可扫读的状态汇总,覆盖每个文档文件:

Documentation health: README.md [status] ([details]) ARCHITECTURE.md [status] ([details]) CONTRIBUTING.md [status] ([details]) CHANGELOG.md [status] ([details]) TODOS.md [status] ([details]) VERSION [status] ([details])

status 取值:Updated(附改了什么)、Current(无需变更)、Voice polished(措辞调整)、Not bumped(用户选择跳过)、Already bumped(版本由 /ship 设置)、Skipped(文件不存在)。

若 Step 1.5 发现缺口,追加覆盖度地图与图漂移小节:

Documentation coverage: [entity] [reference] [how-to] [tutorial] [explanation] /new-skill ✅ ❌ ❌ ❌ --new-flag ✅ ✅ ❌ ❌ Diagram drift: ARCHITECTURE.md: "FooProcessor" renamed to "BarProcessor" in code — diagram may be stale

全覆盖且无图漂移时输出:“Coverage: all shipped features have adequate documentation.”

Codex 跨模型文档复审(默认开启)

文档更新写完之后,/document-release还会跑一个独立的跨模型复审:让另一个模型把文档与“实际发布的代码”对一遍账。这是标准步骤而非可选项,用户只能通过gstack-config set codex_reviews disabled显式关闭。

Preflight:决定复审如何运行

_TEL=$(~/.claude/skills/gstack/bin/gstack-config get telemetry 2>/dev/null || echo off) _CODEX_CFG=$(~/.claude/skills/gstack/bin/gstack-config get codex_reviews 2>/dev/null || echo enabled) source ~/.claude/skills/gstack/bin/gstack-codex-probe 2>/dev/null || true # 依次判定: disabled / under_codex / not_installed / not_authed / model_unusable / ready echo "CODEX_MODE: $_CODEX_MODE"

按回显的CODEX_MODE分支:

模式行为
disabled整段跳过,不回退 Claude 子代理(disabled 即无额外复审)
under_codex会话本身已跑在 Codex host 内(存在CODEX_THREAD_ID/CODEX_SANDBOX环境变量),再 spawn codex 等于同模型审自己且 token 成倍消耗(引用了真实观测:一次 /review 15M tokens),跳过嵌套调用
not_installed无 Codex CLI,回退 Claude 子代理路径
not_authed已装无凭据,回退 Claude 子代理路径
model_unusable账号配置的模型不可用(常见于~/.codex/config.toml里过期的model =pin),透传 probe 的 HINT 与一行修法,回退子代理
ready正式跑 Codex 复审

复审提示词与执行

diff 范围必须重算而不是引用内存变量(shell 变量不跨 block 存活):

DOC_DIFF_BASE=$(git merge-base origin/<base> HEAD 2>/dev/null || echo "<base>")

复审对象是“document-release 本次实际触碰的文档 + diff 范围内受影响的文档声明”——不硬编码固定文件列表(固定 README/ARCHITECTURE/CHANGELOG 列表会漏掉生成的技能文档、包文档与命令文档)。提示词以文件系统边界指令开头(禁止 Codex 读取~/.claude/.claude/skills/等技能定义目录,因为它们含 bash 脚本与 prompt 模板,会浪费 token 并偏离任务),然后要求执行git diff $DOC_DIFF_BASE...HEAD并找出:与代码不再一致的文档声明、发布了但未记录的新 public surface、过期的示例/路径/计数/版本号、以及夸大或低估实际内容的 CHANGELOG 条目。

ready模式下实际执行:

TMPERR_DOC=$(mktemp /tmp/codex-docreview-XXXXXXXX) _REPO_ROOT=$(git rev-parse --show-toplevel) || { echo "ERROR: not in a git repo" >&2; exit 1; } codex exec "<prompt>" -C "$_REPO_ROOT" -s read-only -c 'model_reasoning_effort="high"' -c 'web_search="cached"' < /dev/null 2>"$TMPERR_DOC"

带 5 分钟超时(300000ms),结束后读 stderr,输出原文置于CODEX SAYS (documentation review):之下。所有错误均非阻塞——复审是 informational 而非 gate:认证失败、超时、空响应都只记录跳过。not_installed/not_authed或 Codex 运行时报错时,经 Agent 工具派发同一提示词给 Claude 子代理,输出置于DOCUMENTATION REVIEW (Claude subagent):之下。

应用决策与结果持久化

零发现时输出 “Docs match what shipped — no gaps.” 有发现时只问一次:

“The doc review found N gaps between the docs and what shipped. How do you want to handle them?” RECOMMENDATION: Choose A if the gaps are concrete doc fixes(Completeness: A=9/10, B=4/10, C=8/10)

  • A) Apply all the doc fixes now
  • B) Skip — leave docs as-is
  • C) Decide per-finding

复审器只报告、绝不自动改;A 或逐条批准后的编辑由技能自己完成,B 则在输出中标注缺口保持可见。结果最后持久化:

~/.claude/skills/gstack/bin/gstack-review-log '{"skill":"codex-doc-review","timestamp":"...","status":"STATUS","source":"SOURCE","commit":"..."}'

STATUS 取clean/issues_found,SOURCE 取codex/claude。Codex 用过则清理"$TMPERR_DOC"

测试如何锁定这些行为

/document-release的关键不变量有专门的自动化测试守护。test/document-skills-redaction.test.ts 针对被 carved 的技能,合并SKILL.md.tmplsections/*.md.tmpl后断言:

  • scan-before-edit 顺序gstack-redact --from-file /tmp/gstack-pr-body在模板中的位置必须早于gh pr edit --body-file(即“扫描的字节 = 发布的字节”);
  • HIGH 阻断:模板必须包含exit 3 (HIGH) → do NOT edit语义。

同类断言也用于姊妹技能/document-generate(staged diff 先扫描再git commit,HIGH 阻断提交)。结合 test/helpers/carve-guards.ts 等 guard,这套测试确保 section 拆分(骨架 + release-body)不会让 Step 9 的安全顺序在模板渲染后丢失。

与 /document-generate 的分工

/document-release的收尾纪律呼应了其姊妹技能的分工:coverage map informs, never generates。审计技能只把缺口写进 PR body 作为未来工作;真正按四象限写文档(reference → explanation → how-to → tutorial 的依赖顺序)是/document-generate的职责。典型链路(见 docs/howto-document-a-shipped-feature.md):/document-release审计并产出 Documentation Debt → 用户按债务列表运行/document-generate补缺 → 再跑一遍/document-release验证覆盖度地图转绿。选择 Diataxis 而非自研分类法的理由(外部采用最广:CPython、Django、NumPy、FastAPI 等;象限标签能干净地映射为覆盖度信号)完整论述在 docs/explanation-diataxis-in-gstack.md。

小结

/document-release把“发布后同步文档”这件最容易静默腐烂的维护工作变成了一条有硬边界、可验证、可审计的流水线:base 分支检测(Step 0)→ diff 分析(Step 1)→ Diataxis 覆盖度地图与图漂移检测(Step 1.5)→ 分级审计与自动更新(Steps 2-4)→ CHANGELOG sell-test 润色(Step 5)→ 跨文档一致性与可发现性(Step 6)→ TODOS 清理(Step 7)→ 必须询问的 VERSION 决策(Step 8)→ 带脱敏扫描与防注入 tripwire 的提交与 PR 回写(Step 9)→ 跨模型文档复审。其安全设计集中在几条不可妥协的规则上:CHANGELOG 只润色不重写、VERSION 只问不猜、文档缺口只标记不生成、PR body 发布前必过脱敏扫描、复审只报告不代改。对使用 gstack 的团队来说,它的实际效果正如 README.md 中的描述:文档漂移在 PR 合并前被自动发现并修好,文档债务以象限为单位暴露在 PR body 里,供 reviewer 一眼看清。

【免费下载链接】gstackUse Garry Tan's exact Claude Code setup: 23 opinionated tools that serve as CEO, Designer, Eng Manager, Release Manager, Doc Engineer, and QA项目地址: https://gitcode.com/GitHub_Trending/gs/gstack

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 18:57:25

量子隐形传态+区块链:隐私保护签名如何重塑Web3.0与元宇宙信任体系

量子隐形传态这个词&#xff0c;圈外人听起来像科幻&#xff0c;圈内人听起来像噱头。最近微算法科技&#xff08;NASDAQ: MLGO&#xff09;宣布探索量子隐形传态与区块链隐私保护签名技术的结合&#xff0c;目标是提升Web 3.0和元宇宙环境的效率、安全性与真实性。这条新闻在技…

作者头像 李华
网站建设 2026/9/7 18:55:41

MySQL建表规范与数据导入导出实战全解析

1. 开始之前&#xff1a;为什么建表和导入导出这么重要最近整理笔记时翻到MySQL建表和导入导出这块&#xff0c;发现看似基础的东西&#xff0c;实际用起来坑真不少。无论是刚入门的新手&#xff0c;还是写了几年SQL的老手&#xff0c;几乎天天要跟这两件事打交道——建表决定数…

作者头像 李华
网站建设 2026/9/7 18:55:24

电影院在线订票系统全流程开发:从数据库设计到答辩实战指南

作为每年计算机毕业设计里被选到烂大街、但仍是最经典的几个题目之一&#xff0c;电影院在线订票系统几乎是“Web开发入门完整业务链路”的教科书式组合。我亲眼见过太多人从选题时的满怀期待&#xff0c;到中期开发时对着座位排布和订单状态一脸茫然&#xff0c;再到最后答辩时…

作者头像 李华
网站建设 2026/9/7 18:55:22

JavaScript前端加解密实战:AES与RSA应用指南

1. JavaScript加解密技术概述在现代Web开发中&#xff0c;数据安全传输与存储已成为基本需求。JavaScript作为前端开发的核心语言&#xff0c;其加解密能力直接关系到用户数据的安全性。不同于传统的服务器端加密&#xff0c;前端加密可以在数据离开客户端前就进行保护&#xf…

作者头像 李华