Agent skill
module-systems
Expert skill for designing module systems including resolution algorithms, import/export mechanisms, visibility control, namespace management, and cyclic dependency handling.
Install this agent skill to your Project
npx add-skill https://github.com/a5c-ai/babysitter/tree/main/library/specializations/programming-languages/skills/module-systems
SKILL.md
Module Systems Skill
Design and implement module systems for programming languages with support for resolution, loading, visibility, and dependency management.
Capabilities
- Design module/import/export syntax
- Implement module resolution algorithms
- Handle cyclic module dependencies
- Implement visibility/access control
- Design namespace management systems
- Support module aliases and re-exports
- Implement lazy/on-demand module loading
- Design package/crate system integration
Usage
Invoke this skill when you need to:
- Design a module system for a new language
- Implement module resolution algorithms
- Handle complex dependency graphs
- Build visibility and access control systems
- Integrate with package managers
Inputs
| Parameter | Type | Required | Description |
|---|---|---|---|
| moduleStyle | string | Yes | Style (es6, commonjs, rust, ml) |
| resolutionStrategy | string | Yes | Resolution (node, rust, python, custom) |
| features | array | No | Features to implement |
| cyclicHandling | string | No | How to handle cycles (error, lazy, tarjan) |
| visibility | object | No | Visibility model configuration |
Feature Options
{
"features": [
"import-export",
"re-exports",
"namespace-aliasing",
"selective-imports",
"default-exports",
"lazy-loading",
"cyclic-detection",
"visibility-control",
"inline-modules",
"package-integration"
]
}
Output Structure
module-system/
├── syntax/
│ ├── import.grammar # Import statement syntax
│ ├── export.grammar # Export statement syntax
│ └── module-decl.grammar # Module declaration syntax
├── resolution/
│ ├── resolver.ts # Main resolution algorithm
│ ├── module-graph.ts # Dependency graph
│ ├── path-resolver.ts # Path resolution
│ └── cache.ts # Module cache
├── loading/
│ ├── loader.ts # Module loader
│ ├── lazy-loader.ts # Lazy loading support
│ └── parallel-loader.ts # Parallel loading
├── visibility/
│ ├── access-control.ts # Visibility checking
│ └── namespace.ts # Namespace management
├── analysis/
│ ├── cycle-detector.ts # Cyclic dependency detection
│ └── dependency-analyzer.ts # Dependency analysis
└── tests/
├── resolution.test.ts
├── cycles.test.ts
└── visibility.test.ts
Module System Types
ES6-Style Modules
// Import syntax
import defaultExport from 'module';
import { named, another as alias } from 'module';
import * as namespace from 'module';
// Export syntax
export const value = 42;
export function func() {}
export default class MyClass {}
export { name, other as renamed };
export * from 'other-module';
// Implementation
interface ESModule {
defaultExport?: any;
namedExports: Map<string, any>;
reExports: ReExport[];
}
interface ImportSpecifier {
type: 'default' | 'named' | 'namespace';
imported: string;
local: string;
}
Rust-Style Modules
// Module declaration
mod my_module; // Load from file
mod inline { ... } // Inline module
// Use statements
use crate::module::Item;
use super::parent::*;
use self::child::Thing;
use external_crate::Something;
// Visibility
pub struct Public;
pub(crate) struct CrateVisible;
pub(super) struct ParentVisible;
struct Private; // default
// Implementation
interface RustModule {
name: string;
path: ModulePath;
visibility: Visibility;
items: Map<string, ModuleItem>;
submodules: Map<string, RustModule>;
}
type Visibility =
| { type: 'private' }
| { type: 'public' }
| { type: 'restricted'; path: ModulePath };
ML-Style Modules
(* Module signature *)
module type STACK = sig
type 'a t
val empty : 'a t
val push : 'a -> 'a t -> 'a t
val pop : 'a t -> ('a * 'a t) option
end
(* Module implementation *)
module ListStack : STACK = struct
type 'a t = 'a list
let empty = []
let push x s = x :: s
let pop = function
| [] -> None
| x :: xs -> Some (x, xs)
end
(* Functor *)
module MakeSet (Ord: ORD) : SET = struct
(* ... implementation using Ord.compare *)
end
Resolution Algorithms
Node.js-Style Resolution
interface NodeResolver {
resolveModule(specifier: string, from: string): string | null;
}
function nodeResolve(specifier: string, fromDir: string): string | null {
// 1. If specifier is a core module, return it
if (isCoreModule(specifier)) return specifier;
// 2. If starts with '/' or './', resolve relative
if (specifier.startsWith('/') || specifier.startsWith('./') ||
specifier.startsWith('../')) {
return resolveRelative(specifier, fromDir);
}
// 3. Otherwise, walk up node_modules
let dir = fromDir;
while (dir !== '/') {
const candidate = path.join(dir, 'node_modules', specifier);
const resolved = resolvePackage(candidate);
if (resolved) return resolved;
dir = path.dirname(dir);
}
return null;
}
function resolvePackage(pkgPath: string): string | null {
// Check package.json exports/main
const pkgJson = readPackageJson(pkgPath);
if (pkgJson?.exports) {
return resolveExports(pkgPath, pkgJson.exports);
}
if (pkgJson?.main) {
return path.join(pkgPath, pkgJson.main);
}
// Default to index.js
return path.join(pkgPath, 'index.js');
}
Rust-Style Resolution
interface RustResolver {
resolveUse(usePath: UsePath, currentModule: ModulePath): ResolvedItem;
}
function rustResolve(usePath: UsePath, current: ModulePath): ResolvedItem {
const [first, ...rest] = usePath.segments;
// Determine starting point
let startModule: RustModule;
if (first === 'crate') {
startModule = getCrateRoot();
} else if (first === 'super') {
startModule = getParentModule(current);
} else if (first === 'self') {
startModule = getCurrentModule(current);
} else if (isExternCrate(first)) {
startModule = getExternCrate(first);
} else {
// Start from current module scope
startModule = getCurrentModule(current);
rest.unshift(first);
}
// Resolve path segments
let currentItem: ModuleItem = startModule;
for (const segment of rest) {
currentItem = resolveSegment(currentItem, segment);
checkVisibility(currentItem, current);
}
return currentItem;
}
Cyclic Dependency Handling
// Tarjan's algorithm for SCC detection
function findCycles(graph: ModuleGraph): ModuleCycle[] {
const index = new Map<Module, number>();
const lowlink = new Map<Module, number>();
const onStack = new Set<Module>();
const stack: Module[] = [];
const sccs: Module[][] = [];
let currentIndex = 0;
function strongconnect(module: Module): void {
index.set(module, currentIndex);
lowlink.set(module, currentIndex);
currentIndex++;
stack.push(module);
onStack.add(module);
for (const dep of module.dependencies) {
if (!index.has(dep)) {
strongconnect(dep);
lowlink.set(module, Math.min(lowlink.get(module)!, lowlink.get(dep)!));
} else if (onStack.has(dep)) {
lowlink.set(module, Math.min(lowlink.get(module)!, index.get(dep)!));
}
}
if (lowlink.get(module) === index.get(module)) {
const scc: Module[] = [];
let w: Module;
do {
w = stack.pop()!;
onStack.delete(w);
scc.push(w);
} while (w !== module);
if (scc.length > 1) {
sccs.push(scc);
}
}
}
for (const module of graph.modules) {
if (!index.has(module)) {
strongconnect(module);
}
}
return sccs.map(modules => ({ modules, edges: findCycleEdges(modules) }));
}
Visibility Control
interface VisibilityChecker {
canAccess(item: ModuleItem, fromModule: ModulePath): boolean;
}
function checkVisibility(
item: ModuleItem,
fromModule: ModulePath,
itemModule: ModulePath
): boolean {
switch (item.visibility.type) {
case 'public':
return true;
case 'private':
return isSameModule(fromModule, itemModule);
case 'crate':
return isSameCrate(fromModule, itemModule);
case 'super':
return isParentOrSame(getParent(itemModule), fromModule);
case 'restricted':
return isDescendantOf(fromModule, item.visibility.path);
default:
return false;
}
}
Lazy Loading
interface LazyModule {
path: string;
loaded: boolean;
exports: Map<string, any> | null;
loading: Promise<void> | null;
}
class LazyModuleLoader {
private modules = new Map<string, LazyModule>();
async import(specifier: string): Promise<any> {
const resolved = this.resolve(specifier);
let module = this.modules.get(resolved);
if (!module) {
module = {
path: resolved,
loaded: false,
exports: null,
loading: null
};
this.modules.set(resolved, module);
}
if (module.loaded) {
return module.exports;
}
if (module.loading) {
await module.loading;
return module.exports;
}
module.loading = this.loadModule(module);
await module.loading;
return module.exports;
}
private async loadModule(module: LazyModule): Promise<void> {
const source = await readFile(module.path);
const compiled = compile(source);
module.exports = await execute(compiled);
module.loaded = true;
}
}
Workflow
- Design module syntax - Import, export, module declarations
- Implement resolution - Path resolution algorithm
- Build dependency graph - Track module dependencies
- Detect cycles - Find and report cyclic dependencies
- Implement visibility - Access control checking
- Add lazy loading - On-demand module loading
- Integrate packages - Package manager support
- Generate tests - Resolution, cycles, visibility
Best Practices Applied
- Clear separation of resolution from loading
- Efficient caching of resolved modules
- Informative cycle detection error messages
- Consistent visibility semantics
- Support for both sync and async loading
- Incremental resolution for IDE support
References
- ES Modules Spec: https://tc39.es/ecma262/#sec-modules
- Node.js Module Resolution: https://nodejs.org/api/modules.html
- Rust Module System: https://doc.rust-lang.org/reference/items/modules.html
- OCaml Module System: https://ocaml.org/docs/modules
Target Processes
- module-system-design.js
- semantic-analysis.js
- interpreter-implementation.js
- lsp-server-implementation.js
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
gsd-tools
Central utility skill for GSD operations. Provides config parsing, slug generation, timestamps, path operations, and orchestrates calls to other specialized skills. Acts as the unified entry point that the original gsd-tools.cjs provided via its lib/ modules (commands, config, core, init).
model-profile-resolution
Resolve model profile (quality/balanced/budget) at orchestration start and map agents to specific models. Enables cost/quality tradeoffs by selecting appropriate AI models for each agent role.
verification-suite
Plan structure validation, phase completeness checks, reference integrity verification, and artifact existence confirmation. Provides the structured verification layer ensuring GSD artifacts are well-formed and complete.
state-management
STATE.md reading, writing, and field-level updates. Provides cross-session state persistence via .planning/STATE.md with structured fields for current task, completed phases, blockers, decisions, and quick tasks.
git-integration
Git commit patterns, formats, and conventions for GSD methodology. Provides atomic commits per task, structured commit messages, planning file commits, branch management, and milestone tag operations.
frontmatter-parsing
YAML frontmatter parsing and manipulation for .planning/ documents. Provides read, write, update, query, and validation operations on frontmatter blocks in GSD markdown artifacts.
Didn't find tool you were looking for?