Files
pig/packages/core/test/margin.test.ts
karti 73231a8944
CI / verify (push) Failing after 34s
Add CI, a test suite, and a deploy script
`npm test` did nothing until now. CI that runs no tests is theatre, so the
tests came first — 39 of them, over the two places where an error would be
silent and expensive.

packages/core: the margin arithmetic. Every dashboard figure, idle-capacity
alert and agent answer resolves through it, and wrong numbers still look like
numbers. The cases pin decisions rather than implementation: cost is charged
against the full commitment (a naive version reports the opposite sign on a
loss-making block), aggregation sums cents rather than averaging percentages
(averaging reports +22% on a book that is losing money), break-even prices the
remaining hours and returns null rather than Infinity when there are none, and
internal research burn counts as cost with no revenue.

packages/prime: the upstream mapping. Rounding rather than truncating cents,
because 2.43 is 2.4299999 in binary and a lost cent compounds across millions
of GPU-hours. And interconnect normalisation, where an unrecognised fabric maps
to Unknown rather than Ethernet — guessing low loses a deal, guessing high
sells a training customer a cluster that cannot train.

CI runs on push and pull request: typecheck all six packages, unit tests,
migrations applied twice to a real Postgres, a seed-idempotency assertion that
fails the build if row counts move on a second run, a server boot, the front-end
build, and a Docker build.

It also asserts the inline theme script's hash still matches the CSP the proxy
allows. That script prevents a white flash for dark-mode users; if it changes
without the CSP being updated, the browser silently blocks it and nothing
anywhere reports an error.

Deployment stays a script rather than push-to-deploy. Automating it would put
an SSH key with production write access on the CI runner — a real escalation
for a project this size. The script takes a database dump before migrating and
refuses to finish if an unauthenticated request returns anything but 401.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 20:27:47 -07:00

