diff --git a/document-release/SKILL.md b/document-release/SKILL.md index 64561b0ca..6a25bbe82 100644 --- a/document-release/SKILL.md +++ b/document-release/SKILL.md @@ -780,6 +780,17 @@ subjective decisions. --- +## Section index — Read each section when its situation applies + +This skill is a decision-tree skeleton. The steps below point to on-demand +sections. Read a section in full before doing its step; do not work from memory. + +| When | Read this section | +|------|-------------------| +| auditing each doc file and applying updates, polishing CHANGELOG voice, checking cross-doc consistency, cleaning up TODOS, the VERSION bump, and committing (Steps 2-9, after the coverage map in Step 1.5) | `sections/release-body.md` | + +--- + ## Step 1: Pre-flight & Diff Analysis 1. Check the current branch. If on the base branch, **abort**: "You're on the base branch. Run from a feature branch." @@ -856,364 +867,8 @@ When significant gaps are found, suggest running `/document-generate` to fill th --- -## Step 2: Per-File Documentation Audit - -Read each documentation file and cross-reference it against the diff. Use these generic heuristics -(adapt to whatever project you're in — these are not gstack-specific): - -**README.md:** -- Does it describe all features and capabilities visible in the diff? -- Are install/setup instructions consistent with the changes? -- Are examples, demos, and usage descriptions still valid? -- Are troubleshooting steps still accurate? - -**ARCHITECTURE.md:** -- Do ASCII diagrams and component descriptions match the current code? -- Are design decisions and "why" explanations still accurate? -- Be conservative — only update things clearly contradicted by the diff. Architecture docs - describe things unlikely to change frequently. - -**CONTRIBUTING.md — New contributor smoke test:** -- Walk through the setup instructions as if you are a brand new contributor. -- Are the listed commands accurate? Would each step succeed? -- Do test tier descriptions match the current test infrastructure? -- Are workflow descriptions (dev setup, operational learnings, etc.) current? -- Flag anything that would fail or confuse a first-time contributor. - -**CLAUDE.md / project instructions:** -- Does the project structure section match the actual file tree? -- Are listed commands and scripts accurate? -- Do build/test instructions match what's in package.json (or equivalent)? - -**Any other .md files:** -- Read the file, determine its purpose and audience. -- Cross-reference against the diff to check if it contradicts anything the file says. - -For each file, classify needed updates as: - -- **Auto-update** — Factual corrections clearly warranted by the diff: adding an item to a - table, updating a file path, fixing a count, updating a project structure tree. -- **Ask user** — Narrative changes, section removal, security model changes, large rewrites - (more than ~10 lines in one section), ambiguous relevance, adding entirely new sections. - ---- - -## Step 3: Apply Auto-Updates - -Make all clear, factual updates directly using the Edit tool. - -For each file modified, output a one-line summary describing **what specifically changed** — not -just "Updated README.md" but "README.md: added /new-skill to skills table, updated skill count -from 9 to 10." - -**Never auto-update:** -- README introduction or project positioning -- ARCHITECTURE philosophy or design rationale -- Security model descriptions -- Do not remove entire sections from any document - ---- - -## Step 4: Ask About Risky/Questionable Changes - -For each risky or questionable update identified in Step 2, use AskUserQuestion with: -- Context: project name, branch, which doc file, what we're reviewing -- The specific documentation decision -- `RECOMMENDATION: Choose [X] because [one-line reason]` -- Options including C) Skip — leave as-is - -Apply approved changes immediately after each answer. - ---- - -## Step 5: CHANGELOG Voice Polish - -**CRITICAL — NEVER CLOBBER CHANGELOG ENTRIES.** - -This step polishes voice. It does NOT rewrite, replace, or regenerate CHANGELOG content. - -A real incident occurred where an agent replaced existing CHANGELOG entries when it should have -preserved them. This skill must NEVER do that. - -**Rules:** -1. Read the entire CHANGELOG.md first. Understand what is already there. -2. Only modify wording within existing entries. Never delete, reorder, or replace entries. -3. Never regenerate a CHANGELOG entry from scratch. The entry was written by `/ship` from the - actual diff and commit history. It is the source of truth. You are polishing prose, not - rewriting history. -4. If an entry looks wrong or incomplete, use AskUserQuestion — do NOT silently fix it. -5. Use Edit tool with exact `old_string` matches — never use Write to overwrite CHANGELOG.md. - -**If CHANGELOG was not modified in this branch:** skip this step. - -**If CHANGELOG was modified in this branch**, review the entry for voice: - -- **Sell test (Diataxis rubric):** Score each CHANGELOG entry 0-3: - - **1 point** — answers "What changed?" (reference: names the feature/fix) - - **1 point** — answers "Why should I care?" (explanation: user impact, pain removed) - - **1 point** — answers "How do I use it?" (how-to: command, flag, or link to docs) - - Entries scoring <2 need a rewrite. Entries scoring 3 are gold. -- Lead with what the user can now **do** — not implementation details. -- "You can now..." not "Refactored the..." -- Flag and rewrite any entry that reads like a commit message. -- Internal/contributor changes belong in a separate "### For contributors" subsection. -- Auto-fix minor voice adjustments. Use AskUserQuestion if a rewrite would alter meaning. - ---- - -## Step 6: Cross-Doc Consistency & Discoverability Check - -After auditing each file individually, do a cross-doc consistency pass: - -1. Does the README's feature/capability list match what CLAUDE.md (or project instructions) describes? -2. Does ARCHITECTURE's component list match CONTRIBUTING's project structure description? -3. Does CHANGELOG's latest version match the VERSION file? -4. **Discoverability:** Is every documentation file reachable from README.md or CLAUDE.md? If - ARCHITECTURE.md exists but neither README nor CLAUDE.md links to it, flag it. Every doc - should be discoverable from one of the two entry-point files. -5. Flag any contradictions between documents. Auto-fix clear factual inconsistencies (e.g., a - version mismatch). Use AskUserQuestion for narrative contradictions. - ---- - -## Step 7: TODOS.md Cleanup - -This is a second pass that complements `/ship`'s Step 5.5. Read `review/TODOS-format.md` (if -available) for the canonical TODO item format. - -If TODOS.md does not exist, skip this step. - -1. **Completed items not yet marked:** Cross-reference the diff against open TODO items. If a - TODO is clearly completed by the changes in this branch, move it to the Completed section - with `**Completed:** vX.Y.Z.W (YYYY-MM-DD)`. Be conservative — only mark items with clear - evidence in the diff. - -2. **Items needing description updates:** If a TODO references files or components that were - significantly changed, its description may be stale. Use AskUserQuestion to confirm whether - the TODO should be updated, completed, or left as-is. - -3. **New deferred work:** Check the diff for `TODO`, `FIXME`, `HACK`, and `XXX` comments. For - each one that represents meaningful deferred work (not a trivial inline note), use - AskUserQuestion to ask whether it should be captured in TODOS.md. - ---- - -## Step 8: VERSION Bump Question - -**CRITICAL — NEVER BUMP VERSION WITHOUT ASKING.** - -1. **If VERSION does not exist:** Skip silently. - -2. Check if VERSION was already modified on this branch: - -```bash -git diff ...HEAD -- VERSION -``` - -3. **If VERSION was NOT bumped:** Use AskUserQuestion: - - RECOMMENDATION: Choose C (Skip) because docs-only changes rarely warrant a version bump - - A) Bump PATCH (X.Y.Z+1) — if doc changes ship alongside code changes - - B) Bump MINOR (X.Y+1.0) — if this is a significant standalone release - - C) Skip — no version bump needed - -4. **If VERSION was already bumped:** Do NOT skip silently. Instead, check whether the bump - still covers the full scope of changes on this branch: - - a. Read the CHANGELOG entry for the current VERSION. What features does it describe? - b. Read the full diff (`git diff ...HEAD --stat` and `git diff ...HEAD --name-only`). - Are there significant changes (new features, new skills, new commands, major refactors) - that are NOT mentioned in the CHANGELOG entry for the current version? - c. **If the CHANGELOG entry covers everything:** Skip — output "VERSION: Already bumped to - vX.Y.Z, covers all changes." - d. **If there are significant uncovered changes:** Use AskUserQuestion explaining what the - current version covers vs what's new, and ask: - - RECOMMENDATION: Choose A because the new changes warrant their own version - - A) Bump to next patch (X.Y.Z+1) — give the new changes their own version - - B) Keep current version — add new changes to the existing CHANGELOG entry - - C) Skip — leave version as-is, handle later - - The key insight: a VERSION bump set for "feature A" should not silently absorb "feature B" - if feature B is substantial enough to deserve its own version entry. - ---- - -## Step 9: Commit & Output - -**Empty check first:** Run `git status` (never use `-uall`). If no documentation files were -modified by any previous step, output "All documentation is up to date." and exit without -committing. - -**Commit:** - -1. Stage modified documentation files by name (never `git add -A` or `git add .`). -2. Create a single commit: - -```bash -git commit -m "$(cat <<'EOF' -docs: update project documentation for vX.Y.Z.W - -Co-Authored-By: Claude Opus 4.7 -EOF -)" -``` - -3. Push to the current branch: - -```bash -git push -``` - -**PR/MR body update (idempotent, race-safe):** - -1. Read the existing PR/MR body into a PID-unique tempfile (use the platform detected in Step 0): - -**If GitHub:** -```bash -gh pr view --json body -q .body > /tmp/gstack-pr-body-$$.md -``` - -**If GitLab:** -```bash -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 -``` - -2. If the tempfile already contains a `## Documentation` section, replace that section with the - updated content. If it does not contain one, append a `## Documentation` section at the end. - -3. The Documentation section should include: - - a. **Doc diff preview** — for each file modified, describe what specifically changed (e.g., - "README.md: added /document-release to skills table, updated skill count from 9 to 10"). - - b. **Documentation debt** — if the coverage map from Step 1.5 found gaps, append a - `### Documentation Debt` subsection listing: - - Critical gaps: new public surface with zero documentation coverage - - Common gaps: features with reference-only coverage (no how-to or tutorial) - - Stale diagrams: architecture diagrams with entity names that drifted from the code - - Each item should include a one-line description of what's missing and which Diataxis - quadrant would fill it (e.g., "⚠️ `/new-skill` — has reference in AGENTS.md but no - how-to example in README") - - If there are any documentation debt items, suggest adding a `docs-debt` label to the PR. - -4. Redaction scan-at-sink, then write the updated body back. The body is already - in a temp file (`/tmp/gstack-pr-body-$$.md`); scan THAT file before editing so - the bytes scanned are the bytes sent: - -```bash -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. -``` - -**If GitHub:** -```bash -gh pr edit --body-file /tmp/gstack-pr-body-$$.md -``` - -**If GitLab:** -Read the contents of `/tmp/gstack-pr-body-$$.md` using the Read tool, then pass it to `glab mr update` using a heredoc to avoid shell metacharacter issues: -```bash -glab mr update -d "$(cat <<'MRBODY' - -MRBODY -)" -``` - -5. Clean up the tempfile: - -```bash -rm -f /tmp/gstack-pr-body-$$.md -``` - -6. If `gh pr view` / `glab mr view` fails (no PR/MR exists): skip with message "No PR/MR found — skipping body update." -7. If `gh pr edit` / `glab mr update` fails: warn "Could not update PR/MR body — documentation changes are in the - commit." and continue. - -**PR/MR title sync (idempotent, always-on):** - -PR titles must always start with `v` — same rule as `/ship`. If Step 8 bumped VERSION after `/ship` had already created the PR, the title is now stale. This sub-step fixes it. - -1. Read the current VERSION: - -```bash -V=$(cat VERSION 2>/dev/null | tr -d '[:space:]') -``` - -If `VERSION` does not exist or is empty, skip this sub-step entirely. - -2. Read the current PR/MR title: - -**If GitHub:** -```bash -CURRENT_TITLE=$(gh pr view --json title -q .title 2>/dev/null || true) -``` - -**If GitLab:** -```bash -CURRENT_TITLE=$(glab mr view -F json 2>/dev/null | jq -r .title 2>/dev/null || true) -``` - -If `CURRENT_TITLE` is empty (no open PR/MR), skip with message "No PR/MR found — skipping title sync." - -3. Compute the corrected title using the shared helper (single source of truth — same one `/ship` uses): - -```bash -NEW_TITLE=$(~/.claude/skills/gstack/bin/gstack-pr-title-rewrite.sh "$V" "$CURRENT_TITLE") -``` - -The helper handles three cases: title already correct (no-op), title has a different `v` prefix (replace it), or title has no version prefix (prepend one). - -4. If `NEW_TITLE` differs from `CURRENT_TITLE`, update it: - -**If GitHub:** -```bash -gh pr edit --title "$NEW_TITLE" -``` - -**If GitLab:** -```bash -glab mr update -t "$NEW_TITLE" -``` - -5. If the edit command fails: warn "Could not update PR/MR title — documentation changes are still in the commit." and continue. Do not block on title sync failure. - -**Structured doc health summary (final output):** - -Output a scannable summary showing every documentation file's status: - -``` -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]) -``` - -Where status is one of: -- Updated — with description of what changed -- Current — no changes needed -- Voice polished — wording adjusted -- Not bumped — user chose to skip -- Already bumped — version was set by /ship -- Skipped — file does not exist - -If the coverage map from Step 1.5 identified any gaps, append: - -``` -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 -``` - -If all coverage is complete and no diagrams drifted, output: "Coverage: all shipped features have adequate documentation." +> **STOP.** Before auditing each doc file and applying updates, polishing CHANGELOG voice, checking cross-doc consistency, cleaning up TODOS, the VERSION bump, and committing (Steps 2-9, after the coverage map in Step 1.5), Read `~/.claude/skills/gstack/document-release/sections/release-body.md` and execute it +> in full. Do not work from memory — that section is the source of truth for this step. --- diff --git a/document-release/SKILL.md.tmpl b/document-release/SKILL.md.tmpl index 7367cbf4e..7621cb312 100644 --- a/document-release/SKILL.md.tmpl +++ b/document-release/SKILL.md.tmpl @@ -59,6 +59,10 @@ subjective decisions. --- +{{SECTION_INDEX:document-release}} + +--- + ## Step 1: Pre-flight & Diff Analysis 1. Check the current branch. If on the base branch, **abort**: "You're on the base branch. Run from a feature branch." @@ -135,364 +139,7 @@ When significant gaps are found, suggest running `/document-generate` to fill th --- -## Step 2: Per-File Documentation Audit - -Read each documentation file and cross-reference it against the diff. Use these generic heuristics -(adapt to whatever project you're in — these are not gstack-specific): - -**README.md:** -- Does it describe all features and capabilities visible in the diff? -- Are install/setup instructions consistent with the changes? -- Are examples, demos, and usage descriptions still valid? -- Are troubleshooting steps still accurate? - -**ARCHITECTURE.md:** -- Do ASCII diagrams and component descriptions match the current code? -- Are design decisions and "why" explanations still accurate? -- Be conservative — only update things clearly contradicted by the diff. Architecture docs - describe things unlikely to change frequently. - -**CONTRIBUTING.md — New contributor smoke test:** -- Walk through the setup instructions as if you are a brand new contributor. -- Are the listed commands accurate? Would each step succeed? -- Do test tier descriptions match the current test infrastructure? -- Are workflow descriptions (dev setup, operational learnings, etc.) current? -- Flag anything that would fail or confuse a first-time contributor. - -**CLAUDE.md / project instructions:** -- Does the project structure section match the actual file tree? -- Are listed commands and scripts accurate? -- Do build/test instructions match what's in package.json (or equivalent)? - -**Any other .md files:** -- Read the file, determine its purpose and audience. -- Cross-reference against the diff to check if it contradicts anything the file says. - -For each file, classify needed updates as: - -- **Auto-update** — Factual corrections clearly warranted by the diff: adding an item to a - table, updating a file path, fixing a count, updating a project structure tree. -- **Ask user** — Narrative changes, section removal, security model changes, large rewrites - (more than ~10 lines in one section), ambiguous relevance, adding entirely new sections. - ---- - -## Step 3: Apply Auto-Updates - -Make all clear, factual updates directly using the Edit tool. - -For each file modified, output a one-line summary describing **what specifically changed** — not -just "Updated README.md" but "README.md: added /new-skill to skills table, updated skill count -from 9 to 10." - -**Never auto-update:** -- README introduction or project positioning -- ARCHITECTURE philosophy or design rationale -- Security model descriptions -- Do not remove entire sections from any document - ---- - -## Step 4: Ask About Risky/Questionable Changes - -For each risky or questionable update identified in Step 2, use AskUserQuestion with: -- Context: project name, branch, which doc file, what we're reviewing -- The specific documentation decision -- `RECOMMENDATION: Choose [X] because [one-line reason]` -- Options including C) Skip — leave as-is - -Apply approved changes immediately after each answer. - ---- - -## Step 5: CHANGELOG Voice Polish - -**CRITICAL — NEVER CLOBBER CHANGELOG ENTRIES.** - -This step polishes voice. It does NOT rewrite, replace, or regenerate CHANGELOG content. - -A real incident occurred where an agent replaced existing CHANGELOG entries when it should have -preserved them. This skill must NEVER do that. - -**Rules:** -1. Read the entire CHANGELOG.md first. Understand what is already there. -2. Only modify wording within existing entries. Never delete, reorder, or replace entries. -3. Never regenerate a CHANGELOG entry from scratch. The entry was written by `/ship` from the - actual diff and commit history. It is the source of truth. You are polishing prose, not - rewriting history. -4. If an entry looks wrong or incomplete, use AskUserQuestion — do NOT silently fix it. -5. Use Edit tool with exact `old_string` matches — never use Write to overwrite CHANGELOG.md. - -**If CHANGELOG was not modified in this branch:** skip this step. - -**If CHANGELOG was modified in this branch**, review the entry for voice: - -- **Sell test (Diataxis rubric):** Score each CHANGELOG entry 0-3: - - **1 point** — answers "What changed?" (reference: names the feature/fix) - - **1 point** — answers "Why should I care?" (explanation: user impact, pain removed) - - **1 point** — answers "How do I use it?" (how-to: command, flag, or link to docs) - - Entries scoring <2 need a rewrite. Entries scoring 3 are gold. -- Lead with what the user can now **do** — not implementation details. -- "You can now..." not "Refactored the..." -- Flag and rewrite any entry that reads like a commit message. -- Internal/contributor changes belong in a separate "### For contributors" subsection. -- Auto-fix minor voice adjustments. Use AskUserQuestion if a rewrite would alter meaning. - ---- - -## Step 6: Cross-Doc Consistency & Discoverability Check - -After auditing each file individually, do a cross-doc consistency pass: - -1. Does the README's feature/capability list match what CLAUDE.md (or project instructions) describes? -2. Does ARCHITECTURE's component list match CONTRIBUTING's project structure description? -3. Does CHANGELOG's latest version match the VERSION file? -4. **Discoverability:** Is every documentation file reachable from README.md or CLAUDE.md? If - ARCHITECTURE.md exists but neither README nor CLAUDE.md links to it, flag it. Every doc - should be discoverable from one of the two entry-point files. -5. Flag any contradictions between documents. Auto-fix clear factual inconsistencies (e.g., a - version mismatch). Use AskUserQuestion for narrative contradictions. - ---- - -## Step 7: TODOS.md Cleanup - -This is a second pass that complements `/ship`'s Step 5.5. Read `review/TODOS-format.md` (if -available) for the canonical TODO item format. - -If TODOS.md does not exist, skip this step. - -1. **Completed items not yet marked:** Cross-reference the diff against open TODO items. If a - TODO is clearly completed by the changes in this branch, move it to the Completed section - with `**Completed:** vX.Y.Z.W (YYYY-MM-DD)`. Be conservative — only mark items with clear - evidence in the diff. - -2. **Items needing description updates:** If a TODO references files or components that were - significantly changed, its description may be stale. Use AskUserQuestion to confirm whether - the TODO should be updated, completed, or left as-is. - -3. **New deferred work:** Check the diff for `TODO`, `FIXME`, `HACK`, and `XXX` comments. For - each one that represents meaningful deferred work (not a trivial inline note), use - AskUserQuestion to ask whether it should be captured in TODOS.md. - ---- - -## Step 8: VERSION Bump Question - -**CRITICAL — NEVER BUMP VERSION WITHOUT ASKING.** - -1. **If VERSION does not exist:** Skip silently. - -2. Check if VERSION was already modified on this branch: - -```bash -git diff ...HEAD -- VERSION -``` - -3. **If VERSION was NOT bumped:** Use AskUserQuestion: - - RECOMMENDATION: Choose C (Skip) because docs-only changes rarely warrant a version bump - - A) Bump PATCH (X.Y.Z+1) — if doc changes ship alongside code changes - - B) Bump MINOR (X.Y+1.0) — if this is a significant standalone release - - C) Skip — no version bump needed - -4. **If VERSION was already bumped:** Do NOT skip silently. Instead, check whether the bump - still covers the full scope of changes on this branch: - - a. Read the CHANGELOG entry for the current VERSION. What features does it describe? - b. Read the full diff (`git diff ...HEAD --stat` and `git diff ...HEAD --name-only`). - Are there significant changes (new features, new skills, new commands, major refactors) - that are NOT mentioned in the CHANGELOG entry for the current version? - c. **If the CHANGELOG entry covers everything:** Skip — output "VERSION: Already bumped to - vX.Y.Z, covers all changes." - d. **If there are significant uncovered changes:** Use AskUserQuestion explaining what the - current version covers vs what's new, and ask: - - RECOMMENDATION: Choose A because the new changes warrant their own version - - A) Bump to next patch (X.Y.Z+1) — give the new changes their own version - - B) Keep current version — add new changes to the existing CHANGELOG entry - - C) Skip — leave version as-is, handle later - - The key insight: a VERSION bump set for "feature A" should not silently absorb "feature B" - if feature B is substantial enough to deserve its own version entry. - ---- - -## Step 9: Commit & Output - -**Empty check first:** Run `git status` (never use `-uall`). If no documentation files were -modified by any previous step, output "All documentation is up to date." and exit without -committing. - -**Commit:** - -1. Stage modified documentation files by name (never `git add -A` or `git add .`). -2. Create a single commit: - -```bash -git commit -m "$(cat <<'EOF' -docs: update project documentation for vX.Y.Z.W - -{{CO_AUTHOR_TRAILER}} -EOF -)" -``` - -3. Push to the current branch: - -```bash -git push -``` - -**PR/MR body update (idempotent, race-safe):** - -1. Read the existing PR/MR body into a PID-unique tempfile (use the platform detected in Step 0): - -**If GitHub:** -```bash -gh pr view --json body -q .body > /tmp/gstack-pr-body-$$.md -``` - -**If GitLab:** -```bash -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 -``` - -2. If the tempfile already contains a `## Documentation` section, replace that section with the - updated content. If it does not contain one, append a `## Documentation` section at the end. - -3. The Documentation section should include: - - a. **Doc diff preview** — for each file modified, describe what specifically changed (e.g., - "README.md: added /document-release to skills table, updated skill count from 9 to 10"). - - b. **Documentation debt** — if the coverage map from Step 1.5 found gaps, append a - `### Documentation Debt` subsection listing: - - Critical gaps: new public surface with zero documentation coverage - - Common gaps: features with reference-only coverage (no how-to or tutorial) - - Stale diagrams: architecture diagrams with entity names that drifted from the code - - Each item should include a one-line description of what's missing and which Diataxis - quadrant would fill it (e.g., "⚠️ `/new-skill` — has reference in AGENTS.md but no - how-to example in README") - - If there are any documentation debt items, suggest adding a `docs-debt` label to the PR. - -4. Redaction scan-at-sink, then write the updated body back. The body is already - in a temp file (`/tmp/gstack-pr-body-$$.md`); scan THAT file before editing so - the bytes scanned are the bytes sent: - -```bash -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. -``` - -**If GitHub:** -```bash -gh pr edit --body-file /tmp/gstack-pr-body-$$.md -``` - -**If GitLab:** -Read the contents of `/tmp/gstack-pr-body-$$.md` using the Read tool, then pass it to `glab mr update` using a heredoc to avoid shell metacharacter issues: -```bash -glab mr update -d "$(cat <<'MRBODY' - -MRBODY -)" -``` - -5. Clean up the tempfile: - -```bash -rm -f /tmp/gstack-pr-body-$$.md -``` - -6. If `gh pr view` / `glab mr view` fails (no PR/MR exists): skip with message "No PR/MR found — skipping body update." -7. If `gh pr edit` / `glab mr update` fails: warn "Could not update PR/MR body — documentation changes are in the - commit." and continue. - -**PR/MR title sync (idempotent, always-on):** - -PR titles must always start with `v` — same rule as `/ship`. If Step 8 bumped VERSION after `/ship` had already created the PR, the title is now stale. This sub-step fixes it. - -1. Read the current VERSION: - -```bash -V=$(cat VERSION 2>/dev/null | tr -d '[:space:]') -``` - -If `VERSION` does not exist or is empty, skip this sub-step entirely. - -2. Read the current PR/MR title: - -**If GitHub:** -```bash -CURRENT_TITLE=$(gh pr view --json title -q .title 2>/dev/null || true) -``` - -**If GitLab:** -```bash -CURRENT_TITLE=$(glab mr view -F json 2>/dev/null | jq -r .title 2>/dev/null || true) -``` - -If `CURRENT_TITLE` is empty (no open PR/MR), skip with message "No PR/MR found — skipping title sync." - -3. Compute the corrected title using the shared helper (single source of truth — same one `/ship` uses): - -```bash -NEW_TITLE=$(~/.claude/skills/gstack/bin/gstack-pr-title-rewrite.sh "$V" "$CURRENT_TITLE") -``` - -The helper handles three cases: title already correct (no-op), title has a different `v` prefix (replace it), or title has no version prefix (prepend one). - -4. If `NEW_TITLE` differs from `CURRENT_TITLE`, update it: - -**If GitHub:** -```bash -gh pr edit --title "$NEW_TITLE" -``` - -**If GitLab:** -```bash -glab mr update -t "$NEW_TITLE" -``` - -5. If the edit command fails: warn "Could not update PR/MR title — documentation changes are still in the commit." and continue. Do not block on title sync failure. - -**Structured doc health summary (final output):** - -Output a scannable summary showing every documentation file's status: - -``` -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]) -``` - -Where status is one of: -- Updated — with description of what changed -- Current — no changes needed -- Voice polished — wording adjusted -- Not bumped — user chose to skip -- Already bumped — version was set by /ship -- Skipped — file does not exist - -If the coverage map from Step 1.5 identified any gaps, append: - -``` -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 -``` - -If all coverage is complete and no diagrams drifted, output: "Coverage: all shipped features have adequate documentation." +{{SECTION:release-body}} --- diff --git a/document-release/sections/manifest.json b/document-release/sections/manifest.json new file mode 100644 index 000000000..05d2c6c2b --- /dev/null +++ b/document-release/sections/manifest.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://gstack.dev/schemas/section-manifest.json", + "skill": "document-release", + "version": 1, + "note": "PASSIVE registry (v2 plan T9 / CM2). id/file/title/trigger text ONLY. The skeleton's decision-tree prose decides WHEN to read. No machine predicate here.", + "sections": [ + { + "id": "release-body", + "file": "release-body.md", + "title": "Per-file audit, auto-updates, risky-change asks, CHANGELOG voice polish, cross-doc consistency, TODOS cleanup, VERSION bump, commit + PR body (Steps 2-9)", + "trigger": "auditing each doc file and applying updates, polishing CHANGELOG voice, checking cross-doc consistency, cleaning up TODOS, the VERSION bump, and committing (Steps 2-9, after the coverage map in Step 1.5)" + } + ] +} diff --git a/document-release/sections/release-body.md b/document-release/sections/release-body.md new file mode 100644 index 000000000..f391eb8a3 --- /dev/null +++ b/document-release/sections/release-body.md @@ -0,0 +1,360 @@ + + +## Step 2: Per-File Documentation Audit + +Read each documentation file and cross-reference it against the diff. Use these generic heuristics +(adapt to whatever project you're in — these are not gstack-specific): + +**README.md:** +- Does it describe all features and capabilities visible in the diff? +- Are install/setup instructions consistent with the changes? +- Are examples, demos, and usage descriptions still valid? +- Are troubleshooting steps still accurate? + +**ARCHITECTURE.md:** +- Do ASCII diagrams and component descriptions match the current code? +- Are design decisions and "why" explanations still accurate? +- Be conservative — only update things clearly contradicted by the diff. Architecture docs + describe things unlikely to change frequently. + +**CONTRIBUTING.md — New contributor smoke test:** +- Walk through the setup instructions as if you are a brand new contributor. +- Are the listed commands accurate? Would each step succeed? +- Do test tier descriptions match the current test infrastructure? +- Are workflow descriptions (dev setup, operational learnings, etc.) current? +- Flag anything that would fail or confuse a first-time contributor. + +**CLAUDE.md / project instructions:** +- Does the project structure section match the actual file tree? +- Are listed commands and scripts accurate? +- Do build/test instructions match what's in package.json (or equivalent)? + +**Any other .md files:** +- Read the file, determine its purpose and audience. +- Cross-reference against the diff to check if it contradicts anything the file says. + +For each file, classify needed updates as: + +- **Auto-update** — Factual corrections clearly warranted by the diff: adding an item to a + table, updating a file path, fixing a count, updating a project structure tree. +- **Ask user** — Narrative changes, section removal, security model changes, large rewrites + (more than ~10 lines in one section), ambiguous relevance, adding entirely new sections. + +--- + +## Step 3: Apply Auto-Updates + +Make all clear, factual updates directly using the Edit tool. + +For each file modified, output a one-line summary describing **what specifically changed** — not +just "Updated README.md" but "README.md: added /new-skill to skills table, updated skill count +from 9 to 10." + +**Never auto-update:** +- README introduction or project positioning +- ARCHITECTURE philosophy or design rationale +- Security model descriptions +- Do not remove entire sections from any document + +--- + +## Step 4: Ask About Risky/Questionable Changes + +For each risky or questionable update identified in Step 2, use AskUserQuestion with: +- Context: project name, branch, which doc file, what we're reviewing +- The specific documentation decision +- `RECOMMENDATION: Choose [X] because [one-line reason]` +- Options including C) Skip — leave as-is + +Apply approved changes immediately after each answer. + +--- + +## Step 5: CHANGELOG Voice Polish + +**CRITICAL — NEVER CLOBBER CHANGELOG ENTRIES.** + +This step polishes voice. It does NOT rewrite, replace, or regenerate CHANGELOG content. + +A real incident occurred where an agent replaced existing CHANGELOG entries when it should have +preserved them. This skill must NEVER do that. + +**Rules:** +1. Read the entire CHANGELOG.md first. Understand what is already there. +2. Only modify wording within existing entries. Never delete, reorder, or replace entries. +3. Never regenerate a CHANGELOG entry from scratch. The entry was written by `/ship` from the + actual diff and commit history. It is the source of truth. You are polishing prose, not + rewriting history. +4. If an entry looks wrong or incomplete, use AskUserQuestion — do NOT silently fix it. +5. Use Edit tool with exact `old_string` matches — never use Write to overwrite CHANGELOG.md. + +**If CHANGELOG was not modified in this branch:** skip this step. + +**If CHANGELOG was modified in this branch**, review the entry for voice: + +- **Sell test (Diataxis rubric):** Score each CHANGELOG entry 0-3: + - **1 point** — answers "What changed?" (reference: names the feature/fix) + - **1 point** — answers "Why should I care?" (explanation: user impact, pain removed) + - **1 point** — answers "How do I use it?" (how-to: command, flag, or link to docs) + - Entries scoring <2 need a rewrite. Entries scoring 3 are gold. +- Lead with what the user can now **do** — not implementation details. +- "You can now..." not "Refactored the..." +- Flag and rewrite any entry that reads like a commit message. +- Internal/contributor changes belong in a separate "### For contributors" subsection. +- Auto-fix minor voice adjustments. Use AskUserQuestion if a rewrite would alter meaning. + +--- + +## Step 6: Cross-Doc Consistency & Discoverability Check + +After auditing each file individually, do a cross-doc consistency pass: + +1. Does the README's feature/capability list match what CLAUDE.md (or project instructions) describes? +2. Does ARCHITECTURE's component list match CONTRIBUTING's project structure description? +3. Does CHANGELOG's latest version match the VERSION file? +4. **Discoverability:** Is every documentation file reachable from README.md or CLAUDE.md? If + ARCHITECTURE.md exists but neither README nor CLAUDE.md links to it, flag it. Every doc + should be discoverable from one of the two entry-point files. +5. Flag any contradictions between documents. Auto-fix clear factual inconsistencies (e.g., a + version mismatch). Use AskUserQuestion for narrative contradictions. + +--- + +## Step 7: TODOS.md Cleanup + +This is a second pass that complements `/ship`'s Step 5.5. Read `review/TODOS-format.md` (if +available) for the canonical TODO item format. + +If TODOS.md does not exist, skip this step. + +1. **Completed items not yet marked:** Cross-reference the diff against open TODO items. If a + TODO is clearly completed by the changes in this branch, move it to the Completed section + with `**Completed:** vX.Y.Z.W (YYYY-MM-DD)`. Be conservative — only mark items with clear + evidence in the diff. + +2. **Items needing description updates:** If a TODO references files or components that were + significantly changed, its description may be stale. Use AskUserQuestion to confirm whether + the TODO should be updated, completed, or left as-is. + +3. **New deferred work:** Check the diff for `TODO`, `FIXME`, `HACK`, and `XXX` comments. For + each one that represents meaningful deferred work (not a trivial inline note), use + AskUserQuestion to ask whether it should be captured in TODOS.md. + +--- + +## Step 8: VERSION Bump Question + +**CRITICAL — NEVER BUMP VERSION WITHOUT ASKING.** + +1. **If VERSION does not exist:** Skip silently. + +2. Check if VERSION was already modified on this branch: + +```bash +git diff ...HEAD -- VERSION +``` + +3. **If VERSION was NOT bumped:** Use AskUserQuestion: + - RECOMMENDATION: Choose C (Skip) because docs-only changes rarely warrant a version bump + - A) Bump PATCH (X.Y.Z+1) — if doc changes ship alongside code changes + - B) Bump MINOR (X.Y+1.0) — if this is a significant standalone release + - C) Skip — no version bump needed + +4. **If VERSION was already bumped:** Do NOT skip silently. Instead, check whether the bump + still covers the full scope of changes on this branch: + + a. Read the CHANGELOG entry for the current VERSION. What features does it describe? + b. Read the full diff (`git diff ...HEAD --stat` and `git diff ...HEAD --name-only`). + Are there significant changes (new features, new skills, new commands, major refactors) + that are NOT mentioned in the CHANGELOG entry for the current version? + c. **If the CHANGELOG entry covers everything:** Skip — output "VERSION: Already bumped to + vX.Y.Z, covers all changes." + d. **If there are significant uncovered changes:** Use AskUserQuestion explaining what the + current version covers vs what's new, and ask: + - RECOMMENDATION: Choose A because the new changes warrant their own version + - A) Bump to next patch (X.Y.Z+1) — give the new changes their own version + - B) Keep current version — add new changes to the existing CHANGELOG entry + - C) Skip — leave version as-is, handle later + + The key insight: a VERSION bump set for "feature A" should not silently absorb "feature B" + if feature B is substantial enough to deserve its own version entry. + +--- + +## Step 9: Commit & Output + +**Empty check first:** Run `git status` (never use `-uall`). If no documentation files were +modified by any previous step, output "All documentation is up to date." and exit without +committing. + +**Commit:** + +1. Stage modified documentation files by name (never `git add -A` or `git add .`). +2. Create a single commit: + +```bash +git commit -m "$(cat <<'EOF' +docs: update project documentation for vX.Y.Z.W + +Co-Authored-By: Claude Opus 4.7 +EOF +)" +``` + +3. Push to the current branch: + +```bash +git push +``` + +**PR/MR body update (idempotent, race-safe):** + +1. Read the existing PR/MR body into a PID-unique tempfile (use the platform detected in Step 0): + +**If GitHub:** +```bash +gh pr view --json body -q .body > /tmp/gstack-pr-body-$$.md +``` + +**If GitLab:** +```bash +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 +``` + +2. If the tempfile already contains a `## Documentation` section, replace that section with the + updated content. If it does not contain one, append a `## Documentation` section at the end. + +3. The Documentation section should include: + + a. **Doc diff preview** — for each file modified, describe what specifically changed (e.g., + "README.md: added /document-release to skills table, updated skill count from 9 to 10"). + + b. **Documentation debt** — if the coverage map from Step 1.5 found gaps, append a + `### Documentation Debt` subsection listing: + - Critical gaps: new public surface with zero documentation coverage + - Common gaps: features with reference-only coverage (no how-to or tutorial) + - Stale diagrams: architecture diagrams with entity names that drifted from the code + - Each item should include a one-line description of what's missing and which Diataxis + quadrant would fill it (e.g., "⚠️ `/new-skill` — has reference in AGENTS.md but no + how-to example in README") + + If there are any documentation debt items, suggest adding a `docs-debt` label to the PR. + +4. Redaction scan-at-sink, then write the updated body back. The body is already + in a temp file (`/tmp/gstack-pr-body-$$.md`); scan THAT file before editing so + the bytes scanned are the bytes sent: + +```bash +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. +``` + +**If GitHub:** +```bash +gh pr edit --body-file /tmp/gstack-pr-body-$$.md +``` + +**If GitLab:** +Read the contents of `/tmp/gstack-pr-body-$$.md` using the Read tool, then pass it to `glab mr update` using a heredoc to avoid shell metacharacter issues: +```bash +glab mr update -d "$(cat <<'MRBODY' + +MRBODY +)" +``` + +5. Clean up the tempfile: + +```bash +rm -f /tmp/gstack-pr-body-$$.md +``` + +6. If `gh pr view` / `glab mr view` fails (no PR/MR exists): skip with message "No PR/MR found — skipping body update." +7. If `gh pr edit` / `glab mr update` fails: warn "Could not update PR/MR body — documentation changes are in the + commit." and continue. + +**PR/MR title sync (idempotent, always-on):** + +PR titles must always start with `v` — same rule as `/ship`. If Step 8 bumped VERSION after `/ship` had already created the PR, the title is now stale. This sub-step fixes it. + +1. Read the current VERSION: + +```bash +V=$(cat VERSION 2>/dev/null | tr -d '[:space:]') +``` + +If `VERSION` does not exist or is empty, skip this sub-step entirely. + +2. Read the current PR/MR title: + +**If GitHub:** +```bash +CURRENT_TITLE=$(gh pr view --json title -q .title 2>/dev/null || true) +``` + +**If GitLab:** +```bash +CURRENT_TITLE=$(glab mr view -F json 2>/dev/null | jq -r .title 2>/dev/null || true) +``` + +If `CURRENT_TITLE` is empty (no open PR/MR), skip with message "No PR/MR found — skipping title sync." + +3. Compute the corrected title using the shared helper (single source of truth — same one `/ship` uses): + +```bash +NEW_TITLE=$(~/.claude/skills/gstack/bin/gstack-pr-title-rewrite.sh "$V" "$CURRENT_TITLE") +``` + +The helper handles three cases: title already correct (no-op), title has a different `v` prefix (replace it), or title has no version prefix (prepend one). + +4. If `NEW_TITLE` differs from `CURRENT_TITLE`, update it: + +**If GitHub:** +```bash +gh pr edit --title "$NEW_TITLE" +``` + +**If GitLab:** +```bash +glab mr update -t "$NEW_TITLE" +``` + +5. If the edit command fails: warn "Could not update PR/MR title — documentation changes are still in the commit." and continue. Do not block on title sync failure. + +**Structured doc health summary (final output):** + +Output a scannable summary showing every documentation file's status: + +``` +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]) +``` + +Where status is one of: +- Updated — with description of what changed +- Current — no changes needed +- Voice polished — wording adjusted +- Not bumped — user chose to skip +- Already bumped — version was set by /ship +- Skipped — file does not exist + +If the coverage map from Step 1.5 identified any gaps, append: + +``` +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 +``` + +If all coverage is complete and no diagrams drifted, output: "Coverage: all shipped features have adequate documentation." diff --git a/document-release/sections/release-body.md.tmpl b/document-release/sections/release-body.md.tmpl new file mode 100644 index 000000000..ea5a54524 --- /dev/null +++ b/document-release/sections/release-body.md.tmpl @@ -0,0 +1,358 @@ +## Step 2: Per-File Documentation Audit + +Read each documentation file and cross-reference it against the diff. Use these generic heuristics +(adapt to whatever project you're in — these are not gstack-specific): + +**README.md:** +- Does it describe all features and capabilities visible in the diff? +- Are install/setup instructions consistent with the changes? +- Are examples, demos, and usage descriptions still valid? +- Are troubleshooting steps still accurate? + +**ARCHITECTURE.md:** +- Do ASCII diagrams and component descriptions match the current code? +- Are design decisions and "why" explanations still accurate? +- Be conservative — only update things clearly contradicted by the diff. Architecture docs + describe things unlikely to change frequently. + +**CONTRIBUTING.md — New contributor smoke test:** +- Walk through the setup instructions as if you are a brand new contributor. +- Are the listed commands accurate? Would each step succeed? +- Do test tier descriptions match the current test infrastructure? +- Are workflow descriptions (dev setup, operational learnings, etc.) current? +- Flag anything that would fail or confuse a first-time contributor. + +**CLAUDE.md / project instructions:** +- Does the project structure section match the actual file tree? +- Are listed commands and scripts accurate? +- Do build/test instructions match what's in package.json (or equivalent)? + +**Any other .md files:** +- Read the file, determine its purpose and audience. +- Cross-reference against the diff to check if it contradicts anything the file says. + +For each file, classify needed updates as: + +- **Auto-update** — Factual corrections clearly warranted by the diff: adding an item to a + table, updating a file path, fixing a count, updating a project structure tree. +- **Ask user** — Narrative changes, section removal, security model changes, large rewrites + (more than ~10 lines in one section), ambiguous relevance, adding entirely new sections. + +--- + +## Step 3: Apply Auto-Updates + +Make all clear, factual updates directly using the Edit tool. + +For each file modified, output a one-line summary describing **what specifically changed** — not +just "Updated README.md" but "README.md: added /new-skill to skills table, updated skill count +from 9 to 10." + +**Never auto-update:** +- README introduction or project positioning +- ARCHITECTURE philosophy or design rationale +- Security model descriptions +- Do not remove entire sections from any document + +--- + +## Step 4: Ask About Risky/Questionable Changes + +For each risky or questionable update identified in Step 2, use AskUserQuestion with: +- Context: project name, branch, which doc file, what we're reviewing +- The specific documentation decision +- `RECOMMENDATION: Choose [X] because [one-line reason]` +- Options including C) Skip — leave as-is + +Apply approved changes immediately after each answer. + +--- + +## Step 5: CHANGELOG Voice Polish + +**CRITICAL — NEVER CLOBBER CHANGELOG ENTRIES.** + +This step polishes voice. It does NOT rewrite, replace, or regenerate CHANGELOG content. + +A real incident occurred where an agent replaced existing CHANGELOG entries when it should have +preserved them. This skill must NEVER do that. + +**Rules:** +1. Read the entire CHANGELOG.md first. Understand what is already there. +2. Only modify wording within existing entries. Never delete, reorder, or replace entries. +3. Never regenerate a CHANGELOG entry from scratch. The entry was written by `/ship` from the + actual diff and commit history. It is the source of truth. You are polishing prose, not + rewriting history. +4. If an entry looks wrong or incomplete, use AskUserQuestion — do NOT silently fix it. +5. Use Edit tool with exact `old_string` matches — never use Write to overwrite CHANGELOG.md. + +**If CHANGELOG was not modified in this branch:** skip this step. + +**If CHANGELOG was modified in this branch**, review the entry for voice: + +- **Sell test (Diataxis rubric):** Score each CHANGELOG entry 0-3: + - **1 point** — answers "What changed?" (reference: names the feature/fix) + - **1 point** — answers "Why should I care?" (explanation: user impact, pain removed) + - **1 point** — answers "How do I use it?" (how-to: command, flag, or link to docs) + - Entries scoring <2 need a rewrite. Entries scoring 3 are gold. +- Lead with what the user can now **do** — not implementation details. +- "You can now..." not "Refactored the..." +- Flag and rewrite any entry that reads like a commit message. +- Internal/contributor changes belong in a separate "### For contributors" subsection. +- Auto-fix minor voice adjustments. Use AskUserQuestion if a rewrite would alter meaning. + +--- + +## Step 6: Cross-Doc Consistency & Discoverability Check + +After auditing each file individually, do a cross-doc consistency pass: + +1. Does the README's feature/capability list match what CLAUDE.md (or project instructions) describes? +2. Does ARCHITECTURE's component list match CONTRIBUTING's project structure description? +3. Does CHANGELOG's latest version match the VERSION file? +4. **Discoverability:** Is every documentation file reachable from README.md or CLAUDE.md? If + ARCHITECTURE.md exists but neither README nor CLAUDE.md links to it, flag it. Every doc + should be discoverable from one of the two entry-point files. +5. Flag any contradictions between documents. Auto-fix clear factual inconsistencies (e.g., a + version mismatch). Use AskUserQuestion for narrative contradictions. + +--- + +## Step 7: TODOS.md Cleanup + +This is a second pass that complements `/ship`'s Step 5.5. Read `review/TODOS-format.md` (if +available) for the canonical TODO item format. + +If TODOS.md does not exist, skip this step. + +1. **Completed items not yet marked:** Cross-reference the diff against open TODO items. If a + TODO is clearly completed by the changes in this branch, move it to the Completed section + with `**Completed:** vX.Y.Z.W (YYYY-MM-DD)`. Be conservative — only mark items with clear + evidence in the diff. + +2. **Items needing description updates:** If a TODO references files or components that were + significantly changed, its description may be stale. Use AskUserQuestion to confirm whether + the TODO should be updated, completed, or left as-is. + +3. **New deferred work:** Check the diff for `TODO`, `FIXME`, `HACK`, and `XXX` comments. For + each one that represents meaningful deferred work (not a trivial inline note), use + AskUserQuestion to ask whether it should be captured in TODOS.md. + +--- + +## Step 8: VERSION Bump Question + +**CRITICAL — NEVER BUMP VERSION WITHOUT ASKING.** + +1. **If VERSION does not exist:** Skip silently. + +2. Check if VERSION was already modified on this branch: + +```bash +git diff ...HEAD -- VERSION +``` + +3. **If VERSION was NOT bumped:** Use AskUserQuestion: + - RECOMMENDATION: Choose C (Skip) because docs-only changes rarely warrant a version bump + - A) Bump PATCH (X.Y.Z+1) — if doc changes ship alongside code changes + - B) Bump MINOR (X.Y+1.0) — if this is a significant standalone release + - C) Skip — no version bump needed + +4. **If VERSION was already bumped:** Do NOT skip silently. Instead, check whether the bump + still covers the full scope of changes on this branch: + + a. Read the CHANGELOG entry for the current VERSION. What features does it describe? + b. Read the full diff (`git diff ...HEAD --stat` and `git diff ...HEAD --name-only`). + Are there significant changes (new features, new skills, new commands, major refactors) + that are NOT mentioned in the CHANGELOG entry for the current version? + c. **If the CHANGELOG entry covers everything:** Skip — output "VERSION: Already bumped to + vX.Y.Z, covers all changes." + d. **If there are significant uncovered changes:** Use AskUserQuestion explaining what the + current version covers vs what's new, and ask: + - RECOMMENDATION: Choose A because the new changes warrant their own version + - A) Bump to next patch (X.Y.Z+1) — give the new changes their own version + - B) Keep current version — add new changes to the existing CHANGELOG entry + - C) Skip — leave version as-is, handle later + + The key insight: a VERSION bump set for "feature A" should not silently absorb "feature B" + if feature B is substantial enough to deserve its own version entry. + +--- + +## Step 9: Commit & Output + +**Empty check first:** Run `git status` (never use `-uall`). If no documentation files were +modified by any previous step, output "All documentation is up to date." and exit without +committing. + +**Commit:** + +1. Stage modified documentation files by name (never `git add -A` or `git add .`). +2. Create a single commit: + +```bash +git commit -m "$(cat <<'EOF' +docs: update project documentation for vX.Y.Z.W + +{{CO_AUTHOR_TRAILER}} +EOF +)" +``` + +3. Push to the current branch: + +```bash +git push +``` + +**PR/MR body update (idempotent, race-safe):** + +1. Read the existing PR/MR body into a PID-unique tempfile (use the platform detected in Step 0): + +**If GitHub:** +```bash +gh pr view --json body -q .body > /tmp/gstack-pr-body-$$.md +``` + +**If GitLab:** +```bash +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 +``` + +2. If the tempfile already contains a `## Documentation` section, replace that section with the + updated content. If it does not contain one, append a `## Documentation` section at the end. + +3. The Documentation section should include: + + a. **Doc diff preview** — for each file modified, describe what specifically changed (e.g., + "README.md: added /document-release to skills table, updated skill count from 9 to 10"). + + b. **Documentation debt** — if the coverage map from Step 1.5 found gaps, append a + `### Documentation Debt` subsection listing: + - Critical gaps: new public surface with zero documentation coverage + - Common gaps: features with reference-only coverage (no how-to or tutorial) + - Stale diagrams: architecture diagrams with entity names that drifted from the code + - Each item should include a one-line description of what's missing and which Diataxis + quadrant would fill it (e.g., "⚠️ `/new-skill` — has reference in AGENTS.md but no + how-to example in README") + + If there are any documentation debt items, suggest adding a `docs-debt` label to the PR. + +4. Redaction scan-at-sink, then write the updated body back. The body is already + in a temp file (`/tmp/gstack-pr-body-$$.md`); scan THAT file before editing so + the bytes scanned are the bytes sent: + +```bash +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. +``` + +**If GitHub:** +```bash +gh pr edit --body-file /tmp/gstack-pr-body-$$.md +``` + +**If GitLab:** +Read the contents of `/tmp/gstack-pr-body-$$.md` using the Read tool, then pass it to `glab mr update` using a heredoc to avoid shell metacharacter issues: +```bash +glab mr update -d "$(cat <<'MRBODY' + +MRBODY +)" +``` + +5. Clean up the tempfile: + +```bash +rm -f /tmp/gstack-pr-body-$$.md +``` + +6. If `gh pr view` / `glab mr view` fails (no PR/MR exists): skip with message "No PR/MR found — skipping body update." +7. If `gh pr edit` / `glab mr update` fails: warn "Could not update PR/MR body — documentation changes are in the + commit." and continue. + +**PR/MR title sync (idempotent, always-on):** + +PR titles must always start with `v` — same rule as `/ship`. If Step 8 bumped VERSION after `/ship` had already created the PR, the title is now stale. This sub-step fixes it. + +1. Read the current VERSION: + +```bash +V=$(cat VERSION 2>/dev/null | tr -d '[:space:]') +``` + +If `VERSION` does not exist or is empty, skip this sub-step entirely. + +2. Read the current PR/MR title: + +**If GitHub:** +```bash +CURRENT_TITLE=$(gh pr view --json title -q .title 2>/dev/null || true) +``` + +**If GitLab:** +```bash +CURRENT_TITLE=$(glab mr view -F json 2>/dev/null | jq -r .title 2>/dev/null || true) +``` + +If `CURRENT_TITLE` is empty (no open PR/MR), skip with message "No PR/MR found — skipping title sync." + +3. Compute the corrected title using the shared helper (single source of truth — same one `/ship` uses): + +```bash +NEW_TITLE=$(~/.claude/skills/gstack/bin/gstack-pr-title-rewrite.sh "$V" "$CURRENT_TITLE") +``` + +The helper handles three cases: title already correct (no-op), title has a different `v` prefix (replace it), or title has no version prefix (prepend one). + +4. If `NEW_TITLE` differs from `CURRENT_TITLE`, update it: + +**If GitHub:** +```bash +gh pr edit --title "$NEW_TITLE" +``` + +**If GitLab:** +```bash +glab mr update -t "$NEW_TITLE" +``` + +5. If the edit command fails: warn "Could not update PR/MR title — documentation changes are still in the commit." and continue. Do not block on title sync failure. + +**Structured doc health summary (final output):** + +Output a scannable summary showing every documentation file's status: + +``` +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]) +``` + +Where status is one of: +- Updated — with description of what changed +- Current — no changes needed +- Voice polished — wording adjusted +- Not bumped — user chose to skip +- Already bumped — version was set by /ship +- Skipped — file does not exist + +If the coverage map from Step 1.5 identified any gaps, append: + +``` +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 +``` + +If all coverage is complete and no diagrams drifted, output: "Coverage: all shipped features have adequate documentation." diff --git a/test/helpers/carve-guards.ts b/test/helpers/carve-guards.ts index 8dfd04a04..6b3d1d898 100644 --- a/test/helpers/carve-guards.ts +++ b/test/helpers/carve-guards.ts @@ -192,6 +192,23 @@ export const CARVE_GUARDS: Record = { minUnionBytes: 70_000, mustContain: ['design doc', 'problem statement'], }, + 'document-release': { + skill: 'document-release', + expectedSections: ['release-body.md'], + requiredReads: ['release-body.md'], + scenario: + 'A PR has shipped a new CLI flag and touched README.md and CHANGELOG.md. Skip the git pre-flight shell commands (assume the diff adds --new-flag and updates those two docs). Run the documentation workflow: build the coverage map, then audit the docs, apply updates, and polish the CHANGELOG voice. Produce the documentation health summary.', + staticInvariants: { + mustStayInSkeleton: ['## Step 1: Pre-flight', '## Step 1.5: Coverage Map'], + mustMoveToSection: ['## Step 2: Per-File Documentation Audit', '## Step 5: CHANGELOG Voice Polish'], + // Operational skill (no plan-mode review gate). + gateAfterStop: undefined, + }, + behavioral: 'prompt', + maxSkeletonBytes: 50_000, + minUnionBytes: 55_000, + mustContain: ['CHANGELOG', 'Diataxis', 'coverage'], + }, }; /** Sorted carved-skill names. Consumers derive their lists from this — no parallel lists. */