diff --git a/harnesses/composites/best-practices-opus-repo/v1/harness.yaml b/harnesses/composites/best-practices-opus-repo/v1/harness.yaml new file mode 100644 index 0000000..ab10975 --- /dev/null +++ b/harnesses/composites/best-practices-opus-repo/v1/harness.yaml @@ -0,0 +1,10 @@ +kind: composite +name: best-practices-opus-repo +version: 1 +description: "Best practices review agent with Opus + repo clone via SSH" + +layers: + - context: best-practices/v1 + - context: anthropic-cloud/v1 + - context: gitea-ssh/v1 + - context: agent-repo/v1 diff --git a/harnesses/contexts/agent-repo/v1/finalize.sh b/harnesses/contexts/agent-repo/v1/finalize.sh index 4b467f0..9056bf1 100644 --- a/harnesses/contexts/agent-repo/v1/finalize.sh +++ b/harnesses/contexts/agent-repo/v1/finalize.sh @@ -86,6 +86,29 @@ fi # AR-8: Check if there are any changes to commit git add -A +# AR-37/F73-10: Exclude protected test folders from commit. +# PROTECTED_TEST_FOLDERS is set by entrypoint.py when test_pass_required is active. +# This is defense-in-depth: prevents test file changes reaching the agent branch even +# if the entrypoint revert had a window between the last test run and finalize. +if [ -n "${PROTECTED_TEST_FOLDERS:-}" ]; then + IFS=',' read -ra _PROTECTED_FOLDERS <<< "$PROTECTED_TEST_FOLDERS" + for _folder in "${_PROTECTED_FOLDERS[@]}"; do + _folder=$(echo "$_folder" | xargs) # trim whitespace + if [ -n "$_folder" ]; then + echo "F73: Excluding test folder from commit: $_folder" + git reset HEAD -- "$_folder" 2>/dev/null || true + git checkout HEAD -- "$_folder" 2>/dev/null || true + git clean -fd -- "$_folder" 2>/dev/null || true + fi + done + # Also exclude test infrastructure files + for _infra in conftest.py pyproject.toml pytest.ini setup.cfg tox.ini; do + git reset HEAD -- "$_infra" 2>/dev/null || true + git checkout HEAD -- "$_infra" 2>/dev/null || true + git clean -fd -- "$_infra" 2>/dev/null || true + done +fi + if [ -z "$(git status --porcelain)" ]; then echo "No changes to commit — skipping push (AR-8)" # Write metadata with agent_branch_pushed=false diff --git a/harnesses/contexts/qwen-code-methodology/v1/CLAUDE.md b/harnesses/contexts/qwen-code-methodology/v1/CLAUDE.md index b8ae756..b30a83c 100644 --- a/harnesses/contexts/qwen-code-methodology/v1/CLAUDE.md +++ b/harnesses/contexts/qwen-code-methodology/v1/CLAUDE.md @@ -5,14 +5,20 @@ You are running on **Qwen3.6-27B** via the agentic tool-calling runner. Thinking ## Hard rules (violations fail the task) 1. **NEVER use the `Write` tool on a file that already exists.** Read first, then `Edit` for targeted changes. `Write` is only for creating new files that do not yet exist. -2. **Only modify files directly required by the task.** Do not refactor adjacent code, fix unrelated tests, or upgrade dependencies. -3. **Only run the specific test file for your change.** Never run the full test suite. +2. **Only modify files directly required by the task.** Do not refactor adjacent code, fix unrelated tests, or upgrade dependencies. Before committing, run `git diff --name-only HEAD` — if any unexpected file appears, revert it with `git checkout `. +3. **NEVER delete existing functions, classes, or imports.** Only ADD new code. Append new functions after the last existing one. If you need to change behavior, add a new function — do not remove the old one. +4. **Verify you haven't deleted lines before committing:** + ```bash + git diff HEAD | grep '^-[^-]' | grep -v '^\-\-\-' | head -20 + ``` + If this shows deleted non-blank lines from existing code, you have broken something — revert and try again with a targeted `Edit`. +5. **Only run the specific test file for your change.** Never run the full test suite. ``` python -m pytest tests/test_.py -v --tb=short -x ``` -4. **Do not create backup copies** (`*_orig`, `*_old`, `*_bak`, `*_backup`). -5. **Do not rename existing files before modifying them.** -6. **When the task is done, respond with plain text and stop.** Do not call any tool to signal completion. There is no "finish", "done", or "report" tool — emitting one wastes a turn and the runner will treat it as more work. +6. **Do not create backup copies** (`*_orig`, `*_old`, `*_bak`, `*_backup`). +7. **Do not rename existing files before modifying them.** +8. **When the task is done, respond with plain text and stop.** Do not call any tool to signal completion. There is no "finish", "done", or "report" tool — emitting one wastes a turn and the runner will treat it as more work. ## How to work diff --git a/harnesses/contexts/test-writing/v1/CLAUDE.md b/harnesses/contexts/test-writing/v1/CLAUDE.md index 8789caa..8a992e7 100644 --- a/harnesses/contexts/test-writing/v1/CLAUDE.md +++ b/harnesses/contexts/test-writing/v1/CLAUDE.md @@ -58,8 +58,8 @@ def test_xx1_descriptive_name(): ## Output Conventions -- **If `/workspace/working/` exists** (agent-repo mode): write test files to `tests/` directory -- **If `/workspace/working/` does not exist**: write to `/workspace/.agent-output/` +- **If `/workspace/project/` exists** (agent-repo mode): write test files to `tests/` inside that directory +- **If `/workspace/project/` does not exist**: write to `/workspace/.agent-output/` - Match the project's existing test file naming convention (usually `test_.py`) - Include a docstring at the top of each test file referencing which spec it covers @@ -72,7 +72,7 @@ def test_xx1_descriptive_name(): ## Session Logging -Write a brief session log to `/workspace/.agent-output/session-log.md` (or `/workspace/working/memory/log/` in agent-repo mode) with: +Write a brief session log to `/workspace/.agent-output/session-log.md` (or `/workspace/project/memory/log/` in agent-repo mode) with: - **Summary**: What test files were written/updated, test count - **Coverage Notes**: Which requirements are covered, which are deferred - **Open Questions**: Requirements that are ambiguous or untestable as written diff --git a/task-templates/airouter-code-repo.yaml b/task-templates/airouter-code-repo.yaml index c350cd0..e455b47 100644 --- a/task-templates/airouter-code-repo.yaml +++ b/task-templates/airouter-code-repo.yaml @@ -7,7 +7,8 @@ requires_tags: [agentic-runner, coding-agent, git-access, project-repo, best-pra required_params: [repo_url, agent_repo_url] labels: [airouter] defaults: - timeout: 1800 + timeout: 3600 + max_turns: 100 pre_actions: - type: clone repo: "{{ repo_url }}" diff --git a/task-templates/opus-best-practices-review.yaml b/task-templates/opus-best-practices-review.yaml new file mode 100644 index 0000000..9867277 --- /dev/null +++ b/task-templates/opus-best-practices-review.yaml @@ -0,0 +1,17 @@ +name: opus-best-practices-review +description: "Opus best practices review agent — review specs and code against project best practices" +model: opus +harness: security-review-opus-repo/v1 +requires_tags: [claude-code, best-practices, git-access, project-repo] +required_params: [repo_url, agent_repo_url] +defaults: + timeout: 3600 +pre_actions: + - type: clone + repo: "{{ repo_url }}" + branch: main + depth: 1 +blocked_combinations: + - field: on_success + contains_type: commit_pr + message: "Use agent_repo instead of commit_pr — avoids F77 SSH alias URL bug"