feat: Claude Code Monitor — lanes, pipelines and a merged workspace

Internal SmartGift build of a Claude Code monitoring dashboard.

Lanes: a durable unit of parallel agent work, one per working directory,
tracked across session restarts. Managed lanes are git worktrees the
dashboard provisions and can reset or remove behind a three-check destroy
guard and a counted preflight; adopted lanes are directories you already
own and are never destroyable.

Pipelines: a lane moves through pipeline stages. A stage the agent declares
with evidence renders green; a stage inferred from the tool-event stream
renders dashed amber and never counts as done. Detection is forward-only
within a 30-minute window, and never writes the declared stage.

Workspace: one page at /run with a lane grid, the selected lane's pipeline,
and a full Claude console behind a disclosure.
This commit is contained in:
2026-07-29 17:07:45 +07:00
commit 57dc91585d
783 changed files with 221743 additions and 0 deletions
@@ -0,0 +1,669 @@
/**
* @file Unit tests for the TranscriptCache class, which extracts token usage from Claude transcript JSONL files and caches results for performance. Tests cover cache hits/misses, compaction detection, multiple models, and edge cases like malformed files and eviction behavior.
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
*/
const { describe, it, beforeEach, afterEach } = require("node:test");
const assert = require("node:assert/strict");
const fs = require("fs");
const path = require("path");
const os = require("os");
let tmpDir;
let TranscriptCache;
function writeJsonl(filePath, entries) {
fs.writeFileSync(filePath, entries.map((e) => JSON.stringify(e)).join("\n") + "\n");
}
describe("TranscriptCache", () => {
beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "tc-test-"));
delete require.cache[require.resolve("../../lib/transcript-cache")];
TranscriptCache = require("../../lib/transcript-cache");
});
afterEach(() => {
fs.rmSync(tmpDir, { recursive: true, force: true });
});
it("should extract tokens on first read (cache miss)", () => {
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [
{
message: {
model: "claude-sonnet-4-20250514",
usage: { input_tokens: 100, output_tokens: 50 },
},
},
{
message: {
model: "claude-sonnet-4-20250514",
usage: { input_tokens: 200, output_tokens: 75 },
},
},
]);
const cache = new TranscriptCache();
const result = cache.extract(file);
assert.deepStrictEqual(result.tokensByModel, {
"claude-sonnet-4-20250514": { input: 300, output: 125, cacheRead: 0, cacheWrite: 0 },
});
assert.strictEqual(result.compaction, null);
});
it("should return cached result when file is unchanged", () => {
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [
{
message: {
model: "claude-sonnet-4-20250514",
usage: { input_tokens: 100, output_tokens: 50 },
},
},
]);
const cache = new TranscriptCache();
const r1 = cache.extract(file);
const r2 = cache.extract(file);
assert.deepStrictEqual(r1, r2);
// Same object reference proves cache hit (no re-parse)
assert.strictEqual(r1, r2);
});
it("should detect new data when file grows", () => {
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [
{
message: {
model: "claude-sonnet-4-20250514",
usage: { input_tokens: 100, output_tokens: 50 },
},
},
]);
const cache = new TranscriptCache();
const r1 = cache.extract(file);
assert.strictEqual(r1.tokensByModel["claude-sonnet-4-20250514"].input, 100);
// Append more data (simulates Claude writing to transcript)
fs.appendFileSync(
file,
JSON.stringify({
message: {
model: "claude-sonnet-4-20250514",
usage: { input_tokens: 200, output_tokens: 75 },
},
}) + "\n"
);
const r2 = cache.extract(file);
assert.strictEqual(r2.tokensByModel["claude-sonnet-4-20250514"].input, 300);
assert.strictEqual(r2.tokensByModel["claude-sonnet-4-20250514"].output, 125);
});
it("should do full re-read when file shrinks (compaction rewrite)", () => {
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [
{
message: {
model: "claude-sonnet-4-20250514",
usage: { input_tokens: 500, output_tokens: 200 },
},
},
{
message: {
model: "claude-sonnet-4-20250514",
usage: { input_tokens: 300, output_tokens: 100 },
},
},
]);
const cache = new TranscriptCache();
cache.extract(file);
// Simulate compaction — file is rewritten with fewer entries + summary
writeJsonl(file, [
{ isCompactSummary: true, uuid: "abc-123", timestamp: "2026-03-20T10:00:00Z" },
{
message: {
model: "claude-sonnet-4-20250514",
usage: { input_tokens: 50, output_tokens: 20 },
},
},
]);
const r2 = cache.extract(file);
assert.strictEqual(r2.tokensByModel["claude-sonnet-4-20250514"].input, 50);
assert.strictEqual(r2.compaction.count, 1);
assert.strictEqual(r2.compaction.entries[0].uuid, "abc-123");
});
it("should return null for non-existent file", () => {
const cache = new TranscriptCache();
assert.strictEqual(cache.extract("/nonexistent/file.jsonl"), null);
assert.strictEqual(cache.extract(null), null);
assert.strictEqual(cache.extract(""), null);
});
it("should expose compaction entries via extractCompactions()", () => {
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [
{
message: {
model: "claude-sonnet-4-20250514",
usage: { input_tokens: 100, output_tokens: 50 },
},
},
{ isCompactSummary: true, uuid: "c1", timestamp: "2026-03-20T09:00:00Z" },
{
message: {
model: "claude-sonnet-4-20250514",
usage: { input_tokens: 50, output_tokens: 20 },
},
},
{ isCompactSummary: true, uuid: "c2", timestamp: "2026-03-20T10:00:00Z" },
]);
const cache = new TranscriptCache();
const compactions = cache.extractCompactions(file);
assert.strictEqual(compactions.length, 2);
assert.strictEqual(compactions[0].uuid, "c1");
assert.strictEqual(compactions[1].uuid, "c2");
});
it("should handle multiple models in same file", () => {
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [
{
message: {
model: "claude-sonnet-4-20250514",
usage: { input_tokens: 100, output_tokens: 50 },
},
},
{
message: {
model: "claude-opus-4-20250514",
usage: { input_tokens: 500, output_tokens: 200 },
},
},
]);
const cache = new TranscriptCache();
const result = cache.extract(file);
assert.strictEqual(result.tokensByModel["claude-sonnet-4-20250514"].input, 100);
assert.strictEqual(result.tokensByModel["claude-opus-4-20250514"].input, 500);
});
it("should skip <synthetic> model entries", () => {
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [
{ message: { model: "<synthetic>", usage: { input_tokens: 999, output_tokens: 999 } } },
{
message: {
model: "claude-sonnet-4-20250514",
usage: { input_tokens: 100, output_tokens: 50 },
},
},
]);
const cache = new TranscriptCache();
const result = cache.extract(file);
assert.strictEqual(Object.keys(result.tokensByModel).length, 1);
assert.strictEqual(result.tokensByModel["claude-sonnet-4-20250514"].input, 100);
});
it("should handle cache_read and cache_write tokens", () => {
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [
{
message: {
model: "claude-sonnet-4-20250514",
usage: {
input_tokens: 100,
output_tokens: 50,
cache_read_input_tokens: 30,
cache_creation_input_tokens: 15,
},
},
},
]);
const cache = new TranscriptCache();
const result = cache.extract(file);
assert.strictEqual(result.tokensByModel["claude-sonnet-4-20250514"].cacheRead, 30);
assert.strictEqual(result.tokensByModel["claude-sonnet-4-20250514"].cacheWrite, 15);
});
it("should remove entry on invalidate()", () => {
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [
{ message: { model: "m1", usage: { input_tokens: 100, output_tokens: 50 } } },
]);
const cache = new TranscriptCache();
cache.extract(file);
assert.strictEqual(cache.size, 1);
cache.invalidate(file);
assert.strictEqual(cache.size, 0);
});
it("should clear all entries", () => {
const file1 = path.join(tmpDir, "s1.jsonl");
const file2 = path.join(tmpDir, "s2.jsonl");
writeJsonl(file1, [
{ message: { model: "m1", usage: { input_tokens: 10, output_tokens: 5 } } },
]);
writeJsonl(file2, [
{ message: { model: "m1", usage: { input_tokens: 20, output_tokens: 10 } } },
]);
const cache = new TranscriptCache();
cache.extract(file1);
cache.extract(file2);
assert.strictEqual(cache.size, 2);
cache.clear();
assert.strictEqual(cache.size, 0);
});
it("should return correct stats()", () => {
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [{ message: { model: "m1", usage: { input_tokens: 10, output_tokens: 5 } } }]);
const cache = new TranscriptCache();
cache.extract(file);
const stats = cache.stats();
assert.strictEqual(stats.entries, 1);
assert.strictEqual(stats.paths.length, 1);
assert.strictEqual(stats.paths[0], file);
});
it("should only read new bytes on incremental update", () => {
const file = path.join(tmpDir, "session.jsonl");
const line1 =
JSON.stringify({
message: { model: "m1", usage: { input_tokens: 100, output_tokens: 50 } },
}) + "\n";
fs.writeFileSync(file, line1);
const cache = new TranscriptCache();
cache.extract(file);
// Append a second line
const line2 =
JSON.stringify({
message: { model: "m1", usage: { input_tokens: 200, output_tokens: 75 } },
}) + "\n";
fs.appendFileSync(file, line2);
const r2 = cache.extract(file);
assert.strictEqual(r2.tokensByModel["m1"].input, 300);
// Verify bytesRead advanced to full file size
const entry = cache._cache.get(file);
assert.strictEqual(entry.bytesRead, Buffer.byteLength(line1 + line2, "utf8"));
});
it("should handle incremental read adding new compaction entries", () => {
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [
{ message: { model: "m1", usage: { input_tokens: 100, output_tokens: 50 } } },
]);
const cache = new TranscriptCache();
const r1 = cache.extract(file);
assert.strictEqual(r1.compaction, null);
// Append a compaction entry
fs.appendFileSync(
file,
JSON.stringify({ isCompactSummary: true, uuid: "new-c", timestamp: "2026-03-20T12:00:00Z" }) +
"\n"
);
const r2 = cache.extract(file);
assert.strictEqual(r2.compaction.count, 1);
assert.strictEqual(r2.compaction.entries[0].uuid, "new-c");
});
it("should return null for empty file", () => {
const file = path.join(tmpDir, "empty.jsonl");
fs.writeFileSync(file, "");
const cache = new TranscriptCache();
assert.strictEqual(cache.extract(file), null);
});
it("should skip malformed JSON lines gracefully", () => {
const file = path.join(tmpDir, "session.jsonl");
fs.writeFileSync(
file,
[
"not valid json",
JSON.stringify({
message: { model: "m1", usage: { input_tokens: 100, output_tokens: 50 } },
}),
"{broken",
].join("\n") + "\n"
);
const cache = new TranscriptCache();
const result = cache.extract(file);
assert.strictEqual(result.tokensByModel["m1"].input, 100);
});
it("should evict oldest entries when exceeding maxEntries", () => {
const cache = new TranscriptCache(3); // max 3 entries
const files = [];
for (let i = 0; i < 5; i++) {
const file = path.join(tmpDir, `s${i}.jsonl`);
writeJsonl(file, [
{ message: { model: "m1", usage: { input_tokens: i * 10, output_tokens: i * 5 } } },
]);
files.push(file);
}
// Fill cache with 5 entries, but max is 3
for (const f of files) cache.extract(f);
assert.strictEqual(cache.size, 3);
// Oldest two (s0, s1) should be evicted; newest three (s2, s3, s4) remain
const stats = cache.stats();
assert.ok(!stats.paths.includes(files[0]), "oldest entry s0 should be evicted");
assert.ok(!stats.paths.includes(files[1]), "second-oldest entry s1 should be evicted");
assert.ok(stats.paths.includes(files[2]), "s2 should remain");
assert.ok(stats.paths.includes(files[3]), "s3 should remain");
assert.ok(stats.paths.includes(files[4]), "s4 should remain");
});
it("should refresh LRU order on access", () => {
const cache = new TranscriptCache(3);
const files = [];
for (let i = 0; i < 3; i++) {
const file = path.join(tmpDir, `lru${i}.jsonl`);
writeJsonl(file, [
{ message: { model: "m1", usage: { input_tokens: 10, output_tokens: 5 } } },
]);
files.push(file);
cache.extract(file);
}
// Access file[0] again (moves it to most-recently-used)
fs.appendFileSync(
files[0],
JSON.stringify({ message: { model: "m1", usage: { input_tokens: 5, output_tokens: 2 } } }) +
"\n"
);
cache.extract(files[0]);
// Add a new file — should evict file[1] (now the oldest), not file[0]
const newFile = path.join(tmpDir, "lru_new.jsonl");
writeJsonl(newFile, [
{ message: { model: "m1", usage: { input_tokens: 1, output_tokens: 1 } } },
]);
cache.extract(newFile);
assert.strictEqual(cache.size, 3);
const stats = cache.stats();
assert.ok(stats.paths.includes(files[0]), "recently accessed file should remain");
assert.ok(!stats.paths.includes(files[1]), "oldest untouched file should be evicted");
assert.ok(stats.paths.includes(files[2]), "file[2] should remain");
assert.ok(stats.paths.includes(newFile), "new file should be present");
});
it("should return defensive copy from extractCompactions", () => {
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [
{ isCompactSummary: true, uuid: "c1", timestamp: "2026-03-20T09:00:00Z" },
{ message: { model: "m1", usage: { input_tokens: 10, output_tokens: 5 } } },
]);
const cache = new TranscriptCache();
const compactions = cache.extractCompactions(file);
assert.strictEqual(compactions.length, 1);
// Mutate returned array — should NOT affect cache
compactions.push({ uuid: "fake", timestamp: null });
compactions[0].uuid = "mutated";
const compactions2 = cache.extractCompactions(file);
assert.strictEqual(compactions2.length, 1);
assert.strictEqual(compactions2[0].uuid, "c1");
});
it("should return empty array from extractCompactions for file with no compactions", () => {
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [{ message: { model: "m1", usage: { input_tokens: 10, output_tokens: 5 } } }]);
const cache = new TranscriptCache();
const compactions = cache.extractCompactions(file);
assert.deepStrictEqual(compactions, []);
});
it("should return empty array from extractCompactions for non-existent file", () => {
const cache = new TranscriptCache();
const compactions = cache.extractCompactions("/nonexistent.jsonl");
assert.deepStrictEqual(compactions, []);
});
it("should capture lastInterruptTs from an Esc-interrupt entry (text marker)", () => {
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [
{ message: { model: "m1", usage: { input_tokens: 10, output_tokens: 5 } } },
{
type: "user",
message: {
role: "user",
content: [{ type: "text", text: "[Request interrupted by user]" }],
},
timestamp: "2026-06-28T12:00:00.000Z",
},
]);
const cache = new TranscriptCache();
const result = cache.extract(file);
assert.strictEqual(result.lastInterruptTs, "2026-06-28T12:00:00.000Z");
assert.strictEqual(result.pendingInterrupt, true);
});
it("should capture lastInterruptTs via the interruptedMessageId field", () => {
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [
{
type: "user",
interruptedMessageId: "msg_123",
message: {
role: "user",
content: [{ type: "text", text: "[Request interrupted by user for tool use]" }],
},
timestamp: "2026-06-28T13:30:00.000Z",
},
]);
const cache = new TranscriptCache();
const result = cache.extract(file);
assert.strictEqual(result.lastInterruptTs, "2026-06-28T13:30:00.000Z");
assert.strictEqual(result.pendingInterrupt, true);
});
it("should flag pendingInterrupt for an Esc pressed BEFORE any output (prompt then interrupt)", () => {
// The hard case: user submits, then cancels before the model emits anything.
// Transcript order is [user prompt, interrupt] — no assistant entry between.
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [
{
type: "user",
message: { role: "user", content: [{ type: "text", text: "do a big refactor" }] },
timestamp: "2026-06-28T15:00:00.000Z",
},
{
type: "user",
interruptedMessageId: "m",
message: {
role: "user",
content: [{ type: "text", text: "[Request interrupted by user]" }],
},
timestamp: "2026-06-28T15:00:00.001Z", // 1ms later — the real-world skew case
},
]);
const cache = new TranscriptCache();
const result = cache.extract(file);
assert.strictEqual(result.pendingInterrupt, true, "pre-output Esc must still be detected");
});
it("should flag pendingInterrupt when Esc follows assistant output", () => {
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [
{
type: "assistant",
message: { model: "m1", usage: { input_tokens: 10, output_tokens: 5 } },
timestamp: "2026-06-28T16:00:00.000Z",
},
{
type: "user",
interruptedMessageId: "m",
message: {
role: "user",
content: [{ type: "text", text: "[Request interrupted by user]" }],
},
timestamp: "2026-06-28T16:00:05.000Z",
},
]);
const cache = new TranscriptCache();
const result = cache.extract(file);
assert.strictEqual(result.pendingInterrupt, true);
});
it("should NOT flag pendingInterrupt when the user resumed after the interrupt", () => {
// [interrupt, new prompt] — the user came back and submitted again.
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [
{
type: "user",
interruptedMessageId: "m",
message: {
role: "user",
content: [{ type: "text", text: "[Request interrupted by user]" }],
},
timestamp: "2026-06-28T17:00:00.000Z",
},
{
type: "user",
message: { role: "user", content: [{ type: "text", text: "actually do this instead" }] },
timestamp: "2026-06-28T17:00:30.000Z",
},
]);
const cache = new TranscriptCache();
const result = cache.extract(file);
assert.strictEqual(result.lastInterruptTs, "2026-06-28T17:00:00.000Z");
assert.strictEqual(result.pendingInterrupt, false, "resuming with a new prompt clears it");
});
it("should keep the latest interrupt timestamp (append-only, last wins)", () => {
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [
{
type: "user",
interruptedMessageId: "a",
message: {
role: "user",
content: [{ type: "text", text: "[Request interrupted by user]" }],
},
timestamp: "2026-06-28T10:00:00.000Z",
},
{
type: "user",
interruptedMessageId: "b",
message: {
role: "user",
content: [{ type: "text", text: "[Request interrupted by user]" }],
},
timestamp: "2026-06-28T11:00:00.000Z",
},
]);
const cache = new TranscriptCache();
const result = cache.extract(file);
assert.strictEqual(result.lastInterruptTs, "2026-06-28T11:00:00.000Z");
assert.strictEqual(result.pendingInterrupt, true);
});
it("should carry a newer interrupt across an incremental read", () => {
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [{ message: { model: "m1", usage: { input_tokens: 10, output_tokens: 5 } } }]);
const cache = new TranscriptCache();
const first = cache.extract(file);
assert.strictEqual(first.lastInterruptTs, null);
assert.strictEqual(first.pendingInterrupt, false);
// Append an interrupt entry → incremental read path must surface it.
fs.appendFileSync(
file,
JSON.stringify({
type: "user",
interruptedMessageId: "x",
message: {
role: "user",
content: [{ type: "text", text: "[Request interrupted by user]" }],
},
timestamp: "2026-06-28T14:00:00.000Z",
}) + "\n"
);
const second = cache.extract(file);
assert.strictEqual(second.lastInterruptTs, "2026-06-28T14:00:00.000Z");
assert.strictEqual(second.pendingInterrupt, true);
});
it("should clear pendingInterrupt across an incremental read when the user resumes", () => {
// First read sees a tail interrupt; a later prompt appended in the next
// chunk must flip pendingInterrupt back to false via the merge path.
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [
{
type: "user",
interruptedMessageId: "x",
message: {
role: "user",
content: [{ type: "text", text: "[Request interrupted by user]" }],
},
timestamp: "2026-06-28T18:00:00.000Z",
},
]);
const cache = new TranscriptCache();
assert.strictEqual(cache.extract(file).pendingInterrupt, true);
fs.appendFileSync(
file,
JSON.stringify({
type: "user",
message: { role: "user", content: [{ type: "text", text: "resume" }] },
timestamp: "2026-06-28T18:01:00.000Z",
}) + "\n"
);
assert.strictEqual(cache.extract(file).pendingInterrupt, false, "incremental resume clears it");
});
it("should leave lastInterruptTs null and pendingInterrupt false when there is no interrupt", () => {
const file = path.join(tmpDir, "session.jsonl");
writeJsonl(file, [{ message: { model: "m1", usage: { input_tokens: 10, output_tokens: 5 } } }]);
const cache = new TranscriptCache();
const result = cache.extract(file);
assert.strictEqual(result.lastInterruptTs, null);
assert.strictEqual(result.pendingInterrupt, false);
});
});