---
phase: 01-foundation
plan: 02
type: execute
wave: 2
depends_on: ["01-01"]
files_modified:
  - src/lib/server/db/repository.ts
  - src/hooks.server.ts
  - src/routes/+page.server.ts
  - src/routes/+page.svelte
  - data/.gitkeep
autonomous: true

must_haves:
  truths:
    - "Repository provides create, read, update, delete operations for entries"
    - "Database initializes automatically on first server request"
    - "Data directory structure exists with .gitkeep"
    - "Basic page shows database connection status"
  artifacts:
    - path: "src/lib/server/db/repository.ts"
      provides: "EntryRepository with typed CRUD operations"
      exports: ["entryRepository", "EntryRepository"]
    - path: "src/hooks.server.ts"
      provides: "Server hooks for database initialization"
      contains: "handle"
    - path: "data/.gitkeep"
      provides: "Data directory placeholder for git"
  key_links:
    - from: "src/lib/server/db/repository.ts"
      to: "src/lib/server/db/index.ts"
      via: "import db"
      pattern: "import.*db.*from"
    - from: "src/hooks.server.ts"
      to: "src/lib/server/db/index.ts"
      via: "import db for init"
      pattern: "import.*db"
    - from: "src/routes/+page.server.ts"
      to: "src/lib/server/db/repository.ts"
      via: "import repository"
      pattern: "import.*repository"
---

<objective>
Create the repository layer for typed CRUD operations and wire up database initialization with a verification page.

Purpose: Provides the data access layer that all future features will use, and verifies the foundation works end-to-end.
Output: Working repository with CRUD operations, auto-initializing database, and a verification page proving everything connects.
</objective>

<execution_context>
@/home/tho/.claude/get-shit-done/workflows/execute-plan.md
@/home/tho/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/phases/01-foundation/01-01-SUMMARY.md
@src/lib/server/db/schema.ts
@src/lib/server/db/index.ts
</context>

<tasks>

<task type="auto">
  <name>Task 1: Create EntryRepository with typed CRUD operations</name>
  <files>
    src/lib/server/db/repository.ts
  </files>
  <action>
Create `src/lib/server/db/repository.ts` implementing the repository pattern:

```typescript
import { eq, desc } from 'drizzle-orm';
import { db } from './index';
import { entries, type Entry, type NewEntry } from './schema';
import { nanoid } from 'nanoid';

export interface EntryRepository {
  create(entry: Omit<NewEntry, 'id' | 'createdAt' | 'updatedAt'>): Entry;
  getById(id: string): Entry | undefined;
  getAll(options?: { limit?: number; offset?: number }): Entry[];
  update(id: string, updates: Partial<Omit<Entry, 'id' | 'createdAt'>>): Entry | undefined;
  delete(id: string): boolean;
  count(): number;
}

class SQLiteEntryRepository implements EntryRepository {
  create(entry: Omit<NewEntry, 'id' | 'createdAt' | 'updatedAt'>): Entry {
    const now = new Date().toISOString();
    const newEntry: NewEntry = {
      ...entry,
      id: nanoid(),
      createdAt: now,
      updatedAt: now,
    };

    db.insert(entries).values(newEntry).run();
    return this.getById(newEntry.id)!;
  }

  getById(id: string): Entry | undefined {
    return db.select().from(entries).where(eq(entries.id, id)).get();
  }

  getAll(options: { limit?: number; offset?: number } = {}): Entry[] {
    const { limit = 100, offset = 0 } = options;
    return db
      .select()
      .from(entries)
      .orderBy(desc(entries.createdAt))
      .limit(limit)
      .offset(offset)
      .all();
  }

  update(id: string, updates: Partial<Omit<Entry, 'id' | 'createdAt'>>): Entry | undefined {
    const existing = this.getById(id);
    if (!existing) return undefined;

    db.update(entries)
      .set({
        ...updates,
        updatedAt: new Date().toISOString(),
      })
      .where(eq(entries.id, id))
      .run();

    return this.getById(id);
  }

  delete(id: string): boolean {
    const existing = this.getById(id);
    if (!existing) return false;

    db.delete(entries).where(eq(entries.id, id)).run();
    return true;
  }

  count(): number {
    const result = db.select().from(entries).all();
    return result.length;
  }
}

// Singleton instance
export const entryRepository: EntryRepository = new SQLiteEntryRepository();
```

This provides:
- Type-safe CRUD operations using Drizzle ORM
- Automatic ID generation with nanoid
- Automatic timestamp management (createdAt, updatedAt)
- Pagination support via limit/offset
- Singleton pattern for consistent access
  </action>
  <verify>
Create a quick test by importing the repository:
```typescript
import { entryRepository } from './repository';
const entry = entryRepository.create({ content: 'Test', type: 'thought' });
console.log(entry); // Should have id, createdAt, updatedAt
const retrieved = entryRepository.getById(entry.id);
console.log(retrieved); // Should match entry
entryRepository.delete(entry.id);
```
TypeScript compilation should pass with `npm run check`.
  </verify>
  <done>
EntryRepository interface and implementation exist with create, getById, getAll, update, delete, count methods.
All methods are type-safe with Drizzle schema types.
  </done>
</task>

