Skip to content

Goal Management

Vita's goal system tracks health, relationship, and personal development objectives with built-in progress monitoring, frequency-based scheduling, and check-in integration. Goals drive daily prompts, power the goal-progress memory view, and enable drift detection to prevent goals from silently slipping.

Why This Design?

Goals in Vita serve three purposes that traditional todo lists cannot:

  1. Continuous tracking, not one-time completion - Most health goals ("improve body composition") require ongoing measurement, not a checkbox. The system tracks current_value against target_value over time.

  2. Hypothesis-driven improvement - The goal_framework field links input metrics (controllable actions like "2 strength sessions/week") to output metrics (lagging indicators like "body fat %"). This lets you validate whether your actions actually drive results.

  3. Proactive drift detection - Frequency-based goals alert you before you fall behind. If you typically skate twice a week and miss a session, the system warns you with 3 days left rather than at week's end.

Current State (as of mid-2026)

8 active goals (count drifts as goals are added/achieved; verify against goals/active/) spanning: - Body composition (1): Sub-13% body fat - Fitness (4): Weekly training structure, maintain cardiovascular fitness, backflip, land 10 new skateboard tricks - Work (1): CEO transformation 90-day - System usage (2): VITA daily brief habit, 100B Claude tokens

5 visions in goals/visions/: - Optimal Health, Relationships, Skill Mastery, Financial Prosperity, Effectiveness

Goal v2 schema in use: Goals now support purpose, hypothesis, linked goals, enrichment tracking, and completeness scoring. The "weekly training structure" goal is an input metric that drives the "sub-13% body fat" output metric. The hypothesis: consistent training drives body composition changes.

Note: relationship frequency goals (previously active) have moved to goals/archived/.

Trigger Points

Trigger Action
/goal or /goal list Display all active goals with progress
/goal add <description> Create goal from natural language
/goal update <id> [field] [value] Update progress or settings
/goal enrich <name> Schedule Telegram enrichment for missing fields
/goal complete <id> Mark achieved, move to goals/achieved/
/checkin Goals' check_in_prompts are included in question pool
Memory view build goal-progress view aggregates all goal status
Scheduling drift check Weekly/interval goals checked for overdue status
Occurrence logging Auto-increments current_value for frequency goals
Sleep gate check High-intensity activities blocked when 7-day sleep avg < 6.5h

Process Flow

                                   USER CREATES GOAL
                                          |
                        +------------------+------------------+
                        |                                     |
                        v                                     v
              +-------------------+               +---------------------+
              | /goal add "..."   |               | Manual JSON edit    |
              | (natural language)|               | (full control)      |
              +--------+----------+               +----------+----------+
                       |                                     |
                       v                                     v
              +--------------------------------------------------------+
              |              Goal JSON File Created                     |
              |         goals/active/<filename>.json                    |
              |                                                         |
              |  Required: id, title, status, created_at                |
              |  Common: target_value, current_value, check_in_prompts  |
              |  Optional: frequency (for tracking), goal_framework     |
              +----------------------------+----------------------------+
                                           |
           +---------------+---------------+---------------+
           |               |               |               |
           v               v               v               v
    +-----------+   +-----------+   +-----------+   +-----------+
    | /checkin  |   | goal-     |   | Drift     |   | API       |
    | prompts   |   | progress  |   | detector  |   | /goals    |
    +-----------+   | view      |   +-----------+   +-----------+
           |        +-----------+         |               |
           |              |               |               v
           v              v               v        +------------+
    +-------------+  +----------+  +----------+    | Web UI     |
    | User answers|  | LLM syn- |  | VDB warns|    | dashboard  |
    | questions   |  | thesizes |  | of drift |    +------------+
    +------+------+  | summary  |  +----+-----+
           |         +----------+       |
           |                            |
           v                            v
    +--------------+            +----------------+
    | /goal update |            | /schedule log  |
    | manual value |            | auto-increment |
    +--------------+            +----------------+
           |                            |
           +----------------------------+
                         |
                         v
                  +-------------+
                  | goal.json   |
                  | updated_at  |
                  | current_val |
                  +-------------+

Implementation Details

Goal Types

Vita supports three goal patterns:

  1. Simple numeric goals - Track progress toward a single number
  2. Example: "Improve body composition" (current_value: 18 -> target_value: 15)
  3. Progress is current_value / target_value * 100

  4. Frequency goals (interval) - Ensure regular occurrence

  5. Example: "Date night every 2 weeks" (frequency.type: "interval")
  6. Tracks days since last occurrence, warns before deadline

  7. Frequency goals (weekly) - Hit weekly component targets

  8. Example: "2 skate sessions, 2 strength days per week" (frequency.type: "weekly")
  9. Tracks multiple components with individual targets

