Skip to content

Teaching AI Your Development Philosophy


License: Apache License 2.0 Copyright: © 2025 Smart AI Memory, LLC Project: AI Nurse Florence Repository: https://github.com/silversurfer562/ai-nurse-florence


A comprehensive guide to documenting and transferring your development philosophy to AI collaborators


Introduction

One of the most valuable aspects of working with AI is the ability to teach it your personal development philosophy - the habits, processes, and patterns you've learned from mentors, education, and experience. This chapter explains how to effectively document and transfer this knowledge so AI can consistently apply your approach across all your work.

This builds on the concepts from "How Claude Learns" (Chapter X) and shows you the practical implementation of knowledge transfer.


The Challenge: From Implicit to Explicit Knowledge

Most developers carry their philosophy implicitly: - "I just know how I like code structured" - "That's how Shirley taught me" - "I learned that the hard way in production"

The challenge is making this explicit so AI can learn and apply it.

Why This Matters

When you document your philosophy: 1. AI applies your patterns consistently - No more explaining preferences repeatedly 2. You catch your own deviations - Documentation serves as a checklist 3. Team alignment improves - New members learn your approach 4. Knowledge is preserved - Mentor's teachings don't fade 5. Book material writes itself - Documentation becomes chapters


The Philosophy Stack: A Layered Approach

The most effective way to teach AI your philosophy is through four interconnected layers:

┌─────────────────────────────────────────┐
│ Level 1: High-Level Philosophy          │
│ DEVELOPMENT_PHILOSOPHY.md                │
│ • Core principles and values             │
│ • Decision-making framework              │
│ • Your "why" behind choices              │
└─────────────────────────────────────────┘
              ▼ Applied through
┌─────────────────────────────────────────┐
│ Level 2: Concrete Standards             │
│ CODING_STANDARDS.md                      │
│ • Specific rules AI can follow           │
│ • Code style preferences                 │
│ • Architecture patterns                  │
└─────────────────────────────────────────┘
              ▼ Implemented via
┌─────────────────────────────────────────┐
│ Level 3: Reusable Templates              │
│ PATTERNS.md + example code               │
│ • Actual code AI can copy/adapt          │
│ • Annotated examples                     │
│ • Common solutions to recurring problems │
└─────────────────────────────────────────┘
              ▼ Reinforced by
┌─────────────────────────────────────────┐
│ Level 4: In-Code Documentation           │
│ Comments, docstrings, type hints         │
│ • Points back to standards               │
│ • Explains "why" not just "what"         │
│ • Links to relevant documentation        │
└─────────────────────────────────────────┘

Each layer serves a specific purpose and reinforces the others.


Level 1: High-Level Philosophy

Purpose

Capture your values and decision-making framework - the "why" behind your choices.

What to Include

Core Principles

The fundamental beliefs that guide your development:

Template Structure:

# Development Philosophy

## Core Principles

### 1. Simplicity Over Cleverness
**What**: Choose straightforward solutions over "clever" code

**Why**: Clever code is hard to maintain and debug at 2 AM in production

**When**: Always, unless performance profiling proves complexity necessary

**Example**: Use a simple if/else instead of a one-liner regex if both work

**From**: Production incident at [Company] where regex bug cost $50K

Lessons from Mentors

Shirley Thomas's Teachings:

### Principle: Dependency Injection Always

**What Shirley taught**: "Never instantiate dependencies inside a class"

**Rationale**:
- Makes testing trivial (inject mocks)
- Makes code flexible (swap implementations)
- Makes dependencies explicit (no hidden coupling)

**Example**:
```python
# ❌ BAD (Shirley would reject this PR)
class PatientService:
    def __init__(self):
        self.db = Database()  # Hard-coded dependency!

# ✅ GOOD (Shirley-approved)
class PatientService:
    def __init__(self, db: Database):
        self.db = db  # Injected, testable, flexible

Impact: This pattern has prevented countless production bugs

#### Experience-Based Wisdom

```markdown
### Principle: No Silent Failures

**What**: Never catch exceptions without logging or re-raising

**Why**: Silent failures hide bugs that compound into disasters

