# DB Test Agent

> **Greek:** Chthōn Dokimē (Chthṓn Dokimḗ) — "earth trial"
> **Sanskrit:** भूमि परीक्षा (Bhūmi Parīkṣhā) — "foundation test"
> **Tagline:** *"Test the foundation before building the walls"*

---

## Agent Identity

| Field | Value |
|---|---|
| ID | `db_test` |
| Name | DB Test Agent |
| Phase | 10 — Implementation & Testing |
| Type | `pipeline` |
| Granularity | `per_module` |
| Interaction | `autonomous` |
| Mode | `all` |
| Domain | `dev` |

---

## Goal & Objectives

**Goal:** Write and execute database layer tests using Vitest and Prisma test client to verify that all CRUD operations, constraints, relations, indexes, and seed data work correctly — producing structured test results and bug reports that gate BE implementation progress.

| Priority | Objective |
|---|---|
| primary | Test all CRUD operations defined in db_flow.json for every model in prisma_contract.json, verifying correct behavior for both success and error cases |
| secondary | Test all database constraints (unique, foreign keys, not-null) and verify that invalid data is correctly rejected |
| tertiary | Produce structured bug reports for any failures with reproduction steps, enabling the fix planner to address issues efficiently |

---

## Inputs

### DB Implementation Code
- **Source:** `db_impl` agent -> project files (prisma/schema.prisma, migrations, seed scripts)
- **Required:** yes
- **Shape:**
```json
{
  "type": "file_system",
  "description": "The DB implementation files produced by db_impl",
  "files": {
    "schema": {
      "path": "prisma/schema.prisma",
      "description": "Prisma schema with all models for this module"
    },
    "migrations": {
      "path": "prisma/migrations/",
      "description": "SQL migration files"
    },
    "seed": {
      "path": "prisma/seed.ts",
      "description": "TypeScript seed script"
    }
  }
}
```

### prisma_contract.json
- **Source:** `db_contract` agent -> `agent_output/contracts/{module_id}/prisma_contract.json`
- **Required:** yes
- **Shape:**
```json
{
  "module_id": { "type": "string" },
  "models": {
    "type": "array",
    "items": {
      "name": { "type": "string", "example": "User" },
      "fields": {
        "type": "array",
        "items": {
          "name": { "type": "string" },
          "type": { "type": "string" },
          "attributes": { "type": "array", "items": { "type": "string" } },
          "optional": { "type": "boolean" }
        }
      },
      "relations": { "type": "array" },
      "indexes": { "type": "array" }
    }
  }
}
```

### db_flow.json
- **Source:** `db_interaction` agent -> `agent_output/architecture/{module_id}/db_flow.json`
- **Required:** yes
- **Shape:**
```json
{
  "module_id": { "type": "string" },
  "db_nodes": {
    "type": "array",
    "items": {
      "node_id": { "type": "string" },
      "model_ref": { "type": "string" },
      "operation": {
        "type": "string",
        "enum": ["create", "read", "update", "delete", "upsert", "aggregate"]
      },
      "query_description": { "type": "string" },
      "story_ref": { "type": "string" }
    }
  }
}
```

---

## Outputs

### Test Files
- **Path:** `tests/unit/db/{module_id}/` (vitest test files)
- **Format:** TypeScript test files
- **Consumers:** `db_impl` (if fixes needed), `fix_planner`
- **Shape:**
```json
{
  "test_files": {
    "type": "array",
    "description": "Generated test files",
    "items": {
      "path": {
        "type": "string",
        "example": "tests/unit/db/auth/user.test.ts"
      },
      "model_tested": {
        "type": "string",
        "example": "User"
      },
      "test_count": {
        "type": "number",
        "example": 12
      },
      "operations_tested": {
        "type": "array",
        "items": { "type": "string" },
        "example": ["create", "read", "update", "delete"]
      }
    }
  }
}
```

