Files
Paul O'Reilly c0758cbd71 fix(harness): align workspace paths and best-practices mount target
- Mount best-practices context at /workspace/best-practices/ (was
  /opt/harness/context/best-practices/) for consistent agent access
- Fix /workspace/working/ → /workspace/project/ in all CLAUDE.md files
  (planning, spec-writing, security-review, code-methodology,
  qwen-code-methodology, test-writing)
- Update best-practices path references in all CLAUDE.md files to
  /workspace/best-practices/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 13:24:10 +12:00

5.2 KiB

Code Methodology — Qwen3.6 (Python)

You are running on Qwen3.6-27B via the agentic tool-calling runner. Thinking mode is on by default — your <think> blocks are part of normal output, not something to be scaffolded.

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. Before committing, run git diff --name-only HEAD — if any unexpected file appears, revert it with git checkout <file>.
  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:
    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_<module>.py -v --tb=short -x
    
  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

  1. Read the task. Identify the spec requirement ID if one is referenced; implement exactly that requirement.
  2. Read the files mentioned in the task before changing them.
  3. Find an existing similar file. Copy its structure. Change only what your task requires.
  4. Make small steps. After each, run the single test file from rule 3.
  5. When tests pass, write a short summary as plain text. Stop.

When you get stuck

If the same error appears 3 times:

  • Stop trying the same fix.
  • Reread the error message once.
  • Ask: "Am I editing the right file?" "Should I mock this instead of debugging the environment?"
  • Try a completely different approach.

If a directory or file does not exist where you expect it: do not debug the environment. Mock it or create a test fixture.

Best practices

This container has cross-project best practices mounted at /workspace/best-practices/. For any non-trivial Python task, read the relevant topic file before writing code.

  • /workspace/best-practices/python-patterns.md — Pydantic v2 validators, threading.Lock vs RLock, extra='ignore' silent drops, subprocess mocking, model_validator, packaging
  • /workspace/best-practices/test-driven-development.md — for tasks that involve writing tests
  • /workspace/best-practices/spec-driven-development.md — when a spec/ file is referenced
  • /workspace/best-practices/security-architecture.md — for anything touching auth, credentials, or external boundaries
  • /workspace/best-practices/BESTPRACTICES.md — index of all topics

Python conventions (this codebase)

  • Python 3.12+ with type hints
  • Pydantic v2 for data models — use @model_validator(mode='after') for cross-field validation; @field_validator does not fire for default values
  • pytest for tests; async tests must be async def with @pytest.mark.asyncio (a sync def test_* calling async code silently passes without executing)
  • Structured JSON logging
  • Configuration via environment variables — no hardcoded config

Python safety rules

Module imports

Never call sys.exit() at module level or inside except ImportError. Use a flag:

_HAS_OPENAI = True
try:
    import openai
except ImportError:
    _HAS_OPENAI = False

Check the flag at call time, not at import time.

Threading

threading.Lock is non-reentrant — same-thread re-acquisition deadlocks silently. When in doubt, use threading.RLock.

Pydantic gotcha

After adding a field to a shared model, every Protocol implementation and every _to_row / _row_to_* mapping must learn the new field, or it will silently round-trip as None in the implementation you missed.

Tool-calling notes

  • Use the standard tools provided. Don't invent tool names.
  • Tool arguments must be valid JSON. If you get an "invalid JSON" error back, re-read the schema and try once more with the corrected shape.
  • You can call multiple tools in one turn (parallel) when their results are independent. Don't batch sequentially-dependent calls — wait for the prior result first.

Session log

Before stopping, write a short log to /project/memory/log/<date>.<time>.md (e.g. 2026-04-25.143000.md):

# Session Log — YYYY-MM-DD

## Summary
One paragraph of what was accomplished.

## Decisions
- Key choices and reasoning

## Gotchas Discovered
- [python] description of the gotcha

## Open Questions
- Anything unresolved

## Process Notes
- What worked, what was slow

Omit empty sections. Tag gotchas with a topic prefix ([python], [pydantic], etc.) so they can be routed during reflection.