feat(ts): add real quality gates — Biome lint + effect-law ratchet + class inventory

- biome.json (2.4.16, linter-only) wired as "lint" in all six packages
- scripts/check-effect-laws.ts: Effect-native law enforcement encoding the
  adapted beep-effect effect-first/schema-first laws (no native JSON/switch/
  sort/fetch/timers, no process.env, no throw new, no Effect.run* outside
  boundaries, no Schema-suffixed constants, no node:fs/path, AST-based
  pure-data interface detection per law 38/39)
- ratcheting baseline allowlist (95 entries / 290 findings) that must shrink
  to documented exemptions only; stale counts fail the gate
- root lint chains turbo lint + law check + native-class inventory
- fix all 163 initial Biome findings: import-type style, templates, two `any`s,
  ten non-null assertions (librarian getService gate, A.matchRight in atoms,
  ensureNode returning nodes, main.tsx mount guard)

Gates: lint, check:tsgo, build, test (force, 11 tasks) all green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
elpresidank 2026-06-11 06:40:01 -05:00
parent cf12defcd8
commit 0746d7ffd5
109 changed files with 951 additions and 611 deletions

View file

@ -19,7 +19,8 @@
"build": "bunx --bun tsc",
"dev": "tsc --watch",
"clean": "rm -rf dist",
"test": "bunx --bun vitest run"
"test": "bunx --bun vitest run",
"lint": "bunx --bun biome check src"
},
"dependencies": {
"effect": "4.0.0-beta.78"
@ -36,7 +37,6 @@
"@effect/vitest": "4.0.0-beta.78",
"@types/node": "^22.0.0",
"@types/ws": "^8.5.0",
"typescript": "^5.8.0",
"vitest": "^4.1.6",
"happy-dom": "^20.0.0"

View file

@ -1,6 +1,7 @@
import { describe, it, expect, vi, beforeEach } from "vitest";
import type { BaseApi } from "../socket/trustgraph-socket";
import { FlowsApi, TrustGraphSocketError } from "../socket/trustgraph-socket";
import { FlowResponse } from "../models/messages";
import type { FlowResponse } from "../models/messages";
describe("FlowsApi", () => {
let mockApi: {
@ -12,8 +13,7 @@ describe("FlowsApi", () => {
mockApi = {
makeRequest: vi.fn(),
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
flowsApi = FlowsApi(mockApi as any);
flowsApi = FlowsApi(mockApi as unknown as BaseApi);
});
describe("startFlow", () => {

View file

@ -342,7 +342,7 @@ describe("Message Types", () => {
type: "library-error",
});
expect(response["document-metadatas"]).toHaveLength(1);
expect(response["document-metadatas"]![0].id).toBe("doc-1");
expect(response["document-metadatas"]?.[0].id).toBe("doc-1");
});
});

View file

@ -1,8 +1,10 @@
import { Effect } from "effect";
import { describe, expect, it, vi } from "vitest";
import { DispatchError, DispatchStreamChunk } from "../rpc/contract";
import { type DispatchInput, type RpcConnectionState, withDispatchRequestPolicy } from "../socket/effect-rpc-client";
import { type ConnectionState, makeBaseApiWithRpc } from "../socket/trustgraph-socket";
import type { DispatchInput, RpcConnectionState, } from "../socket/effect-rpc-client";
import { withDispatchRequestPolicy } from "../socket/effect-rpc-client";
import type { ConnectionState, } from "../socket/trustgraph-socket";
import { makeBaseApiWithRpc } from "../socket/trustgraph-socket";
const input: DispatchInput = {
scope: "global",

View file

@ -1,6 +1,8 @@
import { describe, expect, it, vi } from "vitest";
import {
import type {
BaseApi,
} from "../socket/trustgraph-socket";
import {
ConfigApi,
KnowledgeApi,
LibrarianApi,

View file

@ -5,38 +5,38 @@
// TrustGraph namespace
export const TG = "https://trustgraph.ai/ns/";
export const TG_QUERY = TG + "query";
export const TG_EDGE_COUNT = TG + "edgeCount";
export const TG_SELECTED_EDGE = TG + "selectedEdge";
export const TG_EDGE = TG + "edge";
export const TG_REASONING = TG + "reasoning";
export const TG_CONTENT = TG + "content";
export const TG_REIFIES = TG + "reifies";
export const TG_DOCUMENT = TG + "document";
export const TG_QUERY = `${TG}query`;
export const TG_EDGE_COUNT = `${TG}edgeCount`;
export const TG_SELECTED_EDGE = `${TG}selectedEdge`;
export const TG_EDGE = `${TG}edge`;
export const TG_REASONING = `${TG}reasoning`;
export const TG_CONTENT = `${TG}content`;
export const TG_REIFIES = `${TG}reifies`;
export const TG_DOCUMENT = `${TG}document`;
// W3C PROV-O namespace
export const PROV = "http://www.w3.org/ns/prov#";
export const PROV_STARTED_AT_TIME = PROV + "startedAtTime";
export const PROV_WAS_DERIVED_FROM = PROV + "wasDerivedFrom";
export const PROV_WAS_GENERATED_BY = PROV + "wasGeneratedBy";
export const PROV_ACTIVITY = PROV + "Activity";
export const PROV_ENTITY = PROV + "Entity";
export const PROV_STARTED_AT_TIME = `${PROV}startedAtTime`;
export const PROV_WAS_DERIVED_FROM = `${PROV}wasDerivedFrom`;
export const PROV_WAS_GENERATED_BY = `${PROV}wasGeneratedBy`;
export const PROV_ACTIVITY = `${PROV}Activity`;
export const PROV_ENTITY = `${PROV}Entity`;
// RDFS namespace
export const RDFS = "http://www.w3.org/2000/01/rdf-schema#";
export const RDFS_LABEL = RDFS + "label";
export const RDFS_LABEL = `${RDFS}label`;
// RDF namespace
export const RDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
export const RDF_TYPE = RDF + "type";
export const RDF_TYPE = `${RDF}type`;
// Schema.org namespace (used in document metadata)
export const SCHEMA = "https://schema.org/";
export const SCHEMA_NAME = SCHEMA + "name";
export const SCHEMA_DESCRIPTION = SCHEMA + "description";
export const SCHEMA_AUTHOR = SCHEMA + "author";
export const SCHEMA_KEYWORDS = SCHEMA + "keywords";
export const SCHEMA_NAME = `${SCHEMA}name`;
export const SCHEMA_DESCRIPTION = `${SCHEMA}description`;
export const SCHEMA_AUTHOR = `${SCHEMA}author`;
export const SCHEMA_KEYWORDS = `${SCHEMA}keywords`;
// SKOS namespace
export const SKOS = "http://www.w3.org/2004/02/skos/core#";
export const SKOS_DEFINITION = SKOS + "definition";
export const SKOS_DEFINITION = `${SKOS}definition`;

View file

@ -4,7 +4,8 @@ import * as RpcClient from "effect/unstable/rpc/RpcClient";
import type { RpcClientError } from "effect/unstable/rpc/RpcClientError";
import * as RpcSerialization from "effect/unstable/rpc/RpcSerialization";
import * as Socket from "effect/unstable/socket/Socket";
import { DispatchPayload, DispatchError, TrustGraphRpcs, type DispatchStreamChunk } from "../rpc/contract.js";
import type { DispatchStreamChunk } from "../rpc/contract.js";
import { DispatchPayload, DispatchError, TrustGraphRpcs, } from "../rpc/contract.js";
type TrustGraphRpcClient = RpcClient.RpcClient<
RpcGroup.Rpcs<typeof TrustGraphRpcs>,

View file

@ -1,10 +1,12 @@
// Import core types and classes for the TrustGraph API
import type { Term, Triple } from "../models/Triple.js";
import type {
EffectRpcClient,
DispatchInput,
DispatchOptions,
RpcConnectionState,
} from "./effect-rpc-client.js";
import {
type EffectRpcClient,
type DispatchInput,
type DispatchOptions,
type RpcConnectionState,
makeEffectRpcClient,
} from "./effect-rpc-client.js";
import { getDefaultSocketUrl, getRandomValues } from "./websocket-adapter.js";
@ -479,7 +481,7 @@ export function makeBaseApi(
hasApiKey: isNonEmptyString(token),
}),
);
let lastError: string | undefined = undefined;
let lastError: string | undefined ;
let rpcState: RpcConnectionState = { status: "connecting" };
const api = {
@ -536,7 +538,7 @@ export function makeBaseApi(
* Format: {clientTag}-{incrementingNumber}
*/
getNextId() {
const mid = api.tag + "-" + api.id.toString();
const mid = `${api.tag}-${api.id.toString()}`;
api.id++;
return mid;
},
@ -2530,11 +2532,10 @@ export function makeKnowledgeApi(api: BaseApi) {
// End of stream - notify receiver and signal completion
receiver(msg, true);
return true;
} else {
}
// Regular message - continue streaming
receiver(msg, false);
return false;
}
};
return this.api.makeRequestMulti<LibraryRequest, LibraryResponse>(

View file

@ -56,8 +56,7 @@ export interface IsomorphicWebSocket {
addEventListener(type: "close", listener: (event: WsCloseEvent) => void): void;
addEventListener(type: "open", listener: (event: WsEvent) => void): void;
addEventListener(type: "error", listener: (event: WsEvent) => void): void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
removeEventListener(type: string, listener: (...args: any[]) => void): void;
removeEventListener(type: string, listener: (...args: ReadonlyArray<never>) => void): void;
}
/** Constructor signature for an isomorphic WebSocket implementation. */