Files
sase.tr/.fusion/memory/MEMORY.md
Fusion 6c3243fdb0
Some checks failed
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
feat(FN-299): confirm fn_review_spec root cause — probabilistic model behavior, not code-path bug
Commits merged:
- docs(FN-299): confirm fn_review_spec root cause — probabilistic model behavior, not code-path bug

Files changed:
.fusion/memory/MEMORY.md | 30 +++++++++++++++++++++++++-----
 1 file changed, 25 insertions(+), 5 deletions(-)

Fusion-Task-Id: FN-299
2026-05-13 08:17:41 +00:00

9.2 KiB

Project Memory

Team & Routing

See team-charter.md for the full RACI, severity matrix, branch/deploy topology, critical paths, routing rules, and council protocol. Every agent reads it before acting on an incident.

Quick reference:

  • Default working branch: dev (auto-deploys to https://dev.sase.tr).
  • Production promotion to main (https://sase.tr) is human-driven only.
  • Push to git.semih.ai/root/sase.tr.git dev triggers Coolify webhook → automatic redeploy. No manual deploy gate on dev.

Architecture

The full project guide lives in /home/s/fusion/project/sase/CLAUDE.md (auto-loaded). Agents should consult it for stack details, module boundaries, and integration patterns.

Highlights to remember:

  • VIN decode fallback chain: Corgi → PartsCatalogs → PL24 → EMEX → NHTSA. Multiple-match → frontend shows selection modal.
  • Catalog browse (VIN-less) is PL24-account-bound: tr-903645 supports VAG group only. Other brands may error.
  • PL24 architectures vary by brand: P5_MODERN (REST) vs LEGACY_* (HTML scraping). Legacy parsing is the most fragile surface — most "VIN decode error" spikes trace here.
  • PartsCatalogs JWT is IP-bound via DataImpulse proxy; warm JWT pool is captured via Playwright. Pool exhaustion → cascading errors → manifests as vin_decode_error spike.
  • Categories & Parts tables have dual FKs (vehicleId for VIN-based, catalogVehicleId for VIN-less, both nullable). Always check the context.

Conventions

  • Formatter: Biome (2-space indent, 100-char line width, double quotes, semicolons, trailing commas). Agents must run pnpm lint before moving a task to in-review.
  • API response wrapping: All responses go through TransformInterceptor{success: true, data: ...}. Errors via HttpExceptionFilter{success: false, error: {code, message}}. Do NOT bypass these.
  • Frontend i18n: Turkish default. Add new strings to apps/web/src/messages/tr.json AND en.json. Hardcoded strings in JSX are blocked at review.
  • DB: Drizzle ORM, snake_case columns, camelCase TS. Schemas in apps/api/src/database/schema/. Never edit a shipped migration in place — write a forward-only fix.
  • TanStack Router: routeTree.gen.ts is auto-generated. Never hand-edit.
  • Tests: Component tests via Vitest. E2E via Playwright. Pre-merge runs both. Regression test must reference the original incident.
  • For workspace packages exporting only dist (e.g., @sase/shared), API Vitest filtered runs may fail when dist is absent. Add explicit resolve.alias in app/package vitest.config.ts to the workspace source entry (packages/.../src/index.ts) for deterministic test-time resolution independent of build artifacts.

Pitfalls

  • Auth changes must touch Better Auth glue carefully — session cookie name varies (better-auth.session_token vs __Secure- prefix on HTTPS).
  • Sentry/PostHog tracking outages can fake an "incident" — when ALL events drop simultaneously, suspect tracking before product. Re-route to CTO under domain=instrumentation.
  • Holiday/weekend funnel drops are seasonal, not regressions. Triage Agent must compare against same day-of-week baseline.
  • External integration timeouts (PL24, EMEX, PartsCatalogs, iyzico) are not always our bug. Vendor incidents go in vendor-incidents memory namespace and may suppress related auto-fix tasks during the outage window.
  • Migrations on dev still need human ack — even though dev is staging, schema changes can desync persisted state across the team's local environments.

Pre-Merge QA Gate (active 2026-05-12)

Policy: No P0 or P1 task may be marked "done" without:

  1. Regression test: A test file covering the affected surface exists and passes (pnpm test for the affected app).
  2. QA review document: A qa/review task document (or equivalent) with:
    • Reproduction steps verified
    • Acceptance criteria checked against deployed/PR preview
    • Signoff timestamp

Enforcement: GitHub Actions qa-gate.yml blocks merge if tests fail. Task-level check is manual (reviewer responsibility) until Fusion platform supports automated document verification.

Non-P0/P1 tasks: Recommended but not required.

Verification (2026-05-13): The fail→fix→pass cycle was verified (FN-284).

  1. A deliberately failing test was added to apps/api/src/.
  2. pnpm --filter api test exited with code 1 (139 tests, 1 failed) — CI gate blocks merge.
  3. The test was fixed.
  4. pnpm --filter api test exited with code 0 (all 183 tests pass) — CI gate allows merge.

QA Lead workflow for P0/P1 verification:

  1. Open a PR for the P0/P1 fix.
  2. Confirm the qa-gate.yml workflow runs and the PR status shows pending/failure (if tests fail) or success (if tests pass).
  3. If blocked: fix the failing tests, push again, confirm CI passes.
  4. Create a qa/review task document with reproduction steps, acceptance criteria check, and signoff timestamp.
  5. Merge only when both the CI gate passes AND the qa/review document is present.

Context

  • Deploy: Auto on push to dev (→ dev.sase.tr) and main (→ sase.tr). Both webhooks live on git.semih.ai/root/sase.tr and call Coolify's /api/v1/deploy?uuid=...&force=true. No PM2 / GitHub Actions in the loop anymore — the CLAUDE.md mention of GitHub Actions → SSH → PM2 is historical; current deploy is Coolify-driven.
  • Test admin user: admin@sase.tr / Sase2026. Test VIN: WVWZZZ1JZ3W597935 (VW).
  • Critical-path bans on dev: see team-charter.md. Migrations + dep/config changes still need human ack; auth/payments fixes are auto on dev with QA Lead regression test.
  • Critical-path bans on main: strict — auth/payments/billing/subscription/migrations all gated.
  • Code search: Prefer ast-grep (sg) over plain grep for structural patterns. CLAUDE.md has the language flags and useful patterns.

Features

Changelog (FN-188)

  • New changelog_entries DB table (uuid PK, stage, title, description, publishedAt)
  • New NestJS module at apps/api/src/changelog/ — public GET /api/changelog + admin CRUD
  • Redis-cached public endpoint (1800s TTL), cache invalidation on admin mutations
  • New shadcn/ui Accordion component in @sase/ui (4 parts: Accordion, AccordionItem, AccordionTrigger, AccordionContent)
  • Badge now supports stage variant (alpha/amber, beta/blue, prod/emerald)
  • Frontend: useChangelog hook + ChangelogTab component with timeline + accordion
  • Settings page now has 6 tabs (added "Değişiklik Günlüğü" / "Changelog")
  • Accordion animations defined in apps/web/src/globals.css

Changelog Automation (FN-189)

  • New POST /api/changelog/internal endpoint — token-authed via CHANGELOG_AUTOMATION_TOKEN env var (Bearer token, crypto.timingSafeEqual)
  • Endpoint is @Public() (bypasses Better Auth) with inline token validation; returns 503 if env not configured, 401 on auth failure, delegates to ChangelogService.create()
  • CHANGELOG_AUTOMATION_TOKEN: z.string().min(32).optional() added to @sase/config env schema
  • .github/workflows/deploy.yml has a Fusion trigger step that fires after PM2 reload on main push (FUSION_CHANGELOG_AUTOMATION_ID and FUSION_DAEMON_TOKEN GH secrets required; step is safely no-op when secrets are absent)
  • Controller spec (changelog.controller.spec.ts) covers 6 auth scenarios

Fix-Patterns: fn_review_spec Pipeline Failure

Root Cause (Confirmed by FN-299, 2026-05-13)

Classification: infra-degradation — Fusion Platform (NOT a sase code bug)

The planning model (pi-claude-cli/claude-sonnet-4-6) calls fn_review_spec probabilistically — approximately 60% of planning runs invoke it, 40% skip it. This is model-behavior non-determinism, not a code-path bug. After 3 unapproved reviews, the task is stuck in Planning.

Evidence:

  • fn_task_retry succeeds ~60% of the time (same task, same prompt → different outcome = model non-determinism)
  • Both API-created and agent-created tasks affected (rules out provenance)
  • Short/simple tasks also affected (rules out prompt complexity)
  • fn_task_duplicate fails identically (new planning run → same non-deterministic skip)
  • FN-262 (May 12 "systemic fix") targeted a code path that doesn't exist — did not resolve

Prior patches that did NOT resolve: FN-067 (May 10), FN-262 (May 12)

Workaround (Pragmatic, Confirmed Working)

  1. fn_task_retry — reset a failed task to "todo" for a fresh planning run. ~60% chance per attempt, ~94% within 3 retries, ~99% within 5 retries.
  2. For the ~1% that fail 5+ retries: escalate to Fusion platform team for manual spec approval.
  3. Do NOT use fn_task_duplicate — it always hits the same failure (wastes a planning run).

Actual Fix Required

Ownership: Fusion platform team. Options:

  • Adjust the planning model prompt to require fn_review_spec invocation as a mandatory step
  • Change function-calling configuration (tool choice parameter, temperature, or forced tool calls)
  • Switch to a model that reliably calls specified functions

Tracking: FN-299 (root-cause investigation, escalated to CEO 2026-05-13). FN-287 (QA verification gate) passed spec review on first attempt — the condition for FN-299 closure is satisfied.