**When**: Learned this when a silent exception caused data corruption affecting 1000+ patients

**Before (naive approach)**:
```python
try:
    save_patient_data(patient)
except:
    pass  # Silent failure - DISASTER

After (lesson learned):

try:
    save_patient_data(patient)
except PatientDataError as e:
    logger.error(f"Failed to save patient {patient.mrn}: {e}")
    raise  # Re-raise to fail fast

Result: Prevented similar issues in AI Nurse Florence

### Key Questions to Answer

To help articulate your philosophy, consider:

**From Mentors:**
- What were their key teachings?
- What patterns did they emphasize?
- What mistakes did they warn against?
- What's their philosophy on testing, documentation, error handling?

**From Education:**
- What computer science principles do you value most?
- Object-oriented vs functional approaches?
- Data structure preferences?
- Algorithm complexity considerations?

**From Experience:**
- What burned you in production?
- What "clever" code did you regret later?
- What simple solutions worked better than complex ones?
- What technical debt lessons have you learned?

---

## Level 2: Concrete Standards

### Purpose
Provide **specific, enforceable rules** that AI can follow mechanically.

### What to Include

#### File Organization

```markdown
## File Organization

### Naming Conventions

✅ **DO**: Use snake_case for Python files
✅ **DO**: Name files after their primary class/function
❌ **DON'T**: Use generic names like utils.py

**Examples**:
- `patient_service.py` (contains PatientService class)
- `epic_fhir_client.py` (contains EpicFHIRClient class)
- NOT `utils.py` (too vague, AI (or humans) must guess purpose)

### Folder Structure
src/ ├── routers/ # API endpoints only ├── services/ # Business logic only ├── models/ # Data models (Pydantic, SQLAlchemy) ├── utils/ # Shared utilities (must be generic) └── integrations # External system clients (Epic, OpenAI)
**Rule**: One concept per folder. No mixing concerns.

Code Style

## Function Definitions

### Standard Pattern

```python
# ✅ GOOD: Type hints, docstring, clear purpose
async def fetch_patient_data(
    mrn: str,
    include_history: bool = False
) -> PatientData:
    """
    Retrieve patient data from Epic FHIR.

    Args:
        mrn: Medical record number
        include_history: Include historical records

    Returns:
        Complete patient data object

    Raises:
        PatientNotFoundError: If MRN doesn't exist

    See Also:
        - PATTERNS.md: Service Layer Pattern
        - ADR-0002: Epic FHIR Integration
    """
    logger.info(f"Fetching patient: {mrn}")

    # Implementation...
    pass


# ❌ BAD: No types, no docstring, unclear
def get_pat(m, h=0):
    return db.q(m, h)

Why This Standard

  • Type hints: Catch errors at development time, not production
  • Docstring: AI and humans understand purpose
  • Logging: Track operations for debugging
  • Cross-references: Link to philosophy and patterns
    #### Error Handling Pattern
    
    ```markdown
    ## Error Handling
    
    ### Custom Exceptions
    
    ```python
    # Per DEVELOPMENT_PHILOSOPHY.md: Specific exceptions, never generic
    
    # ✅ GOOD: Specific, actionable
    class PatientNotFoundError(Exception):
        """Raised when patient MRN doesn't exist in system"""
        pass
    
    class EpicConnectionError(Exception):
        """Raised when Epic FHIR API is unreachable"""
        pass
    
    # Usage
    try:
        patient = fetch_patient(mrn)
    except PatientNotFoundError:
        # Specific handling for missing patient
        logger.warning(f"Patient {mrn} not found")
        return None
    except EpicConnectionError:
        # Specific handling for connection issues
        logger.error("Epic API down, using cached data")
        return get_cached_patient(mrn)
    
    
    # ❌ BAD: Generic exception, can't handle specifically
    try:
        patient = fetch_patient(mrn)
    except Exception as e:
        # What happened? Network? Missing? Permission denied?
        # Can't handle appropriately
        pass
    

Rule

Always create custom exceptions for domain errors.

---

## Level 3: Reusable Templates

### Purpose
Provide **copy-paste-ready code templates** with explanations.

### Service Layer Pattern

```markdown
# Code Patterns

