import { type PackageFileView, type PacklistProvider } from "./packlist.js"; import { type RuntimeAssetDeclaration, type RuntimeFileAssetView } from "./runtime-files.js"; import { type SourceImportView } from "./source-imports.js"; /** * Minimal filesystem surface the analyzer needs. Injected so the CLI can pass * the real `fs/promises` and tests can pass an in-memory `memfs` volume. * `readFile` always returns a UTF-8 string; adapters bind the encoding. */ export interface LintFs { readFile(p: string): Promise; readdir(p: string): Promise<{ name: string; isDirectory(): boolean; }[]>; stat?(p: string): Promise<{ isDirectory(): boolean; isFile(): boolean; }>; listFiles?(p: string): Promise; } export type Ecosystem = "npm" | "pypi"; export type DependencyField = "dependencies" | "peerDependencies" | "optionalDependencies"; export interface PackageInfo { name: string; /** Path relative to the workspace root, posix-style. "." for the root package. */ dir: string; isRoot: boolean; private: boolean; version: string; license: string | undefined; dependencies: Record; peerDependencies: Record; optionalDependencies: Record; /** Names vendored into this package's published tarball (npm `bundledDependencies`). */ bundledDependencies: string[]; /** Workspace packages compiled into this package's published runtime and type entrypoints. */ inlinedDependencies: string[]; repositoryDirectory: string | undefined; ecosystem: Ecosystem; main: string | undefined; exports: unknown; bin: Record; files: string[]; scripts: Record; runtimeAssets: RuntimeAssetDeclaration[]; hasReadme: boolean; } export interface BinTarget { /** Bin name as declared in root `bin`, e.g. "poe-superintendent-mcp". */ bin: string; /** Target path as declared, e.g. "packages/superintendent/dist/mcp.js". */ target: string; /** Owning package dir, e.g. "packages/superintendent". */ dir: string; } export interface RootEntryPoint { kind: "main" | "export" | "bin"; name: string; target: string; } export interface ReleaseWorkflow { /** File name, e.g. "release-toolcraft.yml". */ file: string; /** The workflow `name:` field. */ name: string; /** Package dirs this workflow publishes, posix-style. "." for the root. */ targetDirs: string[]; /** Package groups whose versions and intra-group dependencies are prepared together. */ lockstepGroups: LockstepGroup[]; } export interface LockstepGroup { dirs: string[]; publishedDirs: string[]; valid: boolean; } export interface WorkspaceModel { root: PackageInfo; packages: PackageInfo[]; byName: Map; byDir: Map; releaseWorkflows: ReleaseWorkflow[]; /** Package dirs whose dist reaches the published `poe-code` tarball. */ shippedDirs: Set; binTargets: BinTarget[]; /** Real import graph of each package's `src`, keyed by package dir. */ sourceImports: SourceImportView; /** Runtime imports of root package entrypoints that ship in the root tarball. */ shippedDistImports: SourceImportView; rootEntryPoints: RootEntryPoint[]; /** Runtime file assets discovered from package source, keyed by package dir. */ runtimeFileAssets: RuntimeFileAssetView; /** Files included by each package artifact, keyed by package dir. */ packageFiles: PackageFileView; } export interface BuildView { /** Package dirs whose source got inlined into a bundle. */ inlinedDirs: Set; /** Bare specifiers left external by the bundle, reduced to package names. */ externals: Set; } export interface Violation { rule: string; package: string; severity: "error" | "warning"; via?: string; detail: Record; message: string; /** One-line hint on how to resolve the violation. */ fix: string; } export interface LintResult { summary: { packages: number; rules: number; violations: number; ok: boolean; }; /** Rule ids that ran, in registry order — drives the report's rule list. */ evaluated: string[]; violations: Violation[]; skipped: string[]; } export interface Rule { id: string; /** When true, the rule is skipped (not failed) if no BuildView is available. */ requiresBuild?: boolean; run(model: WorkspaceModel, build?: BuildView): Violation[]; } export declare function loadWorkspace(fs: LintFs, rootDir: string, options?: { packlistProvider?: PacklistProvider; }): Promise; /** Package dirs that some release workflow publishes (so the package reaches npm). */ export declare function releaseTargetDirs(model: WorkspaceModel): Set; /** A package genuinely reaches npm: it is a public npm package a release workflow publishes. */ export declare function isGenuinelyPublished(model: WorkspaceModel, pkg: PackageInfo): boolean; export declare function parseMetafile(meta: { inputs?: Record; outputs?: Record; }): BuildView; export declare function loadBuildView(fs: LintFs, rootDir: string): Promise; /** All workspace packages plus the root package. */ export declare function allPackages(model: WorkspaceModel): PackageInfo[]; export declare function isPublishedNpm(pkg: PackageInfo): boolean; export interface DependencyEdge { name: string; spec: string; field: DependencyField; } export declare function dependencyEdges(pkg: PackageInfo): DependencyEdge[];