Goal Creation

Goals are typically created via /goal add or by directly editing JSON files. The filename becomes a shorthand alias (e.g., weekly-training-structure.json can be referenced as training).

Required fields: - id: UUID (use scripts.utils.generate_uuid()) - title: Display name - status: One of active, achieved, abandoned - created_at: ISO8601 timestamp

Common optional fields: - target_value, current_value: For progress tracking - check_in_prompts: Array of questions for /checkin - frequency: Configuration for drift detection (see below) - goal_framework: Input/output metric linking and hypothesis tracking

Auto-Increment on Occurrence Logging

When /schedule log <goal> is called, the scheduling engine automatically increments the goal's current_value:

# scripts/scheduling/goals.py
def increment_goal_counter(goal_id: str, amount: int = 1) -> bool:
    goal["current_value"] = goal.get("current_value", 0) + amount
    goal["updated_at"] = datetime.now(TZ).isoformat()
    atomic_write(str(goal_path), goal)

This means goals like "Land 10 new skateboard tricks" auto-update when you log schedule log tricks. No manual /goal update needed.

The inverse runs when an occurrence is deleted. The engine looks up the deleted occurrence's goal_id and calls decrement_goal_counter(goal_id, amount=1), which floors at 0 (max(0, current_value - amount)) so a counter can never go negative:

# scripts/scheduling/goals.py
def decrement_goal_counter(goal_id: str, amount: int = 1) -> bool:
    goal["current_value"] = max(0, goal.get("current_value", 0) - amount)
    goal["updated_at"] = datetime.now(TZ).isoformat()
    atomic_write(str(goal_path), goal)

engine.py fires this from the occurrence-deletion path (it re-reads the JSONL, finds the line marked deleted, and decrements the matching goal). Both helpers return False if the goal file is missing or has no current_value field, and both invalidate the in-process goal/alias caches.

Sleep Gate on High-Intensity Logging

When an occurrence is logged, engine.py runs the sleep gate before recording it. The gate (scripts/scheduling/sleep_gate.py, SLEEP_THRESHOLD = 6.5) blocks high-intensity components when the 7-day sleep average is below 6.5 hours and raises SleepGateError:

# scripts/scheduling/engine.py β€” inside log_occurrence(...)
if not bypass_sleep_gate:
    sleep_check = check_sleep_gate(resolved_component)
    if sleep_check.is_blocked:
        raise SleepGateError(sleep_check.message, sleep_check)

The logging call accepts a bypass_sleep_gate: bool = False parameter. Passing bypass_sleep_gate=True records the occurrence without consulting the gate β€” the escape hatch for cases where the gate should not apply (e.g. backfilling a past session, or logging an activity that was already completed). Only high-intensity components are gated; everything else passes regardless. See Sleep Guardian and the board resolution that defined the policy (Board Meetings).

Check-in Integration