## Service Layer Pattern

**Use when**: Creating business logic for a domain entity

**Philosophy**: From Shirley Thomas - "Services own business logic, routers just route"

**Template**:

```python
from typing import List, Optional
import logging

class PatientService:
    """
    Business logic for patient operations.

    Pattern from Shirley Thomas:
    - One service per domain entity
    - Dependency injection for database/external services
    - All methods return Pydantic models (never raw dicts)
    - Log at INFO for business operations, ERROR for failures
    - Raise custom exceptions, never generic Exception
    """

    def __init__(
        self,
        db: Database,
        logger: logging.Logger
    ):
        self.db = db
        self.logger = logger

    async def get_patient(self, mrn: str) -> Patient:
        """
        Get patient by MRN.

        Per CODING_STANDARDS.md:
        - Log at INFO level for business operations
        - Raise PatientNotFoundError, not generic Exception
        - Return Pydantic model, not dict

        Args:
            mrn: Medical record number

        Returns:
            Patient object with full demographics

        Raises:
            PatientNotFoundError: If MRN doesn't exist
        """
        self.logger.info(f"Fetching patient: {mrn}")

        patient = self.db.query(Patient).filter_by(mrn=mrn).first()

        if not patient:
            raise PatientNotFoundError(f"Patient {mrn} not found")

        return patient

    async def create_patient(
        self,
        data: PatientCreate
    ) -> Patient:
        """
        Create new patient record.

        Per DEVELOPMENT_PHILOSOPHY.md: Validate early, fail fast

        Args:
            data: Patient creation data (Pydantic validates)

        Returns:
            Created patient object

        Raises:
            PatientAlreadyExistsError: If MRN already in use
        """
        self.logger.info(f"Creating patient: {data.mrn}")

        # Check for duplicates (fail fast)
        existing = self.db.query(Patient).filter_by(mrn=data.mrn).first()
        if existing:
            raise PatientAlreadyExistsError(f"MRN {data.mrn} already exists")

        # Create patient
        patient = Patient(**data.dict())
        self.db.add(patient)
        self.db.commit()

        return patient

Why This Pattern: - ✅ Clear separation of concerns (service handles logic, not routing) - ✅ Easy to test (inject mock database) - ✅ Consistent logging (always know what's happening) - ✅ Type-safe (Pydantic ensures data validity) - ✅ Explicit dependencies (no hidden global state)

Anti-Pattern to Avoid:

# ❌ BAD: Business logic in router
@router.get("/patients/{mrn}")
def get_patient(mrn: str):
    patient = db.query(Patient).filter_by(mrn=mrn).first()  # Logic in router!
    if not patient:
        raise HTTPException(404)  # HTTP-specific error in logic!
    return patient  # Unprocessed database model!
### Router Pattern

```markdown
## Router Pattern

**Use when**: Creating API endpoints

**Philosophy**: Routers are thin - they route, validate, and delegate to services

**Template**:

```python
from fastapi import APIRouter, Depends, HTTPException
from typing import List

from src.services.patient_service import PatientService
from src.models.patient import Patient, PatientCreate

router = APIRouter(
    prefix="/patients",
    tags=["Patients"],
    responses={404: {"description": "Patient not found"}},
)


def get_patient_service() -> PatientService:
    """
    Dependency injection for PatientService.

    Per PATTERNS.md: Always use DI for services
    """
    return PatientService(
        db=get_db(),
        logger=logging.getLogger(__name__)
    )


@router.get("/{mrn}", response_model=Patient)
async def get_patient(
    mrn: str,
    service: PatientService = Depends(get_patient_service)
):
    """
    Get patient by MRN.

    Per CODING_STANDARDS.md:
    - Delegate to service for business logic
    - Convert service exceptions to HTTP responses
    - Return Pydantic model (FastAPI serializes)
    """
    try:
        patient = await service.get_patient(mrn)
        return patient
    except PatientNotFoundError:
        raise HTTPException(status_code=404, detail=f"Patient {mrn} not found")
    except EpicConnectionError:
        raise HTTPException(status_code=503, detail="Epic system temporarily unavailable")


@router.post("/", response_model=Patient, status_code=201)
async def create_patient(
    data: PatientCreate,
    service: PatientService = Depends(get_patient_service)
):
    """
    Create new patient.

    Per DEVELOPMENT_PHILOSOPHY.md: Pydantic validates before service layer
    """
    try:
        patient = await service.create_patient(data)
        return patient
    except PatientAlreadyExistsError as e:
        raise HTTPException(status_code=409, detail=str(e))

Why This Pattern: - ✅ Thin routers (easy to understand) - ✅ Business logic in services (reusable, testable) - ✅ Dependency injection (mockable for tests) - ✅ Clean error handling (service errors → HTTP codes)

---

## Level 4: In-Code Documentation

### Purpose
Reinforce the philosophy directly in code files.

### Example: Fully Documented Service

```python
# src/services/patient_service.py

