.agents/skills/ai-submit-work/SKILL.md
Run all status checks locally, fix issues, commit, push, and create an automerge PR. Use when work is ready to submit, or saying 'submit my work' or 'I'm done'.
npx skillsauth add svange/tagmania ai-submit-workInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Run all status checks, fix issues, commit, push, and create an automerge PR: $ARGUMENTS
Workflow automation: This skill is part of an automated workflow. Auto-commit with generated messages (do NOT ask Accept/Edit/Abort). Auto-rebase when behind target. Auto-resolve mechanical rebase conflicts (version files, changelogs, lock files -- target branch wins). Auto-fix formatting AND diagnostic pre-commit failures (mypy, uv-lock-check). Auto-fix patch-level security bumps. Auto-stage known project files. Auto-transition to pipeline monitoring after PR creation. Only stop and ask the user for: non-patch security bumps, license compliance issues, test failures, code-level rebase conflicts, and unrecognized untracked files.
Mirrors the CI pipeline locally to catch issues before pushing. Handles file staging, conventional commits, branch updates, and PR creation.
/ai-submit-work - Full submission (all checks)/ai-submit-work --no-tests - Skip test suite (pre-commit + security still run)/ai-submit-work --no-security - Skip security + license checks/ai-submit-work --no-tests --no-security - Pre-commit only (fastest)CURRENT_BRANCH=$(git branch --show-current)
Verify work branch:
main, master, dev, develop, or staging: ABORT with error "You're on $CURRENT_BRANCH. Create a work branch first with /ai-prepare-branch."Verify branch is current with target:
# Detect target branch -- canonical algorithm from CLAUDE.md
DEV_BRANCH=""
for candidate in dev develop staging; do
if git show-ref --verify --quiet refs/remotes/origin/$candidate; then
DEV_BRANCH=$candidate
break
fi
done
TARGET=${DEV_BRANCH:-$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' || echo "main")}
git fetch origin $TARGET
BEHIND=$(git rev-list --count HEAD..origin/$TARGET)
if [ "$BEHIND" -gt 0 ]; then
echo "WARNING: Your branch is $BEHIND commits behind $TARGET."
echo "This usually means /ai-prepare-branch was not run before starting work."
fi
If the branch is behind, automatically rebase:
git rebase origin/$TARGET
Report: "Rebased on $TARGET (was $BEHIND commits behind)." Do NOT ask the user to choose -- just rebase. If the rebase has conflicts, see the conflict resolution rules in Section 5.
Verify there are changes:
# Check for any changes (staged, unstaged, untracked)
if [ -z "$(git status --porcelain)" ]; then
echo "No changes to submit."
exit 0
fi
Show git status to the user.
For modified/deleted tracked files, stage them:
git add -u
For untracked files, use smart staging:
Auto-stage without asking (known project files):
.claude/, .agents/, .github/ directoriesCLAUDE.md, AGENTS.md, NOTES.mdsrc/, tests/ (matches project structure)Rely on .gitignore for blocking. Do not duplicate exclusion logic in the skill. If .env or other secret files appear as untracked, .gitignore is misconfigured -- suggest fixing it.
Batch-prompt remaining unknowns (if any) in a single table:
New files detected:
Auto-staged: .claude/skills/ai-status/SKILL.md, src/new_module.py, tests/test_new.py
Needs your decision:
1. notes.txt [Ignore?]
2. scratch/debug.py [Ignore?]
Accept defaults, or specify (e.g., "stage 1")?
If >20 untracked files need decisions, warn: "You have N untracked files. This usually means a directory is missing from .gitignore. Fix .gitignore first."
Zero prompts if all untracked files are auto-staged. One prompt if there are unknowns.
If no files are staged after this step, abort.
Parse $ARGUMENTS for skip flags:
--no-tests -> skip Phase D--no-security -> skip Phase B and CDetect: Check if .pre-commit-config.yaml exists.
Run (auto-fix loop, max 2 iterations):
# Iteration 1
uv run pre-commit run --all-files
# If uv not available, try: pre-commit run --all-files
# If exit code != 0 AND files were modified by hooks:
git diff --name-only # Check for auto-fixed files
# Re-stage fixed files and retry
git add -u
uv run pre-commit run --all-files
Auto-fix ALL hook failures (formatting AND diagnostic):
# type: ignore or Any as escape hatches. Fix the real types (missing return annotation, wrong parameter type, missing import, etc.). If the ONLY available fix requires # type: ignore or Any, then stop and ask the user.uv lock to regenerate the lock file. If uv lock fails (conflicting constraints, yanked package), stop and show the error.Circuit breaker: Max 2 iterations total. If the same failure repeats after a fix attempt, stop and show errors.
If pre-commit not available: Run individual linters if detected:
# Python
uv run ruff check --fix src/ tests/ && uv run ruff format src/ tests/
# JavaScript
npx eslint --fix . && npx prettier --write .
Detect and run available security tools:
# Bandit (Python security linter)
if python -c "import bandit" 2>/dev/null || uv run bandit --version 2>/dev/null; then
uv run bandit -r src/ -ll
fi
# pip-audit (dependency vulnerabilities)
if uv run pip-audit --version 2>/dev/null; then
uv export --no-dev --no-hashes -o /tmp/prod-requirements.txt
uv run pip-audit -r /tmp/prod-requirements.txt --no-deps
fi
# npm audit (JavaScript)
if [ -f "package-lock.json" ]; then
npm audit --production
fi
On failure -- auto-fix patch bumps, ask for larger changes:
uv add package==new_version then uv lock. Continue without asking.# Python
if uv run pip-licenses --version 2>/dev/null; then
uv run pip-licenses --from=mixed --summary
# Check for GPL/AGPL (excluding LGPL)
python -c "
import json, subprocess
result = subprocess.run(['uv', 'run', 'pip-licenses', '--from=mixed', '--format=json'], capture_output=True, text=True)
deps = json.loads(result.stdout)
incompatible = [f\"{d['Name']}: {d['License']}\" for d in deps
if any(g in d.get('License','').upper() for g in ['GPL','AGPL'])
and 'LGPL' not in d.get('License','').upper()]
if incompatible:
print('WARNING: Potentially incompatible licenses:')
for item in incompatible:
print(f' - {item}')
"
fi
On incompatible license found: Warn and ask user to continue or abort.
Detect and run the project's test suite:
# Python with pytest
if [ -f "pyproject.toml" ] && grep -q "pytest" pyproject.toml 2>/dev/null; then
uv run pytest --cov=src --cov-fail-under=80 -v
# Python with unittest
elif [ -d "tests" ] && [ -f "pyproject.toml" ]; then
uv run python -m pytest -v
# JavaScript/TypeScript
elif [ -f "package.json" ] && grep -q '"test"' package.json; then
npm test
# Makefile
elif [ -f "Makefile" ] && grep -q '^test:' Makefile; then
make test
fi
On test failure: Show failures and tell the user which tests failed. Do not auto-fix test failures - they require understanding business logic.
BRANCH=$(git branch --show-current)
# Try multiple patterns (in order):
# issue-42, /42-, #42, gh-42
ISSUE_NUM=$(echo "$BRANCH" | grep -oP 'issue-\K\d+' || \
echo "$BRANCH" | grep -oP '(?<=\/)\d+(?=-)' || \
echo "$BRANCH" | grep -oP '#\K\d+' || \
echo "$BRANCH" | grep -oP 'gh-\K\d+' || \
echo "")
# feat/* -> feat:, fix/* -> fix:, docs/* -> docs:, etc.
COMMIT_TYPE=$(echo "$BRANCH" | grep -oP '^[^/]+')
cli, tests, config)Closes #N (for fix/ branches) or Refs #N (for feat/ branches) if issue foundGenerate the commit message and commit immediately. Show the message in the output so the user can see what was committed, but do NOT ask for approval. Do NOT present Accept/Edit/Abort options.
Committed:
---
feat(cli): add metrics dashboard endpoint
Refs #42
---
git commit -m "<generated message>"
Do NOT ask for approval. Auto-commit with the generated message. The user trusts the conventional commit format derived from the branch prefix and diff analysis.
Use the branch detection algorithm from CLAUDE.md (Architecture > Branch Detection Algorithm). Use $TARGET from Section 1 if already detected.
git fetch origin $TARGET
git rebase origin/$TARGET
Mechanical files (target branch wins -- main/dev owns versions and changelogs, semantic-release regenerates them):
CHANGELOG.md -- accept target versionpyproject.toml (version field) -- accept target version__init__.py (version string) -- accept target versionuv.lock, package-lock.json) -- accept target, then regenerate with uv lock or npm installFor each conflicting file during rebase:
git checkout --theirs <file> then git add <file>, continue rebaseRebase conflicts:
- pyproject.toml (version) -- auto-resolved (target branch owns versions)
- CHANGELOG.md -- auto-resolved (target branch owns changelog)
- src/auth.py lines 42-58 -- NEEDS YOUR INPUT
[show conflict diff for auth.py]
After resolving all conflicts: git rebase --continue
# If rebased (branch diverged from remote):
git push --force-with-lease origin $CURRENT_BRANCH
# If no rebase needed:
git push origin $CURRENT_BRANCH
# Determine PR title from commit message (first line)
PR_TITLE="<first line of commit message>"
# Create PR
gh pr create \
--base $TARGET \
--head $CURRENT_BRANCH \
--title "$PR_TITLE" \
--body "## Summary
<brief description of changes>
## Checks run locally
- [x] Pre-commit hooks
- [x] Security scan (bandit + pip-audit)
- [x] License compliance
- [x] Unit tests with coverage
## Issue
<Closes #N or Refs #N if applicable>"
# Set automerge -- use --merge (not --squash) to preserve commit ancestry
# for clean promotion and release sync across long-lived branches
PR_NUMBER=$(gh pr view --json number -q .number)
gh pr merge --auto --merge $PR_NUMBER
Submitted: feat(cli): add metrics dashboard endpoint
PR: https://github.com/owner/repo/pull/99
Target: dev
Automerge: enabled (merge)
Status checks: monitoring...
Automatic next step: After the PR is created and automerge is enabled, immediately invoke /ai-monitor-pipeline to watch the pipeline. Do NOT just print "Next step: /ai-monitor-pipeline" -- actually run it. The user expects the workflow to continue automatically.
/ai-prepare-branchdevelopment
Deploy or validate Renovate dependency update configuration. Detects repo type (library vs IaC), package ecosystem, and generates or fixes renovate.json5.
development
Deploy or validate semantic-release configuration. Handles Python (python-semantic-release) and Node (JS semantic-release) repos with correct Renovate prefix alignment.
development
Audit and fix pre-commit hook configuration. Ensures consistent developer-side quality gates for formatting, linting, type checking, and secret protection.
testing
Audit and fix CI/CD GitHub Actions workflows. Checks security scanning, coverage enforcement, type checking, CVE ignores, and concurrency settings.