Commit Graph
187 Commits
Author SHA1 Message Date
Sai-karthik e444d1be15 Fix compressed resume proxy responses 2026-07-13 06:52:59 +00:00
Sai-karthik fdf4f6468d Cover task-aware curator handoffs 2026-07-13 06:10:15 +00:00
Sai-karthik 8617be7e7c Preserve task details on unavailable handoffs 2026-07-13 01:07:43 +00:00
Sai-karthik 8cb5413766 Keep presentation handoffs task-focused 2026-07-13 00:21:57 +00:00
Sai-karthik 2410a4800b Expose profile asset state in Day 1 tasks 2026-07-13 00:10:38 +00:00
Sai-karthik f848f45429 Remove invented interview role fallback 2026-07-12 23:51:44 +00:00
Sai-karthik 5f5622b3a0 Fix curator task handoffs and profile state 2026-07-12 23:21:52 +00:00
-Puter c7c6f1b8cc fix curator sprint ICP reconciliation 2026-07-13 03:31:02 +05:30
-Puter e7546142b6 fix curator sprint access choice reconciliation 2026-07-13 02:39:29 +05:30
-Puter 78860ecf5e fix(staging): point Social service URL to AWS Social via gqr-staging tunnel (18015)
Live root cause: dashboard gateway reached old developer FastAPI at
social.sai-onchain.me and 404'd on the LinkedIn onboarding route.
The gqr-staging reverse SSH tunnel now exposes AWS Social on host
port 18015 (verified: healthz=200, POST route 422).

- SOCIAL_BRANDING_SERVICE_URL: http://host.docker.internal:18015 (internal tunnel)
- SOCIAL_BRANDING_PUBLIC_URL: https://social-staging.gqr.puter.wtf (public staging)
2026-07-12 21:59:31 +05:30
-Puter e50be827ca fix(scripts): repair onboarding-bulk-reset with A2A user-service endpoint
Rewire Phase 1 to call the user-service POST /api/v1/users/onboarding-reset A2A
endpoint (targeting by clerk_id) instead of the per-user authenticated DELETE
route, which could not reach all users. A 404 from user-service means the user
has no profile (backend-only) — a clean skip that does not block Phase 2.

Phase 2 (backend ledger reset via resetOnboardingLedger) now runs ONLY after
Phase 1 succeeds or is skipped; a non-404 pref error blocks the ledger for that
user to avoid inconsistent state. Triple guard (NODE_ENV=staging,
ONBOARDING_BULK_RESET_ALLOWED=true, --confirm) and aggregate-only output are
preserved. Add source-structure assertions for the CLI contract.
2026-07-12 20:50:17 +05:30
-Puter c54e12972c fix(onboarding): synthetic PATCH /me stale content-length socket close
patchPreferencesRequest forwarded inbound headers (including
content-length from the browser PATCH body) but set a DIFFERENT body
({ preferences }). The Request constructor does NOT recompute
content-length when an explicit body is provided alongside forwarded
headers, so user-service waited for bytes that never arrived and closed
the socket (~2.8s 'other side closed') → uncaught → 500.

Delete content-length and transfer-encoding before constructing the
synthetic request so undici recomputes them from the actual body. Apply
the same defensive deletes in fetchUserProfile.

Extract patchPreferencesRequest into the DB-free
src/services/user-profile.ts module (alongside fetchUserProfile) so the
regression test imports the REAL function and asserts content-length /
transfer-encoding / host / cookie are stripped and the body is the
synthetic { preferences } blob. tsc clean; existing onboarding tests
pass.
2026-07-12 20:29:40 +05:30
-Puter ad1318424b fix(onboarding): PATCH /onboarding 500 — fetchUserProfile must GET /me
PATCH /onboarding read its JSON body via c.req.json() (consuming
c.req.raw), then passed c.req.raw to fetchUserProfile → fetchUserService,
which called req.arrayBuffer() on the already-consumed body:
TypeError: Body is unusable. The global onError caught it as a 500
{"error":"internal"}, so every access-choice save failed. GET
/onboarding worked only because it never reads a body.

fetchUserProfile is a read; it must never replay the inbound method or
body. Extract it (+ userServiceTarget) into a DB-free module that issues
an explicit GET /me with forwarded headers, sidestepping body reuse
entirely and fixing a latent wrong-method bug (PATCH /onboarding would
have issued a PATCH /me write for a read).