During /checkin, the system: 1. Reads all goals/active/*.json files 2. Extracts each goal's check_in_prompts array 3. Prioritizes by drift status (CRITICAL/OVERDUE goals asked first) 4. Includes these in the question pool

API Endpoints

Location: api/src/routers/goals.py

Endpoint Method Description
/api/v1/goals GET List all active goals with completeness scores
/api/v1/goals/{id} GET Get single goal with full v2 schema
/api/v1/goals/{id} PUT Update v2 fields (purpose, hypothesis, links, prompts)
/api/v1/goals/{id}/progress GET Get progress history from goal-progress view
/api/v1/goals/{id}/enrich POST Schedule Telegram enrichment session
/api/v1/goals/{id}/enrich DELETE Cancel pending enrichment

The list endpoint returns GoalSummary objects with completeness scores and purpose info. The single-goal endpoint returns the full Goal model with all v2 fields.

Goal Enrichment

Goals with low completeness scores can be enriched via Telegram-based Q&A (see .claude/skills/goal-enrichment/SKILL.md).

Trigger: /goal enrich <name> or POST /api/v1/goals/{id}/enrich

Workflow: 1. Check completeness - skip if already complete 2. Check for existing pending enrichment - error if one exists 3. Schedule questions via Telegram proactive system 4. Questions target missing fields in priority order: purpose.vision, hypothesis.statement, hypothesis.counter_metrics 5. User responds via Telegram 6. Responses applied to goal file, last_enriched timestamp set

Thread format: enrich-{goal_id[:8]}-{uuid8}

Timeout: Pending enrichment clears after 7 days with no activity.

The /sleep command can auto-trigger enrichment for goals below a completeness threshold.

Delivery class: enrichment is a Telegram Q&A, so its proactive messages route through the message delivery class. Its trigger key (goal_enrichment) sits in the high-priority enqueue tier (TRIGGER_TIER_HIGH in scripts/proactive/queue.py) with its own rate budget, so enrichment questions are not crowded out by general outreach. See Proactive Outreach for the enqueue tiers.

Memory View: goal-progress

Prompt: memory/prompts/build-goal-progress.md Output: memory/views/goal-progress.json

The view builder gathers: - All active goals from goals/active/ - Recent occurrences from data/scheduling/occurrences-*.jsonl - Precedent habit reports (last 14 days)

Then an LLM synthesizes a structured progress report (counts below are illustrative placeholders, not the real goal roster):

{
  "content": {
    "summary": "N active goals tracked. Body composition at target...",
    "status_breakdown": {"on_track": 4, "behind": 2, "at_risk": 1},
    "goals": [...],
    "frequency_goals": [...],
    "attention_needed": [
      {
        "goal_id": "...",
        "issue": "Week 1 cardio behind: no zone 2 or intervals yet",
        "suggested_action": "Do a zone 2 session today or tomorrow"
      }
    ]
  },
  "citations": [
    {"claim": "Body fat at 18%, target 15%", "source": "goals/active/..."}
  ]
}

Frequency-Based Goals and Drift Detection

Goals with a frequency field are monitored by scripts/scheduling/drift_detector.py:

Interval goals (e.g., date nights every 2 weeks):

Day 0        Day 12       Day 14       Day 17
  |-------------|------------|------------|
  Last occ     WARNING      OVERDUE     CRITICAL
              starts       starts       starts

Weekly goals (e.g., 2 skate sessions per week):

For each component, calculates: - count: Occurrences this week - remaining: Target minus count - days_left: Days until week resets

Status is WARNING if remaining > days_left (can't hit target even if you go daily).

Data Structures

Goal JSON Schema (v2)

Goals are stored as individual JSON files in goals/active/. The schema version is 2, with enrichment and completeness tracking.

Required fields:

{
  "id": "uuid-string",
  "title": "Display name",
  "status": "active|achieved|abandoned",
  "created_at": "2026-01-01T00:00:00-08:00"
}

V2 schema fields:

Field Type Purpose
schema_version int Schema version (2)
metric_type "input" / "output" / "behavioral" Whether goal is a controllable action, a lagging indicator, or a behavioral pattern. Schema drift: the Pydantic models declare Literal["input", "output"], but at least one live goal file carries "behavioral" β€” a value the validator does not permit. Treat the declared Literal as aspirational; the data is ahead of it.
purpose.vision string Ultimate impact - what achieving this enables
purpose.ladder string How this connects to higher goals
purpose.why_this_target string Rationale for specific target value
hypothesis.statement string Theory of change
hypothesis.assumptions string[] What must be true for approach to work
hypothesis.counter_metrics string[] Early warning signs that approach isn't working
hypothesis.reassess_date date When to revisit hypothesis
linked_goals object[] {goal_id, relationship: "drives"|"driven_by"}
enrichment.last_enriched timestamp Last enrichment completion
enrichment.pending_thread_id string Active Telegram enrichment thread
enrichment.pending_since timestamp When enrichment was started
enrichment.source string How enrichment was triggered

Standard fields:

Field Type Purpose
description string Longer explanation, context
target_value number/boolean What success looks like
current_value number/boolean Auto-updated on occurrence log
target_date date Deadline for completion
priority "high"/"medium"/"low" Affects sort order, check-in frequency
check_in_prompts string[] Questions included in /checkin
frequency object Drift detection config (see below)
goal_framework object Input/output metric linking (legacy, being replaced by v2 fields)
baseline object Starting measurements for comparison
interventions object[] Logged changes (e.g., supplement adjustment)

Completeness scoring (computed, not stored in file):

The API calculates a completeness score based on which v2 fields are populated: - metric_type - present or not - purpose.vision - highest weight - hypothesis.statement - present or not - hypothesis.assumptions - non-empty - linked_goals - non-empty - check_in_prompts - non-empty - frequency or tracking method - present

Levels: skeleton (0-25%), partial (25-50%), good (50-75%), complete (75-100%)

Frequency Configuration

Interval type (for "every N days" goals):

{
  "frequency": {
    "type": "interval",
    "target_interval_days": 14,
    "drift_warning_days": 12,
    "tolerance_days": 3,
    "preferred_days": ["friday", "saturday"],
    "preferred_times": ["evening"],
    "quiet_mode": false,
    "max_warnings_per_session": 1
  }
}

Weekly type (for "N times per week" goals):

{
  "frequency": {
    "type": "weekly",
    "week_starts": "monday",
    "week_reset_hour": 4,
    "components": {
      "skate_sessions": {"target": 2, "aliases": ["skate", "skating"]},
      "zone_2_cardio": {"target": 2, "aliases": ["zone2", "cardio", "cycling"]},
      "max_effort_interval": {"target": 1, "aliases": ["interval", "hiit"]},
      "strength_days": {"target": 2, "aliases": ["strength", "weights", "gym"]}
    },
    "quiet_mode": false
  }
}

The aliases array lets users log occurrences with natural names: /schedule log training --component=skate works the same as --component=skate_sessions.

Goal Framework (Input/Output Linking)

The v2 schema fields enable hypothesis-driven goal tracking:

Input metric (controllable actions) - v2 schema:

{
  "metric_type": "input",
  "purpose": {
    "vision": "What achieving this truly enables",
    "ladder": "How this connects to higher goals",
    "why_this_target": "Rationale for the specific target"
  },
  "hypothesis": {
    "statement": "Doing X will cause Y to improve",
    "assumptions": ["volume is sufficient", "consistency matters more than intensity"],
    "counter_metrics": ["fatigue indicators", "injury frequency"],
    "reassess_date": "2026-04-01"
  },
  "linked_goals": [
    {"goal_id": "uuid-of-body-comp-goal", "relationship": "drives"}
  ]
}

Output metric (lagging indicators) - v2 schema:

{
  "metric_type": "output",
  "purpose": {
    "vision": "Feel great and confident in my body"
  },
  "hypothesis": {
    "statement": "Consistent weekly training will improve body composition",
    "assumptions": [
      "Training volume is sufficient",
      "Strength work preserves lean mass"
    ],
    "counter_metrics": [
      "Lean mass stays stable",
      "Strength numbers don't decrease"
    ]
  },
  "linked_goals": [
    {"goal_id": "uuid-of-training-goal", "relationship": "driven_by"}
  ]
}

This structure answers: "I'm doing X (input). Will it actually move Y (output)?" The counter_metrics catch unintended consequences (e.g., losing muscle while cutting fat). The linked_goals field makes relationships bidirectional with explicit drives / driven_by semantics.

Note: The migration to v2 is incomplete. The legacy goal_framework field is present on all active goals, while only half carry the v2 schema_version/metric_type fields. In other words, every goal still has the old structure and only some have been upgraded β€” the two representations coexist, and consumers should read whichever is present.

Real Goal Examples

Frequency-based interval goal (example):

{
  "id": "9a23e8bf-...",
  "title": "Weekly hobby session",
  "description": "Weekly dedicated time for a recurring activity.",
  "target_metric": "sessions",
  "target_value": 52,
  "current_value": 1,
  "unit": "sessions",
  "check_in_prompts": [
    "Did you get a session in this week?",
    "Any highlights?",
    "What did you work on?"
  ],
  "frequency": {
    "type": "interval",
    "target_interval_days": 7,
    "drift_warning_days": 6,
    "tolerance_days": 2,
    "preferred_days": ["saturday", "sunday"],
    "preferred_times": ["morning", "afternoon"]
  },
  "status": "active",
  "priority": "high"
}

Note: current_value auto-increments when an occurrence is logged via /schedule log.

Goal with v2 schema (goals/active/weekly-training-structure.json):

{
  "id": "a7a038a5-09e3-436d-9684-2daec6a5702e",
  "title": "Weekly training structure",
  "schema_version": 2,
  "metric_type": "input",
  "purpose": {
    "vision": "Aspirational end-state that captures what success looks and feels like.",
    "ladder": "Training consistency drives progression, body composition, and cardiovascular improvements.",
    "why_this_target": "52 weeks = 1 year of consistent effort."
  },
  "hypothesis": {
    "statement": "Doing this weekly structure with genuine effort will drive body composition and cardiovascular improvements",
    "assumptions": [
      "This training volume is sustainable long-term",
      "Mix of modalities covers all fitness domains",
      "Skating counts as meaningful training (skill + physical)"
    ],
    "counter_metrics": [
      "Chronic fatigue or burnout indicators",
      "Injury frequency increasing",
      "Sleep quality degrading due to overtraining"
    ],
    "reassess_date": "2026-04-01"
  },
  "linked_goals": [
    {"goal_id": "cc00d306-bc21-4e0d-b66c-65b4144f5d61", "relationship": "drives"}
  ],
  "enrichment": {
    "last_enriched": null,
    "pending_thread_id": null,
    "pending_since": null,
    "source": null
  },
  "frequency": {
    "type": "weekly",
    "week_starts": "monday",
    "components": {
      "skate_sessions": {"target": 2, "aliases": ["skate", "skating"]},
      "zone_2_cardio": {"target": 2, "aliases": ["zone2", "cardio", "cycling"]},
      "max_effort_interval": {"target": 1, "aliases": ["interval", "hiit"]},
      "strength_days": {"target": 2, "aliases": ["strength", "weights"]}
    }
  }
}

Visions

Long-term visions live in goals/visions/*.json. These are aspirational North Stars that goals ladder up to.

{
  "id": "1da40fe4-ecd1-459a-88be-13c95a5373d3",
  "title": "Optimal Health",
  "type": "vision",
  "statement": "Reach, maintain, and operate in a state of optimal mental and physical health",
  "qualitative_markers": [
    "Look in mirror and say 'fuck yes'",
    "Body feels capable, energetic, resilient"
  ],
  "domains": ["fitness", "body_composition", "hormones", "sleep", "nutrition"],
  "output_metrics": [
    {"metric": "body_fat_percent", "target": "<13%"},
    {"metric": "vo2_max", "target": ">60"}
  ],
  "linked_goals": ["cc00d306-...", "a7a038a5-..."]
}

Current visions: Optimal Health, Relationships, Skill Mastery, Financial Prosperity, Effectiveness.

Goal Lifecycle

Goals move between directories based on status:

Directory Purpose
goals/active/ Currently tracked goals
goals/achieved/ Goals marked complete (moved on /goal complete)
goals/archived/ Goals abandoned or deprioritized
goals/visions/ Long-term aspirational North Stars

API Response Schema

Location: api/src/schemas/goals.py

class GoalSummary(VitaBaseModel):
    id: str
    title: str
    description: str | None = None
    status: str
    priority: str | None = None
    metric_type: Literal["input", "output"] | None = None
    completeness: GoalCompleteness
    purpose: GoalPurpose | None = None

class Goal(VitaBaseModel):
    # Full v2 model with all fields
    id: str
    title: str
    schema_version: int = 2
    metric_type: Literal["input", "output"] | None = None
    purpose: GoalPurpose = GoalPurpose()
    hypothesis: GoalHypothesis = GoalHypothesis()
    linked_goals: list[GoalLink] = []
    enrichment: GoalEnrichment = GoalEnrichment()
    # ... plus tracking fields, frequency, check_in_prompts

class GoalUpdate(VitaBaseModel):
    metric_type: Literal["input", "output"] | None = None
    purpose: GoalPurpose | None = None
    hypothesis: GoalHypothesis | None = None
    linked_goals: list[GoalLink] | None = None
    check_in_prompts: list[str] | None = None

The list endpoint returns GoalSummary with completeness scores. The single-goal endpoint returns the full Goal model. The GoalUpdate model is used for PUT updates (validates linked goal IDs exist, uses file locking).

Warning: The metric_type Literal above (Literal["input", "output"]) does not match the data on disk β€” at least one live goal file uses "behavioral". A reimplementer should either widen the Literal to include "behavioral" or expect validation to reject those files. The data drifted ahead of the schema.

File Locations

File/Directory Purpose
goals/active/*.json Active goal definitions
goals/achieved/*.json Completed goals (moved on completion)
goals/archived/*.json Abandoned or deprioritized goals
goals/visions/*.json Long-term aspirational visions
api/src/routers/goals.py REST API endpoints (list, get, update, enrich)
api/src/schemas/goals.py Pydantic models (v2 schema with completeness)
api/src/services/goals.py Service layer (completeness scoring, updates)
scripts/scheduling/goals.py Goal resolution, aliases, counter updates, completeness
scripts/scheduling/drift_detector.py Frequency goal monitoring
scripts/scheduling/sleep_gate.py Sleep gate for high-intensity activities
scripts/scheduling/engine.py Occurrence logging, auto-increment, sleep gate
scripts/proactive/goal_enrichment.py Telegram-based enrichment Q&A
.claude/skills/goal-enrichment/SKILL.md Enrichment skill documentation
memory/prompts/build-goal-progress.md LLM prompt for view synthesis
memory/views/goal-progress.json Cached goal status view
data/scheduling/occurrences-YYYY-MM.jsonl Frequency goal events

Error Handling

Error Handling
Goal not found ValueError with list of available aliases
Invalid component ValueError with list of valid components
Sleep gate blocked SleepGateError when 7-day sleep avg < 6.5h (high-intensity only)
Enrichment already pending 409 Conflict with pending_since timestamp
Goal already complete 400 Bad Request (enrichment not needed)
Linked goal not found 400 Bad Request on PUT with invalid goal_id
File lock timeout 503 Service Unavailable (filelock.Timeout)
Duplicate occurrence DuplicateError - same goal+component within 2 hours, or same Garmin/RWGPS ID
Malformed goal JSON Skip file in API, log warning, continue with other goals
Lock contention RuntimeError after 5-second timeout
Missing occurrences Report NO_DATA status, don't fail

Status Definitions

Used in goal-progress view:

Status Meaning
on_track Making expected progress, no intervention needed
ahead Exceeding expected progress rate
behind Below expected progress, needs attention
at_risk Significantly behind or stalled
completed Target achieved

For frequency goals specifically:

Status Meaning
ON_TRACK Within target interval
WARNING Approaching deadline (drift_warning_days reached)
OVERDUE Past target but within tolerance
CRITICAL Past tolerance period
NO_DATA No occurrences logged yet
QUIET Suppressed by quiet_mode

Known Limitations

  1. No automated progress sync for non-frequency goals - Goals like "VO2 Max over 60" require manual current_value updates. Only frequency goals auto-increment.

  2. Goal framework not fully visualized - The input/output metric linking via linked_goals exists in data but the web UI doesn't show the dependency graph of which inputs drive which outputs.

  3. Weekly goal reset timing - Configurable per goal (week_reset_hour) but can cause confusion if logging late at night.

  4. Legacy goal_framework coexists with v2 fields - The v2 migration is only half done: all active goals still carry the old goal_framework object, while only half also carry the new purpose, hypothesis, linked_goals, and schema_version/metric_type fields. Both representations should be kept in sync until the migration completes.

  5. Counter-metrics not auto-monitored - The hypothesis.counter_metrics field documents what to watch for but nothing automatically tracks or alerts on them.

  6. Enrichment 501 fallback - The enrichment module (scripts/proactive/goal_enrichment.py, exporting schedule_goal_enrichment) is wired and imported by the router. The POST /enrich endpoint returns 501 Not Implemented only as a defensive fallback if that import fails (except ImportError); under normal operation the import succeeds and a Telegram Q&A is scheduled.

Improvement Opportunities

High Value

  1. Auto-sync current_value from Garmin - For goals like VO2 Max, body fat, pull latest values from Garmin data files. The data exists in data/garmin/YYYY-MM-DD.json (including training.vo2max_generic) - just needs a daily job to update goal files.

  2. Goal dependency graph in UI - Render the linked_goals relationships visually. Show: "Weekly training structure" --(drives)--> "Sub-13% body fat" laddering up to "Vision: Optimal Health". Would make the system's hypothesis-testing nature visible.

  3. Complete goal_framework -> v2 migration - Some goals still use the legacy goal_framework field alongside v2 purpose, hypothesis, and linked_goals. Need a migration pass to consolidate.

Medium Value

  1. Counter-metric alerts - Parse hypothesis.counter_metrics and create synthetic alerts when they're violated. Example: alert if sleep quality degrades while training volume is high.

  2. Smart check-in prompt rotation - Track which prompts have been asked recently. Avoid "Date night this week?" three days in a row.

  3. Completeness-driven enrichment automation - The /sleep command can auto-trigger enrichment for goals below a completeness threshold. The enrichment trigger was re-tiered into the high-priority enqueue tier (TRIGGER_TIER_HIGH, its own 6/24h cap) in mid-2026 after being starved by the shared outreach budget; further tuning of when /sleep chooses to fire it remains open.

Lower Priority

  1. Intervention tracking view - Surface all goals with interventions array, show timeline of changes. Useful for debugging why a goal stalled.

  2. Vision progress rollup - Aggregate progress of linked goals to show vision-level completion status.