Pattern-050: Context Dataclass Pair

Status: Proven Category: Grammar Application First Documented: January 20, 2026 Ratified: January 20, 2026 (Grammar Implementation)


Problem Statement

Features need to maintain grammar awareness (Entity/Moment/Place) throughout their processing flow, from input collection through execution to result delivery. Common challenges:

This creates “flattened” features that feel mechanical rather than conscious, losing the experiential quality that distinguishes Piper from traditional task management systems.


Solution

Implement a Context/Result dataclass pair where:

  1. Context dataclass - Captures input state with grammar elements explicit
  2. Result dataclass - Returns output with Entity/Moment/Place preserved
  3. Grammar threading - Entity identity flows through both structures
  4. Clean separation - What we know (Context) vs what we learned (Result)

Pattern Description

A Context Dataclass Pair is a two-dataclass structure that maintains grammar consciousness through a feature’s processing flow. The pattern emphasizes:

Key Characteristics

  1. Context dataclass contains:
    • Entity identity (user_id, requester_id)
    • Input timestamp (when request made)
    • Place references (source_places, integration_context)
    • Request parameters
  2. Result dataclass contains:
    • Same Entity identity preserved
    • Generation timestamp (when result created)
    • Findings/output data
    • Place attribution (context_source, where data originated)
    • Metrics and metadata
  3. Grammar flow:
    Entity (user) → Context → Processing → Result → Entity (user)
    Moment (request) → Context → Processing → Result → Moment (generation)
    Place (sources) → Context → Processing → Result → Place (attribution)
    

Implementation

Structure

from dataclasses import dataclass, field
from datetime import datetime
from typing import Any, Dict, List

@dataclass
class [Feature]Context:
    """
    Input context for [feature] - what we know before processing.

    Grammar elements:
    - Entity: user_id (who is requesting)
    - Moment: timestamp (when request made)
    - Place: source_places (where to gather data from)
    """
    user_id: str                              # Entity: The user
    timestamp: datetime                       # Moment: When request occurs
    source_places: Dict[str, Any]            # Place: Integration sources
    session_context: Dict[str, Any] = field(default_factory=dict)

    # Feature-specific parameters
    # ... add as needed

@dataclass
class [Feature]Result:
    """
    Output result from [feature] - what we learned.

    Grammar elements:
    - Entity: user_id (preserved from Context)
    - Moment: generated_at (when result created)
    - Place: context_source (where data came from)
    """
    user_id: str                              # Entity preserved
    generated_at: datetime                    # Moment of result creation
    findings: List[str]                       # What was discovered
    context_source: str                       # Place: Attribution
    performance_metrics: Dict[str, Any]       # Observability

    # Feature-specific results
    # ... add as needed

Example from Morning Standup

File: services/features/morning_standup.py:34-57

@dataclass
class StandupContext:
    """Context for generating morning standup"""
    user_id: str                              # Entity: The user
    date: datetime                            # Moment: When this occurs
    session_context: Dict[str, Any] = field(default_factory=dict)
    github_repos: List[str] = field(default_factory=list)  # Place: Active repositories

@dataclass
class StandupResult:
    """Result of morning standup generation"""
    user_id: str                              # Entity reference maintained
    generated_at: datetime                    # Moment of generation
    generation_time_ms: int
    yesterday_accomplishments: List[str]      # Moments: Past experiences
    today_priorities: List[str]               # Moments: Anticipated experiences
    blockers: List[str]                       # Moments: Current challenges
    context_source: str                       # Place: Where context came from
    github_activity: Dict[str, Any]           # Place-specific data
    performance_metrics: Dict[str, Any]
    time_saved_minutes: int

Grammar embodiment:

Usage Pattern

class FeatureService:
    async def execute_feature(self, user_id: str) -> [Feature]Result:
        """Execute feature with grammar-aware flow."""

        # 1. Construct Context (capture input state)
        context = [Feature]Context(
            user_id=user_id,
            timestamp=datetime.now(),
            source_places={
                "github": await self._get_github_repos(user_id),
                "calendar": await self._get_calendar_context(user_id),
            }
        )

        # 2. Process with grammar preservation
        findings = await self._process_with_context(context)

        # 3. Construct Result (capture output state)
        result = [Feature]Result(
            user_id=context.user_id,  # Entity preserved
            generated_at=datetime.now(),  # Moment of result
            findings=findings,
            context_source="persistent" if context.session_context else "default",
            performance_metrics=self._calculate_metrics()
        )

        return result

Consequences

Benefits

Trade-offs


Complements

Alternatives

Dependencies


Usage Guidelines

When to Use

Use Context Dataclass Pair when:

When NOT to Use

Don’t use when:

Best Practices

  1. Always preserve Entity identity: user_id in both Context and Result
  2. Distinguish input/output moments: Different timestamp fields
  3. Track Place attribution: Record where data came from
  4. Use field factories: field(default_factory=dict) for mutable defaults
  5. Add docstrings: Explain grammar elements in class docstrings
  6. Include metrics: Result should contain performance/observability data
  7. Validate in constructor: Use __post_init__ for validation if needed
  8. Keep Context immutable: Don’t modify Context after creation
  9. Result as data: Result is pure data, no behavior (methods)
  10. Feature-specific fields go last: Grammar fields first, feature fields after

Examples in Codebase

Primary Usage

Applicable To (from audit)

High Priority (should adopt pattern):

Medium Priority (good candidates):


Implementation Checklist


Evidence

Proven Pattern - Successfully implemented in:

  1. Morning Standup (reference implementation)
    • Location: services/features/morning_standup.py
    • Status: Production, full grammar consciousness
    • Context: 4 fields (user_id, date, session_context, github_repos)
    • Result: 9 fields including Entity/Moment/Place preservation
    • Performance: Sub-2-second generation with full traceability

Grammar Audit Results:

Transformation Potential:


Pattern Identified: January 19, 2026 (P0 Morning Standup Analysis) Ratified: January 20, 2026 Category: Grammar Application