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
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.gitdevtriggers 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_errorspike. - Categories & Parts tables have dual FKs (
vehicleIdfor VIN-based,catalogVehicleIdfor 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 lintbefore moving a task to in-review. - API response wrapping: All responses go through
TransformInterceptor→{success: true, data: ...}. Errors viaHttpExceptionFilter→{success: false, error: {code, message}}. Do NOT bypass these. - Frontend i18n: Turkish default. Add new strings to
apps/web/src/messages/tr.jsonANDen.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.tsis 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 whendistis absent. Add explicitresolve.aliasin app/packagevitest.config.tsto 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_tokenvs__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-incidentsmemory 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:
- Regression test: A test file covering the affected surface exists and passes (
pnpm testfor the affected app). - QA review document: A
qa/reviewtask 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).
- A deliberately failing test was added to
apps/api/src/. pnpm --filter api testexited with code 1 (139 tests, 1 failed) — CI gate blocks merge.- The test was fixed.
pnpm --filter api testexited with code 0 (all 183 tests pass) — CI gate allows merge.
QA Lead workflow for P0/P1 verification:
- Open a PR for the P0/P1 fix.
- Confirm the
qa-gate.ymlworkflow runs and the PR status shows pending/failure (if tests fail) or success (if tests pass). - If blocked: fix the failing tests, push again, confirm CI passes.
- Create a
qa/reviewtask document with reproduction steps, acceptance criteria check, and signoff timestamp. - 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) andmain(→ sase.tr). Both webhooks live ongit.semih.ai/root/sase.trand call Coolify's/api/v1/deploy?uuid=...&force=true. No PM2 / GitHub Actions in the loop anymore — the CLAUDE.md mention ofGitHub Actions → SSH → PM2is 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 plaingrepfor structural patterns. CLAUDE.md has the language flags and useful patterns.
Features
Changelog (FN-188)
- New
changelog_entriesDB 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
stagevariant (alpha/amber, beta/blue, prod/emerald) - Frontend:
useChangeloghook +ChangelogTabcomponent 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/internalendpoint — token-authed viaCHANGELOG_AUTOMATION_TOKENenv 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 toChangelogService.create() CHANGELOG_AUTOMATION_TOKEN: z.string().min(32).optional()added to@sase/configenv schema.github/workflows/deploy.ymlhas 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_retrysucceeds ~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_duplicatefails 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)
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.- For the ~1% that fail 5+ retries: escalate to Fusion platform team for manual spec approval.
- 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_specinvocation 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.