Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

130 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import type { Signal } from "@g1t/contracts";
5
6import {
7 bySignalUrgency,
8 countByKind,
9 filterSignals,
10 followUpsDue,
11 isFollowUpDue,
12 isSignalKind,
13 parseWho,
14 reachOutHref,
15 signalMeta,
16 stageMeta,
17 today,
18} from "./signals.ts";
19
20function signal(workspace: string, kind: string, valueMicros = 0, owner: string | null = null): Signal {
21 return { workspace, kind: kind as Signal["kind"], detail: `${workspace} ${kind}`, valueMicros, stage: null, owner };
22}
23
24test("most urgent first: by kind, then the larger figure, else as billing sent them", () => {
25 const sorted = bySignalUrgency([
26 signal("a", "growing", 10),
27 signal("b", "first_payment", 99),
28 signal("c", "near_ceiling", 5),
29 signal("d", "at_limit", 1),
30 signal("e", "near_ceiling", 50),
31 signal("f", "something_new", 1000),
32 signal("g", "declined", 0),
33 signal("h", "growing", 10),
34 ]);
35 assert.deepEqual(
36 sorted.map((s) => s.workspace),
37 ["d", "g", "e", "c", "a", "h", "b", "f"],
38 );
39});
40
41test("sorting leaves the input alone", () => {
42 const input = [signal("a", "growing"), signal("b", "at_limit")];
43 bySignalUrgency(input);
44 assert.equal(input[0].workspace, "a");
45});
46
47test("filter by kind, and by whose they are", () => {
48 const all = [
49 signal("a", "at_limit", 0, "Me@g1t.sh"),
50 signal("b", "at_limit", 0, null),
51 signal("c", "growing", 0, "other@g1t.sh"),
52 signal("d", "growing", 0, ""),
53 ];
54 const me = "me@g1t.sh";
55 assert.deepEqual(
56 filterSignals(all, { kind: null, who: "all", me }).map((s) => s.workspace),
57 ["a", "b", "c", "d"],
58 );
59 assert.deepEqual(
60 filterSignals(all, { kind: "at_limit", who: "all", me }).map((s) => s.workspace),
61 ["a", "b"],
62 );
63 assert.deepEqual(
64 filterSignals(all, { kind: null, who: "unassigned", me }).map((s) => s.workspace),
65 ["b", "d"],
66 );
67 assert.deepEqual(
68 filterSignals(all, { kind: null, who: "mine", me }).map((s) => s.workspace),
69 ["a"],
70 );
71 assert.deepEqual(filterSignals(all, { kind: "growing", who: "mine", me }), []);
72});
73
74test("counts by kind", () => {
75 assert.deepEqual(countByKind([signal("a", "at_limit"), signal("b", "at_limit"), signal("c", "growing")]), { at_limit: 2, growing: 1 });
76});
77
78test("query values are checked", () => {
79 assert.equal(parseWho("mine"), "mine");
80 assert.equal(parseWho("unassigned"), "unassigned");
81 assert.equal(parseWho("everyone"), "all");
82 assert.equal(parseWho(null), "all");
83 assert.ok(isSignalKind("near_ceiling"));
84 assert.ok(!isSignalKind("nearly"));
85 assert.ok(!isSignalKind(null));
86});
87
88test("links into the queue leave out the defaults", () => {
89 assert.equal(reachOutHref({}), "/reach-out");
90 assert.equal(reachOutHref({ kind: "at_limit" }), "/reach-out?kind=at_limit");
91 assert.equal(reachOutHref({ kind: "declined", who: "mine" }), "/reach-out?kind=declined&who=mine");
92 assert.equal(reachOutHref({ kind: null, who: "all" }), "/reach-out");
93});
94
95test("names for kinds and stages, and for ones sudo does not know", () => {
96 assert.equal(signalMeta("at_limit").label, "At limit");
97 assert.equal(signalMeta("at_limit").tone, "danger");
98 assert.equal(signalMeta("brand_new").label, "brand new");
99 assert.equal(stageMeta(null).label, "No stage");
100 assert.equal(stageMeta("churn_risk").label, "Churn risk");
101 assert.equal(stageMeta("odd").label, "odd");
102});
103
104test("follow-ups due: today or earlier, open deals only, one per workspace, oldest first", () => {
105 const s = (workspace: string, nextAt: string | null, stage: string | null = "contacted", kind = "growing"): Signal => ({
106 ...signal(workspace, kind),
107 nextAt,
108 stage,
109 nextStep: nextAt ? "Call" : null,
110 });
111 const on = "2026-10-04";
112 assert.ok(isFollowUpDue(s("a", "2026-10-04"), on));
113 assert.ok(isFollowUpDue(s("a", "2026-10-01"), on));
114 assert.ok(!isFollowUpDue(s("a", "2026-10-05"), on));
115 assert.ok(!isFollowUpDue(s("a", null), on));
116 assert.ok(!isFollowUpDue(s("a", "2026-10-01", "won"), on));
117 assert.ok(!isFollowUpDue(s("a", "2026-10-01", "lost"), on));
118 assert.ok(isFollowUpDue(s("a", "2026-10-01", null), on));
119 const due = followUpsDue(
120 [s("b", "2026-10-03"), s("a", "2026-09-30", "contacted", "at_limit"), s("a", "2026-09-30", "contacted", "high_spend"), s("c", "2026-10-09")],
121 on,
122 );
123 assert.deepEqual(
124 due.map((x) => `${x.workspace}:${x.kind}`),
125 ["a:at_limit", "b:growing"],
126 );
127 assert.equal(today(new Date("2026-10-04T23:59:00Z")), "2026-10-04");
128 assert.equal(reachOutHref({ due: true }), "/reach-out?due=1");
129 assert.equal(reachOutHref({ due: true, who: "mine" }), "/reach-out?due=1&who=mine");
130});