---
# Stage identity per spec Section 6.1
stage: 2
stage_id: "02"
title: "Implement Tests"
workflow: tests
estimated_tokens: 2000

# Context specification
context:
  static:
    persona: "skilled software developer implementing comprehensive test coverage"
    purpose: "Implement all tests from the test plan and improve coverage"
  dynamic:
    - key: feature_dir
      source: cli_arg
    - key: scope_mode
      source: cli_arg
    - key: scope_pattern
      source: cli_arg
    - key: test_type
      source: cli_arg
    - key: target_coverage
      source: cli_arg
    - key: iterations
      source: cli_arg
    - key: max_agents
      source: cli_arg
      default: 5

# Sub-agent architecture for context efficiency
# Purpose: Save main orchestrator context by delegating test file creation to sub-agents
sub_agent:
  enabled: true
  purpose: "Create test files in parallel, preserving main agent context"
  max_concurrent: "{max_agents}"
  checkpoint_after_batch: true
  sub_agent_receives:
    - target_file: "The source file to test"
    - gaps: "List of untested functions/methods from Stage 1 plan"
    - test_type: "unit | integration | both"
    - conventions: "Language-specific test patterns"
  sub_agent_returns:
    - test_file_path: "Created test file path"
    - tests_created: "Number of tests written"
    - status: "success | partial | failed"
    - error: "Error message if failed"

# Pre-validation checks
pre_validation:
  - check: stage_01_completed
    condition: "state.tests.current_stage == '01-coverage-review'"
    message: "Stage 01 (Coverage Review) must be completed first"
    recovery: "civyk-hatch tests --stage=1"
  - check: test_plan_exists
    condition: "test plan was created in stage 01"
    message: "Test plan must exist from stage 01"
    recovery: "civyk-hatch tests --stage=1"

# Execution flow with step types
execution_flow:
  - step: 1
    type: action
    name: load_plan
    instruction: "Load test plan and scope configuration from CLI args"
    output_variable: test_plan
  - step: 2
    type: action
    name: recall_cache
    instruction: "Recall cached understanding for edge cases and gotchas"
  - step: 3
    type: parallel
    name: spawn_test_agents
    instruction: "Spawn sub-agents to create test files (max {max_agents} concurrent)"
    max_concurrent: "{max_agents}"
    checkpoint: true
  - step: 4
    type: action
    name: aggregate_results
    instruction: "Collect results from sub-agents, report progress"
  - step: 5
    type: action
    name: run_suite
    instruction: "Run project's test command with coverage enabled"
    output_variable: new_coverage
  - step: 6
    type: action
    name: commit_tests
    instruction: "Commit test files with appropriate commit message"
  - step: 7
    type: conditional
    name: check_target
    instruction: "Check if target coverage is achieved"
    condition: "new_coverage >= target_coverage"

# Guardrails
guardrails:
  enforcement: active
  allowed_tools:
    - civyk-repoix
    - Read
    - Edit
    - Write
    - Grep
    - Glob
    - Bash
  forbidden_actions:
    - "Delete production source files"
    - "Modify production code (except for minor test-supporting changes)"
    - "Push to remote without user confirmation"
  file_restrictions:
    allowed_paths:
      - "tests/**"
      - "test/**"
      - "spec/**"
      - "**/*_test.*"
      - "**/test_*.*"
    forbidden_paths:
      - ".env"
      - "**/*.key"
      - "**/credentials*"
  read_only: false

# Post-validation checks
post_validation:
  - check: tests_pass
    description: "All new tests pass"
    severity: error
  - check: coverage_improved
    description: "Coverage percentage improved"
    severity: warning
  - check: tests_committed
    description: "Tests were committed to git"
    severity: warning

# Output specification
output:
  state_update:
    tests.current_stage: "02-implement-tests"
  completion_command: "civyk-hatch update-stage tests 02 --status completed"

# Next stage - loops back to 01 until target met
next:
  stage: 1
  stage_id: "01"
  command: "civyk-hatch tests --stage=1"
  auto_continue: true
  is_terminal: false
  condition: "coverage < target"
version: 1.0.0
---
{{include:strict-execution-mode.md}}

{{include:ai-cache-enforcement.md}}

# Stage 2: Implement Tests

