From b5d7ff4278b7ccd7d7d4510ce7136336db97ccfc Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Sun, 30 Aug 2026 21:09:00 -0700 Subject: [PATCH 1/2] Add tests for generateRefId consolidation --- packages/error-sink/src/ref-id.test.ts | 14 ++++++++++++++ packages/hub-client/src/error-envelope.test.ts | 10 +--------- 2 files changed, 15 insertions(+), 9 deletions(-) create mode 100644 packages/error-sink/src/ref-id.test.ts diff --git a/packages/error-sink/src/ref-id.test.ts b/packages/error-sink/src/ref-id.test.ts new file mode 100644 index 000000000..008d29de8 --- /dev/null +++ b/packages/error-sink/src/ref-id.test.ts @@ -0,0 +1,14 @@ +import { describe, expect, test } from "bun:test"; +import { generateRefId } from "./ref-id"; + +describe("generateRefId", () => { + test("produces a non-empty string", () => { + const refId = generateRefId(); + expect(typeof refId).toBe("string"); + expect(refId.length).toBeGreaterThan(0); + }); + + test("is not constant across calls", () => { + expect(generateRefId()).not.toBe(generateRefId()); + }); +}); diff --git a/packages/hub-client/src/error-envelope.test.ts b/packages/hub-client/src/error-envelope.test.ts index 601677b8a..8d2397190 100644 --- a/packages/hub-client/src/error-envelope.test.ts +++ b/packages/hub-client/src/error-envelope.test.ts @@ -1,9 +1,5 @@ import { describe, expect, test } from "bun:test"; -import { - generateRefId, - makeErrorEnvelope, - parseErrorEnvelope, -} from "./error-envelope"; +import { makeErrorEnvelope, parseErrorEnvelope } from "./error-envelope"; describe("error envelope", () => { test("makeErrorEnvelope carries code, userMessage, and a generated refId", () => { @@ -19,10 +15,6 @@ describe("error envelope", () => { expect(envelope.error.refId.length).toBeGreaterThan(0); }); - test("refIds are not constant across calls", () => { - expect(generateRefId()).not.toBe(generateRefId()); - }); - test("parseErrorEnvelope accepts a well-formed envelope", () => { const body = { error: { code: "x", userMessage: "y", refId: "z" }, From c86a7327f6ebcf3b9502303e421e845715c0e1ed Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Sun, 30 Aug 2026 21:09:05 -0700 Subject: [PATCH 2/2] Consolidate generateRefId into @corbits/error-sink @workbench/hub-client re-exports it instead of keeping a byte-for-byte duplicate. Same output format, so no caller-visible refId change. --- bun.lock | 1 + packages/error-sink/src/index.ts | 1 + packages/error-sink/src/ref-id.ts | 11 ++++++----- packages/hub-client/package.json | 1 + packages/hub-client/src/error-envelope.ts | 11 +++-------- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/bun.lock b/bun.lock index ebb446c1a..804210357 100644 --- a/bun.lock +++ b/bun.lock @@ -824,6 +824,7 @@ "dependencies": { "@corbits/assistant-workflow": "workspace:*", "@corbits/echo-workflow": "workspace:*", + "@corbits/error-sink": "workspace:*", "@corbits/heartbeat-workflow": "workspace:*", "@corbits/inference-catalog": "workspace:*", "@corbits/last-30-days-research-workflow": "workspace:*", diff --git a/packages/error-sink/src/index.ts b/packages/error-sink/src/index.ts index 54f20b106..66d9ce767 100644 --- a/packages/error-sink/src/index.ts +++ b/packages/error-sink/src/index.ts @@ -86,3 +86,4 @@ export function reportError( } export type { ErrorContext } from "./context"; +export { generateRefId } from "./ref-id"; diff --git a/packages/error-sink/src/ref-id.ts b/packages/error-sink/src/ref-id.ts index f93aa680c..612242a15 100644 --- a/packages/error-sink/src/ref-id.ts +++ b/packages/error-sink/src/ref-id.ts @@ -1,8 +1,9 @@ -// Mints the same short, quotable, grep-able shape `@workbench/hub-client`'s -// `generateRefId` does, without depending on that package: hub-client -// pulls in the full workflow-catalog and inference stack, which this -// package's browser callers (and its own server-side ones) have no -// reason to carry just to mint an id. +// The sole implementation of the short, quotable, grep-able refId shape +// (CL-7253). `@workbench/hub-client` re-exports this rather than keeping +// its own copy; this package stays free of `@workbench/hub-client`'s +// workflow-catalog and inference stack, which this package's browser +// callers (and its own server-side ones) have no reason to carry just to +// mint an id. export function generateRefId(): string { const random = Math.random().toString(36).slice(2, 8); return `${Date.now().toString(36)}-${random}`; diff --git a/packages/hub-client/package.json b/packages/hub-client/package.json index 126adee17..181b31756 100644 --- a/packages/hub-client/package.json +++ b/packages/hub-client/package.json @@ -18,6 +18,7 @@ "dependencies": { "@corbits/assistant-workflow": "workspace:*", "@corbits/echo-workflow": "workspace:*", + "@corbits/error-sink": "workspace:*", "@corbits/heartbeat-workflow": "workspace:*", "@corbits/inference-catalog": "workspace:*", "@corbits/last-30-days-research-workflow": "workspace:*", diff --git a/packages/hub-client/src/error-envelope.ts b/packages/hub-client/src/error-envelope.ts index 8efd5e035..32249120c 100644 --- a/packages/hub-client/src/error-envelope.ts +++ b/packages/hub-client/src/error-envelope.ts @@ -6,8 +6,11 @@ // hub's own logger, keyed by the same `refId`, so an operator can find // it without the client ever having seen it. See CL-6360. +import { generateRefId } from "@corbits/error-sink"; import { type } from "arktype"; +export { generateRefId }; + export const ErrorEnvelopeShape = type({ error: { code: "string", @@ -18,14 +21,6 @@ export const ErrorEnvelopeShape = type({ export type ErrorEnvelope = typeof ErrorEnvelopeShape.infer; -/** Short enough to read aloud, unique enough to grep a log for. Never a - * secret and never derived from anything sensitive — it is a lookup key, - * not a token. */ -export function generateRefId(): string { - const random = Math.random().toString(36).slice(2, 8); - return `${Date.now().toString(36)}-${random}`; -} - export function makeErrorEnvelope(args: { code: string; userMessage: string;