---
name: xylabs-refactor-cohesion
description: >
  Audits a TypeScript yarn/pnpm monorepo for cohesion and coupling violations across packages,
  presents a priority-sorted list of recommendations, and executes approved remediations one at
  a time with full verification. Use this skill whenever the user asks to audit package structure,
  find misplaced exports, detect circular dependencies, or improve monorepo organization — even
  if they just say something like "audit cohesion" or "clean up the package graph". The skill
  makes only logical grouping changes — it never alters runtime behavior, signatures, or semantics.
---
# xylabs-refactor-cohesion
Guides a complete audit of a TypeScript monorepo, identifying cohesion and coupling violations,
presenting a priority-sorted recommendation report, and executing approved remediations one at a
time with full verification. The goal is a package graph where any agent can look at a package
name, read its exports, and confidently predict what else lives there.
---
## Inputs Required
Before beginning, confirm the following are available:
- Root of the monorepo (path or working directory)
- Package manager: `yarn` workspaces or `pnpm` workspaces
- Access to run build, lint, and test commands (exact commands confirmed with human during Pre-Flight)
- Confirmation of which packages are in scope (default: all workspace packages)
---
## Pre-Flight: Repo Fingerprinting

> **Do not begin analysis until fingerprinting is complete.**
> The goal is to understand the repo's own conventions so all decisions
> respect existing patterns rather than imposing external opinions.

### 1. Workspace Layout

- Read the root `package.json` or `pnpm-workspace.yaml` to enumerate all packages
- Record each package's name, path, and declared internal dependencies
- Build a dependency graph: which packages depend on which

### 2. Layering Model

- Infer the intended layering (e.g. `core` → `shared` → `features` → `apps`)
- Note any packages that appear to be "leaf" (no internal deps) vs "root" (depended on by many)
- Record this as the **canonical layer order** — used later to detect inverted dependencies

### 3. Naming & Export Conventions

- How are packages named? (`@scope/package-name`, `packages/name`, etc.)
- How are barrel exports structured? (`index.ts`, `src/index.ts`, nested barrels?)
- Are there naming conventions for files? (`camelCase.ts`, `kebab-case.ts`, `PascalCase.ts`)
- Record all observed patterns as the **repo style guide** for this session

### 4. Test Conventions

Inspect at least 3 packages to determine:
- Where do tests live? (co-located `*.test.ts`, `__tests__/` sibling directory, root `tests/` folder, or combination)
- What test runner is used? (`jest`, `vitest`, `mocha`, etc.)
- What is the test file naming pattern? (`foo.test.ts`, `foo.spec.ts`, `test-foo.ts`)
- Are there test utilities or fixtures shared across packages? If so, where?
- Record as **test convention** — tests will always be moved alongside their source using this convention

### 5. Build & Lint Tooling — Infer, Then Confirm

Inspect the repo to infer the likely commands, but **do not run anything yet**.

Look at:
- `tsconfig.json` files (root and per-package) — note path alias patterns
- Lint config (`eslint.config.*`, `.eslintrc.*`) — note any import-order rules
- Root `package.json` scripts and any per-package `scripts` blocks
- Any Makefile, `turbo.json`, `nx.json`, or task-runner config at the root

From this, draft the following command table:

| Purpose | Inferred Command |
|---|---|
| Compile full repo | e.g. `pnpm build` / `tsc -b` |
| Compile single package | e.g. `pnpm --filter @scope/foo build` |
| Lint full repo | e.g. `pnpm lint` |
| Lint single package | e.g. `pnpm --filter @scope/foo lint` |
| Test single package | e.g. `pnpm --filter @scope/foo test` |
| Test full repo | e.g. `pnpm test` |

Then present this table to the human and ask:

> "Before I run any build, lint, or test commands, I want to confirm I'm using
> the right ones for this repo. Here's what I've inferred:
>
> (insert the inferred command table here)
>
> Are these correct? Please correct any that are wrong, and let me know if there
> are any flags, environment variables, or setup steps I need to run first
> (e.g. `pnpm install`, code generation, env files).
> I won't run anything until you confirm."

**Do not proceed to baseline verification until the human has explicitly confirmed
or corrected the command table.** Record the confirmed commands as the
**canonical tooling config** for this session. Use these commands — and only
these commands — throughout all verification steps.

### 6. Baseline Verification

Run compile, lint, and full test suite **before any changes**.
Record results as the **baseline state**.

> ⚠️ If the baseline does not compile or has failing tests, surface this to the human
> before proceeding. Do not begin analysis on a broken repo. The human must decide
> whether to proceed anyway and which failures are pre-existing.

---

## Phase 1 — File-Level Summarization (Tier 1)

