ADR-189: Activity Association Fallback Strategies
Status
ACCEPTED (2026-01-28)
Context
Problem Statement
The J.14 Activity-Project Association Pipeline extracts activities from LLM sessions and associates them with projects and TRACK task IDs. However, not all activities can be confidently associated:
| Scenario | Frequency | Challenge |
|---|---|---|
| No task ID in tool_description | ~22% | Governance hooks not enforced pre-ADR-074 |
| Path doesn't match known project | ~15% | Generic paths like /tmp, ~/.config |
| Multiple possible tracks | ~8% | Activity spans multiple domains |
| Completely unassociated | ~22% | No signals available |
Current State (Before)
Activities without clear associations were stored with:
task_id = NULLtrack = NULLproject_name = NULLconfidence = 0.0association_method = 'unassociated'
Problems:
- Query Ambiguity:
WHERE track IS NULLconflates "unknown" with "genuinely no track" - No Resolution Path: No way to flag for review or track resolution attempts
- Lost Context: No record of why association failed
Decision
Four-Tier Confidence Model
Establish clear tiers with distinct behaviors:
| Tier | Method | Confidence | Trigger | Action |
|---|---|---|---|---|
| 1 | explicit | 0.99 | Task ID in tool_description | Direct association |
| 2 | path | 0.85 | File path matches project | Project association, track inferred |
| 3 | temporal | 0.70 | Nearby activity has task ID | Inherit from context |
| 4 | ambiguous | 0.50 | Multiple candidates | Flag for resolution |
| 5 | unassociated | 0.00 | No signals | Default sentinel values |
Sentinel Values
Use explicit sentinel values instead of NULL for queryability:
-- Sentinel value conventions
'_NONE' -- Definitively no track/project (e.g., system activity)
'_UNKNOWN' -- Could not determine (needs investigation)
'_AMBIGUOUS' -- Multiple candidates (needs resolution)
NULL -- Genuinely not applicable (rare)
Database Field Defaults
| Scenario | task_id | track | project_name | confidence | method |
|---|---|---|---|---|---|
| Explicit match | 'H.8.1.6' | 'H' | 'coditect-core' | 0.99 | 'explicit' |
| Path only | NULL | 'H' | 'coditect-core' | 0.85 | 'path' |
| Temporal | 'H.8.1.6' | 'H' | 'coditect-core' | 0.70 | 'temporal' |
| Ambiguous | '_AMBIGUOUS' | '_AMBIGUOUS' | '_AMBIGUOUS' | 0.50 | 'ambiguous' |
| Unassociated | NULL | '_NONE' | '_UNKNOWN' | 0.00 | 'unassociated' |
Resolution Support Schema
Add columns to support resolution workflow:
-- New columns in activity_associations table (sessions.db)
candidate_tasks TEXT, -- JSON: ["H.8.1", "J.14.1"]
candidate_projects TEXT, -- JSON: ["coditect-core", "rollout"]
needs_review INTEGER, -- 1 if flagged for human/LLM review
resolution_notes TEXT, -- Notes from resolution attempts
resolved_at TEXT -- Timestamp when resolved
Resolution Strategies
When activity is ambiguous or unassociated, apply these strategies in order:
┌─────────────────────────────────────────────────────────────────┐
│ Resolution Strategy Cascade │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. SESSION CONTEXT (±5 messages) │
│ │ Look for explicit task IDs in surrounding messages │
│ │ If found → inherit task_id, confidence = 0.70 │
│ ▼ │
│ 2. TEMPORAL PROXIMITY │
│ │ Find most recent explicit task in same session │
│ │ If < 10 messages ago → inherit, confidence = 0.65 │
│ ▼ │
│ 3. PATH HIERARCHY │
│ │ Derive track from project structure │
│ │ /coditect-core/agents/ → Track H (Framework) │
│ │ If match → confidence = 0.60 │
│ ▼ │
│ 4. LLM SEMANTIC (Future) │
│ │ Use LLM to classify content against track descriptions │
│ │ If high similarity → confidence = 0.55 │
│ ▼ │
│ 5. FLAG FOR REVIEW │
│ Set needs_review = 1, store in candidate_* columns │
│ │
└─────────────────────────────────────────────────────────────────┘
Query Patterns
-- Find all unassociated activities
SELECT * FROM activity_associations
WHERE association_method = 'unassociated';
-- Find activities needing review
SELECT * FROM activity_associations
WHERE needs_review = 1;
-- Find ambiguous activities with candidates
SELECT *,
json_extract(candidate_tasks, '$') as candidates
FROM activity_associations
WHERE association_method = 'ambiguous';
-- Confidence distribution
SELECT
association_method,
COUNT(*) as count,
ROUND(AVG(confidence), 2) as avg_conf
FROM activity_associations
GROUP BY association_method;
Consequences
Positive
- Clear Querying: Sentinel values enable unambiguous filtering
- Resolution Path:
needs_reviewflag enables workflow - Audit Trail:
resolution_notescaptures why decisions were made - Candidate Tracking: JSON arrays preserve alternatives
Negative
- Schema Change: Existing data needs migration
- Complexity: More columns to manage
- Resolution Overhead: Manual review for ambiguous cases
Metrics
Track resolution effectiveness:
| Metric | Target |
|---|---|
| Explicit associations | > 25% |
| Path-based associations | > 50% |
| Unassociated activities | < 20% |
| Needs review queue | < 100 items |
Implementation
Phase 1: Schema Update (Complete)
Updated activity_project_associator.py schema with:
- Sentinel value documentation
candidate_tasks,candidate_projectscolumnsneeds_review,resolution_notes,resolved_atcolumns
Phase 2: Resolution Strategies (Planned)
class ResolutionStrategy:
"""Base class for resolution strategies."""
def resolve(self, activity: ActivityAssociation) -> Optional[Resolution]:
raise NotImplementedError
class SessionContextStrategy(ResolutionStrategy):
"""Look at surrounding messages for task IDs."""
def resolve(self, activity):
nearby = get_nearby_messages(activity.session_id, ±5)
for msg in nearby:
if task_id := extract_task_id(msg):
return Resolution(
task_id=task_id,
confidence=0.70,
method='temporal',
notes='Inherited from nearby message'
)
return None
Phase 3: Review Dashboard (Planned)
Create /cxq --needs-review command to surface activities needing attention.
Related
- ADR-118: Four-Tier Database Architecture (sessions.db)
- ADR-054: Track Nomenclature Standard
- ADR-074: Governance Hooks (task_id_validator)
Changelog
| Date | Change |
|---|---|
| 2026-01-28 | Initial version |
Track: J.14 (Memory - Activity-Project Association) Task: J.14.1.3