You are a {persona}.

Implement all tests from Stage 1 plan, then return to Stage 1 for re-measurement.

---

## [!] STAGE 2 RESPONSIBILITIES

**Stage 2 handles ALL test writing:**
- Create new test files for coverage gaps
- Fix failing tests (including pre-existing failures)
- Update outdated tests
- Ensure all tests pass before returning to Stage 1

**Why this separation matters:**
- Stage 1 is read-only analysis - it measures and plans
- Stage 2 is the implementation phase - it writes and fixes
- This prevents mixing discovery with implementation

---

## Rules

- Read code before writing tests (no guessing signatures)
- Implement all tests before running suite
- Return to Stage 1 after implementation (loop ends when target met)
- Respect test type from scope configuration

---

## Reference

{{include:tests-industry-standards-brief.md}}

---

## Step 1: Load Plan and Scope

`civyk-hatch check --json` -> `target`, `current`, `gap`

Load from CLI args:

- `SCOPE_MODE`: branch | module | files | full
- `SCOPE_PATTERN`: glob or class pattern (if applicable)
- `TEST_TYPE`: unit | integration | both
- `TARGET`: coverage percentage

---

## Step 2: Recall Cache and Read Code

```text
# [!] MANDATORY: Recall before reading
understand(action="recall", target="<module_path>")
# Use cached understanding for edge cases and gotchas
```

**For each file you read:**

```text
# [!] MANDATORY: Store understanding after reading code
understand(
  action="store",
  scope="file",
  target="<file_path>",
  purpose="Code analysis for test implementation",
  importance="high",
  key_points=["functions: <list>", "edge_cases: <list>", "dependencies: <list>"],
  gotchas=["<error_paths>", "<null_handling>", "<boundary_conditions>"],
  analysis="<file>: <N> functions. Key behaviors: <list>. Edge cases: <list>."
)
```

---

## Step 3: Implement Tests (Sub-Agent Pattern)

**CRITICAL: Use sub-agents to preserve main orchestrator context.**

The orchestrator (you) spawns sub-agents for each test file. This saves context because:
- Main agent only tracks high-level progress
- Sub-agents handle the detailed code reading/writing
- Results are aggregated back to main agent

### 3.1 Group Test Plan by File

From Stage 1 plan, group tests by target file:

```text
File: src/auth/login.py
  - T-001: test_validate_token
  - T-002: test_handle_error

File: src/payment/process.py
  - T-003: test_payment_flow
  - T-004: test_refund_handling
```

### 3.2 Spawn Sub-Agents in Parallel

For each file group, spawn a sub-agent:

```text
# Orchestrator spawns sub-agents (max {max_agents} concurrent)
PARALLEL FOR file_group IN test_plan DO
    spawn_sub_agent(
        prompt="""
        Create tests for: {file_group.target_file}
        Tests to create: {file_group.tests}
        Test type: {TEST_TYPE}

        Instructions:
        1. Read the target source file
        2. Create test file following naming conventions
        3. Implement each test (one behavior per test)
        4. Verify tests pass individually
        5. Return: test_file_path, tests_created, status
        """,
        tools=[Read, Write, Bash]
    )
END PARALLEL FOR
```

### 3.3 Real-Time Progress (Orchestrator)

**After EACH sub-agent completes:**

```text
OUTPUT: "[{completed}/{total}] [ok] {test_file} - {status}"

# Example outputs:
"[1/5] [ok] tests/test_login.py - created (3 tests)"
"[2/5] [ok] tests/test_process.py - created (2 tests)"
"[3/5] [err] tests/test_auth.py - failed: parse error"
```

**Update TODO for visual progress:**

```text
TodoWrite: "Creating test files: {completed}/{total} ({pct}%)"
```

### 3.4 Checkpoint After Each Batch

```text
understand(
    action="store",
    scope="project",
    target="tests-checkpoint",
    purpose="Test implementation checkpoint",
    importance="high",
    key_points=[
        "files_done: {completed}",
        "files_remaining: {remaining}",
        "tests_created: {total_tests}"
    ],
    gotchas=["Resume with: civyk-hatch tests --stage=2 --resume"]
)
```

### 3.5 Handle Failures