For each package, traverse every source file (excluding test files for now).
For each file, produce an internal summary:

```yaml
file: <relative path>
exports:
  - name: <symbol>
    kind: function | class | type | constant | hook | util
    description: <one sentence — what it does, not how>
    domain_hint: <the conceptual domain this belongs to, e.g. "date formatting", "HTTP auth", "user entity">
apparent_responsibility: <one sentence describing the file's overall concern>
outlier_exports: <any exports that feel inconsistent with the file's apparent responsibility>
```

**Do not make migration decisions yet. Observe only.**

---

## Phase 2 — Package-Level Rollup (Tier 2)

For each package, synthesize all file summaries into a package summary:

```yaml
package: <name>
path: <path>
declared_domain: <inferred single responsibility of this package, 1 sentence>
cohesion_score: 1–5
  5 = all exports serve exactly one concern
  3 = mostly cohesive with a few outliers
  1 = grab-bag, multiple unrelated concerns
exports_by_domain:
  <domain>: [<symbol>, ...]
outlier_exports:
  - symbol: <name>
    current_package: <this package>
    reason: <why it feels out of place>
    candidate_package: <where it might belong, or "NEW_PACKAGE">
internal_dependencies: [<package names>]
layer: <inferred layer from fingerprinting>
```

Process packages in **topological order** (leaf packages first, most-depended-on last).
When summarizing a package, include the summaries of its dependencies as context
so you understand what has already been "claimed" by other packages.

---

## Phase 3 — Cross-Package Graph Analysis (Tier 3)

With the full inventory of all package summaries, reason across the entire graph.

Identify the following violation types:

### Cohesion Violations
A package contains exports that belong to a different package's domain.
- The export's `domain_hint` does not match the package's `declared_domain`
- A clearly more appropriate home exists elsewhere in the graph

### Coupling Violations
- **Inverted dependency**: a lower-layer package imports from a higher-layer package
- **Circular dependency**: two packages depend on each other directly or transitively
- **Reach-through**: Package A imports something from Package B that conceptually
  belongs to Package C, suggesting B is just a pass-through and the real dependency
  is missing

### Missing Package
- A cluster of outlier exports from multiple packages share a domain that has no home
- Creating a new package would resolve multiple violations cleanly

### Over-Broad Package
- A package (often named `utils`, `helpers`, `common`, `shared`) contains exports
  from 3+ distinct domains with no unifying concern
- Should be split into focused packages

---

## Output: Priority-Sorted Recommendation Report

Present findings as a structured report before any action is taken.

### Report Format

```text
# Monorepo Cohesion & Coupling Audit Report
Generated: <date>
Packages analyzed: <N>
Total findings: <N>

## Baseline State
- Compile: PASS / FAIL (<details>)
- Lint: PASS / FAIL (<details>)
- Tests: PASS / FAIL (<N> passing, <N> failing)

---

## Findings

### [HIGH-001] <Short title>
**Type**: Cohesion Violation | Coupling Violation | Missing Package | Over-Broad Package
**Severity**: High
**Why it matters**: <1–2 sentences on impact to agent traversal and developer experience>
**Proposed change**: <concrete description — what moves where>
**Files affected**: <list>
**Tests affected**: <list>
**Import sites to update**: <count and packages>
**Risks**: <anything that warrants human attention>

### [MED-002] ...
### [LOW-003] ...
```

### Severity Assignment

| Severity | Criteria |
|----------|----------|
| **High** | Circular dependency; inverted layer dependency; a package exports things from 3+ unrelated domains; directly impairs agent traversal or causes build issues |
| **Medium** | Cohesion outlier with a clear better home; over-broad package that should be split; reach-through coupling |
| **Low** | Minor organizational preference; single outlier export with a debatable home; naming inconsistency |

### Closing Summary

After the findings list, include:
- A plain-English paragraph summarizing the overall health of the repo
- The top 3 things that, if fixed, would most improve agent traversability
- An estimate of total scope (e.g. "12 file moves, ~40 import updates across 6 packages")

---

## Human Review & Negotiation Protocol

After presenting the report, pause and say:

> "Here is the full audit. I've sorted findings from highest to lowest severity.
> Before I touch anything, I'd like your review.
>
> For each finding you can say:
> - **Approve** — I'll add it to the work queue
> - **Veto** — I'll skip it and note it as declined
> - **Modify** — tell me how you'd like to adjust the proposed change
> - **Defer** — skip for now but keep it in the log
>
> You can also approve all findings of a given severity tier at once.
> What would you like to do?"

Record the human's decisions. Build a **work queue** of approved items in their
original priority order. Do not reorder without asking.

---