# Per CODING_STANDARDS.md: Service layer handles business logic
# Per PATTERNS.md: Use dependency injection pattern
# Per ADR-0003: Session-only storage, no PHI caching

from typing import List, Optional
import logging

# Per CODING_STANDARDS.md: Import order: stdlib, third-party, local
from sqlalchemy.orm import Session
from pydantic import BaseModel

from src.models.patient import Patient
from src.utils.exceptions import PatientNotFoundError


class PatientService:
    """
    Patient business logic service.

    Follows PATTERNS.md: Service Layer Pattern
    From Shirley Thomas: Always inject dependencies

    Philosophy:
    - Services own business logic, routers just route
    - Return Pydantic models, never raw database objects
    - Log all operations for debugging
    - Fail fast with specific exceptions
    """

    def __init__(
        self,
        db: Session,
        logger: logging.Logger
    ):
        # Per PATTERNS.md: Store injected dependencies
        self.db = db
        self.logger = logger

    async def get_patient(self, mrn: str) -> Patient:
        """
        Retrieve patient by MRN.

        Per CODING_STANDARDS.md:
        - Always log business operations at INFO level
        - Raise specific exceptions, not generic Exception
        - Return Pydantic models, not dicts

        Per DEVELOPMENT_PHILOSOPHY.md:
        - Fail fast (raise immediately on not found)
        - Log before and after operations
        - Use meaningful error messages

        Args:
            mrn: Medical record number

        Returns:
            Patient object with full demographics

        Raises:
            PatientNotFoundError: If MRN doesn't exist in system

        Example:
            >>> service = PatientService(db, logger)
            >>> patient = await service.get_patient("12345678")
            >>> print(patient.name)
            "John Smith"
        """
        self.logger.info(f"Fetching patient: {mrn}")

        patient = self.db.query(Patient).filter_by(mrn=mrn).first()

        if not patient:
            # Per PATTERNS.md: Use custom exceptions
            self.logger.warning(f"Patient {mrn} not found")
            raise PatientNotFoundError(f"Patient {mrn} not found")

        self.logger.info(f"Retrieved patient: {mrn}")
        return patient

How This Helps AI

When AI reads this file: 1. Sees the philosophy in comments at top 2. Understands the patterns through references 3. Learns the standards from inline comments 4. Can replicate the structure for new services 5. Maintains consistency across the codebase


How AI Uses This Documentation

When Writing New Code

AI's Internal Process:
1. Check PATTERNS.md for similar feature
2. Copy template, adapt for new domain
3. Follow CODING_STANDARDS.md for style
4. Reference DEVELOPMENT_PHILOSOPHY.md for decisions
5. Add comments linking back to docs

When Reviewing Your Code

AI's Review Checklist:
1. Compare against CODING_STANDARDS.md
2. Check if pattern matches PATTERNS.md
3. Verify philosophy alignment with DEVELOPMENT_PHILOSOPHY.md
4. Flag deviations (in case unintentional)
5. Suggest improvements aligned with your approach

When You're Stuck

AI's Help Process:
1. Review DEVELOPMENT_PHILOSOPHY.md for guiding principles
2. Check PATTERNS.md for similar solved problems
3. Suggest solution aligned with your approach
4. Explain why this fits your philosophy

