Skip to content

ADR-012: Semantic Context Trigger Classification

Status: Accepted Date: 2026-03-19 Context: Context triggers (crisis, team conflict, resource constraint, etc.) were detected via keyword matching on scenario text. This had known failure modes: missing scenarios about resource constraints that don't use the word "budget," false-positives on incidental keyword mentions, and binary present/absent output with no confidence score. Per ADR-011, the delegation map concept requires reliable context classification to base governance authority on.

Decision

Extend the existing classify-driver API endpoint to also classify context triggers semantically. The prompt already receives the full scenario context (title, description, category, option, rationale) — trigger classification is a parallel task that adds negligible cost (~20 extra output tokens).

The response expands from:

{"driver": "pragmatism", "confidence": 0.8, "reasoning": "..."}
To:
{
  "driver": "pragmatism",
  "confidence": 0.8,
  "reasoning": "...",
  "triggers": [{"trigger": "external_pressure", "confidence": 0.9}]
}

In updatePlayerProfile(), keyword detection runs first as the fallback. If the API returns semantic triggers, they override the keyword-detected triggers. Disagreements are logged for analysis.

Rationale

The classify-driver API call already has all the data needed — adding trigger classification to the same call is essentially free. Semantic classification catches triggers that keywords miss (e.g., a scenario about running out of time that doesn't use "budget" but IS a resource constraint) and avoids false-positives (a scenario mentioning "budget" incidentally).

Each trigger now has a confidence score (0.0-1.0, filtered at ≥0.3), which provides richer signal than binary present/absent for context rule confidence accumulation.

Alternatives Considered

  • Separate API endpoint for trigger classification: More modular but doubles the API calls per game. The data needed is identical to classify-driver, so a combined call is more efficient.
  • Improved keyword lists: Cheaper but fundamentally limited — no keyword list can capture the full semantic range of "resource constraint" across all possible scenario phrasings.
  • Classify triggers at scenario generation time: Would work for AI-generated scenarios but not for manually created ones. Also misses the player's rationale context which can clarify ambiguous triggers.

Consequences

  • Context rule confidence data will be more accurate going forward, improving the eventual delegation map's reliability.
  • Trigger exposure tracking becomes more reliable — coverage scores reflect actual context diversity, not keyword coincidence.
  • The keyword fallback ensures graceful degradation for speed rounds (no rationale → no API call → keyword detection) and API failures.
  • Disagreement logging between keyword and semantic triggers creates a dataset for evaluating trigger detection quality over time.

How We Got Here

This came out of the ADR-011 design exploration about the delegation map. When analyzing CoachJ's context rules, we noticed that the confidence scores were relatively low (highest: 33%) despite high exposure counts (22 for external_pressure). One contributing factor: keyword matching was introducing noise — detecting triggers that weren't really the core of the scenario, and missing triggers that were.

The insight that triggered this work: "For a delegation map that determines governance authority, this should be upgraded to semantic classification." The existing classify-driver endpoint provided a natural extension point since it already analyzes the same scenario context. Bundling trigger classification into the same call keeps the cost negligible while significantly improving data quality.

Key files: - src/app/api/ai/classify-driver/route.ts — expanded prompt and response handling - src/lib/ai/player-model.ts — semantic trigger override with keyword fallback