Volume 3: Human-System Collaboration

Pattern 8: Intelligent Defaults

Part II: Interaction Patterns - Intelligence Patterns


Opening Scenario: Filling Out the Same Form Twice

Dr. Sarah Chen was a family physician who'd been using the same electronic medical records system for five years. Every patient visit required documentation, and she saw 25-30 patients per day.

One afternoon, she was documenting a routine follow-up visit for a patient with hypertension. The form started blank:

VISIT DOCUMENTATION

Visit Type: [                    ]
Chief Complaint: [                    ]
Blood Pressure: [     /     ]
Heart Rate: [     ] bpm
Weight: [     ] lbs
Temperature: [     ] °F

Medications Reviewed: ( ) Yes  ( ) No
Vitals Normal: ( ) Yes  ( ) No
Follow-up Needed: ( ) Yes  ( ) No
Next Appointment: [     ] weeks

Every field was empty. Sarah had to: - Select "Follow-up Visit" from a dropdown (she does 15 of these daily) - Type "Hypertension follow-up" (she types this 3-4 times daily) - Manually enter vitals from the nurse's notes - Check "Yes" for medications reviewed (she always reviews medications) - Manually calculate next appointment date

She did this 25 times a day. 125 times a week. 6,000+ times a year.

The system knew: - 60% of Sarah's visits are follow-ups - She sees this patient every 3 months for hypertension - The patient's last BP was 142/88, weight was 187 lbs - The patient takes Lisinopril 10mg daily - Sarah always reviews medications - Her typical follow-up is 12 weeks for stable hypertension, 4 weeks if BP is elevated

But the form offered none of this intelligence.


One day, the hospital upgraded to a new system. The same visit documentation opened differently:

VISIT DOCUMENTATION - Follow-up Visit
Patient: Robert Martinez (Last visit: 3 months ago)

Visit Type: [Follow-up Visit ▼] ← Pre-filled based on 60% of your visits
Chief Complaint: [Hypertension follow-up] ← Based on patient history

VITALS (Nurse entered 5 minutes ago - click to review)
Blood Pressure: 138/86 ← Auto-imported from nurse station
Heart Rate: 72 bpm ← Auto-imported
Weight: 189 lbs ← Auto-imported (Trend: +2 lbs from last visit)
Temperature: 98.4°F ← Auto-imported

Previous visit vitals (3 months ago):
BP: 142/88, HR: 74, Weight: 187

ASSESSMENT
Medications Reviewed: (●) Yes  ( ) No ← You always check this
Vitals Normal: ( ) Yes  (●) No ← BP still elevated
  → BP above target (130/80 for this patient)
  → Consider medication adjustment or lifestyle counseling

Follow-up Needed: (●) Yes  ( ) No ← Based on elevated BP
Next Appointment: [12] weeks ← Your typical follow-up for stable cases
  ⚠️ Suggestion: Consider 4 weeks given BP still above target

[Review & Sign]

The new system was intelligently pre-filled:

Context-aware: Knew this was likely a follow-up based on patient history and Sarah's typical visit mix

Historically informed: Showed previous vitals for comparison, pre-filled chief complaint based on patient's chronic conditions

Automatically integrated: Pulled vitals from the nurse's station tablet (entered 5 minutes ago)

Role-based: Knew Sarah always reviews medications (unlike residents who sometimes skip this)