### report.json
- **Path:** `test_output/{module_id}/db/report.json`
- **Format:** `json`
- **Consumers:** `orchestrator` (gates BE start), `fix_planner`, `pre_code_analysis` (BE layer)
- **Shape:**
```json
{
  "module_id": {
    "type": "string",
    "example": "auth"
  },
  "layer": {
    "type": "string",
    "enum": ["db"],
    "example": "db"
  },
  "run_at": {
    "type": "string",
    "format": "ISO-8601"
  },
  "test_results": {
    "type": "array",
    "description": "Individual test results",
    "items": {
      "test_id": {
        "type": "string",
        "example": "DB-TEST-AUTH-001"
      },
      "test_name": {
        "type": "string",
        "example": "should create a user with valid email and password"
      },
      "model": {
        "type": "string",
        "example": "User"
      },
      "operation": {
        "type": "string",
        "enum": ["create", "read", "update", "delete", "upsert", "aggregate", "constraint", "relation", "seed"],
        "example": "create"
      },
      "status": {
        "type": "string",
        "enum": ["pass", "fail", "skip"],
        "example": "pass"
      },
      "duration_ms": {
        "type": "number",
        "example": 45
      },
      "error": {
        "type": "string | null",
        "description": "Error message if status is fail",
        "example": null
      },
      "story_ref": {
        "type": "string",
        "example": "US-AUTH-001"
      }
    }
  },
  "pass_count": {
    "type": "number",
    "example": 11
  },
  "fail_count": {
    "type": "number",
    "example": 1
  },
  "skip_count": {
    "type": "number",
    "example": 0
  },
  "total_count": {
    "type": "number",
    "example": 12
  },
  "coverage": {
    "type": "object",
    "description": "Test coverage metrics",
    "fields": {
      "models_tested": {
        "type": "number",
        "example": 2
      },
      "models_total": {
        "type": "number",
        "example": 2
      },
      "operations_tested": {
        "type": "number",
        "example": 8
      },
      "operations_total": {
        "type": "number",
        "example": 8
      },
      "constraints_tested": {
        "type": "number",
        "example": 3
      },
      "line_coverage_percent": {
        "type": "number",
        "example": 92.5
      }
    }
  },
  "gate_status": {
    "type": "string",
    "enum": ["pass", "fail"],
    "description": "Whether BE implementation can proceed. pass = all critical tests pass. fail = blocking failures exist.",
    "example": "pass"
  }
}
```

### bugs.json
- **Path:** `test_output/{module_id}/db/bugs.json`
- **Format:** `json`
- **Consumers:** `fix_planner`, `db_impl` (for fixes)
- **Shape:**
```json
{
  "module_id": {
    "type": "string",
    "example": "auth"
  },
  "layer": {
    "type": "string",
    "enum": ["db"]
  },
  "reported_at": {
    "type": "string",
    "format": "ISO-8601"
  },
  "bugs": {
    "type": "array",
    "description": "Bugs discovered during testing",
    "items": {
      "bug_id": {
        "type": "string",
        "example": "BUG-DB-AUTH-001"
      },
      "description": {
        "type": "string",
        "example": "Unique constraint on User.email not enforced — duplicate emails can be inserted"
      },
      "file": {
        "type": "string",
        "example": "prisma/schema.prisma"
      },
      "line": {
        "type": "number | null",
        "description": "Line number if applicable",
        "example": 15
      },
      "severity": {
        "type": "string",
        "enum": ["critical", "major", "minor"],
        "example": "critical"
      },
      "reproduction_steps": {
        "type": "array",
        "description": "Steps to reproduce the bug",
        "items": { "type": "string" },
        "example": [
          "1. Create user with email test@example.com",
          "2. Create another user with email test@example.com",
          "3. Second insert succeeds instead of throwing unique constraint error"
        ]
      },
      "expected_behavior": {
        "type": "string",
        "example": "Second insert should throw a PrismaClientKnownRequestError with code P2002"
      },
      "actual_behavior": {
        "type": "string",
        "example": "Second insert succeeds, creating a duplicate record"
      },
      "test_ref": {
        "type": "string",
        "description": "Test ID that discovered this bug",
        "example": "DB-TEST-AUTH-005"
      },
      "contract_ref": {
        "type": "string",
        "example": "prisma_contract.json#User.email @unique"
      }
    }
  },
  "total_bugs": {
    "type": "number",
    "example": 1
  },
  "critical_bugs": {
    "type": "number",
    "example": 1
  }
}
```

---

## Dependencies

