chore(autonomous-session): consolidate uncommitted work from prior session
Bundles the prior autonomous-session output that was sitting unstaged: - Em-dash sweep across src/ + tests/ (en-dash/em-dash to hyphen, ~2280 instances) - country-flag-icons rollout (CountryFlag component, replaces emoji glyphs that never rendered on Windows; lazy-loads the 3x2 SVG index as a single chunk after the per-subpath dynamic-import approach silently failed in webpack) - Admin IA Phase 1+2: 7-domain regroup, 41 to 38 pages, /admin/berths index, redirects (ocr to ai, reports to dashboard, invitations to users), docs/admin-ia-proposal.md - Per-template email tester (registry + endpoint + UI on Email admin page) - Cancel-document mode picker (delete-from-Documenso vs keep-for-audit) - Dashboard PDF report: 25 widgets, SVG charts, date-range picker, 11 resolvers - Customize-widgets per-region sortables at xl+ (charts/rails/feed); single flat sortable below xl when the layout stacks; per-viewport saved orders - Audit doc updates capturing each shipped item - Lint fixes: react-compiler immutability in DonutChart (reduce instead of let-reassign), set-state-in-effect disables in CountryFlag and UploadForSigning preview-bytes effect, unused 'confirm' destructures in interest contract + reservation tabs, unescaped apostrophe in test-template card copy
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Rule-based deal-health scoring. NO LLMs — every output traces back to a
|
||||
* Rule-based deal-health scoring. NO LLMs - every output traces back to a
|
||||
* dated/structured input the rep can see and contest. The chip displayed
|
||||
* on the interest header exposes the per-signal breakdown via tooltip so
|
||||
* an anti-AI stakeholder reading the screen never sees a black box.
|
||||
@@ -52,11 +52,11 @@ export interface DealHealthInput {
|
||||
reservationDocStatus?: string | null;
|
||||
contractDocStatus?: string | null;
|
||||
/** Optional: count of contact_log entries in the last 7 days. Drives the
|
||||
* +5 "active engagement" signal. When omitted the signal is skipped — keep
|
||||
* +5 "active engagement" signal. When omitted the signal is skipped - keep
|
||||
* the scoring function pure / synchronous so the chip can render without a
|
||||
* separate fetch on every interest list row. */
|
||||
recentActivityCount?: number | null;
|
||||
/** Phase 2 — risk signals captured in deal-pulse-trigger-audit.md.
|
||||
/** Phase 2 - risk signals captured in deal-pulse-trigger-audit.md.
|
||||
* Any of these populated → strong negative signal pushed onto the
|
||||
* chip so reps can triage cooling deals at a glance. All optional;
|
||||
* callers populate from existing schema (document_events for
|
||||
@@ -66,7 +66,7 @@ export interface DealHealthInput {
|
||||
dateBerthSoldToOther?: string | Date | null;
|
||||
/** Optional per-port config that lets admins disable individual
|
||||
* signals or rename their tier labels. When omitted, defaults
|
||||
* apply — current callers stay byte-identical without changes. */
|
||||
* apply - current callers stay byte-identical without changes. */
|
||||
config?: DealHealthConfig | null;
|
||||
}
|
||||
|
||||
@@ -111,12 +111,12 @@ export function computeDealHealth(input: DealHealthInput): DealHealth {
|
||||
let score = 50;
|
||||
const signals: DealHealthSignal[] = [];
|
||||
|
||||
// Master toggle — admin can hide the chip entirely per-port.
|
||||
// Master toggle - admin can hide the chip entirely per-port.
|
||||
// Returning the neutral shape keeps callers happy; the chip uses
|
||||
// a separate "visible" prop derived from config.enabled before
|
||||
// calling compute. We still return real data so reports can read it.
|
||||
|
||||
// Closed / archived deals don't get a pulse score — UI hides the chip
|
||||
// Closed / archived deals don't get a pulse score - UI hides the chip
|
||||
// anyway, but compute a neutral score so callers using this in reports
|
||||
// don't crash on undefined.
|
||||
if (input.archivedAt || input.outcome) {
|
||||
@@ -135,7 +135,7 @@ export function computeDealHealth(input: DealHealthInput): DealHealth {
|
||||
delta: +5,
|
||||
detail: `${input.recentActivityCount} activity log entr${
|
||||
input.recentActivityCount === 1 ? 'y' : 'ies'
|
||||
} in the last 7d — rep is engaged.`,
|
||||
} in the last 7d - rep is engaged.`,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -147,21 +147,21 @@ export function computeDealHealth(input: DealHealthInput): DealHealth {
|
||||
signals.push({
|
||||
id: 'contact_recent',
|
||||
delta: +20,
|
||||
detail: `Contact logged ${contactDays}d ago — fresh.`,
|
||||
detail: `Contact logged ${contactDays}d ago - fresh.`,
|
||||
});
|
||||
} else if (contactDays <= 14) {
|
||||
score += 10;
|
||||
signals.push({
|
||||
id: 'contact_warm',
|
||||
delta: +10,
|
||||
detail: `Contact logged ${contactDays}d ago — still warm.`,
|
||||
detail: `Contact logged ${contactDays}d ago - still warm.`,
|
||||
});
|
||||
} else if (contactDays >= 30) {
|
||||
score -= 15;
|
||||
signals.push({
|
||||
id: 'contact_stale',
|
||||
delta: -15,
|
||||
detail: `No contact logged in ${contactDays}d — going cold.`,
|
||||
detail: `No contact logged in ${contactDays}d - going cold.`,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -236,7 +236,7 @@ export function computeDealHealth(input: DealHealthInput): DealHealth {
|
||||
});
|
||||
}
|
||||
|
||||
// Phase 2 — positive momentum signals.
|
||||
// Phase 2 - positive momentum signals.
|
||||
// EOI sent recently: forward motion that the original score didn't
|
||||
// surface (the awaiting penalty only fires after 14d). Brightens the
|
||||
// chip for fresh-EOI deals so reps see progress.
|
||||
@@ -246,7 +246,7 @@ export function computeDealHealth(input: DealHealthInput): DealHealth {
|
||||
signals.push({
|
||||
id: 'eoi_sent_recent',
|
||||
delta: +5,
|
||||
detail: `EOI sent ${eoiSentDaysPos}d ago — awaiting signature.`,
|
||||
detail: `EOI sent ${eoiSentDaysPos}d ago - awaiting signature.`,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -275,7 +275,7 @@ export function computeDealHealth(input: DealHealthInput): DealHealth {
|
||||
});
|
||||
}
|
||||
|
||||
// Phase 2 — risk signals. These are the strongest cooling indicators
|
||||
// Phase 2 - risk signals. These are the strongest cooling indicators
|
||||
// and previously didn't move the chip at all, leaving reps to discover
|
||||
// them by clicking into the detail page.
|
||||
|
||||
@@ -286,7 +286,7 @@ export function computeDealHealth(input: DealHealthInput): DealHealth {
|
||||
signals.push({
|
||||
id: 'document_declined',
|
||||
delta: -25,
|
||||
detail: `Client declined a document ${declinedDays}d ago — intervene.`,
|
||||
detail: `Client declined a document ${declinedDays}d ago - intervene.`,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -301,7 +301,7 @@ export function computeDealHealth(input: DealHealthInput): DealHealth {
|
||||
});
|
||||
}
|
||||
|
||||
// Berth resold to a different deal — this interest is effectively dead
|
||||
// Berth resold to a different deal - this interest is effectively dead
|
||||
// (the asset they wanted is gone). Sharp drop so the chip turns cold.
|
||||
const berthSoldDays = daysSince(input.dateBerthSoldToOther);
|
||||
if (berthSoldDays !== null && signalEnabled(input, 'berth_sold_to_other')) {
|
||||
|
||||
Reference in New Issue
Block a user