Files
Code_of_Conquest/api/docs/PHASE4_IMPLEMENTATION.md
2025-11-24 23:10:55 -06:00

28 KiB

Phase 4: AI Integration + Story Progression + Quest System

Implementation Plan

Note: This document contains detailed implementation tasks for developers building the API backend. For high-level project roadmap and progress tracking, see /docs/ROADMAP.md.

Document Version: 1.2 Created: November 16, 2025 Last Updated: November 23, 2025 Status: In Progress Duration: 3 weeks (21 days) Total Tasks: 45 tasks Completed Tasks: 22/45 (49%)


Next Tasks

  • Task 8.29: Create story gameplay template with HTMX

Overview

Phase 4 delivers the core single-player gameplay experience for Code of Conquest. This phase integrates AI narrative generation via Replicate (Llama-3 and Claude models), implements turn-based story progression with button-based actions, and creates a context-aware quest system.

Architecture Note: All AI models (Llama-3, Claude Haiku/Sonnet/Opus) are accessed through the Replicate API for unified billing and management.

Key Deliverables:

  • AI narrative generation with tier-based model selection
  • Turn-based story progression system
  • YAML-driven quest system with context-aware offering
  • Cost tracking and usage limits
  • Complete solo gameplay loop

Development Approach:

  • Tasks are moderately granular (4 hours each)
  • Testing bundled into implementation tasks
  • Verification checkpoints after major features
  • YAML data created inline with features

Week 8: Story Progression System (Days 8-14)

Goal: Implement turn-based story progression with button-based actions

Task Group 8: Story UI & Integration (Tasks 29-31)

Task 8.29: Create story gameplay template with HTMX

Duration: 5 hours File: templates/game/story.html

Implementation:

  • Create main story gameplay page layout:
    • Header: Character info, turn count, location
    • Left sidebar: Quest tracker (placeholder for Week 9)
    • Main area: Latest DM response
    • Action panel: Available action buttons
    • Footer: Custom input (if Premium/Elite)
    • Right sidebar: Conversation history (collapsible)
  • Add HTMX for dynamic updates:
    • Action buttons trigger hx-post="/api/v1/sessions/{id}/action"
    • Poll job status with hx-trigger="every 2s"
    • Update content when job completes
  • Add loading spinner during AI processing
  • Style with dark fantasy theme (match existing CSS)
  • Add responsive design (mobile-friendly)
  • Write Flask route to render template
  • Test UI rendering

Dependencies: Tasks 8.25-8.28 (API endpoints) Deliverable: Story gameplay UI template

Key HTMX Patterns:

<!-- Action button -->
<button
  hx-post="/api/v1/sessions/{{ session_id }}/action"
  hx-vals='{"action_type": "button", "prompt_id": "ask_locals"}'
  hx-target="#dm-response"
  hx-swap="innerHTML"
  hx-indicator="#loading">
  Ask locals for information
</button>

<!-- Job status polling -->
<div
  hx-get="/api/v1/jobs/{{ job_id }}/status"
  hx-trigger="every 2s"
  hx-swap="outerHTML">
  Processing...
</div>

Task 8.30: Build action button UI with tier filtering

Duration: 4 hours File: templates/game/story.html (extend), app/routes/game.py

Implementation:

  • Create Jinja2 macro for rendering action buttons
  • Filter actions based on user tier (passed from backend)
  • Show locked actions with upgrade prompt for higher tiers
  • Add tooltips with action descriptions
  • Implement custom text input area:
    • Only visible for Premium/Elite
    • Character counter (250 for Premium, 500 for Elite)
    • Submit button with validation
  • Add HTMX for seamless submission
  • Style buttons with RPG aesthetic (icons optional)
  • Disable buttons during AI processing
  • Write Flask route to provide available actions

Dependencies: Task 8.29 (Story template) Deliverable: Dynamic action button system

Jinja2 Macro:

