Skip to content

Docs validation (agent) #11

Docs validation (agent)

Docs validation (agent) #11

name: Docs validation (agent)
on:
workflow_dispatch:
inputs:
section:
description: 'API section to validate'
required: true
type: choice
options:
- 'Configuration'
- 'Controller'
- 'Global Helpers'
- 'Migrator'
- 'Model Class'
- 'Model Configuration'
- 'Model Object'
- 'View Helpers'
limit:
description: 'Max functions to validate this run (blank = all pending)'
required: false
type: string
default: ''
model:
description: 'Anthropic model id'
required: false
type: string
default: 'claude-sonnet-4-6'
dry_run:
description: 'List targets without invoking the agent'
required: false
type: boolean
default: false
force:
description: 'Re-run already-done functions (overwrites their state.json entries)'
required: false
type: boolean
default: false
permissions:
contents: write
pull-requests: write
concurrency:
group: docs-validation-${{ inputs.section }}
cancel-in-progress: false
jobs:
validate:
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- name: Checkout dispatching ref
# We check out the ref this workflow was dispatched against (typically
# `develop` once merged, but a feature branch during initial testing).
# The agent's edits land in a per-run branch derived from this ref;
# the resulting PR always targets `develop`.
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: 22
- name: Install tools/docs-validation deps
working-directory: tools/docs-validation
run: npm ci --no-audit --no-fund
- name: Set up Linuxbrew
uses: Homebrew/actions/setup-homebrew@master
- name: Install Wheels CLI
run: |
brew tap wheels-dev/wheels || true
brew install wheels
- name: Patch wheels wrapper JAVA_HOME for Linux
run: |
WRAPPER="$(brew --prefix wheels)/bin/wheels"
sed -i 's|/openjdk.jdk/Contents/Home||g' "$WRAPPER"
grep JAVA_HOME "$WRAPPER"
- name: Warm up wheels module
run: wheels --version >/dev/null
- name: Compute branch name
id: branch
run: |
slug=$(echo "${{ inputs.section }}" | tr '[:upper:] ' '[:lower:]-')
echo "name=docs-validation/${slug}-${{ github.run_id }}" >> "$GITHUB_OUTPUT"
- name: Configure git
run: |
git config user.name "wheels-docs-validator[bot]"
git config user.email "wheels-docs-validator@users.noreply.github.com"
git checkout -b "${{ steps.branch.outputs.name }}"
- name: List targets (dry-run)
if: ${{ inputs.dry_run }}
working-directory: tools/docs-validation
run: |
ARGS=(--section "${{ inputs.section }}" --dry-run)
if [[ -n "${{ inputs.limit }}" ]]; then
ARGS+=(--limit "${{ inputs.limit }}")
fi
if [[ "${{ inputs.force }}" == "true" ]]; then
ARGS+=(--force)
fi
node orchestrate.mjs "${ARGS[@]}"
- name: Run agent
if: ${{ !inputs.dry_run }}
working-directory: tools/docs-validation
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
WHEELS_DOCS_MODEL: ${{ inputs.model }}
WHEELS_DOCS_MAX_TURNS: '24'
LUCLI_HOME: ${{ runner.temp }}/.wheels
run: |
ARGS=(--section "${{ inputs.section }}")
if [[ -n "${{ inputs.limit }}" ]]; then
ARGS+=(--limit "${{ inputs.limit }}")
fi
if [[ "${{ inputs.force }}" == "true" ]]; then
ARGS+=(--force)
fi
node orchestrate.mjs "${ARGS[@]}"
- name: Show diff
if: ${{ !inputs.dry_run }}
run: |
git status
git --no-pager diff --stat
echo "---"
git --no-pager diff | head -500 || true
- name: Commit + push if changes
if: ${{ !inputs.dry_run }}
id: commit
run: |
if git diff --quiet && git diff --cached --quiet; then
echo "No changes produced by the agent."
echo "changed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
git add -A
MSG="docs(api): validate ${{ inputs.section }} section (run ${{ github.run_id }})"
git commit -m "$MSG"
git push -u origin "${{ steps.branch.outputs.name }}"
echo "changed=true" >> "$GITHUB_OUTPUT"
- name: Open draft PR
if: ${{ !inputs.dry_run && steps.commit.outputs.changed == 'true' }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
BODY=$(cat <<'EOF'
## Summary
Agent-driven docs validation for the **${{ inputs.section }}** section.
- Snapshot: `docs/api/v4.0.0.json`
- Edits scoped to: `vendor/wheels/**/*.cfc` (docblocks + narrow body fixes) and `vendor/wheels/public/docs/reference/{scope}/{name}.txt`
- Per-function status tracked in `tools/docs-validation/state.json`
## Review checklist
- [ ] Each `state.json` entry with `status: done` has a sensible reference example file added or updated
- [ ] No CFC function signature changes (agent is forbidden from changing them — verify anyway)
- [ ] Any docblock/body edits hold up against the test suite
- [ ] `state.json` items with `status: needs_human` describe the open question in `notes`
EOF
)
gh pr create \
--base develop \
--head "${{ steps.branch.outputs.name }}" \
--title "docs(api): validate ${{ inputs.section }} section" \
--body "$BODY" \
--draft
- name: Upload state artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: docs-validation-state-${{ github.run_id }}
path: tools/docs-validation/state.json
if-no-files-found: ignore