TypeScript governance

Architectural governance for AI-assisted TypeScript development

TypeScript is where most AI-assisted frontend and full-stack work lives today — React, Next.js, Node.js services, monorepos with shared types. Mneme governs the architectural decisions in those repos at the file-write seam. The type system stays under tsc; Mneme governs the choices the type system can't enforce.

Tier 1 · Operationally supported

What governance looks like in TypeScript

The most common AI-assisted regressions in TypeScript repos: state-management library drift, server/client boundary violations in Next.js, ad-hoc data fetching outside the approved layer, and dependencies being re-introduced after the team standardized on alternatives. Mneme blocks them at generation time and gates them in CI.

Five concrete examples of what the governance layer catches under AI-assisted development:

Unauthorized state library introduction

Architecture

Rule. ADR-004 standardized on Zustand. Redux, Jotai, and Recoil are out.

// AI-generated in app/store/cart.ts
import { createStore, combineReducers } from "redux";
import { Provider } from "react-redux";

export const store = createStore(combineReducers({ cart: cartReducer }));
non-approved state managementstack divergence

Server-only import in client component

Next.js architecture

Rule. No server-only modules (db, secrets, fs) inside files marked "use client".

// AI-generated in app/cart/page.tsx
"use client";
import { db } from "@/lib/db";        // server-only
import { stripeSecret } from "@/config"; // server-only

export default function CartPage() {
  const items = db.query("SELECT * FROM cart_items");
  ...
}
server/client boundary breachsecret exposure risk

Direct fetch outside data layer

Layer boundary

Rule. No fetch() in components. All requests go through src/data/ with typed clients.

// AI-generated in components/UserCard.tsx
export function UserCard({ id }: { id: string }) {
  const [user, setUser] = useState(null);
  useEffect(() => {
    fetch(`/api/users/${id}`)
      .then(r => r.json())
      .then(setUser);
  }, [id]);
  ...
}
data fetch in presentation layermissing typed client

Cross-package import in monorepo

Workflow scope

Rule. packages/billing may not import from packages/auth directly. Use packages/shared/identity.

// AI-generated in packages/billing/src/invoice.ts
import { getCurrentUser } from "@acme/auth/internal";
import { decodeSession } from "@acme/auth/private";
scoped ownership breachmonorepo boundary violation

GPL dependency added to package.json

Dependency / licensing

Rule. No GPL-licensed dependencies. The approved list is in .mneme/dependencies.json.

// AI added to package.json during a refactor
{
  "dependencies": {
    ...
    "some-gpl-pdf-lib": "^2.1.0"
  }
}
licensing policy violationapproved-list deviation

Current capabilities

What works today

  • Repository-level governance (paths, scopes, ownership)
  • Architectural boundary enforcement at the file/import level
  • Forbidden dependency checks (package.json and tsconfig.json path mappings)
  • Agent workflow governance across Cursor, Claude Code, Copilot, Cline
  • CI gating via GitHub Actions
  • Cursor rules export from the decision corpus
  • Monorepo scope enforcement (workspaces, Turborepo, Nx)

Not yet

  • TypeScript semantic / AST-aware rules
  • Type-level constraints (no tsc compiler hook)
  • React component-level enforcement (hooks rules, prop-type policies)
  • Next.js app-router policy packs (route conventions, RSC layering)
  • ESLint plugin integration

Where it fits in a TypeScript codebase

Same model as Python: decision corpus at .mneme/project_memory.json, hooks fire on file writes, mneme check --mode strict gates PR diffs in CI. The same corpus serves Cursor's rules system, Claude Code's hooks, and the GitHub Actions runner — one source of architectural truth across the JS/TS toolchain.

See the Cursor integration for the editor-side setup, the GitHub Actions integration for CI, and the CLI reference for the full operational surface.