mirror of
https://github.com/garrytan/gstack.git
synced 2026-06-10 20:07:49 +02:00
v1.57.0.0 feat: carve-guard system + carve cso/document-release/design-consultation (#1907)
* test: canonical CARVE_GUARDS registry; derive parity + size-budget from it Single source of truth for the carved-skill set + per-skill invariants (EQ1). parity-harness.ts sectioned entries and skill-size-budget.ts SECTIONS_EXTRACTED now derive from it instead of hand-maintained lists. Closes a pre-existing drift: plan-devex-review was in SECTIONS_EXTRACTED but had no sectioned parity invariant; now generated. carve-guards.ts is a pure leaf data module (import type only) to avoid an import cycle. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: shared carve-guard check fns with injectable root discoverCarvedSkills/checkOrdering/checkCompleteness take a root param so the negative tests can point the real guards at a fixture dir. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: E2 data-driven carve static ordering guard (gate) Per-PR backstop for every carved skill, one test() per skill, driven by CARVE_GUARDS staticInvariants. Generalizes + retires the ceo-specific ordering test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: E1 carve-guard completeness meta-guard (gate) Asserts filesystem carved set == CARVE_GUARDS set both directions, so a future carve without a registry entry fails CI. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: ET1 guard-of-guards negative tests (gate) Temp fixture broken 3 ways proves E1/E2 actually throw, via the injectable root. Kills the silent-pass-guard failure class. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: T2 data-driven behavioral section-loading guard (periodic) One file iterating CARVE_GUARDS, one test() per skill with GSTACK_CARVE_SKILL cost-scoping (D-CODEX A). external carves (ship, plan-ceo) keep bespoke tests; testNames aligned to their touchfile keys. Registered in touchfiles. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: defer E3 real-session carve canary to TODOS Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: carve document-release into skeleton + on-demand section Steps 2-9 (per-file audit, auto-updates, risky-change asks, CHANGELOG voice polish, cross-doc consistency, TODOS cleanup, VERSION bump, commit + PR body) move to sections/release-body.md, read on demand after the Step 1.5 coverage map. Skeleton 59,256 -> 45,797 B (-23%); union preserved. Adds the CARVE_GUARDS entry (auto-extends parity + size-budget via EQ1). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: carve design-consultation into skeleton + on-demand section Phases 3-6 (complete proposal, drill-downs, design preview, writing DESIGN.md) move to sections/proposal-and-preview.md, read on demand after product context + research. Skeleton 80,719 -> 59,229 B (-27%); union preserved. Adds the CARVE_GUARDS entry. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: carve cso into skeleton + on-demand section (security-safe) Scope-dependent audit Phases 2-11 move to sections/audit-phases.md. Mode dispatch (## Arguments, ## Mode Resolution), always-run Phases 0/1, and the Phase 12 false-positive-filtering exceptions stay ALWAYS-LOADED in the skeleton. Skeleton 79,383 -> 65,117 B (-18%); union preserved. Adds a cso CARVE_GUARDS entry with an earliest-use invariant (mustPrecedeStop): mode dispatch must appear before any STOP-Read, so a directive that decides which sections to read can't be stranded behind the STOP that reads them (codex outside-voice #6). carve-guard-checks gains the mustPrecedeStop check. parity moves cso monolith -> generated carved entry. cso-preserved.test.ts strengthened: phrases checked against the union, plus an always-loaded contract on the skeleton (dispatch + FP-filtering, codex #5). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: make redaction/taxonomy tests union-aware for cso + document-release carves The cso carve moved Secrets Archaeology (prefixes, lib/redact-patterns.ts pointer, git-history scan) into sections/audit-phases.md, and the document-release carve moved the Step 9 PR-body redaction scan into sections/release-body.md. Three content-presence tests asserted that content in the skeleton SKILL.md/.md.tmpl; they now read the skeleton+sections union (same fix as cso-preserved + parity). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: bump version and changelog (v1.57.0.0) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: address pre-landing review (codex) on the carve - cso section: add a scope-gate header so '--owasp' (and other scoped modes) run only their selected phases, not every phase bundled in the section ('execute in full' no longer overrides Mode Resolution). - carve-guard-checks: gateAfterStop now compares against the LAST STOP, not the first, so a gate stranded between two STOPs in a multi-STOP skeleton fails. - TODOS: behavioral section-loading hermeticity (verifier matches global-install path, not the fixture) — pre-existing in auq-sdk-capture.ts, deferred. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+13
-358
@@ -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 <base>...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 <base>...HEAD --stat` and `git diff <base>...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 <noreply@anthropic.com>
|
||||
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'
|
||||
<paste the file contents here>
|
||||
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<VERSION>` — 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<X.Y.Z.W>` 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.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -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 <base>...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 <base>...HEAD --stat` and `git diff <base>...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'
|
||||
<paste the file contents here>
|
||||
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<VERSION>` — 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<X.Y.Z.W>` 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}}
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -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)"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,360 @@
|
||||
<!-- AUTO-GENERATED from release-body.md.tmpl — do not edit directly -->
|
||||
<!-- Regenerate: bun run gen:skill-docs -->
|
||||
## 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 <base>...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 <base>...HEAD --stat` and `git diff <base>...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 <noreply@anthropic.com>
|
||||
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'
|
||||
<paste the file contents here>
|
||||
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<VERSION>` — 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<X.Y.Z.W>` 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."
|
||||
@@ -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 <base>...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 <base>...HEAD --stat` and `git diff <base>...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'
|
||||
<paste the file contents here>
|
||||
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<VERSION>` — 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<X.Y.Z.W>` 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."
|
||||
Reference in New Issue
Block a user