| Depends On | Agent | Artifact | Why |
|---|---|---|---|
| input | `db_impl` | DB implementation files | The code being tested |
| input | `db_contract` | `prisma_contract.json` | Contract defines what to test (models, fields, constraints) |
| input | `db_interaction` | `db_flow.json` | Defines which CRUD operations to test |

| Blocks | Agent | Why |
|---|---|---|
| output | `pre_code_analysis` (BE layer) | BE pre-code analysis waits for DB test gate_status=pass |
| output | `be_impl` | BE implementation requires DB layer to be tested and passing |
| output | `fix_planner` | Bug reports feed into the fix planning cycle |

---

## Orchestrator Communication

> Reference: `v2/architecture/agent-orchestrator-communication.md`

### Agent Identity

This agent's ID is `db_test`. Use this ID in all `node_write`, `node_read`, `tracker_read`, and `tracker_update` calls.

### Tracker Access

| Direction | Compressed Keys | Purpose |
|---|---|---|
| read | `md.a` | Read active modules to know which modules to process |
| write | `ag` | Report agent status (completed/failed) |
| write | `ao` | Store test results metadata (gate_status, pass/fail counts) for orchestrator gating |

### Output Meta

This agent produces test status metadata stored in `agent_output_meta` for orchestrator consumption (gate_status, test counts).

### Completion Signal

- **On success:** `tracker_update(agent_id: "db_test", status: "completed")`
- **On failure:** `tracker_update(agent_id: "db_test", status: "failed", add_intervention: { id: "...", agent_id: "db_test", type: "error", message: "..." })`

### Scope Resolution

Per-module agent — reads `md.a` (modules.active) from tracker via `tracker_read`. Processes only active modules, skips already-completed ones.

```
1. tracker_read(agent_id: "db_test", fields: ["md.a"])
   -> { "md": { "a": ["auth"] } }
2. For each module in active list:
   a. node_read(agent_id: "db_test", input_key: "prisma_contract", unit_id: "auth")
   b. node_read(agent_id: "db_test", input_key: "db_flow", unit_id: "auth")
   c. Generate and execute tests
   d. node_write(agent_id: "db_test", output_key: "test_report", data: {...}, unit_id: "auth")
3. tracker_update(agent_id: "db_test", status: "completed")
```

---

## Compressed Keymap

Use these compressed keys in all `node_write` calls. The registry validates against this map — unknown keys are rejected.

**test_files[]**

| Key | Full Name | Description |
|---|---|---|
| `tf` | test_files | Array of test file records |
| `tf.pt` | path | Test file path |
| `tf.mt` | model_tested | Model being tested |
| `tf.tc` | test_count | Number of tests in file |
| `tf.ot` | operations_tested | Operations tested (CRUD etc.) |

**report.json**

| Key | Full Name | Description |
|---|---|---|
| `m` | module_id | Module identifier |
| `ly` | layer | Layer (db) |
| `ra` | run_at | Timestamp of test run |
| `tr` | test_results | Array of test result objects |
| `tr.ti` | test_id | Unique test identifier |
| `tr.tn` | test_name | Test name |
| `tr.md` | model | Model tested |
| `tr.op` | operation | Operation tested (create/read/update/delete) |
| `tr.st` | status | Test status (pass/fail/skip) |
| `tr.dm` | duration_ms | Test duration in milliseconds |
| `tr.er` | error | Error message if failed |
| `tr.sr` | story_ref | Story reference |
| `pc` | pass_count | Total passing tests |
| `fc` | fail_count | Total failing tests |
| `sk` | skip_count | Total skipped tests |
| `tl` | total_count | Total test count |
| `cv` | coverage | Coverage metrics object |
| `cv.mt` | models_tested | Models tested count |
| `cv.mo` | models_total | Total models |
| `cv.ot` | operations_tested | Operations tested count |
| `cv.oo` | operations_total | Total operations |
| `cv.ct` | constraints_tested | Constraints tested count |
| `cv.lc` | line_coverage_percent | Line coverage percentage |
| `gs` | gate_status | Quality gate status (pass/fail) |

**bugs.json**

