mirror of
https://github.com/garrytan/gbrain.git
synced 2026-07-27 22:15:33 +00:00
Revert "fix(trajectory): stop negative metrics from inverting regression signals (#2621)"
This reverts commit 5dcf3e7b2f.
This commit is contained in:
@@ -34,7 +34,7 @@ export interface TrajectoryRegression {
|
||||
from_date: string; // YYYY-MM-DD
|
||||
to_value: number;
|
||||
to_date: string;
|
||||
delta_pct: number; // negative for a numeric drop; may be < -1 across zero
|
||||
delta_pct: number; // negative for a drop; range typically [-1, 0)
|
||||
}
|
||||
|
||||
export interface TrajectoryStats {
|
||||
@@ -82,10 +82,8 @@ function cosineSim(a: Float32Array, b: Float32Array): number {
|
||||
*
|
||||
* Iterates per-metric (so trajectories that interleave mrr + arr + team_size
|
||||
* don't trip false regressions across metric boundaries). Within each metric,
|
||||
* walks consecutive value pairs; a pair fires when the newer value is lower
|
||||
* than the older value by at least the threshold. The relative delta uses
|
||||
* `abs(older)` as the denominator so negative-valued metrics (net income,
|
||||
* cash flow, etc.) do not invert improvement and regression.
|
||||
* walks consecutive value pairs; a pair fires when
|
||||
* `(newer - older) / older <= -threshold`.
|
||||
*
|
||||
* Pre-condition: caller passed points sorted by (valid_from ASC, fact_id ASC).
|
||||
* The engine's `findTrajectory` enforces this. No re-sort here.
|
||||
@@ -113,7 +111,7 @@ export function detectRegressions(
|
||||
// Guard against division-by-zero: a metric starting at exactly 0
|
||||
// can't compute a relative delta. Skip.
|
||||
if (oldVal === 0) continue;
|
||||
const delta = (newVal - oldVal) / Math.abs(oldVal);
|
||||
const delta = (newVal - oldVal) / oldVal;
|
||||
if (delta <= -threshold) {
|
||||
out.push({
|
||||
metric,
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
import { describe, expect, test } from 'bun:test';
|
||||
import type { TrajectoryPoint } from '../src/core/engine.ts';
|
||||
import {
|
||||
DEFAULT_REGRESSION_THRESHOLD,
|
||||
detectRegressions,
|
||||
} from '../src/core/trajectory.ts';
|
||||
|
||||
function point(args: {
|
||||
id: number;
|
||||
metric?: string;
|
||||
value: number;
|
||||
date: string;
|
||||
}): TrajectoryPoint {
|
||||
return {
|
||||
fact_id: args.id,
|
||||
valid_from: new Date(args.date),
|
||||
metric: args.metric ?? 'net_income',
|
||||
value: args.value,
|
||||
unit: 'USD',
|
||||
period: 'monthly',
|
||||
event_type: null,
|
||||
text: `${args.metric ?? 'net_income'} = ${args.value}`,
|
||||
source_session: null,
|
||||
source_markdown_slug: null,
|
||||
embedding: null,
|
||||
};
|
||||
}
|
||||
|
||||
describe('detectRegressions', () => {
|
||||
test('keeps existing positive-valued drop behavior', () => {
|
||||
const regs = detectRegressions([
|
||||
point({ id: 1, metric: 'mrr', value: 200000, date: '2026-01-01' }),
|
||||
point({ id: 2, metric: 'mrr', value: 150000, date: '2026-02-01' }),
|
||||
], DEFAULT_REGRESSION_THRESHOLD);
|
||||
|
||||
expect(regs).toHaveLength(1);
|
||||
expect(regs[0]).toMatchObject({
|
||||
metric: 'mrr',
|
||||
from_value: 200000,
|
||||
to_value: 150000,
|
||||
});
|
||||
expect(regs[0].delta_pct).toBeCloseTo(-0.25, 4);
|
||||
});
|
||||
|
||||
test('does not flag a negative-valued metric improving toward zero', () => {
|
||||
const regs = detectRegressions([
|
||||
point({ id: 1, value: -1000, date: '2026-01-01' }),
|
||||
point({ id: 2, value: -500, date: '2026-02-01' }),
|
||||
], DEFAULT_REGRESSION_THRESHOLD);
|
||||
|
||||
expect(regs).toEqual([]);
|
||||
});
|
||||
|
||||
test('flags a negative-valued metric worsening away from zero', () => {
|
||||
const regs = detectRegressions([
|
||||
point({ id: 1, value: -500, date: '2026-01-01' }),
|
||||
point({ id: 2, value: -1000, date: '2026-02-01' }),
|
||||
], DEFAULT_REGRESSION_THRESHOLD);
|
||||
|
||||
expect(regs).toHaveLength(1);
|
||||
expect(regs[0]).toMatchObject({
|
||||
metric: 'net_income',
|
||||
from_value: -500,
|
||||
to_value: -1000,
|
||||
from_date: '2026-01-01',
|
||||
to_date: '2026-02-01',
|
||||
});
|
||||
expect(regs[0].delta_pct).toBeCloseTo(-1.0, 4);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user