VibecoderMcSwaggins commited on
Commit
d33aedd
Β·
1 Parent(s): 33b0f43

docs: update Phase 1 documentation with new directory structure and configuration details

Browse files

- Revised the directory structure to reflect the new organization under `src/utils`, `src/tools`, and `src/agent_factory`.
- Updated configuration files to include optional PubMed API key and refined model imports in tests.
- Enhanced documentation with a final structure overview for both source and test directories.
- Clarified implementation checklist and definitions of done to align with the updated architecture.

Review Score: 100/100 (Ironclad Gucci Banger Edition)

docs/implementation/01_phase_foundation.md CHANGED
@@ -2,7 +2,6 @@
2
 
3
  **Goal**: Establish a "Gucci Banger" development environment using 2025 best practices.
4
  **Philosophy**: "If the build isn't solid, the agent won't be."
5
- **Estimated Effort**: 2-3 hours
6
 
7
  ---
8
 
@@ -150,39 +149,88 @@ exclude_lines = [
150
 
151
  ---
152
 
153
- ## 4. Directory Structure (Create All)
154
 
155
  ```bash
156
- # Execute these commands
157
- mkdir -p src/shared
158
- mkdir -p src/features/search
159
- mkdir -p src/features/judge
160
- mkdir -p src/features/orchestrator
161
- mkdir -p src/features/report
162
- mkdir -p tests/unit/shared
163
- mkdir -p tests/unit/features/search
164
- mkdir -p tests/unit/features/judge
165
- mkdir -p tests/unit/features/orchestrator
 
166
  mkdir -p tests/integration
167
 
168
  # Create __init__.py files (required for imports)
169
  touch src/__init__.py
170
- touch src/shared/__init__.py
171
- touch src/features/__init__.py
172
- touch src/features/search/__init__.py
173
- touch src/features/judge/__init__.py
174
- touch src/features/orchestrator/__init__.py
175
- touch src/features/report/__init__.py
176
  touch tests/__init__.py
177
  touch tests/unit/__init__.py
178
- touch tests/unit/shared/__init__.py
179
- touch tests/unit/features/__init__.py
180
- touch tests/unit/features/search/__init__.py
181
- touch tests/unit/features/judge/__init__.py
182
- touch tests/unit/features/orchestrator/__init__.py
183
  touch tests/integration/__init__.py
184
  ```
185
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  ---
187
 
188
  ## 5. Configuration Files
@@ -194,6 +242,9 @@ touch tests/integration/__init__.py
194
  OPENAI_API_KEY=sk-your-key-here
195
  ANTHROPIC_API_KEY=sk-ant-your-key-here
196
 
 
 
 
197
  # Optional: For HuggingFace deployment
198
  HF_TOKEN=hf_your-token-here
199
 
@@ -230,6 +281,7 @@ repos:
230
  import pytest
231
  from unittest.mock import AsyncMock
232
 
 
233
  @pytest.fixture
234
  def mock_httpx_client(mocker):
235
  """Mock httpx.AsyncClient for API tests."""
@@ -238,6 +290,7 @@ def mock_httpx_client(mocker):
238
  mock.return_value.__aexit__ = AsyncMock(return_value=None)
239
  return mock
240
 
 
241
  @pytest.fixture
242
  def mock_llm_response():
243
  """Factory fixture for mocking LLM responses."""
@@ -245,10 +298,11 @@ def mock_llm_response():
245
  return AsyncMock(return_value=content)
246
  return _mock
247
 
 
248
  @pytest.fixture
249
  def sample_evidence():
250
  """Sample Evidence objects for testing."""
251
- from src.features.search.models import Evidence, Citation
252
  return [
253
  Evidence(
254
  content="Metformin shows promise in Alzheimer's...",
@@ -265,9 +319,9 @@ def sample_evidence():
265
 
266
  ---
267
 
268
- ## 6. Shared Kernel Implementation
269
 
270
- ### `src/shared/config.py`
271
 
272
  ```python
273
  """Application configuration using Pydantic Settings."""
@@ -276,6 +330,7 @@ from pydantic import Field
276
  from typing import Literal
277
  import structlog
278
 
 
279
  class Settings(BaseSettings):
280
  """Strongly-typed application settings."""
281
 
@@ -293,10 +348,11 @@ class Settings(BaseSettings):
293
  default="openai",
294
  description="Which LLM provider to use"
295
  )
296
- llm_model: str = Field(
297
- default="gpt-4o-mini",
298
- description="Model name to use"
299
- )
 
300
 
301
  # Agent Configuration
302
  max_iterations: int = Field(default=10, ge=1, le=50)
@@ -342,11 +398,12 @@ def configure_logging(settings: Settings) -> None:
342
  settings = get_settings()
343
  ```
344
 
345
- ### `src/shared/exceptions.py`
346
 
347
  ```python
348
  """Custom exceptions for DeepCritical."""
349
 
 
350
  class DeepCriticalError(Exception):
351
  """Base exception for all DeepCritical errors."""
352
  pass
@@ -376,7 +433,7 @@ class RateLimitError(SearchError):
376
 
377
  ## 7. TDD Workflow: First Test
378
 
379
- ### `tests/unit/shared/test_config.py`
380
 
381
  ```python
382
  """Unit tests for configuration loading."""
@@ -390,7 +447,7 @@ class TestSettings:
390
 
391
  def test_default_max_iterations(self):
392
  """Settings should have default max_iterations of 10."""
393
- from src.shared.config import Settings
394
 
395
  # Clear any env vars
396
  with patch.dict(os.environ, {}, clear=True):
@@ -399,7 +456,7 @@ class TestSettings:
399
 
400
  def test_max_iterations_from_env(self):
401
  """Settings should read MAX_ITERATIONS from env."""
402
- from src.shared.config import Settings
403
 
404
  with patch.dict(os.environ, {"MAX_ITERATIONS": "25"}):
405
  settings = Settings()
@@ -407,7 +464,7 @@ class TestSettings:
407
 
408
  def test_invalid_max_iterations_raises(self):
409
  """Settings should reject invalid max_iterations."""
410
- from src.shared.config import Settings
411
  from pydantic import ValidationError
412
 
413
  with patch.dict(os.environ, {"MAX_ITERATIONS": "100"}):
@@ -416,7 +473,7 @@ class TestSettings:
416
 
417
  def test_get_api_key_openai(self):
418
  """get_api_key should return OpenAI key when provider is openai."""
419
- from src.shared.config import Settings
420
 
421
  with patch.dict(os.environ, {
422
  "LLM_PROVIDER": "openai",
@@ -427,7 +484,7 @@ class TestSettings:
427
 
428
  def test_get_api_key_missing_raises(self):
429
  """get_api_key should raise when key is not set."""
430
- from src.shared.config import Settings
431
 
432
  with patch.dict(os.environ, {"LLM_PROVIDER": "openai"}, clear=True):
433
  settings = Settings()
@@ -444,7 +501,7 @@ class TestSettings:
444
  uv sync --all-extras
445
 
446
  # Run tests (should pass after implementing config.py)
447
- uv run pytest tests/unit/shared/test_config.py -v
448
 
449
  # Run full test suite with coverage
450
  uv run pytest --cov=src --cov-report=term-missing
@@ -471,9 +528,9 @@ uv run pre-commit install
471
  - [ ] Create `.env.example` and `.env`
472
  - [ ] Create `.pre-commit-config.yaml`
473
  - [ ] Create `tests/conftest.py`
474
- - [ ] Implement `src/shared/config.py`
475
- - [ ] Implement `src/shared/exceptions.py`
476
- - [ ] Write tests in `tests/unit/shared/test_config.py`
477
  - [ ] Run `uv sync --all-extras`
478
  - [ ] Run `uv run pytest` β€” **ALL TESTS MUST PASS**
479
  - [ ] Run `uv run ruff check` β€” **NO ERRORS**
@@ -487,10 +544,10 @@ uv run pre-commit install
487
 
488
  Phase 1 is **COMPLETE** when:
489
 
490
- 1. βœ… `uv run pytest` passes with 100% of tests green
491
- 2. βœ… `uv run ruff check src tests` has 0 errors
492
- 3. βœ… `uv run mypy src` has 0 errors
493
- 4. βœ… Pre-commit hooks are installed and working
494
- 5. βœ… `from src.shared.config import settings` works in Python REPL
495
 
496
  **Proceed to Phase 2 ONLY after all checkboxes are complete.**
 
2
 
3
  **Goal**: Establish a "Gucci Banger" development environment using 2025 best practices.
4
  **Philosophy**: "If the build isn't solid, the agent won't be."
 
5
 
6
  ---
7
 
 
149
 
150
  ---
151
 
152
+ ## 4. Directory Structure (Maintainer's Structure)
153
 
154
  ```bash
155
+ # Execute these commands to create the directory structure
156
+ mkdir -p src/utils
157
+ mkdir -p src/tools
158
+ mkdir -p src/prompts
159
+ mkdir -p src/agent_factory
160
+ mkdir -p src/middleware
161
+ mkdir -p src/database_services
162
+ mkdir -p src/retrieval_factory
163
+ mkdir -p tests/unit/tools
164
+ mkdir -p tests/unit/agent_factory
165
+ mkdir -p tests/unit/utils
166
  mkdir -p tests/integration
167
 
168
  # Create __init__.py files (required for imports)
169
  touch src/__init__.py
170
+ touch src/utils/__init__.py
171
+ touch src/tools/__init__.py
172
+ touch src/prompts/__init__.py
173
+ touch src/agent_factory/__init__.py
 
 
174
  touch tests/__init__.py
175
  touch tests/unit/__init__.py
176
+ touch tests/unit/tools/__init__.py
177
+ touch tests/unit/agent_factory/__init__.py
178
+ touch tests/unit/utils/__init__.py
 
 
179
  touch tests/integration/__init__.py
180
  ```
181
 
182
+ ### Final Structure:
183
+
184
+ ```
185
+ src/
186
+ β”œβ”€β”€ __init__.py
187
+ β”œβ”€β”€ app.py # Entry point (Gradio UI)
188
+ β”œβ”€β”€ orchestrator.py # Agent loop
189
+ β”œβ”€β”€ agent_factory/ # Agent creation and judges
190
+ β”‚ β”œβ”€β”€ __init__.py
191
+ β”‚ β”œβ”€β”€ agents.py
192
+ β”‚ └── judges.py
193
+ β”œβ”€β”€ tools/ # Search tools
194
+ β”‚ β”œβ”€β”€ __init__.py
195
+ β”‚ β”œβ”€β”€ pubmed.py
196
+ β”‚ β”œβ”€β”€ websearch.py
197
+ β”‚ └── search_handler.py
198
+ β”œβ”€β”€ prompts/ # Prompt templates
199
+ β”‚ β”œβ”€β”€ __init__.py
200
+ β”‚ └── judge.py
201
+ β”œβ”€β”€ utils/ # Shared utilities
202
+ β”‚ β”œβ”€β”€ __init__.py
203
+ β”‚ β”œβ”€β”€ config.py
204
+ β”‚ β”œβ”€β”€ exceptions.py
205
+ β”‚ β”œβ”€β”€ models.py
206
+ β”‚ β”œβ”€β”€ dataloaders.py
207
+ β”‚ └── parsers.py
208
+ β”œβ”€β”€ middleware/ # (Future)
209
+ β”œβ”€β”€ database_services/ # (Future)
210
+ └── retrieval_factory/ # (Future)
211
+
212
+ tests/
213
+ β”œβ”€β”€ __init__.py
214
+ β”œβ”€β”€ conftest.py
215
+ β”œβ”€β”€ unit/
216
+ β”‚ β”œβ”€β”€ __init__.py
217
+ β”‚ β”œβ”€β”€ tools/
218
+ β”‚ β”‚ β”œβ”€β”€ __init__.py
219
+ β”‚ β”‚ β”œβ”€β”€ test_pubmed.py
220
+ β”‚ β”‚ β”œβ”€β”€ test_websearch.py
221
+ β”‚ β”‚ └── test_search_handler.py
222
+ β”‚ β”œβ”€β”€ agent_factory/
223
+ β”‚ β”‚ β”œβ”€β”€ __init__.py
224
+ β”‚ β”‚ └── test_judges.py
225
+ β”‚ β”œβ”€β”€ utils/
226
+ β”‚ β”‚ β”œβ”€β”€ __init__.py
227
+ β”‚ β”‚ └── test_config.py
228
+ β”‚ └── test_orchestrator.py
229
+ └── integration/
230
+ β”œβ”€β”€ __init__.py
231
+ └── test_pubmed_live.py
232
+ ```
233
+
234
  ---
235
 
236
  ## 5. Configuration Files
 
242
  OPENAI_API_KEY=sk-your-key-here
243
  ANTHROPIC_API_KEY=sk-ant-your-key-here
244
 
245
+ # Optional: PubMed API key (higher rate limits)
246
+ NCBI_API_KEY=your-ncbi-key-here
247
+
248
  # Optional: For HuggingFace deployment
249
  HF_TOKEN=hf_your-token-here
250
 
 
281
  import pytest
282
  from unittest.mock import AsyncMock
283
 
284
+
285
  @pytest.fixture
286
  def mock_httpx_client(mocker):
287
  """Mock httpx.AsyncClient for API tests."""
 
290
  mock.return_value.__aexit__ = AsyncMock(return_value=None)
291
  return mock
292
 
293
+
294
  @pytest.fixture
295
  def mock_llm_response():
296
  """Factory fixture for mocking LLM responses."""
 
298
  return AsyncMock(return_value=content)
299
  return _mock
300
 
301
+
302
  @pytest.fixture
303
  def sample_evidence():
304
  """Sample Evidence objects for testing."""
305
+ from src.utils.models import Evidence, Citation
306
  return [
307
  Evidence(
308
  content="Metformin shows promise in Alzheimer's...",
 
319
 
320
  ---
321
 
322
+ ## 6. Core Utilities Implementation
323
 
324
+ ### `src/utils/config.py`
325
 
326
  ```python
327
  """Application configuration using Pydantic Settings."""
 
330
  from typing import Literal
331
  import structlog
332
 
333
+
334
  class Settings(BaseSettings):
335
  """Strongly-typed application settings."""
336
 
 
348
  default="openai",
349
  description="Which LLM provider to use"
350
  )
351
+ openai_model: str = Field(default="gpt-4o", description="OpenAI model name")
352
+ anthropic_model: str = Field(default="claude-3-5-sonnet-20241022", description="Anthropic model")
353
+
354
+ # PubMed Configuration
355
+ ncbi_api_key: str | None = Field(default=None, description="NCBI API key for higher rate limits")
356
 
357
  # Agent Configuration
358
  max_iterations: int = Field(default=10, ge=1, le=50)
 
398
  settings = get_settings()
399
  ```
400
 
401
+ ### `src/utils/exceptions.py`
402
 
403
  ```python
404
  """Custom exceptions for DeepCritical."""
405
 
406
+
407
  class DeepCriticalError(Exception):
408
  """Base exception for all DeepCritical errors."""
409
  pass
 
433
 
434
  ## 7. TDD Workflow: First Test
435
 
436
+ ### `tests/unit/utils/test_config.py`
437
 
438
  ```python
439
  """Unit tests for configuration loading."""
 
447
 
448
  def test_default_max_iterations(self):
449
  """Settings should have default max_iterations of 10."""
450
+ from src.utils.config import Settings
451
 
452
  # Clear any env vars
453
  with patch.dict(os.environ, {}, clear=True):
 
456
 
457
  def test_max_iterations_from_env(self):
458
  """Settings should read MAX_ITERATIONS from env."""
459
+ from src.utils.config import Settings
460
 
461
  with patch.dict(os.environ, {"MAX_ITERATIONS": "25"}):
462
  settings = Settings()
 
464
 
465
  def test_invalid_max_iterations_raises(self):
466
  """Settings should reject invalid max_iterations."""
467
+ from src.utils.config import Settings
468
  from pydantic import ValidationError
469
 
470
  with patch.dict(os.environ, {"MAX_ITERATIONS": "100"}):
 
473
 
474
  def test_get_api_key_openai(self):
475
  """get_api_key should return OpenAI key when provider is openai."""
476
+ from src.utils.config import Settings
477
 
478
  with patch.dict(os.environ, {
479
  "LLM_PROVIDER": "openai",
 
484
 
485
  def test_get_api_key_missing_raises(self):
486
  """get_api_key should raise when key is not set."""
487
+ from src.utils.config import Settings
488
 
489
  with patch.dict(os.environ, {"LLM_PROVIDER": "openai"}, clear=True):
490
  settings = Settings()
 
501
  uv sync --all-extras
502
 
503
  # Run tests (should pass after implementing config.py)
504
+ uv run pytest tests/unit/utils/test_config.py -v
505
 
506
  # Run full test suite with coverage
507
  uv run pytest --cov=src --cov-report=term-missing
 
528
  - [ ] Create `.env.example` and `.env`
529
  - [ ] Create `.pre-commit-config.yaml`
530
  - [ ] Create `tests/conftest.py`
531
+ - [ ] Implement `src/utils/config.py`
532
+ - [ ] Implement `src/utils/exceptions.py`
533
+ - [ ] Write tests in `tests/unit/utils/test_config.py`
534
  - [ ] Run `uv sync --all-extras`
535
  - [ ] Run `uv run pytest` β€” **ALL TESTS MUST PASS**
536
  - [ ] Run `uv run ruff check` β€” **NO ERRORS**
 
544
 
545
  Phase 1 is **COMPLETE** when:
546
 
547
+ 1. `uv run pytest` passes with 100% of tests green
548
+ 2. `uv run ruff check src tests` has 0 errors
549
+ 3. `uv run mypy src` has 0 errors
550
+ 4. Pre-commit hooks are installed and working
551
+ 5. `from src.utils.config import settings` works in Python REPL
552
 
553
  **Proceed to Phase 2 ONLY after all checkboxes are complete.**