fix: make documentation release review and publication consistent

Review before commit, clarify changelog safeguards and unavailable reviewer modes, and preserve raw PR bodies across separate shell calls. Keep title sync in one shell and add regression coverage.

Co-authored-by: OpenAI Codex <noreply@openai.com>
This commit is contained in:
Garry Tan
2026-09-09 05:42:05 +00:00
co-authored by OpenAI Codex
parent 9096d9f3f8
commit 24ed2030f4
9 changed files with 383 additions and 366 deletions
+4 -4
View File
@@ -63,8 +63,8 @@ describe('content-binding template drift', () => {
test('release-body write side carries the banner tripwire (and it actually fires)', () => {
const body = rendered('document-release/sections/release-body.md');
expect(body).toContain('grep -c "UNTRUSTED TRACKER CONTENT" /tmp/gstack-pr-body-$$.md');
expect(body).toContain('grep -c "UNTRUSTED TRACKER CONTENT" /tmp/gstack-pr-body-orig-$$.md');
expect(body).toContain('grep -c "UNTRUSTED TRACKER CONTENT" "<run-dir>/body.md"');
expect(body).toContain('grep -c "UNTRUSTED TRACKER CONTENT" "<run-dir>/body-original.md"');
// The fail-open shape: grep -c prints 0 AND exits 1 on no-match, so an
// `|| echo 0` double-emits and breaks the -gt into the clean branch.
expect(body).not.toContain('|| echo 0');
@@ -94,8 +94,8 @@ describe('content-binding template drift', () => {
fs.writeFileSync(path.join(dir, 'orig.md'), origContent);
fs.writeFileSync(path.join(dir, 'new.md'), newContent);
return block![0]
.replaceAll('/tmp/gstack-pr-body-orig-$$.md', path.join(dir, 'orig.md'))
.replaceAll('/tmp/gstack-pr-body-$$.md', path.join(dir, 'new.md'));
.replaceAll('<run-dir>/body-original.md', path.join(dir, 'orig.md'))
.replaceAll('<run-dir>/body.md', path.join(dir, 'new.md'));
};
// Banner leaked into the outgoing body → the ABORT branch fires, loudly.
+18 -2
View File
@@ -4,6 +4,7 @@
import { describe, test, expect } from "bun:test";
import * as fs from "fs";
import * as path from "path";
import { spawnSync } from "child_process";
const ROOT = path.resolve(import.meta.dir, "..");
// document-release is carved (skeleton + sections/release-body.md). Step 9
@@ -25,14 +26,29 @@ const GENERATE = fs.readFileSync(path.join(ROOT, "document-generate", "SKILL.md.
describe("/document-release redaction", () => {
test("scans the PR-body temp file before gh pr edit", () => {
const scanIdx = RELEASE.indexOf("gstack-redact --from-file /tmp/gstack-pr-body");
const editIdx = RELEASE.indexOf("gh pr edit --body-file /tmp/gstack-pr-body");
const scanIdx = RELEASE.indexOf('gstack-redact --from-file "<run-dir>/body.md"');
const editIdx = RELEASE.indexOf('gh pr edit --body-file "<run-dir>/body.md"');
expect(scanIdx).toBeGreaterThan(-1);
expect(editIdx).toBeGreaterThan(scanIdx);
});
test("HIGH blocks the edit", () => {
expect(RELEASE).toMatch(/exit 3 \(HIGH\).*do NOT edit/i);
});
test("separate shell calls share an explicit run directory and never re-read raw tracker text", () => {
expect(RELEASE).toContain('mktemp -d /tmp/gstack-doc-release-XXXXXXXX');
expect(RELEASE).not.toContain('/tmp/gstack-pr-body-$$');
expect(RELEASE).not.toContain('<paste the file contents here>');
expect(RELEASE).toContain('pathlib.Path(sys.argv[1]).read_text()');
});
test("title synchronization keeps every variable in one valid shell block", () => {
const section = RELEASE.slice(RELEASE.indexOf('**PR/MR title sync'));
const script = section.match(/```bash\n([\s\S]*?)\n```/)![1];
for (const command of ['V=$(cat VERSION', 'CURRENT_TITLE=$(gh pr view', 'NEW_TITLE=$(', 'gh pr edit --title "$NEW_TITLE"', 'glab mr update -t "$NEW_TITLE"']) {
expect(script).toContain(command);
}
const result = spawnSync('bash', ['-n'], { input: script, encoding: 'utf8', timeout: 5000 });
expect(result.status, result.stderr).toBe(0);
});
});
describe("/document-generate redaction", () => {
+12
View File
@@ -65,6 +65,18 @@ describe('workflow judge excerpts', () => {
expect(text).toContain('## Step 9:');
});
test('documentation review precedes publication and keeps changelog protection', () => {
const text = readWorkflowExcerpt('document-release/SKILL.md', '# Document Release:', '## Important Rules');
expect(text).toContain('DOC_DIFF_BASE=$(git merge-base origin/<base> HEAD 2>/dev/null || git merge-base <base> HEAD) || exit 1');
expect(text.indexOf('## Codex Documentation Review')).toBeLessThan(text.indexOf('## Step 9:'));
expect(text).toContain('no in-host substitute is defined here');
expect(text).toContain('all Claude fallback modes');
expect(text).toContain('Step 9 then commits and pushes those edits');
expect(text).toContain('Entries scoring <2 need attention, not replacement');
expect(text).not.toContain('Flag and rewrite');
expect(text).toContain('if VERSION is absent, use the completion date only');
});
test('plan review evidence and design approval rules precede their use', () => {
const eng = readWorkflowExcerpt('plan-eng-review/SKILL.md', '## Review Sections', '## CRITICAL RULE');
expect(eng.indexOf('## Confidence Calibration')).toBeLessThan(eng.indexOf('### 1. Architecture review'));