# tools/rules/purity.rule.ts

> 64 lines of code and 11 definitions.

Tree: Coordination tree
Language: typescript
Canonical: https://banes-lab.com/anatomy/coordination#file-coordination-tools-rules-purity-rule-ts
Source text: https://banes-lab.com/assets/sources/source.e2257ab3d4c1d57581acf544a31d893aed563572d2e1ad665f64aeaaa738fecf.generated.txt

## Definitions

- `inLeafTier` (lexical_declaration, line 19)
- `climbsOut` (lexical_declaration, line 23)
- `check` (method_definition, line 45, exported)
- `CONFIG_ROOT` (lexical_declaration, line 7)
- `prefix` (lexical_declaration, line 8)
- `DECIDE` (lexical_declaration, line 12)
- `leafFinding` (lexical_declaration, line 27)
- `rule` (lexical_declaration, line 44, exported)
- `known` (lexical_declaration, line 46, exported)
- `reached` (lexical_declaration, line 47, exported)
- `findings` (lexical_declaration, line 48, exported)

## Source

```typescript
import type { RuleContext, RuleDeclaration, RuleResult } from "../core/types/rule.types.ts";
import type { Finding } from "../core/types/segment.types.ts";
import { LEAF_FOLDERS } from "../core/constants/layer.constants.ts";
import { localImports } from "../core/analyzers/graph.analyzer.ts";
import { surfacePrefix } from "../../config/surface.config.ts";

const CONFIG_ROOT = ((): string => {
    const prefix = surfacePrefix();
    return prefix.length === 0 ? "config/" : `${prefix}/config/`;
})();

const DECIDE =
    "a leaf is the innermost tier and imports only leaves, which is what keeps the dependency graph acyclic " +
    "at its base and stops domain vocabulary reaching the tier every other tier depends on. An import " +
    "climbing OUT of the leaf tier inverts that: the leaf now needs what needs it, so nothing can be read " +
    "or replaced without reading the layer above it. Move the shared value DOWN into a leaf, or move the " +
    "importing module UP out of the leaf tier — never satisfy it by widening what counts as a leaf";

const inLeafTier = function inLeafTier(path: string): boolean {
    return LEAF_FOLDERS.some((folder) => path.startsWith(folder));
};

const climbsOut = function climbsOut(imported: string): boolean {
    return !inLeafTier(imported) && !imported.startsWith(CONFIG_ROOT);
};

const leafFinding = function leafFinding(path: string, imported: string): Finding {
    return {
        actual: imported,
        expected: null,
        healed: false,
        line: 1,
        locus: imported,
        path,
        remediation: { action: "none", decide: DECIDE, deterministic: false, from: path, target: path, to: null },
        rule: "purity/leafClimbsOut",
        stack: [
            { check: "tier", resolved: "leaf" },
            { check: "importedTier", resolved: "above" },
        ],
    };
};

export const rule: RuleDeclaration = {
    check(context: RuleContext): RuleResult {
        const known = new Set(context.paths);
        const reached = context.paths.filter(inLeafTier);
        const findings = reached.flatMap((path) =>
            localImports(path, context.read(path), known)
                .filter(climbsOut)
                .map((imported) => leafFinding(path, imported)),
        );

        return {
            derivations: {
                leafFolders: [...LEAF_FOLDERS],
                reached,
                skippedAsOutsideLeafTier: context.paths.filter((path) => !inLeafTier(path)),
            },
            findings,
            healed: [],
        };
    },
    extensions: [".ts"],
    heals: false,
    invariant:
        "a module in the leaf tier imports only from the leaf tier or from the parameter surface beneath it, which depends on nothing in the tree and so cannot close a cycle",
    jurisdiction: "all",
    kinds: ["leafClimbsOut"],

    stage: "structure",
};
```
