domain-dag/SKILL.md
Validates and guides Domain DAG architecture for domain ownership, acyclic local dependency graphs, composition roots, boundary direction, public contracts, interface-surface pressure, and shared-bucket drift. Use when auditing, refactoring, or extending modular codebases across frontend, backend, extensions, CLIs, SDKs, and service packages.
npx skillsauth add llblab/skills domain-dagInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Maintain source code as a directed acyclic graph of cohesive responsibility modules.
A Domain DAG keeps architecture readable by making every durable module answer four questions:
The skill is not tied to one stack or folder style. It applies to frontend features, backend bounded contexts, extension hosts, SDK packages, CLIs, workers, and service adapters.
composition root / delivery surface
→ orchestration or use-case modules
→ domain capability modules
→ support/foundation modules
→ platform, runtime, standard library, external adapters
The filesystem may be flat, layered, package-based, or mixed. The graph is architectural, not decorative: ownership lives in module boundaries, import direction, public contracts, and explicit composition points.
Domain DAG is a graph discipline, not one folder template.
Choose the smallest shape that explains the code. Do not force a layered tree onto a flat extension or flatten a product frontend that has earned route/feature/domain separation.
Each durable responsibility has one owning module or package. Types, constants, helpers, adapters, state, policies, and tests that define a responsibility live with that owner.
A strong boundary says what it does not own. This prevents accumulation of adjacent workflows, transport concerns, persistence policy, UI chrome, or runtime wiring just because the code is nearby.
Local imports must form a DAG. Cycles are architecture bugs because they hide ownership and make change impact non-local.
Entrypoints wire live ports, configuration, adapters, routes, framework lifecycles, queues, and domain runtimes. Domain modules must not import composition roots.
Files or folders named types, constants, utils, helpers, shared, or common are suspect. Use them only when the responsibility is genuinely cross-domain and cannot belong to a more specific owner.
When a module needs another module's behavior, depend on the smallest public contract that expresses the capability. Avoid importing internals, broad mutable runtime state, or sibling orchestration surfaces.
Start with the smallest useful graph. Add layers, public barrels, forbidden edges, header clauses, and custom checks only after real project constraints make them valuable.
A very wide boundary can be as harmful as a wrong dependency. Many callbacks, parameters, exported knobs, or adapter methods are pressure to group related concepts into named contracts, ports, state objects, command objects, or smaller capabilities.
Use these questions when creating or moving code:
cards feature and a cards domain can coexist if one owns the journey and the other owns reusable card capabilities.Before adding or enforcing rules, calibrate the project:
When decomposing or extending a module:
Do not keep decomposing just because a file is large. Stop when:
At this point, switch to review: check for misplaced ownership, too-wide contracts, stale imports, and validator gaps.
types, utils, or constants become the real hidden domain.Run the bundled validator from a project root:
SKILL_DIR=/path/to/domain-dag
bash "${SKILL_DIR}/scripts/validate-domain-dag.sh" --root .
Useful flags:
--root <path> — project root; defaults to the current directory--config <path> — JSON config; defaults to domain-dag.json, then .domain-dag.json--strict — treat warnings as failures--json — machine-readable outputThe validator checks:
Add a project-local domain-dag.json when defaults are too broad or too narrow:
{
"sourceRoots": ["src", "lib"],
"sourceExtensions": [".ts", ".tsx", ".js", ".jsx", ".svelte"],
"entrypoints": ["src/main.ts", "src/app/bootstrap.ts"],
"importAliases": {
"@/*": "src/*",
"$lib/*": "src/lib/*"
},
"requireHeaders": true,
"headerPattern": "\\b(Domain|Domains|Zone|Zones|Owns):\\s*\\S",
"headerSeverity": "warn",
"headerRequiredClauses": ["Owns:", "Excludes:"],
"headerRequiredClausesSeverity": "warn",
"flatRoots": false,
"sharedBucketSeverity": "warn",
"allowedSharedBuckets": ["src/platform/shared/**"],
"surfaceRules": [
{
"name": "wide callback surface",
"files": ["src/features/**"],
"pattern": "\\b(on[A-Z][A-Za-z0-9_]*)\\b",
"max": 15,
"severity": "warn",
"message": "Wide callback surface; group related handlers into contract objects"
}
],
"forbiddenEdges": [
{
"from": "src/domain/**",
"to": "src/app/**",
"severity": "error",
"message": "Domain layer must not import app layer"
}
],
"layers": [
{
"name": "foundation",
"rank": 0,
"files": ["src/platform/**"]
},
{
"name": "domain",
"rank": 1,
"files": ["src/domain/**"]
},
{
"name": "composition",
"rank": 2,
"files": ["src/app/**", "src/main.ts"]
}
]
}
Layer rule: lower ranks must not import higher ranks. Same-rank and downward imports are allowed.
importAliases lets the validator resolve local path aliases such as @/*, $lib/*, or package-internal aliases. Keep aliases project-local; the skill should not assume any particular bundler or language server convention.
Glob support is intentionally small and portable: *, **, and ? are supported, but brace expansion such as src/{a,b}/** is not. Use multiple explicit glob entries or rules instead; the validator warns when configured globs contain unsupported braces.
surfaceRules are intentionally generic: by default they count unique regex matches in selected files, and with metric: "lines" they count file lines. Use them for local pressure signals such as too many callback props, too many exported commands, broad adapter methods, oversized widgets/modules, or other project-specific interface smells. Keep them warnings unless the signal is proven noise-free.
Use severity deliberately:
A mature Domain DAG has few hard rules and good explanations. It does not need many rules to be strong.
scripts/validate-domain-dag.sh with generic defaults.--- DOMAIN DAG VALIDATOR ---, blank line, [INFO] ...; after the last [PASS] / [WARN] / [FAIL], blank line, Result: N error(s), M warning(s). Do not add this spacing inside --json output.A good Domain DAG review asks:
development
High-density memetic-systems cognition mode. Use for extra self, be yourself, give me the base, foundational synthesis, first-principles compression, deep structure, memetic analysis, strong framing, naming, narrative architecture, ideology, culture, protocol dynamics, governance, economics, product strategy, institutional diagnosis, prompt/spec compression, or architecture-first strategic thought.
development
Manage a guarded release flow that commits prepared release work on dev, opens a dev-to-main pull request with a release-focused PR summary, waits for checks, merges on success, tags, and optionally publishes an existing npm package. Use when the user asks to prepare or execute a dev→main release PR, hotfix release PR, or Dev2Main PR Summary workflow.
tools
Build, refactor, review, or debug Svelte 5 components that use Bits UI primitives. Use when working with bits-ui dialogs, popovers, dropdowns, comboboxes, selects, tabs, date/time controls, menus, tooltips, portals, render delegation, or Bits UI type helpers.
development
Evidence-grounded review for code, diffs, PRs, documents, plans, specs, and architecture. Use for evidence review, review, code review, quick review, sanity check, quality check, architecture review, production readiness, security review, scaling review, document review, evaluate, or check.