Creating Your Philosophy Documentation

Step 1: High-Level Philosophy Conversation (30-60 minutes)

Have a conversation with AI where you share: - 3-5 core principles that guide your development - Key lessons from mentors (like Shirley Thomas) - Your biggest "never again" moments from production - Your philosophy on testing, docs, and code quality

AI will capture this and create DEVELOPMENT_PHILOSOPHY.md.

Step 2: Extract Patterns from Existing Code (1-2 hours)

AI analyzes your current codebase: - Identifies patterns you already follow - Documents what you're doing right - Notes inconsistencies to address

This creates CODING_STANDARDS.md based on your actual code.

Step 3: Formalize Templates (30 minutes)

Based on extracted patterns: - AI creates copy-paste templates - Annotates with explanations - Links to philosophy and standards

This creates PATTERNS.md.

Step 4: Refactor with Documentation (Ongoing)

As you write code: - Add comments referencing the docs - Update docs when patterns evolve - Use docs as checklist for consistency


Real-World Example: AI Nurse Florence

The Philosophy

Core Principle: "Healthcare software must be transparent and explainable"

From Shirley: "Never hide complexity - make it explicit and testable"

Production Lesson: "Silent failures in healthcare can harm patients"

The Implementation

DEVELOPMENT_PHILOSOPHY.md (excerpt):

### Principle: Explainable AI Decisions

**What**: Every AI-generated clinical suggestion must include reasoning

**Why**: Nurses need to understand and validate AI recommendations

**Example**:
```python
# ✅ GOOD: Explainable
recommendation = {
    "suggestion": "Monitor blood pressure q2h",
    "reasoning": "Patient systolic >160 with history of hypertension",
    "confidence": 0.92,
    "sources": ["JNC-8 Guidelines", "Patient history"]
}

# ❌ BAD: Black box
recommendation = "Monitor BP"  # Why? How did AI decide this?
**CODING_STANDARDS.md** (excerpt):
```markdown
### Clinical AI Responses

**Rule**: All AI responses must include `reasoning` field

**Format**:
```python
class ClinicalRecommendation(BaseModel):
    suggestion: str
    reasoning: str  # REQUIRED - explain the logic
    confidence: float  # REQUIRED - how certain is AI
    sources: List[str]  # REQUIRED - evidence basis
**PATTERNS.md** (excerpt):
```python
# Clinical AI Service Pattern

class ClinicalAIService:
    """
    Per DEVELOPMENT_PHILOSOPHY.md: All AI must be explainable
    """

    async def get_recommendation(
        self,
        patient: Patient,
        context: str
    ) -> ClinicalRecommendation:
        """
        Generate clinical recommendation with reasoning.

        Per DEVELOPMENT_PHILOSOPHY.md: Include explicit reasoning
        Per CODING_STANDARDS.md: Return ClinicalRecommendation model
        """
        # Get AI response
        ai_response = await self.openai_client.chat(
            messages=[
                {"role": "system", "content": "You are a clinical assistant. Always explain your reasoning."},
                {"role": "user", "content": context}
            ]
        )

        # Parse and validate (Pydantic enforces required fields)
        recommendation = ClinicalRecommendation(
            suggestion=ai_response.suggestion,
            reasoning=ai_response.reasoning,  # Required!
            confidence=ai_response.confidence,
            sources=ai_response.sources
        )

        return recommendation

Result: Every clinical suggestion is transparent, which builds trust with nurses and ensures safe AI integration.


Common Pitfalls and Solutions

Pitfall 1: Too Abstract

Problem: Philosophy too vague to be actionable

Example:

❌ "Write good code"  # What does "good" mean?

Solution: Be specific with examples

✅ "Functions should do one thing well"

Example:
```python
# ❌ BAD: Function does too much
def process_patient(patient):
    validate(patient)
    save_to_db(patient)
    send_notification(patient)
    log_audit(patient)

# ✅ GOOD: Each function does one thing
def validate_patient(patient): ...
def save_patient(patient): ...
def notify_new_patient(patient): ...
### Pitfall 2: Too Detailed

**Problem**: Standards become a novel, AI gets lost

**Solution**: Use hierarchy - detailed patterns in separate files

```markdown
# In CODING_STANDARDS.md (concise)
✅ "Use dependency injection. See PATTERNS.md for templates."