{% macro render_action(action, user_tier, locked=False) %}
<button
  class="action-btn {% if locked %}locked{% endif %}"
  {% if not locked %}
  hx-post="/api/v1/sessions/{{ session_id }}/action"
  hx-vals='{"action_type": "button", "prompt_id": "{{ action.prompt_id }}"}'
  {% else %}
  disabled
  {% endif %}
  title="{{ action.description }}">
  {{ action.display_text }}
  {% if locked %}<span class="lock-icon">🔒</span>{% endif %}
</button>
{% endmacro %}

Task 8.31: CHECKPOINT - Full story turn integration test

Duration: 4 hours

Verification Steps:

  1. Create a new session via UI
  2. Click an action button
  3. Verify loading state appears
  4. Wait for AI response
  5. Verify DM response displayed
  6. Check conversation history updated
  7. Verify turn number incremented
  8. Test with different action buttons
  9. Test custom text input (Premium tier)
  10. Verify tier restrictions enforced (Free can't use Premium actions)
  11. Test rate limiting
  12. Verify Realtime updates work

Success Criteria:

  • Full story turn loop works end-to-end
  • UI updates smoothly with HTMX
  • AI responses are coherent and relevant
  • Tier filtering works correctly
  • Rate limits enforced
  • No errors in browser console or server logs

Week 9: Quest System (Days 15-21)

Goal: Implement YAML-driven quest system with context-aware offering

Task Group 9: Quest Data Models (Tasks 32-34)

Task 9.32: Create Quest dataclasses

Duration: 5 hours File: app/models/quest.py

Implementation:

  • Create QuestObjective dataclass:
    • objective_id, description, objective_type (enum)
    • required_progress, current_progress, completed
  • Create QuestReward dataclass:
    • gold, experience, items (List[Item])
    • reputation (optional, for future use)
  • Create Quest dataclass:
    • quest_id, name, description, quest_giver
    • difficulty (enum: EASY, MEDIUM, HARD, EPIC)
    • objectives (List[QuestObjective])
    • rewards (QuestReward)
    • offering_triggers (QuestTriggers)
    • narrative_hooks (List[str])
    • status (enum: AVAILABLE, ACTIVE, COMPLETED, FAILED)
  • Implement methods:
    • is_complete() - Check if all objectives done
    • get_next_objective() - Get first incomplete objective
    • update_progress(objective_id, amount) - Increment progress
  • Add to_dict() / from_dict() serialization
  • Write unit tests for all methods

Dependencies: None Deliverable: Quest data models

Example:

quest = Quest(
    quest_id="quest_goblin_cave",
    name="Clear the Goblin Cave",
    description="A nearby cave is infested with goblins...",
    quest_giver="Village Elder",
    difficulty=QuestDifficulty.EASY,
    objectives=[
        QuestObjective(
            objective_id="kill_goblins",
            description="Defeat 5 goblins",
            objective_type=ObjectiveType.KILL,
            required_progress=5,
            current_progress=0
        )
    ],
    rewards=QuestReward(gold=50, experience=100, items=[])
)

quest.update_progress("kill_goblins", 1)
quest.is_complete()  # False (4 more goblins needed)

Task 9.33: Create QuestTriggers with offering logic

Duration: 4 hours File: app/models/quest.py (extend)

Implementation:

  • Create QuestTriggers dataclass:
    • location_types (List[LocationType]) - Where quest can be offered
    • specific_locations (List[str]) - Optional specific location names
    • min_character_level, max_character_level (int)
    • required_quests_completed (List[str]) - Quest prerequisites
    • probability_weights (Dict[LocationType, float]) - Offer chance by location
  • Implement methods:
    • can_offer(character_level, completed_quests) - Check eligibility
    • get_offer_probability(location_type) - Get chance for location
  • Add validation (probabilities 0.0-1.0)
  • Write unit tests for offering logic
  • Document trigger system in docstrings

Dependencies: Task 9.32 (Quest model) Deliverable: Quest offering trigger system

Example:

triggers = QuestTriggers(
    location_types=[LocationType.TOWN, LocationType.TAVERN],
    min_character_level=1,
    max_character_level=5,
    probability_weights={
        LocationType.TOWN: 0.30,
        LocationType.TAVERN: 0.35
    }
)

triggers.can_offer(character_level=3, completed_quests=[])  # True
triggers.get_offer_probability(LocationType.TAVERN)  # 0.35 (35% chance)

Task 9.34: CHECKPOINT - Verify quest model serialization

Duration: 2 hours

Verification Steps:

  1. Create sample quest with all fields
  2. Convert to dict with to_dict()
  3. Serialize to JSON
  4. Deserialize from JSON
  5. Recreate quest with from_dict()
  6. Verify all fields match original
  7. Test quest methods (is_complete, update_progress)
  8. Test trigger methods (can_offer, get_offer_probability)
  9. Test edge cases (invalid progress, level requirements)

Success Criteria:

  • Quest serialization round-trips correctly
  • All methods work as expected
  • Offering logic accurate
  • No data loss during serialization

Task Group 10: Quest Content & Loading (Tasks 35-38)

Task 9.35: Create quest YAML schema

Duration: 3 hours File: app/data/quests/schema.yaml (documentation), update docs/QUEST_SYSTEM.md

Implementation:

  • Document YAML structure for quests
  • Define all required and optional fields
  • Provide examples for each objective type
  • Document narrative_hooks usage
  • Create template quest file
  • Add validation rules
  • Update QUEST_SYSTEM.md with schema details

Dependencies: Task 9.32 (Quest models) Deliverable: Quest YAML schema documentation

Schema Example:

quest_id: quest_goblin_cave
name: Clear the Goblin Cave
description: |
  A nearby cave has been overrun by goblins who are raiding nearby farms.
  The village elder asks you to clear them out.
quest_giver: Village Elder
difficulty: EASY

objectives:
  - objective_id: kill_goblins
    description: Defeat 5 goblins
    objective_type: KILL
    required_progress: 5

rewards:
  gold: 50
  experience: 100
  items: []

offering_triggers:
  location_types: [TOWN, TAVERN]
  min_character_level: 1
  max_character_level: 5
  probability_weights:
    TOWN: 0.30
    TAVERN: 0.35

narrative_hooks:
  - "The village elder looks worried about recent goblin attacks"
  - "You hear farmers complaining about lost livestock"
  - "A town guard mentions a cave to the north"

Task 9.36: Write 10 example quests

Duration: 5 hours Files: app/data/quests/easy/*.yaml, app/data/quests/medium/*.yaml, etc.

Implementation:

  • Create quest files organized by difficulty:
    • Easy (4 quests): Levels 1-3, simple objectives
      1. Clear Goblin Cave (kill 5 goblins)
      2. Gather Healing Herbs (collect 10 herbs)
      3. Deliver Message to Town (travel to location)
      4. Find Lost Cat (discover location)
    • Medium (3 quests): Levels 3-7, multi-objective 5. Investigate Bandit Camp (kill + collect + discover) 6. Rescue Kidnapped Villager (travel + interact) 7. Ancient Artifact Recovery (discover + collect)
    • Hard (2 quests): Levels 7-10, complex chains 8. Stop the Necromancer (multi-step with prerequisites) 9. Dragon's Hoard (discover + kill boss + collect)
    • Epic (1 quest): Level 10+, multi-chapter 10. The Demon Lord's Return (epic multi-objective chain)
  • Include rich narrative_hooks for each quest
  • Vary reward amounts by difficulty
  • Add location variety
  • Ensure proper level gating

Dependencies: Task 9.35 (YAML schema) Deliverable: 10 complete quest YAML files


Task 9.37: Implement QuestService with YAML loader

Duration: 5 hours File: app/services/quest_service.py

Implementation:

  • Create QuestService class
  • Implement load_quests_from_yaml(directory) method
  • Parse all YAML files in quest directory
  • Convert to Quest objects
  • Validate quest structure and fields
  • Cache loaded quests in memory
  • Implement methods:
    • get_quest_by_id(quest_id)
    • get_eligible_quests(character_level, location_type, completed_quests)
    • filter_by_difficulty(difficulty)
    • get_all_quests()
  • Add error handling for malformed YAML
  • Write unit tests with sample quests
  • Add logging for quest loading

Dependencies: Task 9.36 (Quest YAML files) Deliverable: Quest loading and filtering service

Usage:

service = QuestService()
service.load_quests_from_yaml("app/data/quests/")

# Get eligible quests
eligible = service.get_eligible_quests(
    character_level=3,
    location_type=LocationType.TAVERN,
    completed_quests=[]
)
# Returns: [Quest(...), Quest(...)]

Task 9.38: CHECKPOINT - Verify quest loading and validation

Duration: 2 hours

Verification Steps:

  1. Load all 10 quests from YAML files
  2. Verify all quests parsed correctly
  3. Check quest filtering by level works
  4. Test filtering by location type
  5. Verify offering probability calculations
  6. Test get_eligible_quests() with various inputs
  7. Verify error handling for invalid YAML
  8. Check quest caching works

Success Criteria:

  • All 10 quests load without errors
  • Filtering logic accurate
  • Offering probabilities correct
  • No performance issues loading quests
  • Error handling graceful

Task Group 11: Quest Offering & Management (Tasks 39-42)

Task 9.39: Implement context-aware quest offering logic

Duration: 5 hours File: app/services/quest_offering_service.py

Implementation:

  • Create QuestOfferingService class
  • Implement two-stage offering:
    1. Location probability roll:
      • Get location type probability from triggers
      • Roll random 0.0-1.0, check if < probability
      • If fail, no quest offered
    2. Context-aware AI selection:
      • Get eligible quests from QuestService
      • Build AI prompt with narrative_hooks
      • Ask AI to select most contextually relevant quest
      • Parse AI response to get selected quest_id
  • Implement should_offer_quest(location_type) method (probability roll)
  • Implement select_quest_for_context(eligible_quests, game_context) method (AI selection)
  • Implement main offer_quest(session_id) method (full flow)
  • Add validation (max 2 active quests)
  • Write integration tests with mocked AI
  • Add logging for quest offerings

Dependencies: Tasks 7.10 (NarrativeGenerator), 9.37 (QuestService) Deliverable: Context-aware quest offering system

Flow:

offering_service = QuestOfferingService()

# Called after each story turn
if offering_service.should_offer_quest(LocationType.TAVERN):
    eligible = quest_service.get_eligible_quests(...)
    selected_quest = offering_service.select_quest_for_context(
        eligible_quests=eligible,
        game_context={
            "location": "The Rusty Anchor",
            "recent_actions": ["talked to locals", "rested"],
            "active_quests": []
        }
    )
    # Returns: Quest object or None

Task 9.40: Integrate quest offering into story turns

Duration: 4 hours File: app/tasks/ai_tasks.py (extend generate_dm_response job)

Implementation:

  • Update generate_dm_response() RQ job
  • After AI narrative generated and before saving:
    1. Check if quest should be offered (probability roll)
    2. If yes, get eligible quests
    3. Call AI to select contextually relevant quest
    4. Add quest offering to response data
    5. Store offered quest in session state (pending acceptance)
  • Add quest offering to conversation entry:
    {
      "turn": 5,
      "action": "...",
      "dm_response": "...",
      "quest_offered": {
        "quest_id": "quest_goblin_cave",
        "quest_name": "Clear the Goblin Cave"
      }
    }
    
  • Update API response format to include quest offering
  • Write integration tests for offering flow
  • Add logging for quest offerings

Dependencies: Task 9.39 (Quest offering logic) Deliverable: Integrated quest offering in story turns

Updated Response:

{
  "status": 200,
  "result": {
    "dm_response": "As you chat with the locals...",
    "quest_offered": {
      "quest_id": "quest_goblin_cave",
      "name": "Clear the Goblin Cave",
      "description": "...",
      "rewards": {"gold": 50, "experience": 100}
    }
  }
}

Task 9.41: Implement quest accept endpoint

Duration: 4 hours File: app/routes/quests.py (new file)

Implementation:

  • Create POST /api/v1/quests/accept endpoint
  • Validate request body:
    {
      "session_id": "sess_789",
      "quest_id": "quest_goblin_cave"
    }
    
  • Validate quest is currently offered to session
  • Check max 2 active quests limit
  • Add quest to session's active_quests
  • Initialize quest with status ACTIVE
  • Store quest state in character (or session)
  • Return accepted quest details
  • Add @require_auth decorator
  • Write integration tests
  • Document in API_REFERENCE.md

Dependencies: Task 9.39 (Quest offering) Deliverable: Quest acceptance endpoint

Response:

{
  "status": 200,
  "result": {
    "quest_id": "quest_goblin_cave",
    "status": "ACTIVE",
    "objectives": [
      {
        "objective_id": "kill_goblins",
        "description": "Defeat 5 goblins",
        "progress": "0/5"
      }
    ]
  }
}

Task 9.42: Implement quest complete endpoint with rewards

Duration: 5 hours File: app/routes/quests.py (extend)

Implementation:

  • Create POST /api/v1/quests/complete endpoint
  • Validate request body:
    {
      "session_id": "sess_789",
      "quest_id": "quest_goblin_cave"
    }
    
  • Verify quest is active for session
  • Check all objectives completed
  • Grant rewards:
    • Add gold to character
    • Add experience to character
    • Add items to inventory
    • Check for level up
  • Update quest status to COMPLETED
  • Remove from active_quests
  • Add to completed_quests list
  • Return completion details with level up info
  • Add @require_auth decorator
  • Write integration tests
  • Document in API_REFERENCE.md

Dependencies: Task 9.41 (Quest accept) Deliverable: Quest completion and reward system

Response:

{
  "status": 200,
  "result": {
    "quest_id": "quest_goblin_cave",
    "status": "COMPLETED",
    "rewards_granted": {
      "gold": 50,
      "experience": 100,
      "items": []
    },
    "level_up": {
      "leveled_up": true,
      "new_level": 4,
      "skill_points_gained": 1
    }
  }
}

Task Group 12: Quest UI & Final Testing (Tasks 43-45)

Task 9.43: Create quest tracker sidebar UI

Duration: 4 hours File: templates/game/story.html (extend left sidebar)

Implementation:

  • Add quest tracker to left sidebar
  • Display active quests (max 2)
  • Show quest name and description
  • Display objective progress (X/Y format)
  • Add "View Details" button for each quest
  • Style with RPG theme
  • Add HTMX for dynamic updates when objectives progress
  • Show "No active quests" message when empty
  • Add quest complete notification (toast/modal)
  • Test UI rendering

Dependencies: Tasks 9.41-9.42 (Quest endpoints) Deliverable: Quest tracker sidebar UI

UI Structure:

<div class="quest-tracker">
  <h3>Active Quests ({{ active_quests|length }}/2)</h3>
  {% for quest in active_quests %}
  <div class="quest-card">
    <h4>{{ quest.name }}</h4>
    <div class="objectives">
      {% for obj in quest.objectives %}
      <div class="objective {% if obj.completed %}completed{% endif %}">
        {{ obj.description }}: {{ obj.current_progress }}/{{ obj.required_progress }}
      </div>
      {% endfor %}
    </div>
    <button hx-get="/quests/{{ quest.quest_id }}/details">View Details</button>
  </div>
  {% endfor %}
</div>

Task 9.44: Create quest offering modal UI

Duration: 4 hours File: templates/game/partials/quest_offer_modal.html

Implementation:

  • Create modal component for quest offering
  • Display when quest offered in DM response
  • Show quest name, description, quest giver
  • Display objectives and rewards clearly
  • Add "Accept Quest" button (HTMX post to /api/v1/quests/accept)
  • Add "Decline" button (closes modal)
  • Style modal with RPG theme (parchment background)
  • Add HTMX to update quest tracker when accepted
  • Show error if max quests reached (2/2)
  • Test modal behavior

Dependencies: Task 9.41 (Quest accept endpoint) Deliverable: Quest offering modal UI

Modal Structure:

<div class="modal quest-offer-modal">
  <div class="modal-content parchment">
    <h2>{{ quest.quest_giver }} offers you a quest!</h2>
    <h3>{{ quest.name }}</h3>
    <p>{{ quest.description }}</p>

    <div class="objectives">
      <h4>Objectives:</h4>
      <ul>
        {% for obj in quest.objectives %}
        <li>{{ obj.description }}</li>
        {% endfor %}
      </ul>
    </div>

    <div class="rewards">
      <h4>Rewards:</h4>
      <p>Gold: {{ quest.rewards.gold }} | XP: {{ quest.rewards.experience }}</p>
    </div>

    <div class="actions">
      <button
        hx-post="/api/v1/quests/accept"
        hx-vals='{"session_id": "{{ session_id }}", "quest_id": "{{ quest.quest_id }}"}'
        hx-target="#quest-tracker"
        class="btn-accept">Accept Quest</button>
      <button class="btn-decline" onclick="closeModal()">Decline</button>
    </div>
  </div>
</div>

Task 9.45: FINAL CHECKPOINT - Full quest integration test

Duration: 4 hours

Comprehensive Test Flow:

Setup:

  1. Create new character (level 1)
  2. Create solo session
  3. Verify starting state

Quest Offering: 4. Take multiple story actions in a town/tavern 5. Wait for quest offering (may take several turns) 6. Verify quest modal appears 7. Check quest details display correctly 8. Accept quest 9. Verify quest appears in tracker (1/2 active)

Quest Progress: 10. Simulate quest progress (update objective manually via API or through combat) 11. Verify tracker updates in real-time 12. Complete all objectives 13. Verify completion indicator

Quest Completion: 14. Call complete quest endpoint 15. Verify rewards granted (gold, XP) 16. Check for level up if applicable 17. Verify quest removed from active list 18. Verify quest in completed list

Edge Cases: 19. Try accepting 3rd quest (should fail with max 2 message) 20. Try completing incomplete quest (should fail) 21. Test with ineligible quest (wrong level) 22. Verify offering probabilities work (multiple sessions)

Success Criteria:

  • Full quest lifecycle works end-to-end
  • Quest offering feels natural in story flow
  • UI updates smoothly with HTMX
  • Rewards granted correctly
  • Level up system works
  • Max 2 quest limit enforced
  • Error handling graceful
  • No bugs in browser console or server logs

Deferred Tasks

Task 7.15: Set up cost monitoring and alerts

Duration: 3 hours Files: app/tasks/monitoring_tasks.py, app/services/alert_service.py

Implementation:

  • Create calculate_daily_cost() RQ job (runs daily at midnight)
  • Aggregate all AI usage from previous day
  • Calculate total cost by summing estimated costs
  • Store daily cost in Redis timeseries
  • Create AlertService class
  • Implement alert triggers:
    • Daily cost > $50 → Warning email
    • Daily cost > $100 → Critical email
    • Monthly projection > $1500 → Warning email
  • Add email sending via SMTP or service (e.g., SendGrid)
  • Create admin dashboard endpoint: GET /admin/costs
  • Write tests for cost calculation

Dependencies: Task 7.13 (Usage tracking) Deliverable: Automated cost monitoring with alerts

Daily Job:

# Runs at midnight UTC
@job('monitoring_tasks')
def calculate_daily_cost():
    yesterday = date.today() - timedelta(days=1)
    total_cost = sum_all_user_costs(yesterday)

    if total_cost > 100:
        send_alert(f"CRITICAL: Daily AI cost ${total_cost}")
    elif total_cost > 50:
        send_alert(f"WARNING: Daily AI cost ${total_cost}")

    store_cost_metric(yesterday, total_cost)

Phase 4 Complete!

Deliverables Summary:

Week 7: AI Engine Foundation

  • Redis/RQ infrastructure working
  • AI clients for Replicate + Anthropic (Haiku/Sonnet/Opus)
  • Model selection with tier-based routing
  • Jinja2 prompt templates (4 types)
  • Narrative generator wrapper
  • Async AI task jobs with Appwrite integration
  • Usage tracking and cost monitoring
  • Daily limits per tier enforced

Week 8: Story Progression System

  • 10 action prompts defined in YAML
  • ActionPrompt loader with tier/context filtering
  • Solo GameSession model with state tracking
  • SessionService for CRUD operations
  • Conversation history management
  • 4 API endpoints (create, state, action, history)
  • Story gameplay UI with HTMX
  • Dynamic action buttons with tier filtering
  • Full story turn loop working

Week 9: Quest System

  • Quest data models (Quest, Objective, Reward, Triggers)
  • 10 example quests in YAML (4 easy, 3 medium, 2 hard, 1 epic)
  • QuestService with YAML loader
  • Context-aware quest offering logic
  • Quest offering integrated into story turns
  • Quest accept/complete API endpoints
  • Quest tracker sidebar UI
  • Quest offering modal UI
  • Full quest lifecycle tested

Next Phase: Phase 5 - Combat System + Skill Tree UI (Week 10-11)


Dependencies Graph

Week 7 (AI Engine):
Task 7.1 (Redis) → 7.2 (RQ) → 7.3 (AI jobs) → 7.4 (✅ Verify)
Task 7.5 (Replicate+Claude) → 7.7 (Model selector) → 7.8 (✅ Verify)
                                        │
Task 7.9 (Templates) ───────────────────┘→ 7.10 (Narrative gen) → 7.11 (AI jobs) → 7.12 (✅ Verify)
                                                                       │
Task 7.13 (Usage track) → 7.14 (Rate limits) ────────────────────────┘
                       └→ 7.15 (Cost monitoring)

Note: Task 7.6 merged into 7.5 (all models via Replicate API)

Week 8 (Story Progression):
Task 8.16 (ActionPrompt) → 8.17 (YAML) → 8.18 (Loader) → 8.19 (✅ Verify)
                                                           │
Task 8.20 (GameSession) → 8.21 (SessionService) ──────────┤
                       └→ 8.22 (History) ──────────────────┤
                       └→ 8.23 (State tracking) → 8.24 (✅ Verify)
                                                  │
Task 8.25 (Create API) ───────────────────────────┤
Task 8.26 (Action API) ───────────────────────────┤
Task 8.27 (State API) ────────────────────────────┤
Task 8.28 (History API) ──────────────────────────┤
                                                  │
Task 8.29 (Story UI) → 8.30 (Action buttons) → 8.31 (✅ Integration test)

Week 9 (Quest System):
Task 9.32 (Quest models) → 9.33 (Triggers) → 9.34 (✅ Verify)
                                              │
Task 9.35 (YAML schema) → 9.36 (10 quests) → 9.37 (QuestService) → 9.38 (✅ Verify)
                                                                     │
Task 9.39 (Offering logic) ──────────────────────────────────────────┤
Task 9.40 (Story integration) → 9.41 (Accept API) → 9.42 (Complete API)
                                                     │
Task 9.43 (Tracker UI) ──────────────────────────────┤
Task 9.44 (Offer modal) ─────────────────────────────┤
                                                     │
Task 9.45 (✅ Final integration test)

Notes

Testing Strategy:

  • Unit tests bundled into each implementation task
  • Integration tests at verification checkpoints
  • Manual testing for UI/UX flows
  • Use docs/API_TESTING.md for endpoint testing

Cost Management:

  • Target: < $500/month total AI costs
  • Free tier users cost $0 (Replicate)
  • Monitor daily costs via Task 7.15
  • Adjust tier limits if costs spike

Development Tips:

  • Start each week by reviewing previous week's work
  • Commit frequently with conventional commit messages
  • Update API_REFERENCE.md as you build endpoints
  • Test with real AI calls periodically (not just mocks)
  • Keep YAML files well-documented and validated

Estimated Timeline:

  • Week 7: ~40 hours (5 days at 8 hours/day)
  • Week 8: ~44 hours (5.5 days at 8 hours/day)
  • Week 9: ~42 hours (5.25 days at 8 hours/day)
  • Total: ~126 hours (~16 days of focused work)

Success Metrics:

  • All 45 tasks completed
  • All verification checkpoints passed
  • No critical bugs in core gameplay loop
  • AI costs within budget (<$50/day during development)
  • Story progression feels engaging and responsive
  • Quest system feels natural and rewarding

Document History:

  • v1.0 (2025-11-16): Initial Phase 4 implementation plan created