<task type="auto">
  <name>Task 2: Create data directory, server hooks, and verification page</name>
  <files>
    data/.gitkeep
    data/attachments/.gitkeep
    src/hooks.server.ts
    src/routes/+page.server.ts
    src/routes/+page.svelte
  </files>
  <action>
1. Create data directory structure for persistence:

```bash
mkdir -p data/attachments
touch data/.gitkeep
touch data/attachments/.gitkeep
```

Add to `.gitignore`:
```
# Data directory (persistent data)
data/*.db
data/*.db-wal
data/*.db-shm
data/attachments/*
!data/.gitkeep
!data/attachments/.gitkeep
```

2. Create `src/hooks.server.ts` for database initialization:

```typescript
import type { Handle } from '@sveltejs/kit';
import { db } from '$lib/server/db';
import { entries } from '$lib/server/db/schema';
import { sql } from 'drizzle-orm';

// Ensure database tables exist on first request
let initialized = false;

export const handle: Handle = async ({ event, resolve }) => {
  if (!initialized) {
    // Run a simple query to ensure connection works
    // Drizzle with push handles schema creation, but this verifies connectivity
    try {
      db.select().from(entries).limit(1).all();
      initialized = true;
      console.log('Database initialized successfully');
    } catch (error) {
      console.error('Database initialization failed:', error);
      // Don't block - let the error propagate to the request
    }
  }

  return resolve(event);
};
```

3. Create `src/routes/+page.server.ts` for verification data:

```typescript
import type { PageServerLoad } from './$types';
import { entryRepository } from '$lib/server/db/repository';

export const load: PageServerLoad = async () => {
  const count = entryRepository.count();

  // Create a test entry if none exist (for verification)
  let testEntry = null;
  if (count === 0) {
    testEntry = entryRepository.create({
      title: 'Foundation Test',
      content: 'This entry was created to verify the foundation is working.',
      type: 'thought',
    });
  }

  const entries = entryRepository.getAll({ limit: 5 });

  return {
    dbStatus: 'connected',
    entryCount: testEntry ? count + 1 : count,
    recentEntries: entries,
  };
};
```

4. Update `src/routes/+page.svelte` to show verification status:

```svelte
<script lang="ts">
  let { data } = $props();
</script>

<main class="min-h-screen bg-gray-50 p-8">
  <div class="max-w-2xl mx-auto">
    <h1 class="text-3xl font-bold text-gray-900 mb-2">TaskPlanner</h1>
    <p class="text-gray-600 mb-8">Foundation Phase Complete</p>

    <div class="bg-white rounded-lg shadow p-6 mb-6">
      <h2 class="text-lg font-semibold text-gray-800 mb-4">System Status</h2>

      <div class="space-y-3">
        <div class="flex items-center gap-2">
          <span class="w-3 h-3 rounded-full bg-green-500"></span>
          <span class="text-gray-700">Database: {data.dbStatus}</span>
        </div>
        <div class="flex items-center gap-2">
          <span class="w-3 h-3 rounded-full bg-green-500"></span>
          <span class="text-gray-700">Entries in database: {data.entryCount}</span>
        </div>
        <div class="flex items-center gap-2">
          <span class="w-3 h-3 rounded-full bg-green-500"></span>
          <span class="text-gray-700">Repository layer: operational</span>
        </div>
      </div>
    </div>

    {#if data.recentEntries.length > 0}
      <div class="bg-white rounded-lg shadow p-6">
        <h2 class="text-lg font-semibold text-gray-800 mb-4">Recent Entries</h2>
        <ul class="space-y-2">
          {#each data.recentEntries as entry}
            <li class="p-3 bg-gray-50 rounded">
              <div class="font-medium text-gray-900">{entry.title || '(no title)'}</div>
              <div class="text-sm text-gray-600">{entry.content}</div>
              <div class="text-xs text-gray-400 mt-1">
                Type: {entry.type} | Created: {new Date(entry.createdAt).toLocaleString()}
              </div>
            </li>
          {/each}
        </ul>
      </div>
    {/if}
  </div>
</main>
```
  </action>
  <verify>
1. `ls data/` - should show .gitkeep and attachments/
2. `npm run dev` - server starts without errors
3. Visit http://localhost:5173 - page shows:
   - "Database: connected"
   - "Entries in database: 1" (or more)
   - "Repository layer: operational"
   - The test entry displayed in "Recent Entries"
4. Check `data/taskplaner.db` exists
5. Run `npm run check` - no TypeScript errors
  </verify>
  <done>
Data directory structure created with .gitkeep files.
Server hooks initialize database on first request.
Verification page displays database status and entry count.
Full end-to-end data flow works: hooks -> repository -> page.
  </done>
</task>

</tasks>

<verification>
1. Repository CRUD operations work (create, read, update, delete)
2. Database auto-initializes on first server request
3. Data directory exists with attachments subdirectory
4. Verification page shows green status for all systems
5. Test entry appears in recent entries list
6. `npm run check` passes
7. `npm run dev` serves the page without errors
</verification>

<success_criteria>
- EntryRepository provides typed create, getById, getAll, update, delete, count operations
- Database initializes automatically via server hooks
- Data directory structure exists (data/, data/attachments/)
- Verification page confirms database connected, entry count, repository operational
- Test entry created and displayed proving end-to-end data flow
</success_criteria>

<output>
After completion, create `.planning/phases/01-foundation/01-02-SUMMARY.md`
</output>
