/** * Asset discovery orchestrator. * * Walks a directory tree, identifies asset manifests via deterministic * filename matching, parses each manifest, computes file filters, and * extracts the requires graph. * * Zero storage dependencies — reused by LocalCatalogSource (Phase 1) and * the store backend (Phase 2). */ import type { AssetKindFileFilter, IAssetKindRegistry } from "@skaile/workspaces/plugins"; import { AssetKindRegistry } from "./asset-kind-registry.js"; import { type DomainIndexEntry } from "./domains.js"; import { type ReferenceWarning } from "./reference-lint.js"; import { type RequiresEdge, type RequiresGraph } from "./requires-graph.js"; import type { SourceConfig } from "./source-config.js"; export { computeDeterministicHash } from "./hash.js"; /** * How aggressively a discovered asset's byte set is closed over its references. * * - `strict` — structural filter only; uncovered in-dir references are * reported as warnings but NOT pulled in (default). * - `closure` — structural filter + reference closure: in-dir files the asset * textually references are pulled in transitively. * - `full-dir` — capture the entire asset directory (minus nested sub-assets). * * All three are mirrored byte-for-byte by the virtual-tree (store) discovery * path, so store/local SHA256 parity is exact under every policy. * * @docLink packages/discovery/concepts#atomization */ export type AtomizationPolicy = "strict" | "closure" | "full-dir"; /** * Default atomization policy. `strict` keeps the byte set to the structural * filter (never silently bundling referenced-but-uncaptured files); closure and * full-dir are opt-in and expand it. All three hold store/local parity. */ export declare const DEFAULT_ATOMIZATION_POLICY: AtomizationPolicy; /** * A single asset discovered during a {@link discoverAssetsInTree} run, including its parsed * manifest, file filter, deterministic hash, and cross-asset dependency edges. * * @docLink packages/discovery/concepts#discovered-asset */ export interface DiscoveredAsset { /** Canonical ref: `/@`. */ ref: string; /** Asset kind (from registry resolution). */ kind: string; publisher: string; name: string; version: string; /** Parsed manifest (frontmatter for .md, full YAML for .yaml/.json). */ manifest: Record; /** Absolute path to the manifest file. */ manifestPath: string; /** Relative path from source root. */ relativePath: string; /** Files included in this asset's tarball. */ fileFilter: AssetKindFileFilter; /** SHA256 hash of the deterministic tarball content. */ sha256: string; /** Cross-asset dependency edges originating from this asset. */ requires: RequiresEdge[]; /** * Navigational domain slug assigned from a sidecar `DOMAIN.md`, or `undefined` * when no domain claims this asset. Display-only — never part of identity. * * @docLink packages/discovery/concepts#domains */ domainSlug?: string; } export interface DiscoveryOptions { /** Optional source config (adapted from `skaile.manifest.yaml`) for publisher resolution. */ sourceConfig?: SourceConfig; /** * Optional sidecar directory (e.g. `~/.skaile/sources//`) carrying a * local overlay `skaile.manifest.yaml`. When set and `sourceConfig` is * `undefined`, the helper loads the base in-repo config from `rootPath` and * merges the sidecar overlay on top. When both `sourceConfig` and * `sidecarPath` are set, the explicit `sourceConfig` wins (the caller is * responsible for merging). * * @docLink packages/discovery/concepts#sidecar-overlay */ sidecarPath?: string; /** * Explicit overlay manifest FILE path (e.g. the local store's flat * `~/.skaile/store/manifests/.yaml`). When set and `sourceConfig` is * `undefined`, the base config from `rootPath` is merged with this overlay via * {@link loadMergedSourceConfigFromFile}. Takes precedence over `sidecarPath` * (the dir convention) when both are set. * * @docLink packages/discovery/concepts#sidecar-overlay */ sidecarManifestFile?: string; /** * Explicit `DOMAIN.md` descriptors (path relative to the repo root + raw * content). When provided, these are the authoritative domain source and the * in-tree / sidecar `DOMAIN.md` scan is skipped — the store supplies these * from a sidecar repo. Paths resolve against the upstream tree. * * @docLink packages/discovery/concepts#domains */ domainFiles?: Array<{ path: string; content: string; }>; /** Optional kind registry. If omitted, a default registry with all built-in providers is used. */ registry?: IAssetKindRegistry; /** * Include assets under the source config's `dev_paths` prefixes. Defaults to * `false` — a normal run excludes dev-only assets (e.g. `ai-assets-dev/`). * Set by the `--dev` flag on `skaile source sync` / `source add`. * * @docLink packages/discovery/concepts#dev-paths */ includeDev?: boolean; /** * Atomization policy controlling how an asset's byte set is derived from the * structural filter. Defaults to {@link DEFAULT_ATOMIZATION_POLICY}. * * @docLink packages/discovery/concepts#atomization */ atomization?: AtomizationPolicy; } /** * The complete output of a {@link discoverAssetsInTree} scan: all discovered assets, the * full requires graph across those assets, and any non-fatal parse errors encountered. * * @docLink packages/discovery/concepts#discovery-result */ export interface DiscoveryResult { assets: DiscoveredAsset[]; graph: RequiresGraph; errors: Array<{ path: string; error: string; }>; /** * Non-fatal advisories, `{ path, warning }` per entry. Two sources feed this * channel: (1) atomization warnings — an asset reference that points at a real * file/directory inside the asset's own directory yet was dropped by the * structural file filter (see {@link ./reference-lint.ts}); (2) author-shipped * manifest advisories — an unknown asset kind (ghost-install) or a missing * `sha256` (auto-computed locally). Advisory only: identity, hashes, and the * captured byte set are unchanged. * * @docLink packages/discovery/concepts#atomization */ warnings: ReferenceWarning[]; /** * Resolved navigational domains (from sidecar `DOMAIN.md`), ordered for * display. Absent when no `DOMAIN.md` was supplied. * * @docLink packages/discovery/concepts#domains */ domains?: DomainIndexEntry[]; } /** * Create a default AssetKindRegistry with all built-in providers registered. * Used when no registry is passed to discoverAssetsInTree(). */ export declare function createDefaultRegistry(): AssetKindRegistry; /** * Discover all assets in a directory tree. * * Walks `rootPath` recursively, identifies manifests by filename, parses * them, computes file filters and SHA256 hashes, and extracts the * requires graph. * * @param rootPath - Absolute path to the directory tree to scan * @param optionsOrSourceConfig - Discovery options, or a SourceConfig for backward compat * @returns A {@link DiscoveryResult} with all discovered assets, the requires graph, and any parse errors * @docLink packages/discovery/concepts#discover-assets-in-tree */ export declare function discoverAssetsInTree(rootPath: string, optionsOrSourceConfig?: DiscoveryOptions | SourceConfig): DiscoveryResult; //# sourceMappingURL=discover.d.ts.map