```text
IF sub_agent.status == "failed" THEN
    errors.append({file: sub_agent.target_file, error: sub_agent.error})
    CONTINUE
END IF

# After all agents complete:
IF errors THEN
    OUTPUT "=== ERRORS (will retry on next iteration) ==="
    FOR error IN errors DO
        OUTPUT "  - {error.file}: {error.error}"
    END FOR
END IF
```

**Fallback:** If sub-agents fail repeatedly, fall back to sequential processing.

```text
Planned: [N] | Done: [N] | Failed: [N] | Remaining: [0]
```

---

## Test Type Conventions

### Unit Tests (`TEST_TYPE=unit`)

**File naming:**

- JavaScript/TypeScript: `*.test.ts`, `*.test.js`, `*.spec.ts`
- Python: `test_*.py`, `*_test.py`
- Java: `*Test.java`
- Go: `*_test.go`

**Characteristics:**

- Mock all external dependencies
- No database, network, or file system calls
- Fast execution (< 100ms per test)
- Isolated - no shared state between tests

**Example structure:**

```text
describe('UserValidator', () => {
  it('should reject empty email', () => {
    // Arrange - setup with mocks
    // Act - call the function
    // Assert - verify behavior
  });
});
```

### Integration Tests (`TEST_TYPE=integration`)

**File naming:**

- JavaScript/TypeScript: `*.integration.ts`, `*.e2e.ts`, `*.integration.test.ts`
- Python: `test_*_integration.py`, `*_integration_test.py`
- Java: `*IntegrationTest.java`, `*IT.java`
- Go: `*_integration_test.go`

**Characteristics:**

- Use real dependencies (database, services)
- Test module boundaries and contracts
- May require setup/teardown for resources
- Slower execution (acceptable)

**Example structure:**

```text
describe('UserAPI Integration', () => {
  beforeAll(() => {
    // Setup test database, seed data
  });

  afterAll(() => {
    // Cleanup resources
  });

  it('should create user and return 201', () => {
    // Test real API endpoint
  });
});
```

### Both (`TEST_TYPE=both`)

Assign test type based on what's being tested:

| Testing | Type | Rationale |
|---------|------|-----------|
| Pure functions | unit | No dependencies |
| Validators | unit | Logic only |
| API endpoints | integration | Full request/response cycle |
| Database operations | integration | Real data layer |
| Service orchestration | integration | Multiple components |
| Error handling (internal) | unit | Logic flow |
| Error handling (external) | integration | Real error responses |

---

## Step 4: Run Suite

Run project's test command with coverage enabled.

**Filter by test type if needed:**

- Unit only: run fast test suite (exclude integration tags/folders)
- Integration only: run integration suite (specific tags/folders)
- Both: run full suite

---

## Step 5: Commit

```bash
# Add test files by pattern (match test type naming)
git add <test-files>

git commit -m "$(cat <<'EOF'
test({type}): add {test_type} tests for coverage improvement

Scope: {SCOPE_MODE}
Coverage: {old}% -> {new}%
Tests added: [list test files]
EOF
)"
```

Commit message prefix by type:

- Unit: `test(unit):`
- Integration: `test(integration):`
- Both: `test:`

Avoid `git add -A` (may include secrets, binaries).

### Store Test Implementation Summary

```text
# [!] MANDATORY: Store test implementation results
understand(
  action="store",
  scope="project",
  target="test-implementation",
  purpose="Test implementation progress",
  importance="high",
  key_points=["tests_added: <count>", "coverage: <old>% -> <new>%", "test_type: <type>"],
  gotchas=["<failed_tests>", "<uncovered_areas>"],
  analysis="Stage 2 complete. Added <N> tests. Coverage: <old>% -> <new>%. Target: <target>%."
)
```

---

## Step 6: Gate

If new >= target: `[ok] TARGET ACHIEVED` -> STOP

---

## [AUTO-CONTINUE]

After implementing tests, automatically return to Stage 1 to re-measure coverage (loop until target met).

## NEXT

```bash
civyk-hatch tests --stage=1 --iterations={next_iteration} \
  --target-coverage={TARGET} \
  --scope-mode={SCOPE_MODE} \
  --scope-pattern="{SCOPE_PATTERN}" \
  --test-type={TEST_TYPE}
```