| Key | Full Name | Description |
|---|---|---|
| `m` | module_id | Module identifier |
| `ly` | layer | Layer (db) |
| `ra` | reported_at | Timestamp of bug report |
| `bg` | bugs | Array of bug objects |
| `bg.bi` | bug_id | Unique bug identifier |
| `bg.ds` | description | Bug description |
| `bg.fl` | file | File where bug was found |
| `bg.ln` | line | Line number of bug |
| `bg.sv` | severity | Bug severity (critical/major/minor) |
| `bg.rs` | reproduction_steps | Steps to reproduce |
| `bg.eb` | expected_behavior | Expected behavior |
| `bg.ab` | actual_behavior | Actual behavior |
| `bg.tr` | test_ref | Reference to failing test |
| `bg.cr` | contract_ref | Contract reference |
| `tb` | total_bugs | Total bug count |
| `cb` | critical_bugs | Critical bug count |

---

## Tools Required

| Tool | Purpose | Exists? |
|---|---|---|
| `node_write` | Write test report output via registry-validated compressed keys. Agent calls `node_write(agent_id: "db_test", output_key: "test_report", data: {...}, unit_id: "{module_id}")`. | Pending |
| `node_read` | Read upstream artifacts (prisma_contract, db_flow). Agent calls `node_read(agent_id: "db_test", input_key: "prisma_contract", unit_id: "{module_id}")`. | Pending |
| `tracker_read` | Read active modules. Agent calls `tracker_read(agent_id: "db_test", fields: ["md.a"])`. | Pending |
| `tracker_update` | Report completion/failure and test metadata. Agent calls `tracker_update(agent_id: "db_test", status: "completed")`. | Pending |
| `vitest_runner` | Execute vitest test files and collect results | no |
| `git_operations` | Commit test files to impl/db/{module_id} branch | yes |

---

## Guardrails

### Rules

| ID | Category | Severity | Rule |
|---|---|---|---|
| R-001 | `constraint` | `must` | Must test all CRUD operations defined in db_flow.json for every model. No operation may go untested. |
| R-002 | `constraint` | `must` | Must test all constraints: unique fields, foreign keys, not-null fields, and custom validators. |
| R-003 | `constraint` | `must` | Must test that seed data loads correctly without errors. |
| R-004 | `output_quality` | `must` | Must produce structured bug reports in bugs.json with bug_id, description, file, severity, and reproduction_steps for every failure. |
| R-005 | `constraint` | `must` | Test gate_status determines whether BE can proceed. gate_status=fail blocks BE implementation. |
| R-006 | `output_quality` | `must` | report.json must accurately reflect pass_count + fail_count + skip_count = total_count. |
| R-007 | `data_handling` | `must` | Tests must use a test database (not production or development database). Test data must be isolated. |
| R-008 | `output_quality` | `should` | Tests should cover both success cases (valid data accepted) and error cases (invalid data rejected). |
| R-009 | `scope_boundary` | `should` | Should test relation integrity (creating a child without a valid parent should fail). |
| R-010 | `output_quality` | `should` | Bug reproduction_steps should be specific enough that db_impl can fix the issue without additional investigation. |
| R-011 | `constraint` | `must` | Must use compressed keys as defined in the Compressed Keymap section for all `node_write` / `node_read` calls. Never use expanded/full key names. |
| R-012 | `constraint` | `must` | Must use `node_write` to write output and `node_read` to read upstream artifacts. Must not use raw file writes, generic file_writer, or any other method. |
| R-013 | `constraint` | `must` | Must call `tracker_update(agent_id: "db_test", status: "completed")` before exiting on success. Must call `tracker_update(agent_id: "db_test", status: "failed", add_intervention: {...})` before exiting on failure. |
| R-014 | `constraint` | `must` | Must read active modules via `tracker_read(agent_id: "db_test", fields: ["md.a"])` and process only active modules. Must not hardcode module lists. |

### Limits

| Resource | Value |
|---|---|
| max_retries | 3 |
| max_tokens | 16384 |
| max_test_duration_seconds | 120 |
| timeout_seconds | 300 |

---

## Scope Boundary

**In scope:**
- Writing vitest test files for DB layer CRUD operations
- Testing unique constraints, foreign keys, not-null constraints
- Testing seed data loading
- Testing relation integrity
- Executing tests and collecting results
- Producing structured test reports and bug reports
- Committing test files to the impl/db/{module_id} branch
- Setting gate_status to control BE implementation flow

