mirror of
https://github.com/computerim/impactflow-discovery.git
synced 2026-08-27 06:20:36 +00:00
b4d8d17aed
Add the mirror-not-compass reflection layer between profile generation and
affirmation. The coach reflects the person's profile back, and only when they
explicitly correct or add something does it propose revisions in their own
direction — never prescribing goals.
- ReflectionCoach service (app/services/reflector.py): Anthropic-backed,
returns {message, revisions, revision_note}; revisions filtered to the seven
editable prose fields (never triad/type); one-retry JSON handling.
- Endpoints (owner-scoped, 409 when locked): POST /discovery/profile/me/reflect
(opener + turns, applies revisions), GET .../reflection (dialogue),
GET .../revisions (iteration history). complete records an 'extraction'
revision; PATCH records 'manual_edit'.
- Models + migration 004: reflection_message (coach/person turns) and
profile_revision (snapshots: extraction | reflection | manual_edit) —
captures edits and iterations rather than overwriting.
- Frontend: reflect.html chat (coach/person bubbles, live profile summary that
refreshes on revision, affirm); linked from profile.html.
- Affirmation remains the existing confirm/lock.
Also refresh README for Phase 2 and for the HTTPS deployment
(https://impactflow.teamci.org:8011, OAUTH_REDIRECT_URI + COOKIE_SECURE notes).
Tests: 50 passing (added reflector unit tests and reflection endpoint tests;
run in-container).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
57 lines
2.0 KiB
Python
57 lines
2.0 KiB
Python
from pathlib import Path
|
|
|
|
|
|
def test_discovery_page_uses_cookie_session_not_user_id():
|
|
"""The browser session is a server-set cookie, so the page must not mint
|
|
or carry a client-side user id, and all calls go through authedFetch."""
|
|
html = Path("app/static/discovery.html").read_text(encoding="utf-8")
|
|
|
|
assert "impactflow_user_id" not in html
|
|
assert "createUserId" not in html
|
|
assert "user_id" not in html
|
|
assert "authedFetch" in html
|
|
assert '/static/auth.js' in html
|
|
|
|
|
|
def test_profile_page_uses_me_endpoints_and_authed_fetch():
|
|
"""Profile reads/confirms via the user-scoped /me routes, authenticated by
|
|
the session cookie through authedFetch — not the old user_id-in-URL paths."""
|
|
html = Path("app/static/profile.html").read_text(encoding="utf-8")
|
|
|
|
assert "/discovery/profile/me" in html
|
|
assert "/discovery/profile/me/confirm" in html
|
|
assert "user_id" not in html
|
|
assert "authedFetch" in html
|
|
|
|
|
|
def test_profile_page_has_edit_affordance():
|
|
"""The read/edit/affirm DoD: an Edit control that PATCHes the profile."""
|
|
html = Path("app/static/profile.html").read_text(encoding="utf-8")
|
|
|
|
assert "renderEdit" in html
|
|
assert 'method: "PATCH"' in html
|
|
assert "Edit my words" in html
|
|
|
|
|
|
def test_reflect_page_uses_reflection_endpoints():
|
|
"""Phase 2 reflection page drives the coach loop via authedFetch."""
|
|
html = Path("app/static/reflect.html").read_text(encoding="utf-8")
|
|
|
|
assert "/discovery/profile/me/reflect" in html
|
|
assert "/discovery/profile/me/reflection" in html
|
|
assert "authedFetch" in html
|
|
assert "user_id" not in html
|
|
|
|
|
|
def test_profile_page_links_to_reflection():
|
|
html = Path("app/static/profile.html").read_text(encoding="utf-8")
|
|
assert "/static/reflect.html" in html
|
|
|
|
|
|
def test_auth_helper_sends_credentials_and_refreshes():
|
|
js = Path("app/static/auth.js").read_text(encoding="utf-8")
|
|
|
|
assert 'credentials: "include"' in js
|
|
assert "/api/auth/refresh" in js
|
|
assert "/api/auth/login" in js
|