Verified against staging logs (TypeError stack at fetchUserService →
fetchUserProfile → PATCH handler). Focused regression test consumes the
body first and asserts GET + no body re-read + profile parse; tsc clean.
2026-07-12 20:14:22 +05:30
-Puter 62208d385f feat(onboarding): persist resettable user state 2026-07-12 19:23:29 +05:30
Sai-karthik a1de355ea0 fix: propagate curator context to service routes 2026-07-11 23:47:00 +00:00
Sai-karthik 411ad591bf fix: route curator tasks to unified service pages 2026-07-11 23:02:29 +00:00
Sai-karthik 63619f5047 Implement canonical onboarding and static curator sprint 2026-07-11 21:27:21 +00:00
-Puter b2283476d1 fix(staging): route social through edge tunnel 2026-07-11 16:49:59 +05:30
-Puter 09d3da0d7a fix(staging): route social service to dedicated host 2026-07-11 16:46:14 +05:30
-Puter c715171aa2 fix(staging): use canonical matchmaking network 2026-07-11 14:59:00 +05:30
-Puter f4964e5030 fix(events): keep actor state inside workflow steps 2026-07-11 14:57:10 +05:30
-Puterandindependent review (2 rounds) 5f5b08bfda fix(events): prevent userEventActor queue saturation from duplicate routing
Root cause: recordGrowEvent returned the existing row on dedupe hits, and
routeGrowEventToUserActor was called unconditionally — so every duplicate
ingest re-enqueued the same event to the actor queue, saturating it.

Fix at the persistence boundary:
- recordGrowEventWithResult returns {event, inserted} using atomic
  onConflictDoNothing().returning() (row present = fresh insert, no row =
  dedupe hit). No clock heuristics, no xmax probe.
- Conflict lookup tries dedupeKey first, then id PK fallback, covering both
  constraint types.
- shouldRouteGrowEvent(event, inserted) gates routing to only newly-inserted,
  user-resolved, pending events. Dedupe hits never re-enqueue.
- recordGrowEvent kept as thin .event wrapper — zero changes to ~10 callers.

Fix the actor run loop (mirrors workflow-run-actor.ts):
- tryStep with catch:['timeout','exhausted'] replaces step+rethrow. Per-event
  failure is marked terminal in a separate record-failure step, loop advances.
- isProcessableStatus guard allows pending/processing/processed — only skips
  failed/unresolved. This ensures mission reducers (actor-only) still run on
  events that got synchronous projections.
- Status guard + claim moved inside tryStep's run for atomic retry unit.
- onError handler added to workflow().

Ingress callers migrated (3 paths):
- redis-consumer recordAndRoute: shouldRouteGrowEvent gate + always mark
  processed after projections.
- routes/events.ts ingest: shouldRouteGrowEvent gate + always mark processed.
- v1/events/events-routes.ts /track: inserted flag for dedupe skip.

Tests: 3 new (event-dedupe-routing, user-event-actor-advance,
event-ingress-route-integration with injectable enqueue proving 5x duplicate
ingest enqueues exactly once). All existing touched-scope tests green.

Co-authored-by: independent review (2 rounds)
2026-07-11 06:19:38 +05:30
-Puter 3f2dabd23d fix(events): bound actor routing latency 2026-07-10 20:26:38 +05:30
-Puter ac7bdca912 feat(backend): REST-authoritative qscore pipeline with Redis opt-in
- Gate both Redis ingestion paths (canonical + legacy) behind separate
  default-off flags (GROW_EVENTS_REDIS_ENABLED, LEGACY_SERVICE_REDIS_ENABLED).
  The redis module is never imported when both flags are off.
- Sever legacy URL cascade: interview/roleplay/resume/courses Redis URLs
  resolve ONLY from their own explicit env vars, never from REDIS_URL or
  GROW_EVENTS_REDIS_URL.
- Export resolveRedisConfig() pure resolver for testability.
- Fix onboarding signal ID from 'onboarding.completed_baseline' to
  'onboarding.completed' (registry-valid in all v2 formula JSONs).
- Ensure interview/roleplay completed events emit at least a single
  completion signal when session_count/scenario_count is absent (default 1).
- Extract computeStreakFromDays() into streak-utils.ts (pure, no DB dep)
  with defensive dedup so duplicate days never inflate streaks.
- Add focused tests: redis-gating, signal-registry membership, count
  fallback, streak policy (current/longest/duplicate/gap/recovery/7-day),
  service-ingest projector behavior.