# In PATTERNS.md (detailed)
[Full template with examples]

Pitfall 3: Philosophy vs Reality Mismatch

Problem: Documented philosophy doesn't match actual code

Solution: Start with what you actually do, then refine

1. AI analyzes your existing code
2. Documents patterns it finds
3. You validate: "Yes, that's my approach" or "No, I should change that"
4. Update either docs or code to match

Pitfall 4: No Cross-References

Problem: Docs exist in silos, AI doesn't connect them

Solution: Link everything

# In code
# Per PATTERNS.md: Service Layer Pattern
# Per ADR-0002: Epic FHIR Integration
# See DEVELOPMENT_PHILOSOPHY.md: Dependency Injection principle

# In docs
See PATTERNS.md for implementation template
Reference ADR-0003 for architectural decision

Integration with Book Writing

From Philosophy to Book Chapter

Your development philosophy documentation doubles as book material:

DocumentationBook Chapter

Add: - Personal narrative ("When Shirley first taught me this...") - War stories ("The production incident that taught me...") - Evolution of thinking ("I used to believe X, but learned Y") - Impact and results ("This approach prevented...")

Example:

From DEVELOPMENT_PHILOSOPHY.md (technical):

### Principle: Fail Fast

**What**: Raise exceptions immediately when invariants violated
**Why**: Prevents cascading failures and data corruption

To Book Chapter (narrative):

## The $50,000 Lesson in Failing Fast

I learned this principle the hard way. At my previous company, I wrote
code that silently ignored validation errors, thinking I was being
"defensive" by letting the system continue. Three months later, those
silent failures had corrupted 10,000 patient records.

Shirley Thomas reviewed my code after the incident. "Patrick," she said,
"defensive programming doesn't mean swallowing errors. It means failing
fast and loud when something's wrong."

That lesson cost the company $50,000 in data cleanup. It taught me a
principle I now apply religiously in AI Nurse Florence...

[Technical explanation and code examples follow]


Summary: The Complete System

What You've Built

  1. DEVELOPMENT_PHILOSOPHY.md: Your "why" and values
  2. CODING_STANDARDS.md: Specific rules AI follows
  3. PATTERNS.md: Copy-paste templates
  4. In-Code Documentation: Reinforcement and links

How It Works

Your Philosophy (implicit)
    ↓ Made explicit through
Documentation (PHILOSOPHY + STANDARDS + PATTERNS)
    ↓ Applied by
AI (reads docs, follows patterns, maintains consistency)
    ↓ Reinforced by
In-Code Comments (link back to docs)
    ↓ Results in
Consistent Codebase (aligned with your philosophy)

Benefits

For You: - AI applies your patterns without repeated explanations - Documentation serves as your own checklist - Knowledge is preserved for future team members - Book chapters write themselves

For AI: - Clear rules to follow - Context for decision-making - Ability to maintain your style - Framework for helpful suggestions

For AI Nurse Florence: - Consistent architecture - Maintainable, understandable code - Documented patterns for scaling - Foundation for intelligent features


Next Steps

  1. Schedule 1 hour with AI for philosophy conversation
  2. Let AI analyze your existing codebase
  3. Review and refine the generated documentation
  4. Start referencing docs in new code
  5. Iterate as patterns evolve

The investment in documenting your philosophy pays dividends immediately and compounds over time.


Conclusion

Teaching AI your development philosophy isn't just about AI - it's about codifying the wisdom you've gained from mentors like Shirley Thomas, from your education, and from hard-won production experience. When you make implicit knowledge explicit, everyone benefits: AI becomes more helpful, your code becomes more consistent, your team becomes more aligned, and your book writes itself.


Written: January 7, 2025 Author: Patrick Roebuck (with Claude) Purpose: Book chapter on transferring development philosophy to AI Status: Complete - Ready for book inclusion