OpenWriterControle/.github/workflows/pr-checks.yml
Darren Hinde 784ffadf92
chore: verify and stabilize main branch (#42)
* chore: update package-lock.json after npm install

* chore: remove unused ajv-cli, keep vitest at stable 1.6.1

- Removed ajv-cli (unused dev dependency, had high severity vulnerability)
- Kept vitest at 1.6.1 (stable, upgrading to v4 requires extensive refactoring)
- Reduced vulnerabilities from 6 to 4 (all moderate, dev-only)
- All remaining vulnerabilities are in esbuild/vite (dev server only, no production impact)
- Build and tests verified working

* feat(evals): add execution-balance validation to 21 OpenAgent tests and enhance agent system

Major improvements to evaluation framework and agent capabilities:

## Execution Balance Evaluator Integration
- Added execution-balance rule to 21 OpenAgent tests (2.7% → 31.5% coverage)
- Validates "read before execute" pattern across critical rules, workflows, and edge cases
- Tests now check: read operations before execution tools, healthy read/exec ratio (≥1.0)
- Coverage includes: approval-gate, context-loading, stop-on-failure, report-first tests

## Agent System Enhancements
- Enhanced OpenCoder agent with critical rules enforcement (approval gates, context loading)
- Added structured delegation rules and workflow phases
- Improved error handling with REPORT→PROPOSE→REQUEST→FIX pattern

## New Agent Creation System
- Added research-backed agent creation templates and guides
- Includes 8 test templates covering planning, context, incremental execution, tools
- Automated agent scaffolding with /create-agent command
- Complete documentation in .opencode/command/openagents/new-agents/

## OpenCoder Test Suite
- Added 8 comprehensive test cases for OpenCoder agent
- Tests cover: planning, context-loading, delegation, error-handling, implementation
- Includes DEBUG_GUIDE.md and QUICK_TEST_GUIDE.md for developers

## Documentation & Tooling
- Added DEVELOPMENT.md guide for contributors
- Enhanced CONTRIBUTING.md with quick reference and common commands
- Improved event-logger with DEBUG_VERBOSE mode for detailed output
- Added debug scripts: show-test-conversation.sh, run-test-verbose.sh
- Removed deprecated EXTERNAL_PR_GUIDE.md

## Version Bump
- Bumped version to 0.0.3 (patch)

Files changed: 60+ files (21 test updates, 16 new agent templates, 8 new tests, docs, tooling)

* feat(ci): add PR title validation for semantic versioning

Add automated PR title validation to ensure conventional commit format.
This enables proper automatic version bumping when PRs are merged.

Features:
- Validates PR titles against conventional commit patterns
- Shows expected version bump (major/minor/patch)
- Posts helpful comment with examples if validation fails
- Supports all conventional commit types (feat, fix, docs, etc.)
- Supports breaking changes (feat!, fix!)
- Supports pre-release tags ([alpha], [beta], [rc])

When PR titles follow the format, version bumping works correctly:
- feat: → minor bump (0.3.0 → 0.4.0)
- fix: → patch bump (0.3.0 → 0.3.1)
- feat!: → major bump (0.3.0 → 1.0.0)

* fix(ci): improve PR checks workflow with sequential execution

Reorganize PR checks to run in logical sequence and skip unnecessary checks:

Changes:
- Run PR title validation first (fast, always required)
- Detect changed files to determine which checks to run
- Only run build checks if evals/ files changed
- Add comprehensive summary job showing all check results
- Prevent cache errors when evals files not changed

Benefits:
- Faster PR checks (skip unnecessary builds)
- Clear sequential execution (title → changes → build)
- Better error messages and summaries
- Reduced CI/CD costs

* fix(ci): resolve PR #42 issues and refactor prompt architecture

## Fixed PR #42 Issues

1. **Prompt Validation** - Refactored to new architecture where agent files are canonical defaults
2. **Package-lock.json** - Fixed workflow to use root package-lock (npm workspaces)
3. **Git Merge Base** - Added fetch-depth: 0 to PR checks workflow

## New Prompt Architecture

**Before:**
- Agent files had to match .opencode/prompts/<agent>/default.md
- Caused validation failures when updating prompts
- Redundant duplication

**After:**
- Agent files (.opencode/agent/*.md) = Canonical defaults (source of truth)
- Prompt variants (.opencode/prompts/<agent>/<model>.md) = Model-specific optimizations
- No more default.md files needed

## Changes

### Workflows
- pr-checks.yml: Added fetch-depth: 0 for full git history
- validate-test-suites.yml: Fixed package-lock path for npm workspaces
- validate-registry.yml: Updated validation messaging

### Scripts
- validate-pr.sh: Validates prompt library structure (rejects default.md files)
- use-prompt.sh: Handles 'default' as agent file, variants as model-specific
- test-prompt.sh: Tests default variant correctly, saves results to prompts/results/

### Documentation
- .opencode/prompts/README.md: Updated architecture explanation
- docs/contributing/CONTRIBUTING.md: Updated prompt workflow
- scripts/development/demo.sh: Updated structure display

## Results

- 12 files changed, 231 insertions(+), 811 deletions(-)
- Net reduction: 580 lines (cleaner codebase)
- All validations passing
- Results directory structure preserved
- Backwards compatible with existing test results
2025-12-09 13:26:52 +00:00

323 lines
12 KiB
YAML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

name: PR Checks
on:
pull_request:
branches: [main, dev]
types: [opened, edited, synchronize, reopened]
jobs:
pr-title-check:
name: Validate PR Title
runs-on: ubuntu-latest
outputs:
title-valid: ${{ steps.validate.outputs.valid }}
steps:
- name: Check PR title format
id: validate
uses: actions/github-script@v7
with:
script: |
const prTitle = context.payload.pull_request.title;
// Conventional commit patterns
const patterns = {
feat: /^feat(\(.+\))?!?:\s.+/,
fix: /^fix(\(.+\))?!?:\s.+/,
docs: /^docs(\(.+\))?:\s.+/,
style: /^style(\(.+\))?:\s.+/,
refactor: /^refactor(\(.+\))?:\s.+/,
perf: /^perf(\(.+\))?:\s.+/,
test: /^test(\(.+\))?:\s.+/,
chore: /^chore(\(.+\))?:\s.+/,
ci: /^ci(\(.+\))?:\s.+/,
build: /^build(\(.+\))?:\s.+/,
revert: /^revert(\(.+\))?:\s.+/,
alpha: /^\[alpha\]\s.+/,
beta: /^\[beta\]\s.+/,
rc: /^\[rc\]\s.+/
};
// Check if title matches any pattern
const matchedType = Object.entries(patterns).find(([type, pattern]) =>
pattern.test(prTitle)
);
if (!matchedType) {
const validExamples = [
'✅ feat(evals): add new evaluator',
'✅ fix(agents): correct delegation logic',
'✅ docs(readme): update installation guide',
'✅ test(evals): add execution-balance tests',
'✅ chore(deps): update dependencies',
'✅ feat!: breaking API change',
'✅ [alpha] experimental feature'
];
const message = `
## ❌ Invalid PR Title Format
**Current title:** \`${prTitle}\`
### Required Format
PR titles must follow [Conventional Commits](https://www.conventionalcommits.org/) format:
\`\`\`
<type>(<scope>): <description>
\`\`\`
### Valid Types
- **feat** - New feature (triggers minor version bump: 0.3.0 → 0.4.0)
- **fix** - Bug fix (triggers patch version bump: 0.3.0 → 0.3.1)
- **docs** - Documentation changes (triggers patch bump)
- **test** - Test additions/changes (triggers patch bump)
- **refactor** - Code refactoring (triggers patch bump)
- **chore** - Maintenance tasks (triggers patch bump)
- **ci** - CI/CD changes (triggers patch bump)
- **perf** - Performance improvements (triggers patch bump)
- **style** - Code style changes (triggers patch bump)
- **build** - Build system changes (triggers patch bump)
- **revert** - Revert previous commit (triggers patch bump)
### Breaking Changes
- **feat!:** or **fix!:** - Breaking change (triggers major version bump: 0.3.0 → 1.0.0)
- **BREAKING CHANGE:** in description
### Pre-release Tags
- **[alpha]** - Alpha release (0.3.0 → 0.3.1-alpha.1)
- **[beta]** - Beta release (0.3.0 → 0.3.1-beta.1)
- **[rc]** - Release candidate (0.3.0 → 0.3.1-rc.1)
### Valid Examples
${validExamples.map(ex => `- ${ex}`).join('\n')}
### Why This Matters
- ✅ Enables automatic semantic versioning
- ✅ Generates meaningful changelogs
- ✅ Makes commit history searchable
- ✅ Clarifies the impact of changes
### How to Fix
Edit your PR title to match the format above.
`;
core.setFailed(message);
// Also post as a comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: message
});
} else {
const [type] = matchedType;
let versionBump = 'patch (0.3.0 → 0.3.1)';
if (type === 'feat' && prTitle.includes('!')) {
versionBump = 'major (0.3.0 → 1.0.0) - BREAKING CHANGE';
} else if (type === 'feat') {
versionBump = 'minor (0.3.0 → 0.4.0)';
} else if (type === 'fix' && prTitle.includes('!')) {
versionBump = 'major (0.3.0 → 1.0.0) - BREAKING CHANGE';
} else if (type === 'alpha') {
versionBump = 'alpha (0.3.0 → 0.3.1-alpha.1)';
} else if (type === 'beta') {
versionBump = 'beta (0.3.0 → 0.3.1-beta.1)';
} else if (type === 'rc') {
versionBump = 'rc (0.3.0 → 0.3.1-rc.1)';
}
const message = `
## ✅ PR Title Valid
**Title:** \`${prTitle}\`
**Type:** \`${type}\`
**Version bump:** ${versionBump}
When this PR is merged using **"Squash and Merge"**, the version will be automatically bumped.
`;
core.info(message);
// Set output for summary
core.summary
.addHeading('✅ PR Title Validation Passed', 2)
.addRaw(`**Title:** \`${prTitle}\``)
.addBreak()
.addRaw(`**Type:** \`${type}\``)
.addBreak()
.addRaw(`**Version bump:** ${versionBump}`)
.write();
// Set output for dependent jobs
core.setOutput('valid', 'true');
}
check-changes:
name: Detect Changed Files
runs-on: ubuntu-latest
needs: pr-title-check
if: needs.pr-title-check.outputs.title-valid == 'true'
outputs:
has-evals: ${{ steps.filter.outputs.evals }}
has-docs: ${{ steps.filter.outputs.docs }}
has-workflows: ${{ steps.filter.outputs.workflows }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check changed files
id: filter
run: |
# Get list of changed files
git fetch origin ${{ github.base_ref }}
CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)
echo "Changed files:"
echo "$CHANGED_FILES"
# Check for evals changes
if echo "$CHANGED_FILES" | grep -q "^evals/"; then
echo "has-evals=true" >> $GITHUB_OUTPUT
echo "✅ Evals changes detected"
else
echo "has-evals=false" >> $GITHUB_OUTPUT
echo "ℹ️ No evals changes"
fi
# Check for docs changes
if echo "$CHANGED_FILES" | grep -q "^docs/"; then
echo "has-docs=true" >> $GITHUB_OUTPUT
echo "✅ Docs changes detected"
else
echo "has-docs=false" >> $GITHUB_OUTPUT
echo "ℹ️ No docs changes"
fi
# Check for workflow changes
if echo "$CHANGED_FILES" | grep -q "^.github/workflows/"; then
echo "has-workflows=true" >> $GITHUB_OUTPUT
echo "✅ Workflow changes detected"
else
echo "has-workflows=false" >> $GITHUB_OUTPUT
echo "ℹ️ No workflow changes"
fi
build-check:
name: Build & Validate
runs-on: ubuntu-latest
timeout-minutes: 5
needs: [pr-title-check, check-changes]
if: |
needs.pr-title-check.outputs.title-valid == 'true' &&
needs.check-changes.outputs.has-evals == 'true'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: 'evals/framework/package-lock.json'
- name: Install dependencies
working-directory: evals/framework
run: npm ci
- name: Build framework
working-directory: evals/framework
run: npm run build
- name: Validate test suites
working-directory: evals/framework
run: npm run validate:suites:all
- name: Summary
if: success()
run: |
echo "## ✅ Build Check Passed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- ✅ TypeScript compilation successful" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Test suite validation passed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Note:** Full agent tests are not run on PRs to save time and costs." >> $GITHUB_STEP_SUMMARY
echo "Maintainers can run \`npm run test:ci\` locally if needed." >> $GITHUB_STEP_SUMMARY
- name: Failure summary
if: failure()
run: |
echo "## ❌ Build Check Failed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Please check the logs above for details." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Common fixes:**" >> $GITHUB_STEP_SUMMARY
echo "- TypeScript errors: Fix type issues in \`evals/framework/src/\`" >> $GITHUB_STEP_SUMMARY
echo "- YAML validation: Check test files in \`evals/agents/*/tests/\`" >> $GITHUB_STEP_SUMMARY
summary:
name: PR Checks Summary
runs-on: ubuntu-latest
needs: [pr-title-check, check-changes, build-check]
if: always()
steps:
- name: Generate summary
run: |
echo "## 📊 PR Checks Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# PR Title Check
if [ "${{ needs.pr-title-check.result }}" == "success" ]; then
echo "✅ **PR Title:** Valid conventional commit format" >> $GITHUB_STEP_SUMMARY
else
echo "❌ **PR Title:** Invalid format - please fix" >> $GITHUB_STEP_SUMMARY
fi
# Changed Files Detection
if [ "${{ needs.check-changes.result }}" == "success" ]; then
echo "✅ **Changed Files:** Detected successfully" >> $GITHUB_STEP_SUMMARY
if [ "${{ needs.check-changes.outputs.has-evals }}" == "true" ]; then
echo " - 📦 Evals changes detected" >> $GITHUB_STEP_SUMMARY
fi
if [ "${{ needs.check-changes.outputs.has-docs }}" == "true" ]; then
echo " - 📚 Docs changes detected" >> $GITHUB_STEP_SUMMARY
fi
if [ "${{ needs.check-changes.outputs.has-workflows }}" == "true" ]; then
echo " - ⚙️ Workflow changes detected" >> $GITHUB_STEP_SUMMARY
fi
else
echo "⏭️ **Changed Files:** Skipped (title validation failed)" >> $GITHUB_STEP_SUMMARY
fi
# Build Check
if [ "${{ needs.build-check.result }}" == "success" ]; then
echo "✅ **Build & Validate:** Passed" >> $GITHUB_STEP_SUMMARY
elif [ "${{ needs.build-check.result }}" == "skipped" ]; then
echo "⏭️ **Build & Validate:** Skipped (no evals changes)" >> $GITHUB_STEP_SUMMARY
elif [ "${{ needs.build-check.result }}" == "failure" ]; then
echo "❌ **Build & Validate:** Failed - check logs" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
# Overall status
if [ "${{ needs.pr-title-check.result }}" == "success" ] && \
([ "${{ needs.build-check.result }}" == "success" ] || [ "${{ needs.build-check.result }}" == "skipped" ]); then
echo "### ✅ All Required Checks Passed!" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "This PR is ready for review." >> $GITHUB_STEP_SUMMARY
else
echo "### ❌ Some Checks Failed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Please fix the failing checks before merging." >> $GITHUB_STEP_SUMMARY
fi