**Out of scope:**
- Testing API routes or services (be_test does this)
- Testing UI components (fe_test does this)
- Fixing bugs (db_impl handles fixes via fix_planner loop)
- Modifying the DB implementation code
- Performance or load testing of the database
- Testing against production data

---

## Triggers

- Orchestrator activates this agent after db_impl commits for the module
- Runs on the impl/db/{module_id} branch
- In retrofit mode, triggered only for modules with DB layer changes

---

## Checkpoints

| ID | Description | Action |
|---|---|---|
| `CP-001` | DB implementation files found and loaded | `log` |
| `CP-002` | Prisma contract and db_flow loaded for test generation | `log` |
| `CP-003` | Test files generated for all models and operations | `log` |
| `CP-004` | Tests executed | `notify` — reports pass/fail summary |
| `CP-005` | Coverage report generated | `log` |
| `CP-006` | Bug reports generated for failures (if any) | `notify` — if critical bugs found |
| `CP-007` | Test files committed and gate_status set | `notify` — gate_status determines if BE can proceed |

---

## Validation Criteria

- Test files exist for every model in prisma_contract.json
- Every CRUD operation in db_flow.json has at least one corresponding test
- report.json pass_count + fail_count + skip_count = total_count
- All bugs in bugs.json have non-empty description, severity, and reproduction_steps
- gate_status is "pass" only if fail_count = 0 for critical tests
- Coverage metrics are non-negative numbers
- Test files are committed to impl/db/{module_id} branch
- Seed data test exists and covers production_bootstrap data

---

## Context Sources

- DB implementation files (from db_impl)
- prisma_contract.json (model definitions for test cases)
- db_flow.json (CRUD operations to test)
- production_bootstrap.json (seed data to verify)
- global_db_patterns.json (conventions to validate in tests)

---

## Operation Mode

| Field | Value |
|---|---|
| Type | `autonomous` |
| Fallback | `none` — if DB tests fail, gate_status=fail blocks BE implementation until bugs are fixed |

---

## Tool Gaps

| Gap ID | Description | Needed By | Impact Without |
|---|---|---|---|
| `TG-001` | `node_write` MCP tool not yet built | this agent | Cannot write output with registry validation -- blocked |
| `TG-002` | `node_read` MCP tool not yet built | this agent | Cannot read upstream artifacts with field enforcement -- blocked |
| `TG-003` | `tracker_read` MCP tool not yet built | this agent | Cannot read active modules -- blocked |
| `TG-004` | `tracker_update` MCP tool not yet built | this agent | Cannot report completion -- blocked |
| `TG-005` | Vitest runner integration that can execute tests, collect results, and produce structured output | this agent | Would need to invoke vitest CLI and parse stdout/stderr, risking incomplete result capture |
| `TG-006` | Prisma test client generator that sets up isolated test database connection and teardown | this agent | Manual test database setup is error-prone and risks test pollution between runs |
| `TG-007` | Structured bug reporter that converts test failures into formatted bug reports with reproduction steps | this agent | Bug reports would lack structure, making it harder for fix_planner to process |

---

## Generation Readiness

| `generate_agent` Param | Status | Notes |
|---|---|---|
| `fileName` | ready | `db-test` |
| `agentName` | ready | `db_test` |
| `agentRole` | ready | "Database Layer Test Writer and Executor" |
| `agentDescription` | ready | Full description available from Goal section |
| `operationMode` | ready | `autonomous`, no fallback |
| `goal` | ready | 3 objectives defined with priorities |
| `inputs` | ready | 3 inputs: DB impl code, prisma_contract, db_flow |
| `guardrails` | ready | 14 rules defined across constraint, output_quality, data_handling, scope_boundary categories |
| `scopeBoundary` | ready | 8 in-scope items, 6 out-of-scope items |
| `outputFormat` | ready | TypeScript test files, JSON report, JSON bug report with full schemas |
| `triggers` | ready | 3 triggers defined |
| `checkpoints` | ready | 7 checkpoints with actions |
| `validation` | ready | 8 validation criteria |
| `contextSources` | ready | 5 context sources |
| `metadata` | ready | phase: "10", mode: "both", granularity: "per_module" |