## Remediation Protocol (Per Item)

Work through the queue one item at a time. For each item:

### Step 1 — Dry-Run Summary

Present a friendly, plain-English summary of exactly what will happen:

> "Here's what I'm going to do for **`[HIGH-001]`**:
>
> - Move `formatCurrency` and `formatPercent` from `@scope/utils` → `@scope/formatting`
> - Move their co-located tests (`formatCurrency.test.ts`, `formatPercent.test.ts`)
>   into `packages/formatting/src/__tests__/` following the repo's test convention
> - Update `@scope/utils/src/index.ts` to remove those exports
> - Add them to `@scope/formatting/src/index.ts`
> - Update all import sites (found in 4 packages: `@scope/app`, `@scope/reports`, ...)
>
> No logic will change. This is purely a move and re-export.
>
> Shall I proceed?"

Wait for explicit approval before touching any files.

### Step 2 — Execute Atomically

Perform all of the following as a single unit:

1. Move source file(s) to new package location
2. Move test file(s) alongside source, preserving the repo's test convention
3. Update the source package's `index.ts` — remove the moved exports
4. Update the destination package's `index.ts` — add the moved exports
5. Update all import references across the entire repo to point to the new package
6. Update any path aliases in `tsconfig.json` if relevant

Do not proceed to verification until all of the above are complete.

### Step 3 — Verification Loop

Run the following in order:

```text
1. Compile (full repo or targeted build)
2. Lint (full repo or affected packages)
3. Tests (affected packages first, then full suite)
```

#### If everything passes:

> "✅ `[HIGH-001]` complete. Compile, lint, and tests all pass.
> Moving to `[MED-002]` — ready when you are."

#### If compile or lint fails:

Inspect the failure. Apply the following rule:

> **If the failure is a direct consequence of the move** (broken import path,
> missing re-export, tsconfig path alias not updated) — fix it automatically,
> re-verify, and report what was corrected.
>
> **If the failure is unrelated to the move, or would require changing
> the logic or signature of any function** — stop immediately, surface the
> failure to the human, and do not attempt a fix without approval.

Never change function signatures, return types, logic, or behavior to resolve a failure.

#### If tests fail:

Same rule applies:

> **If the test failure is caused by the move** (wrong import path in the test,
> test helper moved but not updated) — fix it automatically, re-verify, report.
>
> **If the test failure existed before the move, or the fix would require
> changing test assertions or tested logic** — stop. Surface to human.
> **Do not proceed to the next queue item until the human intervenes.**

The definition of done for each item:
- ✅ Compile passes
- ✅ Lint passes
- ✅ All previously-passing tests still pass
- ✅ Human has been informed of completion

---

## Continuation Protocol

After each completed item:

> "That's **X of N** approved items complete.
> Next up: **`NEXT-ID`** — one-line description.
> Ready to proceed, or would you like to pause?"

If the human pauses, hold state and resume from the next queue item when asked.

If all items are complete:

> "All approved items are done. Here's a summary of what changed:
> (table of: item ID, what moved, files changed, tests moved)
>
> Remaining vetoed/deferred items: (list)
> Would you like to revisit any deferred items, or is the session complete?"

---

## Edge Cases & Decision Rules

### When NOT to flag something

- A `types` package that everything imports from — expected, not a coupling violation
- A `config` or `constants` package depended on widely — acceptable shared leaf
- A `utils` package with fewer than 3 distinct domains — low cohesion score but not a violation
- Test utilities in a shared package — only flag if they're mixed with runtime code

### Naming Conflicts

If moving a symbol would create a naming conflict in the destination package,
surface this to the human before executing. Do not rename symbols automatically.

### New Package Creation

If the recommendation is to create a new package:
- Follow the repo's existing package scaffolding pattern exactly
  (copy `package.json`, `tsconfig.json` structure from a similar package)
- Do not add dependencies, scripts, or config that don't follow existing patterns
- Present the proposed `package.json` to the human for approval before creating

### Circular Dependencies Introduced by a Move

Before executing any move, check whether it would introduce a new circular dependency.
If it would, surface this to the human — do not proceed automatically.

### Out-of-Scope Changes Noticed During Remediation

If during file inspection you notice bugs, performance issues, or style problems
unrelated to the reorganization — do not fix them. Log them as a note in the
session summary only.

---

## Session Log

Maintain a running log throughout the session:

```text
[APPROVED]  HIGH-001 — formatCurrency moved to @scope/formatting ✅
[APPROVED]  MED-002 — pending
[VETOED]    MED-003 — human declined, reason: intentional design
[DEFERRED]  LOW-004 — revisit later
```

This log is presented in full at the end of the session.