mirror of
https://github.com/glittercowboy/get-shit-done
synced 2026-04-25 17:25:23 +02:00
* feat: add /gsd:code-review and /gsd:code-review-fix commands Closes #1636 Add two new slash commands that close the gap between phase execution and verification. After /gsd:execute-phase completes, /gsd:code-review reviews produced code for bugs, security issues, and quality problems. /gsd:code-review-fix then auto-fixes issues found by the review. ## New Files - agents/gsd-code-reviewer.md — Review agent with 3 depth levels (quick/standard/deep) and structured REVIEW.md output - agents/gsd-code-fixer.md — Fix agent with atomic git rollback, 3-tier verification, per-finding atomic commits, logic-bug flagging - commands/gsd/code-review.md — Slash command definition - commands/gsd/code-review-fix.md — Slash command definition - get-shit-done/workflows/code-review.md — Review orchestration: 3-tier file scoping, repo-boundary path validation, config gate - get-shit-done/workflows/code-review-fix.md — Fix orchestration: --all/--auto flags, 3-iteration cap, artifact backup across iterations - tests/code-review.test.cjs — 35 tests covering agents, commands, workflows, config, integration, rollback strategy, and logic-bug flagging ## Modified Files - get-shit-done/bin/lib/config.cjs — Register workflow.code_review and workflow.code_review_depth with defaults and typo suggestions - get-shit-done/workflows/execute-phase.md — Add code_review_gate step (PIPE-01): runs after aggregate_results, advisory only, non-blocking - get-shit-done/workflows/quick.md — Add Step 6.25 code review (PIPE-03): scopes via git diff, uses gsd-code-reviewer, advisory only - get-shit-done/workflows/autonomous.md — Add Step 3c.5 review+fix chain (PIPE-02): auto-chains code-review-fix --auto when issues found ## Design Decisions - Rollback uses git checkout -- {file} (atomic) not Write tool (partial write risk) - Logic-bug fixes flagged "requires human verification" (syntax check cannot verify semantics) - Path traversal guard rejects --files paths outside repo root - Fail-closed scoping: no HEAD~N heuristics when scope is ambiguous Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: add /gsd:code-review and /gsd:code-review-fix commands Closes #1636 Add two new slash commands that close the gap between phase execution and verification. After /gsd:execute-phase completes, /gsd:code-review reviews produced code for bugs, security issues, and quality problems. /gsd:code-review-fix then auto-fixes issues found by the review. ## New Files - agents/gsd-code-reviewer.md — Review agent: 3 depth levels, REVIEW.md - agents/gsd-code-fixer.md — Fix agent: git rollback, 3-tier verification, logic-bug flagging, per-finding atomic commits - commands/gsd/code-review.md, code-review-fix.md — Slash command definitions - get-shit-done/workflows/code-review.md — Review orchestration: 3-tier file scoping, path traversal guard, config gate - get-shit-done/workflows/code-review-fix.md — Fix orchestration: --all/--auto flags, 3-iteration cap, artifact backup - tests/code-review.test.cjs — 35 tests: agents, commands, workflows, config, integration, rollback, logic-bug flagging ## Modified Files - get-shit-done/bin/lib/config.cjs — Register workflow.code_review and workflow.code_review_depth config keys - get-shit-done/workflows/execute-phase.md — Add code_review_gate step (PIPE-01): after aggregate_results, advisory, non-blocking - get-shit-done/workflows/quick.md — Add Step 6.25 code review (PIPE-03): git diff scoping, gsd-code-reviewer, advisory - get-shit-done/workflows/autonomous.md — Add Step 3c.5 review+fix chain (PIPE-02): auto-chains code-review-fix --auto when issues found ## Design decisions - Rollback uses git checkout -- {file} (atomic) not Write tool - Logic-bug fixes flagged requires human verification (syntax != semantics) - --files paths validated within repo root (path traversal guard) - Fail-closed: no HEAD~N heuristics when scope ambiguous Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: resolve contradictory rollback instructions in gsd-code-fixer rollback_strategy said git checkout, critical_rules said Write tool. Align all three sections (rollback_strategy, execution_flow step b, critical_rules) to use git checkout -- {file} consistently. Also remove in-memory PRE_FIX_CONTENT capture — no longer needed since git checkout is the rollback mechanism. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address all review feedback from rounds 3-4 Blocking (bash compatibility): - Replace mapfile -t with portable while IFS= read -r loops in both workflows (mapfile is bash 4+; macOS ships bash 3.2 by default) - Add macOS bash version note to platform_notes Blocking (quick.md scope heuristic): - Replace fragile HEAD~$(wc -l SUMMARY.md) with git log --grep based diff, matching the more robust approach in code-review.md Security (path traversal): - Document realpath -m macOS behavior in platform_notes; guard remains fail-closed on macOS without coreutils Logic / correctness: - Fix REVIEW_PATH / FIX_REPORT_PATH interpolation in node -e strings; use process.env.REVIEW_PATH via env var prefix to avoid single-quote path injection risk - Add iteration semantics comment clarifying off-by-one behavior - Remove duplicate "3. Determine changed files" heading in gsd-code-reviewer.md Agent: - Add logic-bug limitation section to gsd-code-fixer verification_strategy Tests (39 total, up from 32): - Add rollback uses git checkout test - Add success_criteria consistency test (must not say Write tool) - Add logic-bug flagging test - Add files_reviewed_list spec test - Add path traversal guard structural test - Add mapfile-in-bash-blocks tests (bash 3.2 compatibility) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: add gsd-code-reviewer to quick.md available_agent_types and copilot install test - quick.md Step 6.25 spawns gsd-code-reviewer but the workflow's <available_agent_types> block did not list it, failing the spawn consistency CI check (#1357) - copilot-install.test.cjs hardcoded agent list was missing gsd-code-fixer.agent.md and gsd-code-reviewer.agent.md, failing the Copilot full install verification test Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: replace /gsd: colon refs with /gsd- hyphen format in new files Fixes stale-colon-refs CI test (#1748). All 19 violations replaced: - agents/gsd-code-fixer.md (2): description + role spawned-by text - agents/gsd-code-reviewer.md (4): description + role + fallback note + error msg - get-shit-done/workflows/code-review-fix.md (7): error msgs + retry suggestions - get-shit-done/workflows/code-review.md (5): error msgs + retry suggestions - get-shit-done/workflows/execute-phase.md (1): code_review_gate suggestion Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
402 lines
18 KiB
JavaScript
402 lines
18 KiB
JavaScript
/**
|
|
* GSD Code Review Tests
|
|
*
|
|
* Validates all code review artifacts from Phases 1-4:
|
|
* - Agent frontmatter (gsd-code-reviewer, gsd-code-fixer)
|
|
* - Command structure (code-review.md, code-review-fix.md)
|
|
* - Workflow structure (code-review.md, code-review-fix.md)
|
|
* - Config key registration (workflow.code_review, workflow.code_review_depth)
|
|
* - Workflow integration points (execute-phase, quick, autonomous)
|
|
*
|
|
* Test structure:
|
|
* - CR-AGENT: Hermetic agent tests (repo files only)
|
|
* - CR-CMD: Hermetic command tests (repo files only)
|
|
* - CR-WORKFLOW: Hermetic workflow tests (repo files only)
|
|
* - CR-CONFIG: Hermetic config tests (repo files only)
|
|
* - CR-INTEGRATION: Conditional integration tests (skip if plugin dir absent)
|
|
*/
|
|
|
|
const { test, describe } = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const os = require('os');
|
|
const { runGsdTools, createTempProject, cleanup } = require('./helpers.cjs');
|
|
|
|
// --- Test Environment Setup ---
|
|
|
|
const AGENTS_DIR = path.join(__dirname, '..', 'agents');
|
|
const COMMANDS_DIR = path.join(__dirname, '..', 'commands', 'gsd');
|
|
const WORKFLOWS_DIR = path.join(__dirname, '..', 'get-shit-done', 'workflows');
|
|
const CONFIG_PATH = path.join(__dirname, '..', 'get-shit-done', 'bin', 'lib', 'config.cjs');
|
|
|
|
// Plugin directory resolution (cross-platform safe)
|
|
const PLUGIN_WORKFLOWS_DIR = process.env.GSD_PLUGIN_ROOT || path.join(os.homedir(), '.claude', 'get-shit-done', 'workflows');
|
|
const PLUGIN_AVAILABLE = fs.existsSync(PLUGIN_WORKFLOWS_DIR);
|
|
|
|
// --- CR-AGENT: code review agent frontmatter ---
|
|
|
|
describe('CR-AGENT: code review agent frontmatter', () => {
|
|
test('gsd-code-reviewer.md has required frontmatter fields', () => {
|
|
const content = fs.readFileSync(path.join(AGENTS_DIR, 'gsd-code-reviewer.md'), 'utf-8');
|
|
const frontmatter = content.split('---')[1] || '';
|
|
|
|
assert.ok(frontmatter.includes('name:'), 'gsd-code-reviewer missing name:');
|
|
assert.ok(frontmatter.includes('description:'), 'gsd-code-reviewer missing description:');
|
|
assert.ok(frontmatter.includes('tools:'), 'gsd-code-reviewer missing tools:');
|
|
assert.ok(frontmatter.includes('color:'), 'gsd-code-reviewer missing color:');
|
|
});
|
|
|
|
test('gsd-code-fixer.md has required frontmatter fields', () => {
|
|
const content = fs.readFileSync(path.join(AGENTS_DIR, 'gsd-code-fixer.md'), 'utf-8');
|
|
const frontmatter = content.split('---')[1] || '';
|
|
|
|
assert.ok(frontmatter.includes('name:'), 'gsd-code-fixer missing name:');
|
|
assert.ok(frontmatter.includes('description:'), 'gsd-code-fixer missing description:');
|
|
assert.ok(frontmatter.includes('tools:'), 'gsd-code-fixer missing tools:');
|
|
assert.ok(frontmatter.includes('color:'), 'gsd-code-fixer missing color:');
|
|
});
|
|
|
|
test('gsd-code-reviewer.md has Read, Bash, Glob, Grep, Write tools', () => {
|
|
const content = fs.readFileSync(path.join(AGENTS_DIR, 'gsd-code-reviewer.md'), 'utf-8');
|
|
const frontmatter = content.split('---')[1] || '';
|
|
|
|
assert.ok(frontmatter.includes('Read'), 'gsd-code-reviewer missing Read tool');
|
|
assert.ok(frontmatter.includes('Bash'), 'gsd-code-reviewer missing Bash tool');
|
|
assert.ok(frontmatter.includes('Glob'), 'gsd-code-reviewer missing Glob tool');
|
|
assert.ok(frontmatter.includes('Grep'), 'gsd-code-reviewer missing Grep tool');
|
|
assert.ok(frontmatter.includes('Write'), 'gsd-code-reviewer missing Write tool');
|
|
});
|
|
|
|
test('gsd-code-fixer.md has Read, Edit, Write, Bash, Grep, Glob tools', () => {
|
|
const content = fs.readFileSync(path.join(AGENTS_DIR, 'gsd-code-fixer.md'), 'utf-8');
|
|
const frontmatter = content.split('---')[1] || '';
|
|
|
|
assert.ok(frontmatter.includes('Read'), 'gsd-code-fixer missing Read tool');
|
|
assert.ok(frontmatter.includes('Edit'), 'gsd-code-fixer missing Edit tool');
|
|
assert.ok(frontmatter.includes('Write'), 'gsd-code-fixer missing Write tool');
|
|
assert.ok(frontmatter.includes('Bash'), 'gsd-code-fixer missing Bash tool');
|
|
});
|
|
|
|
test('gsd-code-reviewer.md does not have skills: in frontmatter', () => {
|
|
const content = fs.readFileSync(path.join(AGENTS_DIR, 'gsd-code-reviewer.md'), 'utf-8');
|
|
const frontmatter = content.split('---')[1] || '';
|
|
|
|
assert.ok(!frontmatter.includes('skills:'),
|
|
'gsd-code-reviewer has skills: in frontmatter — breaks Gemini CLI');
|
|
});
|
|
|
|
test('gsd-code-fixer.md does not have skills: in frontmatter', () => {
|
|
const content = fs.readFileSync(path.join(AGENTS_DIR, 'gsd-code-fixer.md'), 'utf-8');
|
|
const frontmatter = content.split('---')[1] || '';
|
|
|
|
assert.ok(!frontmatter.includes('skills:'),
|
|
'gsd-code-fixer has skills: in frontmatter — breaks Gemini CLI');
|
|
});
|
|
|
|
test('gsd-code-fixer.md rollback uses git checkout (not Write tool)', () => {
|
|
const content = fs.readFileSync(path.join(AGENTS_DIR, 'gsd-code-fixer.md'), 'utf-8');
|
|
assert.ok(content.includes('git checkout --'),
|
|
'gsd-code-fixer rollback should use git checkout -- {file} for atomic rollback');
|
|
assert.ok(!content.includes('PRE_FIX_CONTENT'),
|
|
'gsd-code-fixer should not use PRE_FIX_CONTENT in-memory capture (use git checkout instead)');
|
|
});
|
|
|
|
test('gsd-code-fixer.md success_criteria consistent with rollback strategy (git checkout)', () => {
|
|
const content = fs.readFileSync(path.join(AGENTS_DIR, 'gsd-code-fixer.md'), 'utf-8');
|
|
const successCriteria = content.match(/<success_criteria>([\s\S]*?)<\/success_criteria>/)?.[1] || '';
|
|
assert.ok(successCriteria.includes('git checkout'),
|
|
'gsd-code-fixer success_criteria must reference git checkout rollback');
|
|
assert.ok(!successCriteria.includes('Write tool with captured'),
|
|
'gsd-code-fixer success_criteria must not say Write tool for rollback');
|
|
});
|
|
|
|
test('gsd-code-fixer.md flags logic-bug fixes for human review', () => {
|
|
const content = fs.readFileSync(path.join(AGENTS_DIR, 'gsd-code-fixer.md'), 'utf-8');
|
|
assert.ok(content.includes('requires human verification'),
|
|
'gsd-code-fixer should flag logic-bug fixes as requiring human verification');
|
|
});
|
|
|
|
test('gsd-code-reviewer.md REVIEW.md spec includes files_reviewed_list field', () => {
|
|
const content = fs.readFileSync(path.join(AGENTS_DIR, 'gsd-code-reviewer.md'), 'utf-8');
|
|
assert.ok(content.includes('files_reviewed_list'),
|
|
'gsd-code-reviewer REVIEW.md frontmatter spec must include files_reviewed_list for --auto scope persistence');
|
|
});
|
|
});
|
|
|
|
// --- CR-CMD: code review command structure ---
|
|
|
|
describe('CR-CMD: code review command structure', () => {
|
|
test('code-review.md has correct frontmatter name: gsd:code-review', () => {
|
|
const content = fs.readFileSync(path.join(COMMANDS_DIR, 'code-review.md'), 'utf-8');
|
|
const frontmatter = content.split('---')[1] || '';
|
|
|
|
assert.ok(frontmatter.includes('name: gsd:code-review'),
|
|
'code-review.md missing correct name in frontmatter');
|
|
});
|
|
|
|
test('code-review-fix.md has correct frontmatter name: gsd:code-review-fix', () => {
|
|
const content = fs.readFileSync(path.join(COMMANDS_DIR, 'code-review-fix.md'), 'utf-8');
|
|
const frontmatter = content.split('---')[1] || '';
|
|
|
|
assert.ok(frontmatter.includes('name: gsd:code-review-fix'),
|
|
'code-review-fix.md missing correct name in frontmatter');
|
|
});
|
|
|
|
test('code-review.md references workflow: code-review.md', () => {
|
|
const content = fs.readFileSync(path.join(COMMANDS_DIR, 'code-review.md'), 'utf-8');
|
|
|
|
assert.ok(content.includes('code-review.md'),
|
|
'code-review.md does not reference its workflow');
|
|
});
|
|
|
|
test('code-review-fix.md references workflow: code-review-fix.md', () => {
|
|
const content = fs.readFileSync(path.join(COMMANDS_DIR, 'code-review-fix.md'), 'utf-8');
|
|
|
|
assert.ok(content.includes('code-review-fix.md'),
|
|
'code-review-fix.md does not reference its workflow');
|
|
});
|
|
|
|
test('code-review.md has argument-hint in frontmatter', () => {
|
|
const content = fs.readFileSync(path.join(COMMANDS_DIR, 'code-review.md'), 'utf-8');
|
|
const frontmatter = content.split('---')[1] || '';
|
|
|
|
assert.ok(frontmatter.includes('argument-hint:'),
|
|
'code-review.md missing argument-hint');
|
|
});
|
|
|
|
test('code-review-fix.md has argument-hint in frontmatter', () => {
|
|
const content = fs.readFileSync(path.join(COMMANDS_DIR, 'code-review-fix.md'), 'utf-8');
|
|
const frontmatter = content.split('---')[1] || '';
|
|
|
|
assert.ok(frontmatter.includes('argument-hint:'),
|
|
'code-review-fix.md missing argument-hint');
|
|
});
|
|
|
|
test('code-review.md has allowed-tools in frontmatter', () => {
|
|
const content = fs.readFileSync(path.join(COMMANDS_DIR, 'code-review.md'), 'utf-8');
|
|
const frontmatter = content.split('---')[1] || '';
|
|
|
|
assert.ok(frontmatter.includes('allowed-tools:'),
|
|
'code-review.md missing allowed-tools');
|
|
});
|
|
|
|
test('code-review-fix.md has allowed-tools in frontmatter', () => {
|
|
const content = fs.readFileSync(path.join(COMMANDS_DIR, 'code-review-fix.md'), 'utf-8');
|
|
const frontmatter = content.split('---')[1] || '';
|
|
|
|
assert.ok(frontmatter.includes('allowed-tools:'),
|
|
'code-review-fix.md missing allowed-tools');
|
|
});
|
|
});
|
|
|
|
// --- CR-WORKFLOW: code review workflow structure ---
|
|
|
|
describe('CR-WORKFLOW: code review workflow structure', () => {
|
|
test('code-review.md workflow has <step name="initialize">', () => {
|
|
const content = fs.readFileSync(path.join(WORKFLOWS_DIR, 'code-review.md'), 'utf-8');
|
|
|
|
assert.ok(content.includes('<step name="initialize">'),
|
|
'code-review.md workflow missing initialize step');
|
|
});
|
|
|
|
test('code-review.md workflow has <step name="check_config_gate">', () => {
|
|
const content = fs.readFileSync(path.join(WORKFLOWS_DIR, 'code-review.md'), 'utf-8');
|
|
|
|
assert.ok(content.includes('<step name="check_config_gate">'),
|
|
'code-review.md workflow missing check_config_gate step');
|
|
});
|
|
|
|
test('code-review.md workflow references gsd-code-reviewer agent', () => {
|
|
const content = fs.readFileSync(path.join(WORKFLOWS_DIR, 'code-review.md'), 'utf-8');
|
|
|
|
assert.ok(content.includes('gsd-code-reviewer'),
|
|
'code-review.md workflow does not reference gsd-code-reviewer agent');
|
|
});
|
|
|
|
test('code-review-fix.md workflow has <step name="initialize">', () => {
|
|
const content = fs.readFileSync(path.join(WORKFLOWS_DIR, 'code-review-fix.md'), 'utf-8');
|
|
|
|
assert.ok(content.includes('<step name="initialize">'),
|
|
'code-review-fix.md workflow missing initialize step');
|
|
});
|
|
|
|
test('code-review-fix.md workflow references gsd-code-fixer agent', () => {
|
|
const content = fs.readFileSync(path.join(WORKFLOWS_DIR, 'code-review-fix.md'), 'utf-8');
|
|
|
|
assert.ok(content.includes('gsd-code-fixer'),
|
|
'code-review-fix.md workflow does not reference gsd-code-fixer agent');
|
|
});
|
|
|
|
test('code-review-fix.md workflow has iteration cap', () => {
|
|
const content = fs.readFileSync(path.join(WORKFLOWS_DIR, 'code-review-fix.md'), 'utf-8');
|
|
|
|
// Check for iteration logic with cap
|
|
assert.ok(content.includes('MAX_ITERATIONS') || (content.includes('3') && content.includes('iteration')),
|
|
'code-review-fix.md workflow missing iteration cap logic');
|
|
});
|
|
|
|
test('code-review.md --files path traversal guard rejects paths outside repo', () => {
|
|
const content = fs.readFileSync(path.join(WORKFLOWS_DIR, 'code-review.md'), 'utf-8');
|
|
// Guard must resolve and compare against REPO_ROOT
|
|
assert.ok(content.includes('REPO_ROOT') && content.includes('realpath'),
|
|
'code-review.md missing path traversal guard (realpath + REPO_ROOT check)');
|
|
assert.ok(content.includes('File path outside repository'),
|
|
'code-review.md missing rejection message for paths outside repo');
|
|
});
|
|
|
|
test('code-review.md uses portable while-read loop for array dedup (not mapfile)', () => {
|
|
const content = fs.readFileSync(path.join(WORKFLOWS_DIR, 'code-review.md'), 'utf-8');
|
|
// mapfile is bash 4+ only; macOS ships bash 3.2. Dedup must use portable while-read.
|
|
// Note: 'mapfile' may appear in platform_notes documentation — check bash code blocks only
|
|
const codeBlocks = content.match(/```bash[\s\S]*?```/g) || [];
|
|
const hasMapfileInCode = codeBlocks.some(block => block.includes('mapfile -t'));
|
|
assert.ok(!hasMapfileInCode,
|
|
'code-review.md bash code blocks use mapfile which is bash 4+ only — breaks macOS default bash 3.2');
|
|
assert.ok(content.includes('while IFS= read -r'),
|
|
'code-review.md should use portable while-read loop instead of mapfile');
|
|
});
|
|
|
|
test('code-review-fix.md uses portable while-read loop for array construction (not mapfile)', () => {
|
|
const content = fs.readFileSync(path.join(WORKFLOWS_DIR, 'code-review-fix.md'), 'utf-8');
|
|
const codeBlocks = content.match(/```bash[\s\S]*?```/g) || [];
|
|
const hasMapfileInCode = codeBlocks.some(block => block.includes('mapfile -t'));
|
|
assert.ok(!hasMapfileInCode,
|
|
'code-review-fix.md bash code blocks use mapfile which is bash 4+ only — breaks macOS default bash 3.2');
|
|
assert.ok(content.includes('while IFS= read -r'),
|
|
'code-review-fix.md should use portable while-read loop instead of mapfile');
|
|
});
|
|
});
|
|
|
|
// --- CR-CONFIG: config key registration ---
|
|
|
|
describe('CR-CONFIG: config key registration', () => {
|
|
test('config.cjs contains workflow.code_review key', () => {
|
|
const content = fs.readFileSync(CONFIG_PATH, 'utf-8');
|
|
|
|
assert.ok(content.includes('workflow.code_review'),
|
|
'config.cjs missing workflow.code_review key registration');
|
|
});
|
|
|
|
test('config.cjs contains workflow.code_review_depth key', () => {
|
|
const content = fs.readFileSync(CONFIG_PATH, 'utf-8');
|
|
|
|
assert.ok(content.includes('workflow.code_review_depth'),
|
|
'config.cjs missing workflow.code_review_depth key registration');
|
|
});
|
|
|
|
test('gsd-tools config-get workflow.code_review succeeds', () => {
|
|
const tmpDir = createTempProject();
|
|
|
|
try {
|
|
// Initialize config with code_review key
|
|
const configPath = path.join(tmpDir, '.planning', 'config.json');
|
|
fs.writeFileSync(configPath, JSON.stringify({
|
|
workflow: {
|
|
code_review: true,
|
|
code_review_depth: 'standard'
|
|
}
|
|
}, null, 2), 'utf-8');
|
|
|
|
const result = runGsdTools(['config-get', 'workflow.code_review'], tmpDir);
|
|
|
|
assert.ok(result.success,
|
|
'config-get workflow.code_review failed — key not recognized');
|
|
assert.strictEqual(result.output, 'true',
|
|
'workflow.code_review should return "true"');
|
|
} finally {
|
|
cleanup(tmpDir);
|
|
}
|
|
});
|
|
|
|
test('gsd-tools config-get workflow.code_review_depth succeeds', () => {
|
|
const tmpDir = createTempProject();
|
|
|
|
try {
|
|
// Initialize config with code_review_depth key
|
|
const configPath = path.join(tmpDir, '.planning', 'config.json');
|
|
fs.writeFileSync(configPath, JSON.stringify({
|
|
workflow: {
|
|
code_review: true,
|
|
code_review_depth: 'standard'
|
|
}
|
|
}, null, 2), 'utf-8');
|
|
|
|
const result = runGsdTools(['config-get', 'workflow.code_review_depth'], tmpDir);
|
|
|
|
assert.ok(result.success,
|
|
'config-get workflow.code_review_depth failed — key not recognized');
|
|
// Output may include quotes from JSON serialization
|
|
assert.ok(result.output === 'standard' || result.output === '"standard"',
|
|
`workflow.code_review_depth should return "standard", got ${result.output}`);
|
|
} finally {
|
|
cleanup(tmpDir);
|
|
}
|
|
});
|
|
});
|
|
|
|
// --- CR-INTEGRATION: workflow integration points ---
|
|
|
|
describe('CR-INTEGRATION: workflow integration points', () => {
|
|
test('execute-phase.md contains code_review_gate step', { skip: !PLUGIN_AVAILABLE ? 'Plugin dir not installed' : false }, () => {
|
|
const content = fs.readFileSync(path.join(PLUGIN_WORKFLOWS_DIR, 'execute-phase.md'), 'utf-8');
|
|
|
|
assert.ok(content.includes('code_review_gate'),
|
|
'execute-phase.md missing code_review_gate step name');
|
|
});
|
|
|
|
test('execute-phase.md contains config-get workflow.code_review', { skip: !PLUGIN_AVAILABLE ? 'Plugin dir not installed' : false }, () => {
|
|
const content = fs.readFileSync(path.join(PLUGIN_WORKFLOWS_DIR, 'execute-phase.md'), 'utf-8');
|
|
|
|
assert.match(content, /config-get\s+workflow\.code_review/,
|
|
'execute-phase.md missing config-get workflow.code_review call');
|
|
});
|
|
|
|
test('execute-phase.md does NOT contain ls.*REVIEW.md.*head pattern', { skip: !PLUGIN_AVAILABLE ? 'Plugin dir not installed' : false }, () => {
|
|
const content = fs.readFileSync(path.join(PLUGIN_WORKFLOWS_DIR, 'execute-phase.md'), 'utf-8');
|
|
|
|
// Extract code_review_gate section to check
|
|
const gateMatch = content.match(/<step name="code_review_gate">([\s\S]*?)<\/step>/);
|
|
if (gateMatch) {
|
|
const gateContent = gateMatch[1];
|
|
assert.ok(!gateContent.match(/ls.*REVIEW\.md.*head/),
|
|
'execute-phase.md code_review_gate uses non-deterministic glob pattern (ls | head)');
|
|
}
|
|
});
|
|
|
|
test('quick.md contains code-review invocation', { skip: !PLUGIN_AVAILABLE ? 'Plugin dir not installed' : false }, () => {
|
|
const content = fs.readFileSync(path.join(PLUGIN_WORKFLOWS_DIR, 'quick.md'), 'utf-8');
|
|
|
|
assert.ok(content.includes('code-review') || content.includes('code_review'),
|
|
'quick.md missing code-review invocation');
|
|
});
|
|
|
|
test('quick.md contains config-get workflow.code_review', { skip: !PLUGIN_AVAILABLE ? 'Plugin dir not installed' : false }, () => {
|
|
const content = fs.readFileSync(path.join(PLUGIN_WORKFLOWS_DIR, 'quick.md'), 'utf-8');
|
|
|
|
assert.match(content, /config-get\s+workflow\.code_review/,
|
|
'quick.md missing config-get workflow.code_review call');
|
|
});
|
|
|
|
test('autonomous.md contains gsd:code-review skill invocation', { skip: !PLUGIN_AVAILABLE ? 'Plugin dir not installed' : false }, () => {
|
|
const content = fs.readFileSync(path.join(PLUGIN_WORKFLOWS_DIR, 'autonomous.md'), 'utf-8');
|
|
|
|
assert.ok(content.includes('gsd:code-review'),
|
|
'autonomous.md missing gsd:code-review skill invocation');
|
|
});
|
|
|
|
test('autonomous.md contains gsd:code-review-fix skill invocation', { skip: !PLUGIN_AVAILABLE ? 'Plugin dir not installed' : false }, () => {
|
|
const content = fs.readFileSync(path.join(PLUGIN_WORKFLOWS_DIR, 'autonomous.md'), 'utf-8');
|
|
|
|
assert.ok(content.includes('gsd:code-review-fix'),
|
|
'autonomous.md missing gsd:code-review-fix skill invocation');
|
|
});
|
|
|
|
test('autonomous.md contains --auto flag for code-review-fix', { skip: !PLUGIN_AVAILABLE ? 'Plugin dir not installed' : false }, () => {
|
|
const content = fs.readFileSync(path.join(PLUGIN_WORKFLOWS_DIR, 'autonomous.md'), 'utf-8');
|
|
|
|
assert.ok(content.includes('--auto'),
|
|
'autonomous.md missing --auto flag for code-review-fix iteration');
|
|
});
|
|
});
|