- typecheck: 80 pre-existing errors unchanged, 0 new.
2026-07-10 20:12:13 +05:30
-Puter d3a4e63e4a refactor: backend becomes pure signal feeder to qscore_service
- applyQscoreProjection forwards extracted signals to qscore_service via HTTP
- applyCuratorTaskDeltaProjection removed (no local additive scoring)
- forwardSignalsToQscoreService helper added to service-agents.ts
- New qscore-proxy.ts: getQscoreFromService proxies all reader sites
- 7 reader endpoints proxy to qscore_service (services, qscore-routes, analytics, home-feed, curator context, curator-store, curator-tools)
- Onboarding baseline forwards to qscore_service
- All existing response shapes preserved for dashboard compatibility
- tsc --noEmit passes clean
2026-07-10 00:28:19 +05:30
-Puter 722d5825bf fix(staging): use zen balance endpoint for minimax 2026-07-09 22:14:20 +05:30
-Puter 389a9fb014 fix(staging): attach backend to service networks 2026-07-09 22:12:41 +05:30
-Puter 689bfb6c52 fix(staging): bind backend compose ports locally 2026-07-09 22:09:59 +05:30
-Puter c3e7b00250 fix(staging): pin backend runtime overrides 2026-07-09 21:58:30 +05:30
-Puter 7bcd664afb fix(events): keep mission metadata on service sessions 2026-07-09 19:07:30 +05:30
-Puter 64c245535f feat(events): project course and matchmaking activity 2026-07-09 18:55:00 +05:30
-Puter 237c65f328 fix(social): remove incorrect /api/v1/ prefix from social proxy
The social-branding service routes are at root level (/accounts/connect,
/profiles/fetch-by-url, etc.) — NOT under /api/v1/. The proxy was
prepending /api/v1/ to every forwarded path, causing 404 Not Found on
all social POST endpoints including LinkedIn account connect.
2026-07-09 14:52:40 +05:30
-Puter ee964a5d13 feat(social): emit GrowQR events from social-branding proxy routes
The social-branding proxy was a raw passthrough that never called
recordGatewayEvent — so no grow_events rows were created for any social
action (account connect, profile polish, post publish, etc.), breaking
the curator/streak/QScore loop.

Follow the proxyResumeRequest pattern exactly:
- GET/HEAD pass through directly (no event)
- POST/PUT/PATCH/DELETE buffer response, record gateway event, return
- Add socialEventTypeForRest() mapping 10+ social routes to event types
- Add 'social' to canonicalSubjectServiceId mapping
- Event payload is strictly {path, method, status, action} — no raw
  cookies, tokens, passwords, or LinkedIn session data
- Extract account_id from path/response for correlation.externalId
2026-07-09 14:30:04 +05:30
Sai-karthik f61742b38f Add two-day trial sprint recovery flags 2026-07-09 04:50:29 +00:00
Sai-karthik da065d1077 Include curator task metadata in service handoffs 2026-07-08 09:04:54 +00:00
Sai-karthik 38c147b331 Point backend social branding URL to live service 2026-07-08 07:53:18 +00:00
Sai-karthik 8314ffbe75 Configure social branding service URL 2026-07-08 07:49:30 +00:00
Sai-karthik ee304b0016 Enable social branding curator handoffs 2026-07-08 07:41:57 +00:00
Sai-karthik 0c9ddd3b25 Route social branding curator handoffs to Nova 2026-07-08 07:38:59 +00:00
Sai-karthik 098056458e Project streak task completions into QX score 2026-07-07 20:45:30 +00:00
Sai-karthik 6eeaf50423 Fix QX fallback dimension initialization 2026-07-07 20:12:10 +00:00
Sai-karthik 4b0bf4379f Fix QX task impact registry initialization 2026-07-07 20:10:16 +00:00
Sai-karthik 6d996882bf Apply deterministic QX values to streak tasks 2026-07-07 20:06:48 +00:00
Sai-karthik 82859d8d08 Wire CareerSprint context into talk conversations 2026-07-07 09:37:59 +00:00
Sai-karthik 7b4f6f7d94 Merge pull request #16 system notifications backend 2026-07-06 12:31:03 +00:00
dv 790db95bda feat: back system notification bell with database 2026-07-06 01:46:14 +05:30
Sai-karthik 7142c8f7e8 PRM-88 use full service registry for KPI signals 2026-07-05 19:12:25 +00:00
Sai-karthik 9062ce9f22 PRM-88 add CareerSprint report KPI backend 2026-07-05 11:43:08 +00:00
Sai-karthik d252077135 Expose static curator day outcomes 2026-07-04 12:22:29 +00:00
Sai-karthik 5606f987c5 Serve static curator reads without actor startup 2026-07-02 20:19:57 +00:00