Property On wird als Funktionsbereich "Teamübersicht" in Property Match
eingebettet — sieben digitale Mitarbeiter, die ausführen, während der Mensch
freigibt, anpasst oder zurückweist.
Durchgehend Provider → Service → Hook, kein übersprungener Layer:
- domain/: teamAgent, agentWorkItem, agentProtocol, agentConnection, agentFilters
- mock-data/: 7 Personalblätter aus dem Agenten-Katalog (Aufgabenzahlen exakt:
Ferdi 9, Sina 7, Lea 11, Bruno 9, Reto 10, Livia 11, Nora 8), 14 Vorgänge,
38 Protokolleinträge, 9 Verbindungen
- provider/: vier Mockup-Provider mit versionierter localStorage-Persistenz
- services/: Fachlogik inkl. Freigabe, Zurückweisung, Kennzahlen, Demo-Reset
- hooks/: React Query, Mutationen entwerten Vorgänge, Kennzahlen und Protokoll
gemeinsam — sonst zeigt die Oberfläche widersprüchliche Zahlen
Namensgebung: Der Entitätstyp heisst TeamAgent, nicht Agent. Im Repo existiert
bereits PowerOn als KI-Backend-Proxy, und Claude Code legt Arbeitskopien unter
agent-* ab; ein nackter Typ Agent wäre in Suchen nicht auffindbar. Alle
Satellitentypen sind Agent*-präfixiert, weil domain/index.ts per export *
bündelt und generische Namen dort kollidieren.
Eigener Protokolltyp statt ActivityEvent: den Namen gibt es im Repo dreifach
und gegenseitig inkompatibel (domain/activityEvent.ts, governanceService.ts,
PropertyActivityLogPanel.tsx). Ein Anschluss hätte den Konflikt zementiert.
Demo-Uhr in lib/teamClock.ts: die Mockdaten sind auf den 20.05.2026 verankert.
Gegen die Systemzeit gerechnet wären die Filter "heute / diese Woche / dieser
Monat" an jedem anderen Kalendertag leer und die Auswertung sähe kaputt aus,
obwohl sie korrekt rechnet.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Mieterausbau / fit-out economics — surface true total cost of occupancy:
- Annuity calc (annuityFactor + effectiveAnnualBurdenPerSqm) replaces straight-line ÷5; FITOUT_ANNUITY_RATE=5%
- New hardFacts.fitOutByLandlord: "Wer baut aus?" toggle in NewListing — landlord-borne fit-out is priced into rent (no surcharge), tenant-borne SHELL/BASIC adds annuitized cost minus MAB
- scoreBudget now compares effective annual burden (rent + fit-out annuity) vs budget instead of cold rent only; FULL/PREMIUM and landlord-borne unchanged
- FitOutCostPanel + CompareTableBody compute annuitized, tenant-aware burden
- Central FIT_OUT_LABELS with industry/international vocabulary (Rohbau·Core&Shell, Edelrohbau·CAT A, etc.)
- Activate existing generateFitOutAdvice via useFitOutAdvice hook + new FitOutAdvicePanel (MIETERAUSBAU/BKZ/MAB-Amortisation + negotiation tip), shown for tenant-borne SHELL/BASIC
- MAB field only asked when tenant builds out (optional) — one new toggle, no extra data burden for property managers
Fix: DQ/confidence modifiers were computed but never applied to finalScore (hardcoded 0 in output) — now folded into rawFinal and exposed. Trust-first: weak data quality lowers the score. Resolves 3 pre-existing red tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- AISearch: clear parsed criteria when user manually edits text input so stale locations (e.g. Zürich) no longer persist after retyping
- needParser: fix ZURICH_SIGNALS substring bug — "kreis N" now uses word-boundary regex so "umkreis 22" no longer matches "kreis 2"
- CompareTableBody: row 9 shows full cost breakdown (Miete + NK + amortised fit-out) using FITOUT_AMORTIZATION_YEARS from constants
- FitOutCostPanel: replace local AMORTIZATION_YEARS with FITOUT_AMORTIZATION_YEARS from constants.ts (single source of truth)
- constants.ts: add FITOUT_AMORTIZATION_YEARS = 5 — change here to affect all cost calculations
- PropertyIntelligenceCard: translate raw fitOut enum to German labels (Rohbau/Grundausbau/Vollausbau/Premium-Ausbau) with explanatory tooltips; add tooltip on contract duration chip
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All external market properties now surface as VERIFIED_PORTFOLIO.
Removes the type from enums, domain types, mock data, matching engine,
components, hooks, and tests — zero user-visible distinction remains.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- layoutStore: remove 4 dead field groups (pinnedPanels, selectedResultId,
compareTrayVisible, notificationsOpen) — none were read outside the store
- CompareTray: drop dead useLayoutStore side-effect (state was write-only)
- 8 components: replace bare useStore() with explicit selectors / useShallow
to prevent unnecessary re-renders on unrelated state mutations
- lib/constants: add STALE_MARKET_SIGNALS + STALE_REVIEW_QUEUE (30s each)
- useMarketSignals, useReviewQueue: use global constants instead of
hook-local magic numbers
- Add STATE_MANAGEMENT.md: decision tree + rules for RQ/Zustand/local/derived
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>