185 lines
7.3 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Tests for the margin arithmetic.
*
* This is the most load-bearing pure code in the project: every dashboard
* figure, every idle-capacity alert and every answer an agent gives resolves
* through these functions. An error here is an error everywhere, and it would
* be a quiet one — wrong numbers still look like numbers.
*
* The cases below are chosen to pin the *decisions*, not merely the
* implementation. Several would pass under a naive version that is wrong in a
* way that flatters the business, which is precisely why they exist.
*/
import { strict as assert } from 'node:assert';
import { describe, it } from 'node:test';
import {
aggregateMargin,
breakEvenPricePerGpuHourCents,
computeMargin,
formatCents,
} from '../src/margin';
describe('computeMargin', () => {
it('charges cost against the FULL commitment, not only the hours sold', () => {
// The decision the whole product rests on. A naive implementation charges
// only the allocated share and reports this block as profitable, when in
// fact it loses money: the unsold hours were already paid for.
const result = computeMargin(
{ gpuHours: 1000, costPerGpuHourCents: 100 },
[{ gpuHours: 500, pricePerGpuHourCents: 150 }],
);
assert.equal(result.costCents, 100_000, 'cost must cover all 1000 hours');
assert.equal(result.revenueCents, 75_000);
assert.equal(result.grossMarginCents, -25_000, 'this block is underwater');
// Under the naive treatment: cost 500×100 = 50,000 against revenue 75,000,
// reporting +25,000 — a sign error on the thing that matters most.
assert.ok(result.grossMarginCents < 0);
});
it('reports utilisation and idle hours', () => {
const r = computeMargin({ gpuHours: 1000, costPerGpuHourCents: 100 }, [
{ gpuHours: 700, pricePerGpuHourCents: 200 },
]);
assert.equal(r.allocatedGpuHours, 700);
assert.equal(r.idleGpuHours, 300);
assert.equal(r.utilisation, 0.7);
});
it('sums several allocations against one commitment', () => {
const r = computeMargin({ gpuHours: 1000, costPerGpuHourCents: 100 }, [
{ gpuHours: 400, pricePerGpuHourCents: 200 },
{ gpuHours: 300, pricePerGpuHourCents: 250 },
]);
assert.equal(r.allocatedGpuHours, 700);
assert.equal(r.revenueCents, 400 * 200 + 300 * 250);
});
it('counts internal consumption as cost with no revenue', () => {
// Research burn is a zero-price allocation. Leaving it out would overstate
// available capacity; pricing it at anything but zero would invent revenue.
const r = computeMargin({ gpuHours: 1000, costPerGpuHourCents: 100 }, [
{ gpuHours: 600, pricePerGpuHourCents: 200 },
{ gpuHours: 200, pricePerGpuHourCents: 0 },
]);
assert.equal(r.allocatedGpuHours, 800);
assert.equal(r.revenueCents, 120_000, 'the internal 200 hours earn nothing');
assert.equal(r.idleGpuHours, 200);
});
it('clamps idle at zero when capacity is deliberately oversubscribed', () => {
// Selling beyond 100% is a real policy, not a data-entry error. Negative
// idle hours would be nonsense to display.
const r = computeMargin({ gpuHours: 1000, costPerGpuHourCents: 100 }, [
{ gpuHours: 1200, pricePerGpuHourCents: 150 },
]);
assert.equal(r.idleGpuHours, 0);
assert.equal(r.utilisation, 1.2, 'utilisation itself is not clamped — it is the signal');
});
it('returns null rather than dividing by zero on an empty book', () => {
const r = computeMargin({ gpuHours: 1000, costPerGpuHourCents: 100 }, []);
assert.equal(r.revenueCents, 0);
assert.equal(r.grossMarginCents, -100_000);
assert.equal(r.grossMarginPct, null, 'no revenue means no percentage, not Infinity');
assert.equal(r.marginPerAllocatedGpuHourCents, null);
});
it('handles a zero-hour commitment without producing NaN', () => {
const r = computeMargin({ gpuHours: 0, costPerGpuHourCents: 100 }, []);
assert.equal(r.utilisation, 0);
assert.ok(!Number.isNaN(r.utilisation));
});
it('keeps money in whole cents', () => {
// Fractional hours are normal; fractional cents are not. A dashboard that
// renders 1234.9999999 has lost the plot.
const r = computeMargin({ gpuHours: 0.1, costPerGpuHourCents: 3 }, [
{ gpuHours: 0.1, pricePerGpuHourCents: 7 },
]);
assert.ok(Number.isInteger(r.costCents));
assert.ok(Number.isInteger(r.revenueCents));
});
});
describe('breakEvenPricePerGpuHourCents', () => {
it('prices the REMAINING hours, not the whole block', () => {
// Half a 1000-hour block at 100c cost is sold at 120c: 60,000 of 100,000
// recovered, 40,000 outstanding across 500 remaining hours = 80c.
const price = breakEvenPricePerGpuHourCents({ gpuHours: 1000, costPerGpuHourCents: 100 }, [
{ gpuHours: 500, pricePerGpuHourCents: 120 },
]);
assert.equal(price, 80);
});
it('falls as more of the block sells', () => {
const commitment = { gpuHours: 1000, costPerGpuHourCents: 100 };
const early = breakEvenPricePerGpuHourCents(commitment, [
{ gpuHours: 200, pricePerGpuHourCents: 120 },
])!;
const later = breakEvenPricePerGpuHourCents(commitment, [
{ gpuHours: 800, pricePerGpuHourCents: 120 },
])!;
assert.ok(later < early, 'a mostly-sold block is cheaper to break even on');
});
it('returns zero once cost is covered — further sales are pure upside', () => {
const price = breakEvenPricePerGpuHourCents({ gpuHours: 1000, costPerGpuHourCents: 100 }, [
{ gpuHours: 500, pricePerGpuHourCents: 300 },
]);
// Not a negative price, which would be meaningless to show a seller.
assert.equal(price, 0);
});
it('returns null when nothing is left to sell', () => {
const price = breakEvenPricePerGpuHourCents({ gpuHours: 1000, costPerGpuHourCents: 100 }, [
{ gpuHours: 1000, pricePerGpuHourCents: 150 },
]);
assert.equal(price, null, 'no remaining hours means no break-even price, not Infinity');
});
});
describe('aggregateMargin', () => {
it('sums cents rather than averaging percentages', () => {
// A tiny block at a wonderful margin next to a huge one at a terrible
// margin. Averaging the two percentages would report roughly break-even;
// the truth is a large loss dominated by the big block.
const result = aggregateMargin([
{
commitment: { gpuHours: 10, costPerGpuHourCents: 100 },
allocations: [{ gpuHours: 10, pricePerGpuHourCents: 1000 }],
},
{
commitment: { gpuHours: 10_000, costPerGpuHourCents: 100 },
allocations: [{ gpuHours: 5_000, pricePerGpuHourCents: 110 }],
},
]);
assert.equal(result.costCents, 10 * 100 + 10_000 * 100);
assert.equal(result.revenueCents, 10 * 1000 + 5_000 * 110);
assert.ok(result.grossMarginCents < 0, 'the big block dominates');
// The naive mean of +90% and -45% is about +22%, which is the wrong sign.
assert.ok(result.grossMarginPct! < 0);
});
it('is empty-safe', () => {
const r = aggregateMargin([]);
assert.equal(r.costCents, 0);
assert.equal(r.grossMarginPct, null);
assert.equal(r.utilisation, 0);
});
});
describe('formatCents', () => {
it('renders whole currency from integer cents', () => {
assert.equal(formatCents(123_456), '$1,234.56');
assert.equal(formatCents(0), '$0.00');
});
it('renders negatives, which is the case that matters', () => {
assert.ok(formatCents(-5000).includes('50'));
});
});