Phase 5: iteration & polish (visualizations, goal history, smart tagging)

Final roadmap phase. No DB migration — it reads data already captured.

- Goal-evolution history: GET /discovery/profile/me/goal-history derives a
  per-goal timeline from the profile_revision snapshots (pure aggregator in
  app/services/profile_history.py).
- Smart tagging: POST /discovery/integration/suggest-foundation suggests which
  foundation a task builds toward + rationale/confidence (FoundationTagger,
  app/services/tagging.py). Suggestion only; the person confirms by posting the
  task mapping.
- Deeper goal-refinement: the reflect loop accepts an optional focus ("goals")
  that steers the coach toward sharpening goals — still mirror, not compass.
- Visualizations: visuals.html renders an Ikigai Venn and an Enneagram diagram
  (plain-language callouts, not the raw type number) plus the goal-evolution
  timeline; linked from profile.html.

Tests: 99 passing (added pure goal-history tests, goal-history + suggest
endpoint tests, reflect-focus passthrough; run in-container). README updated.

This completes the ImpactFlow Vision roadmap (Phases 1-5) on the Discovery side.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joel Salmon
2026-06-16 21:37:33 -05:00
parent c4fc1cccd7
commit b9d7b0e22b
14 changed files with 798 additions and 9 deletions
+28
View File
@@ -77,6 +77,9 @@ class ConfirmResponse(BaseModel):
class ReflectRequest(BaseModel):
# Empty/omitted starts the loop (the coach's opening reflection).
message: str = ""
# Phase 5: optional refinement focus, e.g. "goals" to steer the coach
# toward sharpening the near/long-term goals.
focus: str = ""
class ReflectionMessageOut(BaseModel):
@@ -194,6 +197,31 @@ class WorkPatternsOut(BaseModel):
neglected: list[str]
# -- Phase 5: iteration & polish ---------------------------------------------
class GoalHistoryEntry(BaseModel):
value: Optional[str] = None
source: Optional[str] = None
at: Optional[datetime] = None
class GoalHistoryOut(BaseModel):
short_term_goals: list[GoalHistoryEntry]
long_term_goals: list[GoalHistoryEntry]
class SuggestFoundationRequest(BaseModel):
task_label: str
class SuggestFoundationOut(BaseModel):
foundation: str
label: str
rationale: str = ""
confidence: str = "low"
class ConversationResponse(BaseModel):
id: str
user_id: str