import { dirname, resolve } from "node:path"; import { existsSync, readFileSync } from "node:fs"; import { surfacePrefix, surfaceRoot } from "../../../config/surface.config.ts"; import type { TaxonomyData } from "../types/taxonomy.types.ts"; import { taxonomy } from "../../../config/taxonomy.config.ts"; const derivedLetters = function derivedLetters(): string[] { const source = resolve(surfaceRoot(), taxonomy.derivedVariants.source); if (!existsSync(source)) { return []; } const out = new Set(); for (const line of readFileSync(source, "utf8").split("\n")) { if (!line.startsWith("|")) { continue; } const cell = (line.split("|")[1] ?? "").trim(); if (cell.length === 0) { continue; } let letters = true; for (const char of cell) { if ((char < "A" || char > "Z") && (char < "a" || char > "z")) { letters = false; } } if (letters) { out.add(cell.toLowerCase()); } } return [...out]; }; const withinSurface = function withinSurface( declared: Readonly>, ): Record { const prefix = surfacePrefix(); const out: Record = {}; for (const [key, members] of Object.entries(declared)) { if (prefix.length === 0) { out[key] = members; continue; } out[key === "." ? prefix : `${prefix}/${key}`] = members; } return out; }; export const loadTaxonomy = function loadTaxonomy(): TaxonomyData { const folderToTag: Record = {}; const folderToLayer: Record = {}; const concernFolders: string[] = []; const concernTags: string[] = []; for (const entry of taxonomy.concerns) { folderToTag[entry.folder] = entry.tag; folderToLayer[entry.folder] = entry.layer; concernFolders.push(entry.folder); concernTags.push(entry.tag); } return { agentLetters: derivedLetters(), artifactRoots: taxonomy.artifactRoots, boundaryDocuments: taxonomy.boundaryDocuments, compoundMarkers: taxonomy.grammar.compoundMarkers, concernFolders, concernTags, containers: withinSurface(taxonomy.containers), corpusRoots: taxonomy.corpusRoots, folderToLayer, folderToTag, foreignContainers: withinSurface(taxonomy.foreignContainers), foreignGrammar: taxonomy.foreignGrammar, ignored: taxonomy.Ignored.foldersFiles, maxDepthFromRoot: taxonomy.grammar.maxDepthFromRoot, specialContainers: withinSurface(taxonomy.specialContainers), subjects: taxonomy.subjects, variants: taxonomy.variants, verificationMarkers: taxonomy.grammar.verificationMarkers, }; }; export const rootOf = function rootOf(path: string, data: TaxonomyData): string | null { const roots = [...Object.keys(data.containers), ...Object.keys(data.specialContainers)]; let best: string | null = null; for (const root of roots) { if (path === root || path.startsWith(`${root}/`)) { if (best === null || root.length > best.length) { best = root; } } } return best; }; export interface GovernedPath { readonly root: string; readonly segments: readonly string[]; } export const governedPath = function governedPath(path: string, data: TaxonomyData): GovernedPath | null { const root = rootOf(path, data); if (root === null) { return null; } const dir = dirname(path); const tail = dir === root ? "" : dir.slice(root.length + 1); return { root, segments: tail.length === 0 ? [] : tail.split("/") }; };