← Matt Skills CuratedCONTENT HISTORY

Update to Matt Skills Curated

Snapshot Sep 30, 2026 · 23:14 UTC · version 1.1.0

Collection source: not recorded for this historical snapshot.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "description": "Enforce TypeScript package boundaries, entry points, and cyclic dependency rules with dependency-cruiser. Use when structuring monorepo packages, establishing public API entry points, or preventing circular imports — even if the user says \"fix TS package boundaries\". Do NOT use for non-TypeScript repositories.",
  "included_files": [
    {
      "relative_path": "agents/openai.yaml",
      "size_in_bytes": 106
    },
    {
      "relative_path": "dependency-cruiser.config.cjs",
      "size_in_bytes": 3712
    }
  ],
  "name": "setup-ts-deep-modules",
  "skill_md_contents": "---\nname: setup-ts-deep-modules\ndescription: \"Enforce TypeScript package boundaries, entry points, and cyclic dependency rules with dependency-cruiser. Use when structuring monorepo packages, establishing public API entry points, or preventing circular imports — even if the user says \\\"fix TS package boundaries\\\". Do NOT use for non-TypeScript repositories.\"\n---\n\n# Setup TS Deep Modules\n\nConfigure and verify strict deep-module boundaries across TypeScript packages using `dependency-cruiser`, ensuring public interfaces exist exclusively at package root files while private implementations remain sealed inside subdirectories.\n\n---\n\n## Core Invariants\n\n1. **Root Files as Exclusive Entry Points**: External callers and consumers may only import package root files (`index.ts`, `client.ts`, `server.ts`); all subdirectories (`lib/`, `internal/`, `tests/`) are private.\n2. **Four Strict Dependency Rules**: Enforce (1) Entry-point boundary, (2) Intra-package internal freedom, (3) Tests import entry-points only, (4) Zero dependency cycles.\n3. **Barrels Strongly Discouraged**: Expose focused, multiple root entry points instead of giant barrel files that re-export whole subtrees.\n4. **Mandatory Biting Proof**: Before completing setup, deliberately introduce a forbidden deep import to verify that `lint:boundaries` fails fast.\n5. **No Speculative Path Aliases**: Wire boundary checks directly through dependency-cruiser rather than altering `tsconfig.json` paths or building complex build-time layers.\n\n---\n\n## Architecture & Map of Content (MOC)\n\n```\nsrc/packages/\n  <package-name>/\n    index.ts          ◄── Public Entry Point (exported to other packages)\n    client.ts         ◄── Additional Public Entry Point\n    lib/              ◄── Private Implementation (sealed from outsiders)\n    tests/            ◄── Tests (import only root entry points)\n```\n\n| Rule | Enforcement | Target |\n|---|---|---|\n| **Entry Boundary** | `not-to-subfolder` | Outside code $\\rightarrow$ root files only |\n| **Test Boundary** | `tests-through-entrypoints` | `tests/` $\\rightarrow$ root entry points only |\n| **Cycle Prevention** | `no-circular` | Disallow all circular dependencies |\n| **Verification Gate** | `lint:boundaries` script | Automated CI failure on breach |\n\n---\n\n## Step-by-Step Procedure (TWI)\n\n### Step 1: Detect Environment & Package Manager\n- **Action**: Detect the package manager (`bun.lockb` $\\rightarrow$ bun, `pnpm-lock.yaml` $\\rightarrow$ pnpm, `yarn.lock` $\\rightarrow$ yarn, else npm) and locate the packages root (`src/packages` or `packages`).\n- **Key Point**: Check for existing `.dependency-cruiser.*` configuration to merge rules rather than overwriting.\n- **Why**: Preserving existing project package manager standards ensures zero friction with current CI scripts.\n\n### Step 2: Install and Configure Dependency Cruiser\n- **Action**: Install `dependency-cruiser` as a devDependency and copy `dependency-cruiser.config.cjs` to `.dependency-cruiser.cjs` with updated `PACKAGES_ROOT`.\n- **Key Point**: Use `.cjs` extension so CommonJS exports function seamlessly in ESM / `\"type\": \"module\"` projects.\n- **Inline Checklist**:\n  - [ ] Package manager identified correctly\n  - [ ] `dependency-cruiser` added to `devDependencies`\n  - [ ] `.dependency-cruiser.cjs` configured with 4 core rules\n\n### Step 3: Wire Scripts & Scaffold Clean Example\n- **Action**: Add `\"lint:boundaries\": \"depcruise <packages-root>\"` to `package.json` and create an example deep package:\n  - `<packages-root>/example/index.ts` (public entry point delegating to `lib/`)\n  - `<packages-root>/example/lib/impl.ts` (hidden implementation)\n  - `<packages-root>/example/tests/example.test.ts` (imports `../index`)\n- **Why**: A reference package serves as living documentation and a starter template for developers.\n\n### Step 4: Prove the Rules Bite (Verification Gate)\n- **Action**: Execute three validation passes:\n  1. Run `lint:boundaries` $\\rightarrow$ must **PASS** on clean repo.\n  2. Add deep import `import { impl } from \"../lib/impl\"` in test $\\rightarrow$ must **FAIL**.\n  3. Revert deep import and run `lint:boundaries` $\\rightarrow$ must **PASS**.\n- **Key Point**: Never sign off on boundary rules without observing an intentional test failure.\n- **Why**: Unproven linter configs frequently have syntax or glob errors that silently pass all code.\n\n### Step 5: Document Package Conventions & Agent Pointer\n- **Action**: Create `<packages-root>/README.md` explaining layout and rules, and add a single-line context pointer in `AGENTS.md` / `CLAUDE.md`.\n- **Key Point**: Explicitly explain why barrel files are discouraged.\n- **Why**: Agent pointers ensure future autonomous sessions respect package boundaries from their first prompt.\n\n---\n\n## Anti-Rationalization Guardrails\n\n| Tempting Rationalization | Binding Rule | Engineering Rationale |\n|---|---|---|\n| *\"Skip testing whether the rule fails on bad imports.\"* | **Mandatory 3-step proof (Pass $\\rightarrow$ Fail $\\rightarrow$ Pass).** | Linters with invalid glob configurations pass silently without enforcing anything. |\n| *\"Export all submodules through a giant root index.ts barrel.\"* | **Discourage large barrel files.** | Giant barrels destroy tree-shaking and create hidden cyclic import dependencies. |\n| *\"Import directly from lib/ in unit tests for convenience.\"* | **Enforce tests through public entry points only.** | Deep imports in tests tightly couple test suites to volatile internal refactors. |\n\n"
}

SHA-256 of public snapshot: 15b279e683702d86a076756a86ce41f2f38d63046f6e978300c98d1395254977