UNPKG

socraticode

Version:

SocratiCode — MCP server for local codebase indexing, semantic search, and code dependency graphs. All private, all local via Docker.

117 lines • 6.04 kB
/** * What `createIgnoreFilter` answers with: one question, on a path relative to * the project root and written with forward slashes. * * Two kinds of rule stand behind it. Patterns — the defaults, `.gitignore` * files and `.socraticodeignore` — are gitignore syntax and go to the `ignore` * package. The environments the walk *discovers* are not patterns, they are * directories that exist, and they are kept as the literal prefixes they are. * Writing one as a pattern meant escaping it, and the escape is only as good as * the package's reading of it: `\?` is not understood by the installed * version, so an environment at `env?/` was scanned despite its marker * (review finding), while `\[`, `\*`, `\!`, `\#` and `\\` happened to work. * A prefix compare has no syntax to get wrong. * * The one thing the pattern route allowed that a bare prefix would not: a * negation written later — `!tests/fixtures/sample-venv/**` in * `.socraticodeignore`, for a checked-in fixture that any tool parsing * `pyvenv.cfg` has — re-included the environment. That precedence is kept * (review finding): a path an explicit negation claims is not excluded by a * discovered prefix either. `unignored` is what the package answers exactly * when a negative rule spoke last and no positive one stands over it. */ export interface IgnoreFilter { /** Whether the path, relative to the project root, is excluded. */ ignores(relativePath: string): boolean; /** * Whether the path, with or without its trailing slash, is the root of an * environment the walk discovered. The watcher asks this of a directory * event, since an environment moved away arrives as one event on the * directory and nothing on the marker inside it. */ isEnvironmentRoot(relativePath: string): boolean; /** * The ignore files this filter read, project-relative and in the order they * were applied, each with the bytes it was built from. * * A filter's answers are read off the tree once, when it is built, so * anything caching a walk this filter shaped has to know which files to * watch — the code graph records them as build inputs. The content comes * with the path rather than being read again by the caller: a second read * would both cost a second pass and leave a window in which the file changes * between the two, recording a state the walk never actually ran under. * Reported from where they are read, so a new source cannot be added without * appearing here. */ sources: IgnoreSource[]; /** * The environment roots the walk discovered, each as `dir/` relative to the * project root. * * Reported for the same reason as {@link IgnoreFilter.sources}: they are an * input to what this filter answers, and unlike the ignore files they are * not files at all — a directory is an environment because of a marker * *inside* it, somewhere nothing that reads the tree will ever look again. * A caller caching a walk has to watch them, or a `pyvenv.cfg` deleted * re-admits a whole subtree with nothing observable having changed. */ environments: string[]; } /** One ignore file a filter was built from. */ export interface IgnoreSource { /** Project-relative, forward-slashed. */ path: string; /** The bytes the filter was built from. */ content: string; } /** * Build an ignore filter for a project directory. * * Combines (in order): * 1. Built-in defaults (node_modules, .git, dist, build, lock files, etc.) * 2. .gitignore files (root + nested) — unless RESPECT_GITIGNORE=false * 3. Python and conda environments found by their markers, as literal prefixes * 4. .socraticodeignore — optional project-specific exclusions * * Set env RESPECT_GITIGNORE=false to skip .gitignore processing entirely. * * The two status lines below log at debug, not info: context-artifact reads * build a filter per artifact on every staleness check, so an info line here * would fire once per artifact per context search. */ export declare function createIgnoreFilter(projectPath: string): IgnoreFilter; /** * Whether a change at this path can change what the filter answers: it is one * of the environment markers the walk looks for, or lies inside one. * * The rules a filter carries are read off the tree once, when it is built, and * an environment is recognised by a file or directory that may appear or * vanish while the tree is being watched. A watcher that ran every event * through its filter first never saw either: a new `pyvenv.cfg` is not an * indexable file, and the one being deleted sits under a directory the stale * filter still excludes (review finding). The name is enough here — the event * only schedules a reconciliation, and the rebuilt filter reads the shape. * `conda-meta` is matched as any segment, since the directory's creation * arrives with the files inside it. */ export declare function isEnvironmentMarker(relativePath: string): boolean; /** * Whether the directory is an environment: it carries a marker, in the shape * its tool writes it. Two markers, because two tools build these directories — * `pyvenv.cfg` for a PEP 405 virtualenv, `conda-meta/` for a conda * environment. Both hold installed libraries and neither is source. * * The shape matters. Merely existing is not enough: a source directory holding * a file named `conda-meta` would otherwise disappear whole, and a discarded * source file costs far more than a kept one. * * Shared with the watcher, which asks it of a directory that has just * appeared: an environment moved into place arrives as one event on the * directory, and nothing on the marker inside it. */ export declare function isEnvironmentDirectory(dirPath: string): boolean; /** * Check if a relative path should be ignored. */ export declare function shouldIgnore(ig: IgnoreFilter, relativePath: string): boolean; //# sourceMappingURL=ignore.d.ts.map