Pattern-learning: Suggested 4-week follow-up instead of 12 weeks because BP was still elevated (learned from 5 years of Sarah's documentation patterns)

Medically intelligent: Calculated that BP 138/86 is above the 130/80 target for this patient (who has diabetes as comorbidity)

Sarah's documentation time dropped from 3-4 minutes per patient to 45 seconds. She reviewed the pre-filled information, made adjustments where needed, and signed. Over a year, this saved her 500+ hours - time she could spend with patients instead of with forms.

More importantly: The defaults encoded medical expertise. The suggestion to follow up in 4 weeks instead of 12 weeks for elevated BP wasn't arbitrary - it was based on clinical guidelines combined with Sarah's own practice patterns. The system learned from thousands of her previous decisions and offered that expertise back to her as intelligent defaults.

Context

Intelligent Defaults applies when:

Repetitive data entry: Users enter similar information frequently

Predictable patterns exist: Context, role, or history indicates likely values

Time is valuable: Data entry takes time that could be spent elsewhere

Expertise can be encoded: Default values represent domain knowledge

User override is possible: Defaults should help, not constrain

Context is available: System has access to relevant information (history, role, location, time)

Accuracy matters: Wrong defaults are worse than blank fields

Problem Statement

Most forms start blank, forcing users to enter information the system could reasonably predict:

Ignoring obvious context:

// User is creating their 47th invoice this month
// Previous 46 invoices all used:
//   - Same tax rate (6%)
//   - Same payment terms (Net 15)
//   - Same currency (USD)

Tax Rate: [     ]  ← Blank!
Payment Terms: [     ]  ← Blank!
Currency: [     ]  ← Blank!

Not learning from history:

// User has entered shipping address 15 times
// 14 times it was their home address
// 1 time it was their office

Shipping Address:
Street: [                    ]  ← Make user type it again
City: [                    ]
State: [     ]
ZIP: [     ]

Missing role-based intelligence:

// Manager creating expense report
// Managers always select "Department Budget"
// Staff always select "Project Budget"

Budget Source: [                    ]  ← Should know based on role
Approver: [                    ]  ← Should default to their manager

Failing to integrate available data:

// Form asking for birth date
// User is logged in
// Birth date is in their profile

Date of Birth: [  /  /    ]  ← System already knows this!

No temporal intelligence:

// Creating appointment on December 24th
// December 25th is a holiday
// System allows selection of 12/25

Appointment Date: [  /  /    ]  ← Should skip holidays

We need forms that intelligently pre-fill based on context, learn from patterns, encode expertise, and save users time while improving accuracy.

Forces

Convenience vs Privacy

  • Pre-filling saves time
  • But reveals what system knows about user
  • Some users uncomfortable with "the system knows too much"
  • Balance helpfulness with privacy comfort

Prediction Accuracy vs User Autonomy

  • Accurate defaults help users
  • Inaccurate defaults frustrate and mislead
  • Users must be able to easily override
  • System shouldn't assume it knows better than user

Learning vs Staleness

  • Systems should learn from user behavior
  • But patterns change over time
  • Old patterns may no longer apply
  • Need to weight recent behavior more heavily

Explicit vs Implicit Defaults

  • Explicit: "Based on your last 10 orders, we suggest..."
  • Implicit: Field is just pre-filled
  • Transparency builds trust
  • But too much explanation is clunky

Performance vs Freshness

  • Computing intelligent defaults takes time
  • Fetching historical data adds latency
  • Cached defaults are fast but may be stale
  • Balance speed with accuracy

Solution

Pre-populate form fields with intelligent predictions based on context, history, role, and learned patterns, while making defaults obvious, easily overridable, and continuously improving.

The pattern has five types of intelligent defaults:

1. Contextual Defaults (Based on Current Situation)

Use available context to predict values:

class ContextualDefaults {
  getDefaults(formType, context) {
    const defaults = {};

    // Geographic context
    if (context.userLocation) {
      defaults.timezone = this.getTimezoneFromLocation(context.userLocation);
      defaults.country = context.userLocation.country;
      defaults.state = context.userLocation.state;
      defaults.language = this.getPreferredLanguage(context.userLocation.country);
    }

    // Temporal context
    const now = new Date();
    defaults.currentDate = now.toISOString().split('T')[0];
    defaults.currentTime = now.toTimeString().slice(0,5);

    // Next business day (skip weekends and holidays)
    defaults.nextBusinessDay = this.getNextBusinessDay(now, context.holidays);

    // Session context
    if (context.userRole) {
      defaults.department = this.getDepartmentForRole(context.userRole);
      defaults.approver = this.getDefaultApprover(context.userRole);
    }

    // Related entity context
    if (formType === 'invoice' && context.customerId) {
      const customer = this.getCustomer(context.customerId);
      defaults.billingAddress = customer.billingAddress;
      defaults.paymentTerms = customer.defaultPaymentTerms;
      defaults.currency = customer.preferredCurrency;
      defaults.taxRate = this.getTaxRate(customer.location);
    }

    // Project context
    if (context.projectId) {
      const project = this.getProject(context.projectId);
      defaults.budgetCode = project.defaultBudgetCode;
      defaults.clientName = project.clientName;
      defaults.projectManager = project.manager;
    }

    return defaults;
  }

  getNextBusinessDay(date, holidays = []) {
    let nextDay = new Date(date);
    nextDay.setDate(nextDay.getDate() + 1);

    while (this.isWeekend(nextDay) || this.isHoliday(nextDay, holidays)) {
      nextDay.setDate(nextDay.getDate() + 1);
    }

    return nextDay.toISOString().split('T')[0];
  }

  isWeekend(date) {
    const day = date.getDay();
    return day === 0 || day === 6;  // Sunday or Saturday
  }

  isHoliday(date, holidays) {
    const dateStr = date.toISOString().split('T')[0];
    return holidays.includes(dateStr);
  }
}

2. Historical Defaults (Based on Past Behavior)

Learn from user's previous entries:

class HistoricalDefaults {
  async getDefaults(userId, formType) {
    const history = await this.getUserHistory(userId, formType);

    if (history.length === 0) return {};

    const defaults = {};

    // Most common values
    defaults.mostCommonCategory = this.getMostFrequent(
      history.map(h => h.category)
    );

    defaults.typicalAmount = this.getMedian(
      history.map(h => h.amount)
    );

    // Last used values (recent behavior often predicts next action)
    const lastEntry = history[0];  // Assuming sorted by recency
    defaults.lastUsedVendor = lastEntry.vendor;
    defaults.lastUsedPaymentMethod = lastEntry.paymentMethod;

    // Time-based patterns
    if (formType === 'timesheet') {
      defaults.projectAssignment = this.predictCurrentProject(
        history, 
        new Date()
      );
    }

    // Frequency-based defaults
    if (this.isRecurringPattern(history)) {
      const recurring = this.identifyRecurringEntries(history);
      defaults.suggestedRecurrence = recurring.frequency;
      defaults.nextOccurrence = recurring.nextDate;
    }

    return defaults;
  }

  getMostFrequent(values) {
    const frequency = {};
    values.forEach(v => {
      frequency[v] = (frequency[v] || 0) + 1;
    });

    return Object.keys(frequency).reduce((a, b) => 
      frequency[a] > frequency[b] ? a : b
    );
  }

  getMedian(numbers) {
    const sorted = numbers.sort((a, b) => a - b);
    const mid = Math.floor(sorted.length / 2);

    if (sorted.length % 2 === 0) {
      return (sorted[mid - 1] + sorted[mid]) / 2;
    }
    return sorted[mid];
  }

  predictCurrentProject(timesheetHistory, currentDate) {
    // Look at what projects user worked on recently
    const recentEntries = timesheetHistory
      .filter(h => this.isRecentDate(h.date, currentDate, 7))  // Last 7 days
      .map(h => h.project);

    // Weight recent projects more heavily
    const weights = {};
    recentEntries.forEach((project, index) => {
      const recency = recentEntries.length - index;  // More recent = higher weight
      weights[project] = (weights[project] || 0) + recency;
    });

    return Object.keys(weights).reduce((a, b) => 
      weights[a] > weights[b] ? a : b
    );
  }

  isRecurringPattern(history) {
    if (history.length < 3) return false;

    // Check if entries occur at regular intervals
    const intervals = [];
    for (let i = 1; i < history.length; i++) {
      const days = this.daysBetween(history[i].date, history[i-1].date);
      intervals.push(days);
    }

    // If intervals are consistent (within 2 days), it's recurring
    const avgInterval = intervals.reduce((a, b) => a + b) / intervals.length;
    const consistent = intervals.every(i => Math.abs(i - avgInterval) <= 2);

    return consistent;
  }
}

3. Role-Based Defaults (Based on User Role)

Different roles have different typical values:

class RoleBasedDefaults {
  getDefaults(userRole, formType) {
    const roleDefaults = {
      'manager': {
        expenseReport: {
          budgetSource: 'Department Budget',
          requiresApproval: false,  // Managers self-approve
          expenseLimit: 5000,
          approver: null  // No approver needed
        },
        timesheet: {
          billable: false,  // Managers typically non-billable
          category: 'Management',
          client: 'Internal'
        },
        purchaseRequest: {
          approvalRequired: false,
          spendingLimit: 10000
        }
      },

      'staff': {
        expenseReport: {
          budgetSource: 'Project Budget',
          requiresApproval: true,
          expenseLimit: 1000,
          approver: this.getManager(userId)
        },
        timesheet: {
          billable: true,  // Staff typically billable
          category: 'Client Work',
          client: this.getCurrentClient(userId)
        },
        purchaseRequest: {
          approvalRequired: true,
          spendingLimit: 500
        }
      },

      'contractor': {
        expenseReport: {
          budgetSource: 'Project Budget',
          requiresApproval: true,
          expenseLimit: 500,
          approver: this.getProjectManager(userId),
          reimbursementType: 'Direct Deposit'  // Not payroll
        },
        timesheet: {
          billable: true,
          category: 'Contractor Services',
          client: this.getContractClient(userId),
          overtimeEligible: false  // Contractors typically not OT eligible
        }
      },

      'executive': {
        expenseReport: {
          budgetSource: 'Executive Budget',
          requiresApproval: false,
          expenseLimit: 25000,
          approver: null
        },
        purchaseRequest: {
          approvalRequired: false,
          spendingLimit: 50000,
          expedited: true  // Executive requests prioritized
        }
      }
    };

    return roleDefaults[userRole]?.[formType] || {};
  }

  // Industry-specific role defaults
  getIndustryRoleDefaults(industry, role, formType) {
    const industryDefaults = {
      'healthcare': {
        'physician': {
          patientNote: {
            template: 'SOAP Note',
            reviewMedications: true,
            orderLabs: true
          }
        },
        'nurse': {
          patientNote: {
            template: 'Nursing Assessment',
            reviewMedications: true,
            orderLabs: false  // Nurses don't typically order labs
          }
        }
      },

      'legal': {
        'partner': {
          caseIntake: {
            conflictCheckRequired: true,
            billingType: 'Hourly',
            standardRate: 450,
            approvalRequired: false
          }
        },
        'associate': {
          caseIntake: {
            conflictCheckRequired: true,
            billingType: 'Hourly',
            standardRate: 275,
            approvalRequired: true,
            assigningPartner: this.getSupervisingPartner(userId)
          }
        }
      }
    };

    return industryDefaults[industry]?.[role]?.[formType] || {};
  }
}

4. Learned Defaults (Machine Learning from Patterns)

Discover patterns algorithmically:

class LearnedDefaults {
  async getDefaults(userId, formType, context) {
    const patterns = await this.learnPatterns(userId, formType);
    const defaults = {};

    // Time-based patterns
    if (patterns.timeOfDay) {
      const currentHour = new Date().getHours();
      const typicalValueAtThisTime = patterns.timeOfDay[currentHour];
      if (typicalValueAtThisTime) {
        defaults.predictedCategory = typicalValueAtThisTime.category;
        defaults.predictedAmount = typicalValueAtThisTime.avgAmount;
      }
    }

    // Day-of-week patterns
    if (patterns.dayOfWeek) {
      const currentDay = new Date().getDay();
      const typicalValueOnThisDay = patterns.dayOfWeek[currentDay];
      if (typicalValueOnThisDay) {
        defaults.predictedProject = typicalValueOnThisDay.project;
      }
    }

    // Conditional patterns (if X then usually Y)
    if (context.relatedEntity && patterns.conditionalDefaults) {
      const conditional = patterns.conditionalDefaults[context.relatedEntity];
      if (conditional) {
        Object.assign(defaults, conditional);
      }
    }

    return defaults;
  }

  async learnPatterns(userId, formType) {
    const history = await this.getUserHistory(userId, formType, 180);  // Last 6 months

    const patterns = {
      timeOfDay: {},
      dayOfWeek: {},
      conditionalDefaults: {}
    };

    // Learn time-of-day patterns
    history.forEach(entry => {
      const hour = new Date(entry.timestamp).getHours();
      if (!patterns.timeOfDay[hour]) {
        patterns.timeOfDay[hour] = {
          category: [],
          amounts: []
        };
      }
      patterns.timeOfDay[hour].category.push(entry.category);
      patterns.timeOfDay[hour].amounts.push(entry.amount);
    });

    // Aggregate to most common values
    for (const hour in patterns.timeOfDay) {
      patterns.timeOfDay[hour] = {
        category: this.getMostFrequent(patterns.timeOfDay[hour].category),
        avgAmount: this.getMedian(patterns.timeOfDay[hour].amounts)
      };
    }

    // Learn conditional patterns (e.g., "when customer is X, usually category is Y")
    const conditionalGroups = {};
    history.forEach(entry => {
      const key = entry.customer || entry.project || entry.vendor;
      if (!conditionalGroups[key]) {
        conditionalGroups[key] = [];
      }
      conditionalGroups[key].push(entry);
    });

    // For each group, find most common values
    for (const key in conditionalGroups) {
      const group = conditionalGroups[key];
      if (group.length >= 3) {  // Need at least 3 occurrences to establish pattern
        patterns.conditionalDefaults[key] = {
          category: this.getMostFrequent(group.map(g => g.category)),
          paymentTerms: this.getMostFrequent(group.map(g => g.paymentTerms)),
          typicalAmount: this.getMedian(group.map(g => g.amount)),
          confidence: group.length / history.length  // How confident are we?
        };
      }
    }

    return patterns;
  }
}

5. Hierarchical Defaults (Cascade from General to Specific)

Apply defaults in priority order:

class HierarchicalDefaults {
  async getDefaults(userId, formType, context) {
    // Start with system-wide defaults
    let defaults = this.getSystemDefaults(formType);

    // Override with organization defaults
    if (context.organizationId) {
      const orgDefaults = await this.getOrganizationDefaults(
        context.organizationId,
        formType
      );
      defaults = { ...defaults, ...orgDefaults };
    }

    // Override with department defaults
    if (context.departmentId) {
      const deptDefaults = await this.getDepartmentDefaults(
        context.departmentId,
        formType
      );
      defaults = { ...defaults, ...deptDefaults };
    }

    // Override with role defaults
    if (context.userRole) {
      const roleDefaults = await this.getRoleDefaults(
        context.userRole,
        formType
      );
      defaults = { ...defaults, ...roleDefaults };
    }

    // Override with user's personal defaults
    const userDefaults = await this.getUserDefaults(userId, formType);
    defaults = { ...defaults, ...userDefaults };

    // Finally, override with context-specific values (highest priority)
    if (context.overrides) {
      defaults = { ...defaults, ...context.overrides };
    }

    return defaults;
  }

  getSystemDefaults(formType) {
    // Universal defaults that apply unless overridden
    return {
      currency: 'USD',
      language: 'en-US',
      dateFormat: 'MM/DD/YYYY',
      timezone: 'America/New_York'
    };
  }

  async getOrganizationDefaults(orgId, formType) {
    // Organization-wide policies
    const org = await this.getOrganization(orgId);

    return {
      currency: org.defaultCurrency,
      fiscalYearStart: org.fiscalYearStart,
      approvalWorkflow: org.defaultApprovalWorkflow,
      expensePolicy: org.expensePolicy
    };
  }

  async getDepartmentDefaults(deptId, formType) {
    const dept = await this.getDepartment(deptId);

    return {
      budgetCode: dept.defaultBudgetCode,
      costCenter: dept.costCenter,
      approver: dept.manager
    };
  }
}

Implementation Details

Complete Intelligent Defaults Engine

class IntelligentDefaultsEngine {
  constructor(config) {
    this.contextual = new ContextualDefaults();
    this.historical = new HistoricalDefaults();
    this.roleBased = new RoleBasedDefaults();
    this.learned = new LearnedDefaults();
    this.hierarchical = new HierarchicalDefaults();

    this.config = config;
  }

  async getDefaults(formType, userId, context = {}) {
    const allDefaults = {};

    // Strategy 1: Hierarchical defaults (system → org → dept → role → user)
    const hierarchical = await this.hierarchical.getDefaults(
      userId, 
      formType, 
      context
    );
    Object.assign(allDefaults, hierarchical);

    // Strategy 2: Contextual defaults (current situation)
    const contextual = this.contextual.getDefaults(formType, {
      ...context,
      userId: userId,
      userLocation: await this.getUserLocation(userId),
      userRole: await this.getUserRole(userId)
    });
    Object.assign(allDefaults, contextual);

    // Strategy 3: Historical defaults (past behavior)
    const historical = await this.historical.getDefaults(userId, formType);
    // Only apply if confidence is high
    if (historical.confidence > 0.7) {
      Object.assign(allDefaults, historical);
    }

    // Strategy 4: Role-based defaults
    const roleBased = this.roleBased.getDefaults(
      await this.getUserRole(userId),
      formType
    );
    Object.assign(allDefaults, roleBased);

    // Strategy 5: Learned patterns (ML-based)
    const learned = await this.learned.getDefaults(userId, formType, context);
    if (learned.confidence > 0.6) {
      Object.assign(allDefaults, learned);
    }

    // Add metadata about why each default was chosen
    const defaultsWithMetadata = this.addExplanations(allDefaults, {
      hierarchical,
      contextual,
      historical,
      roleBased,
      learned
    });

    return defaultsWithMetadata;
  }

  addExplanations(defaults, sources) {
    const explained = {};

    for (const [field, value] of Object.entries(defaults)) {
      explained[field] = {
        value: value,
        source: this.identifySource(field, sources),
        confidence: this.calculateConfidence(field, sources),
        editable: true
      };
    }

    return explained;
  }

  identifySource(field, sources) {
    // Track which strategy provided this default
    if (sources.contextual[field] !== undefined) {
      return {
        type: 'contextual',
        explanation: 'Based on current context'
      };
    }

    if (sources.historical[field] !== undefined) {
      return {
        type: 'historical',
        explanation: `Based on your last ${sources.historical.sampleSize} entries`
      };
    }

    if (sources.roleBased[field] !== undefined) {
      return {
        type: 'role',
        explanation: `Typical for ${sources.roleBased.role} role`
      };
    }

    if (sources.learned[field] !== undefined) {
      return {
        type: 'learned',
        explanation: 'Predicted from your patterns'
      };
    }

    return {
      type: 'hierarchical',
      explanation: 'Organization default'
    };
  }

  calculateConfidence(field, sources) {
    // How confident are we in this default?
    // Higher confidence = more data supporting it

    let confidence = 0.5;  // Base confidence

    // Boost confidence if multiple strategies agree
    const strategies = [
      sources.contextual,
      sources.historical,
      sources.roleBased,
      sources.learned
    ];

    const agreementCount = strategies.filter(s => 
      s[field] === sources.hierarchical[field]
    ).length;

    confidence += agreementCount * 0.1;

    // Boost if historical data is strong
    if (sources.historical[field] && sources.historical.confidence > 0.8) {
      confidence += 0.2;
    }

    return Math.min(confidence, 1.0);
  }
}

// UI Integration
class SmartForm {
  constructor(formDefinition, defaultsEngine) {
    this.fields = formDefinition;
    this.engine = defaultsEngine;
    this.values = {};
    this.defaults = {};
    this.userModified = new Set();  // Track user overrides
  }

  async initialize(userId, context) {
    // Get intelligent defaults
    this.defaults = await this.engine.getDefaults(
      this.fields.formType,
      userId,
      context
    );

    // Apply defaults to form
    for (const [fieldName, defaultData] of Object.entries(this.defaults)) {
      if (!this.userModified.has(fieldName)) {
        this.values[fieldName] = defaultData.value;
      }
    }

    // Render form with defaults
    this.render();
  }

  render() {
    // For each field, show default with visual indicator
    for (const fieldName in this.fields) {
      const field = this.fields[fieldName];
      const defaultData = this.defaults[fieldName];

      if (defaultData) {
        this.renderFieldWithDefault(fieldName, field, defaultData);
      } else {
        this.renderEmptyField(fieldName, field);
      }
    }
  }

  renderFieldWithDefault(fieldName, field, defaultData) {
    const container = document.getElementById(`field-${fieldName}`);

    // Create input with default value
    const input = document.createElement('input');
    input.value = defaultData.value;
    input.name = fieldName;

    // Add visual indicator that this is a default
    input.classList.add('has-default');

    // Add explanation tooltip
    const explanation = document.createElement('span');
    explanation.classList.add('default-explanation');
    explanation.textContent = `✓ ${defaultData.source.explanation}`;
    explanation.title = `Confidence: ${(defaultData.confidence * 100).toFixed(0)}%`;

    // Add "clear default" button
    const clearBtn = document.createElement('button');
    clearBtn.textContent = '×';
    clearBtn.classList.add('clear-default');
    clearBtn.onclick = () => this.clearDefault(fieldName);

    container.appendChild(input);
    container.appendChild(explanation);
    container.appendChild(clearBtn);

    // Track user modifications
    input.addEventListener('change', () => {
      this.userModified.add(fieldName);
      input.classList.remove('has-default');
      explanation.style.display = 'none';
      clearBtn.style.display = 'none';
    });
  }

  clearDefault(fieldName) {
    this.values[fieldName] = '';
    this.userModified.add(fieldName);
    this.render();
  }

  // Track which defaults users accept vs override
  async submitForm() {
    const analytics = {
      defaultsProvided: Object.keys(this.defaults).length,
      defaultsAccepted: 0,
      defaultsModified: this.userModified.size,
      acceptanceRate: 0
    };

    // Calculate acceptance rate
    for (const fieldName in this.defaults) {
      if (!this.userModified.has(fieldName)) {
        analytics.defaultsAccepted++;
      }
    }

    analytics.acceptanceRate = 
      analytics.defaultsAccepted / analytics.defaultsProvided;

    // Send analytics to improve defaults
    await this.engine.recordDefaultPerformance(
      this.fields.formType,
      analytics
    );

    // Submit form data
    return this.values;
  }
}

Adaptive Learning

class AdaptiveDefaultLearning {
  async recordFormSubmission(userId, formType, submittedValues, providedDefaults) {
    // Track which defaults were accepted vs modified
    const feedback = {
      userId,
      formType,
      timestamp: new Date(),
      defaults: {},
      accepted: [],
      modified: [],
      cleared: []
    };

    for (const field in providedDefaults) {
      const defaultValue = providedDefaults[field].value;
      const finalValue = submittedValues[field];

      feedback.defaults[field] = {
        suggested: defaultValue,
        actual: finalValue,
        source: providedDefaults[field].source.type,
        confidence: providedDefaults[field].confidence
      };

      if (finalValue === defaultValue) {
        feedback.accepted.push(field);
      } else if (finalValue === '' || finalValue === null) {
        feedback.cleared.push(field);
      } else {
        feedback.modified.push({
          field,
          from: defaultValue,
          to: finalValue
        });
      }
    }

    // Calculate acceptance rate for each default strategy
    const strategyPerformance = this.calculateStrategyPerformance(feedback);

    // Store feedback
    await this.storeFeedback(feedback);

    // Update strategy weights based on performance
    await this.updateStrategyWeights(userId, formType, strategyPerformance);

    return feedback;
  }

  calculateStrategyPerformance(feedback) {
    const performance = {
      contextual: { accepted: 0, total: 0 },
      historical: { accepted: 0, total: 0 },
      roleBased: { accepted: 0, total: 0 },
      learned: { accepted: 0, total: 0 },
      hierarchical: { accepted: 0, total: 0 }
    };

    for (const field in feedback.defaults) {
      const source = feedback.defaults[field].source;
      performance[source].total++;

      if (feedback.accepted.includes(field)) {
        performance[source].accepted++;
      }
    }

    // Calculate acceptance rate for each strategy
    for (const strategy in performance) {
      const stats = performance[strategy];
      stats.rate = stats.total > 0 ? stats.accepted / stats.total : 0;
    }

    return performance;
  }

  async updateStrategyWeights(userId, formType, performance) {
    // Get current weights
    const weights = await this.getStrategyWeights(userId, formType) || {
      contextual: 1.0,
      historical: 1.0,
      roleBased: 1.0,
      learned: 1.0,
      hierarchical: 1.0
    };

    // Adjust weights based on performance
    for (const strategy in performance) {
      const rate = performance[strategy].rate;

      if (performance[strategy].total >= 5) {  // Need enough data
        // Increase weight if acceptance rate is high
        if (rate > 0.8) {
          weights[strategy] = Math.min(weights[strategy] * 1.1, 2.0);
        }
        // Decrease weight if acceptance rate is low
        else if (rate < 0.4) {
          weights[strategy] = Math.max(weights[strategy] * 0.9, 0.5);
        }
      }
    }

    await this.saveStrategyWeights(userId, formType, weights);
  }
}

Consequences

Benefits

Massive Time Savings: - Users don't re-enter information the system knows - Dr. Sarah saved 500+ hours per year - Reduced cognitive load on routine tasks

Improved Accuracy: - Pre-filled values are typically correct - Fewer typos than manual entry - Consistency across related forms

Encoded Expertise: - Defaults represent domain knowledge - New users benefit from organization's experience - Best practices preserved in defaults

Reduced Friction: - Forms feel intelligent and helpful - Users more likely to complete forms - Better user experience overall

Learning Organization: - System improves from user behavior - Patterns identified and codified - Continuous improvement cycle

Context Awareness: - Forms adapt to situation - Right defaults for right context - Professional, polished experience

Liabilities

Privacy Concerns: - Pre-filling reveals what system tracks - Some users uncomfortable with "system knows too much" - Transparency needed about data usage

Accuracy Dependence: - Wrong defaults worse than blank fields - Users may not notice incorrect defaults - Can reinforce incorrect patterns

Over-reliance Risk: - Users may stop thinking critically - Defaults accepted without review - Automation bias: trusting system over judgment

Maintenance Burden: - Patterns change over time - Defaults need continuous updating - Requires monitoring and tuning

Implementation Complexity: - Multiple strategies to coordinate - Historical data to maintain - Performance optimization needed

User Adaptation: - Power users want control - Novices need guidance - One size doesn't fit all

Domain Examples

Healthcare: Patient Visit Documentation

const visitDefaults = {
  // Context: Follow-up visit for chronic condition patient
  visitType: 'Follow-up',  // 60% of this doctor's visits

  // Historical: Last visit was 3 months ago for hypertension
  chiefComplaint: 'Hypertension follow-up',

  // Imported: Vitals entered by nurse 5 minutes ago
  bloodPressure: '138/86',  // From nurse station
  heartRate: '72',
  weight: '189',

  // Calculated: Comparison to previous visit
  bpChange: '+4/-2',  // Compared to last visit
  weightChange: '+2 lbs',

  // Learned: This doctor always reviews medications
  medicationsReviewed: true,

  // Domain intelligence: BP above target for diabetic patient
  treatmentPlan: 'Consider medication adjustment - BP above 130/80 target',

  // Pattern: Typical follow-up interval for stable patient
  nextVisit: '12 weeks',

  // But: Suggestion based on elevated BP
  suggestedNextVisit: '4 weeks',
  suggestedReason: 'BP still elevated above target'
};
const intakeDefaults = {
  // Role-based: Associate needs partner approval
  assignedAttorney: 'Sarah Chen, Esq.',
  supervisingPartner: 'Michael Roberts',  // User's supervisor

  // Historical: Last 8 intakes were family law
  practiceArea: 'Family Law',
  subSpecialty: 'Divorce',

  // Learned: This attorney's typical billing
  billingType: 'Hourly',
  standardRate: 275,  // Associate rate

  // Contextual: Current date
  intakeDate: '2024-12-25',

  // Template: Standard conflict check questions
  conflictCheckQuestions: [
    'Opposing party name and DOB',
    'Related parties',
    'Previous legal representation',
    'Known adverse parties'
  ],

  // Organization: Standard intake process
  initialConsultFee: 150,
  retainerAmount: 3500,  // Typical for family law

  // Domain intelligence: Pennsylvania-specific
  jurisdiction: 'Pennsylvania',
  applicableLaw: 'PA Domestic Relations Code',
  filingCourt: 'Court of Common Pleas'
};

E-commerce: Checkout

const checkoutDefaults = {
  // Historical: Last 15 orders shipped here
  shippingAddress: {
    name: 'Richard Roberts',
    street: '123 Main Street',
    city: 'Pittsburgh',
    state: 'PA',
    zip: '15217'
  },

  // Learned: User always selects 2-day shipping
  shippingMethod: 'UPS 2-Day',
  shippingCost: 12.99,

  // Saved: Payment method on file
  paymentMethod: {
    type: 'Credit Card',
    last4: '4242',
    expiry: '12/2025'
  },

  // Contextual: Pennsylvania sales tax
  taxRate: 0.06,
  taxAmount: calculateTax(subtotal, 0.06),

  // Pattern: User typically adds gift message for December orders
  giftMessage: '',
  suggestGiftMessage: true,  // It's December

  // Smart suggestion: Combine with saved cart items?
  savedCartItems: 3,
  suggestCombine: 'You have 3 items in your saved cart. Add them to this order?'
};

Real Estate: Listing Creation

const listingDefaults = {
  // Context: Agent creating listing
  listingAgent: 'Maria Rodriguez',
  listingOffice: 'Keller Williams Downtown',

  // Historical: Agent's typical commission
  commissionRate: 6.0,  // This agent's standard

  // Imported: From MLS pre-search
  propertyAddress: '456 Oak Avenue, Pittsburgh, PA 15213',
  parcelId: '123-45-678',
  lotSize: '0.18 acres',
  yearBuilt: 1925,

  // Calculated: From comparable sales
  suggestedPrice: 425000,
  pricePerSqFt: 212,
  comparables: [
    { address: '460 Oak Ave', price: 415000, sqft: 2100 },
    { address: '452 Oak Ave', price: 435000, sqft: 1950 }
  ],

  // Template: Standard listing description structure
  descriptionTemplate: 'Charming [style] home in [neighborhood]...',

  // Learned: This agent always includes
  includedAppliances: ['Refrigerator', 'Dishwasher', 'Washer/Dryer'],

  // Domain: Pennsylvania seller disclosure requirements
  requiredDisclosures: [
    'Property Disclosure Statement',
    'Lead Paint Disclosure (pre-1978)',
    'Well/Septic Disclosure'
  ],

  // Smart: Photos from previous listing (if relisting)
  previousListing: {
    id: 'MLS-12345',
    photos: 24,
    suggestReuse: 'Reuse photos from previous listing?'
  }
};

Construction: Material Order

const materialOrderDefaults = {
  // Project context: Active job
  project: 'Riverside Apartments - Building C',
  jobNumber: 'RA2024-003',
  costCode: '03-Concrete',

  // Historical: Last 5 orders from this vendor
  vendor: 'Pittsburgh Concrete Supply',
  deliveryTerms: 'Job Site',
  paymentTerms: 'Net 30',

  // Calculated: From project schedule
  requestedDeliveryDate: '2025-01-15',  // When concrete pour scheduled
  earliestAcceptable: '2025-01-14',
  latestAcceptable: '2025-01-15',  // Concrete timing critical

  // Learned: Superintendent's preferences
  deliveryTimeWindow: '7:00 AM - 9:00 AM',  // Before crew break
  contactOnsite: 'John Smith (Foreman)',
  contactPhone: '(412) 555-0123',

  // Template: Standard concrete order
  material: '3000 PSI Concrete',
  quantity: calculateQuantity(area, thickness, wasteFactor),
  unit: 'Cubic Yards',

  // Domain intelligence: Weather-based suggestion
  weatherForecast: 'Rain predicted Jan 15',
  suggestion: 'Consider rescheduling pour - rain forecast',
  alternativeDates: ['2025-01-14', '2025-01-16'],

  // Safety: Required certifications
  requiredCerts: [
    'Material Safety Data Sheet',
    'Concrete Mix Design',
    'Slump Test Requirements'
  ]
};

Prerequisites: - Volume 3, Pattern 6: Domain-Aware Validation (defaults must be valid) - Volume 3, Pattern 7: Calculated Dependencies (some defaults are calculated)

Synergies: - Volume 3, Pattern 1: Progressive Disclosure (defaults make sections feel complete) - Volume 3, Pattern 2: Contextual Scaffolding (defaults adapt to expertise level) - Volume 3, Pattern 9: Contextual Constraints (defaults respect constraints) - Volume 3, Pattern 23: Intelligent Pre-Population (specific implementation of this pattern)

Conflicts: - Audit requirements (some systems need blank forms for compliance) - Learning systems (need clean data, not influenced by defaults)

Alternatives: - Templates (user explicitly chooses a starting point) - Duplication (copy from previous entry) - Import (pull from external system)

Known Uses

Gmail: Smart Compose suggests sentence completions based on your writing patterns

QuickBooks: Pre-fills invoice fields based on customer history and previous invoices

Electronic Health Records (Epic, Cerner): Smart phrases, order sets, and documentation templates

TurboTax: Imports previous year's return, suggests deductions based on occupation

Salesforce: Pre-populates lead/contact fields based on email domain and company info

Google Calendar: Suggests meeting times based on availability patterns

Adobe Creative Cloud: Recent files, frequent colors, common settings all pre-selected

GitHub: Pre-fills PR descriptions with commit messages and issue references

Stripe: Remembers customer payment methods, pre-fills billing addresses

Further Reading

On Default Values and UX: - "The Power of Defaults." Nielsen Norman Group. https://www.nngroup.com/articles/the-power-of-defaults/ (How defaults influence behavior) - Thaler, Richard H., and Cass R. Sunstein. Nudge. Penguin, 2008. (Default effects on decision-making)

On Machine Learning for Predictions: - "Autocompletion and Suggestion APIs." Google Cloud. https://cloud.google.com/places/docs/predictions (Smart suggestions at scale) - Scikit-learn: https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html (k-NN for similar cases)

On Form Design Best Practices: - Wroblewski, Luke. Web Form Design: Filling in the Blanks. Rosenfeld Media, 2008. (Chapter on smart defaults) - "Form Design: 13 Empirically-Backed Best Practices." Baymard Institute. https://baymard.com/blog/form-design-best-practices

On Privacy and Defaults: - "Privacy by Design." GDPR Guidelines. https://gdpr.eu/privacy-by-design/ (Default settings must respect privacy) - "Dark Patterns." Deceptive Patterns. https://www.deceptive.design/ (What NOT to do with defaults)

Implementation Examples: - Autofill Specification: https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill (HTML autocomplete attribute) - React Hook Form Controller: https://react-hook-form.com/api/usecontroller/controller (Controlled defaults in React)


  • Pattern 6: Domain-Aware Validation - Defaults must be valid
  • Pattern 7: Calculated Dependencies - Can pre-populate based on calculations
  • Pattern 9: Contextual Constraints - Defaults respect constraints
  • Pattern 10: Semantic Suggestions - Intelligent suggestions complement smart defaults
  • Volume 2, Pattern 11: Historical Pattern Matching - Finding similar cases for defaults
  • Volume 2, Pattern 18: Opportunity Mining - Group-specific defaults
  • Volume 1, Chapter 9: User Experience Design - Forms feed documents—good defaults improve document quality