@chrisdudek/yg 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bin.ts","../src/cli/init.ts","../src/templates/default-config.ts","../src/templates/platform.ts","../src/templates/rules.ts","../src/core/migrator.ts","../src/migrations/to-2.0.0.ts","../src/migrations/index.ts","../src/core/graph-loader.ts","../src/io/config-parser.ts","../src/io/node-parser.ts","../src/io/aspect-parser.ts","../src/io/artifact-reader.ts","../src/io/flow-parser.ts","../src/io/schema-parser.ts","../src/utils/paths.ts","../src/core/context-builder.ts","../src/utils/tokens.ts","../src/core/validator.ts","../src/formatters/context-text.ts","../src/cli/build-context.ts","../src/cli/validate.ts","../src/cli/drift.ts","../src/io/drift-state-store.ts","../src/utils/hash.ts","../src/core/context-files.ts","../src/core/drift-detector.ts","../src/cli/drift-sync.ts","../src/cli/status.ts","../src/cli/tree.ts","../src/cli/owner.ts","../src/core/dependency-resolver.ts","../src/cli/deps.ts","../src/core/graph-from-git.ts","../src/cli/impact.ts","../src/cli/aspects.ts","../src/cli/flows.ts","../src/cli/preflight.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { registerInitCommand } from './cli/init.js';\nimport { registerBuildCommand } from './cli/build-context.js';\nimport { registerValidateCommand } from './cli/validate.js';\nimport { registerDriftCommand } from './cli/drift.js';\nimport { registerDriftSyncCommand } from './cli/drift-sync.js';\nimport { registerStatusCommand } from './cli/status.js';\nimport { registerTreeCommand } from './cli/tree.js';\nimport { registerOwnerCommand } from './cli/owner.js';\nimport { registerDepsCommand } from './cli/deps.js';\nimport { registerImpactCommand } from './cli/impact.js';\nimport { registerAspectsCommand } from './cli/aspects.js';\nimport { registerFlowsCommand } from './cli/flows.js';\nimport { registerPreflightCommand } from './cli/preflight.js';\nimport { readFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { dirname, join } from 'node:path';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));\n\nconst program = new Command();\n\nprogram\n .name('yg')\n .description('Yggdrasil — architectural knowledge infrastructure for AI agents')\n .version(pkg.version);\n\nregisterInitCommand(program);\nregisterBuildCommand(program);\nregisterValidateCommand(program);\nregisterDriftCommand(program);\nregisterDriftSyncCommand(program);\nregisterStatusCommand(program);\nregisterTreeCommand(program);\nregisterOwnerCommand(program);\nregisterDepsCommand(program);\nregisterImpactCommand(program);\nregisterAspectsCommand(program);\nregisterFlowsCommand(program);\nregisterPreflightCommand(program);\n\nprogram.parse();\n","import { Command } from 'commander';\nimport { mkdir, writeFile, readdir, readFile, stat } from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { readFileSync } from 'node:fs';\nimport { gt, valid } from 'semver';\nimport { DEFAULT_CONFIG } from '../templates/default-config.js';\nimport { installRulesForPlatform, PLATFORMS, type Platform } from '../templates/platform.js';\nimport { detectVersion, runMigrations } from '../core/migrator.js';\nimport { MIGRATIONS } from '../migrations/index.js';\n\nfunction getGraphSchemasDir(): string {\n const currentDir = path.dirname(fileURLToPath(import.meta.url));\n const packageRoot = path.join(currentDir, '..');\n return path.join(packageRoot, 'graph-schemas');\n}\n\nfunction getCliVersion(): string {\n const currentDir = path.dirname(fileURLToPath(import.meta.url));\n const packageRoot = path.join(currentDir, '..');\n const pkg = JSON.parse(readFileSync(path.join(packageRoot, 'package.json'), 'utf-8')) as {\n version: string;\n };\n return pkg.version;\n}\n\nasync function refreshSchemas(yggRoot: string): Promise<void> {\n const schemasDir = path.join(yggRoot, 'schemas');\n await mkdir(schemasDir, { recursive: true });\n const graphSchemasDir = getGraphSchemasDir();\n try {\n const entries = await readdir(graphSchemasDir, { withFileTypes: true });\n const schemaFiles = entries.filter((e) => e.isFile()).map((e) => e.name);\n for (const file of schemaFiles) {\n const srcPath = path.join(graphSchemasDir, file);\n const content = await readFile(srcPath, 'utf-8');\n await writeFile(path.join(schemasDir, file), content, 'utf-8');\n }\n } catch {\n // Ignore schema copy errors\n }\n}\n\nconst GITIGNORE_CONTENT = ``;\n\nexport function registerInitCommand(program: Command): void {\n program\n .command('init')\n .description('Initialize Yggdrasil graph in current project')\n .option(\n '--platform <name>',\n 'Agent platform: cursor, claude-code, copilot, cline, roocode, codex, windsurf, aider, gemini, amp, generic',\n 'generic',\n )\n .option('--upgrade', 'Refresh rules only (when .yggdrasil/ already exists)')\n .action(async (options: { platform?: string; upgrade?: boolean }) => {\n const projectRoot = process.cwd();\n const yggRoot = path.join(projectRoot, '.yggdrasil');\n\n let upgradeMode = false;\n try {\n const statResult = await stat(yggRoot);\n if (!statResult.isDirectory()) {\n process.stderr.write('Error: .yggdrasil exists but is not a directory.\\n');\n process.exit(1);\n }\n if (options.upgrade) {\n upgradeMode = true;\n } else {\n process.stderr.write(\n 'Error: .yggdrasil/ already exists. Use --upgrade to refresh rules only.\\n',\n );\n process.exit(1);\n }\n } catch {\n // Directory does not exist — proceed with full init\n }\n\n const platform = (options.platform ?? 'generic') as Platform;\n if (!PLATFORMS.includes(platform)) {\n process.stderr.write(\n `Error: Unknown platform '${platform}'. Use: ${PLATFORMS.join(', ')}\\n`,\n );\n process.exit(1);\n }\n\n if (upgradeMode) {\n const projectVersion = await detectVersion(yggRoot);\n\n if (!projectVersion) {\n process.stderr.write('Error: No Yggdrasil project found. Run `yg init` first.\\n');\n process.exit(1);\n }\n\n const cliVersion = getCliVersion();\n\n // Warn if project is newer than CLI\n if (valid(projectVersion) && valid(cliVersion) && gt(projectVersion, cliVersion)) {\n process.stderr.write(\n `Warning: Project version (${projectVersion}) is newer than CLI (${cliVersion}). Upgrade your CLI.\\n`,\n );\n process.exit(1);\n }\n\n // Run migrations if project is older than CLI\n if (valid(projectVersion) && valid(cliVersion) && gt(cliVersion, projectVersion)) {\n process.stdout.write(`Migrating from ${projectVersion} to ${cliVersion}...\\n\\n`);\n const results = await runMigrations(projectVersion, MIGRATIONS, yggRoot);\n for (const result of results) {\n for (const action of result.actions) {\n process.stdout.write(` ✓ ${action}\\n`);\n }\n for (const warning of result.warnings) {\n process.stdout.write(` ⚠ ${warning}\\n`);\n }\n }\n if (results.length > 0) {\n process.stdout.write('\\n');\n }\n }\n\n // Refresh schemas (copy latest schema files)\n await refreshSchemas(yggRoot);\n\n // Refresh rules\n const rulesPath = await installRulesForPlatform(projectRoot, platform);\n process.stdout.write('✓ Rules refreshed.\\n');\n process.stdout.write(` ${path.relative(projectRoot, rulesPath)}\\n`);\n return;\n }\n\n await mkdir(path.join(yggRoot, 'model'), { recursive: true });\n await mkdir(path.join(yggRoot, 'aspects'), { recursive: true });\n await mkdir(path.join(yggRoot, 'flows'), { recursive: true });\n const schemasDir = path.join(yggRoot, 'schemas');\n await mkdir(schemasDir, { recursive: true });\n\n const graphSchemasDir = getGraphSchemasDir();\n try {\n const entries = await readdir(graphSchemasDir, { withFileTypes: true });\n const schemaFiles = entries.filter((e) => e.isFile()).map((e) => e.name);\n for (const file of schemaFiles) {\n const srcPath = path.join(graphSchemasDir, file);\n const content = await readFile(srcPath, 'utf-8');\n await writeFile(path.join(schemasDir, file), content, 'utf-8');\n }\n } catch (err) {\n process.stderr.write(\n `Warning: Could not copy graph schemas from ${graphSchemasDir}: ${(err as Error).message}\\n`,\n );\n }\n\n await writeFile(path.join(yggRoot, 'yg-config.yaml'), DEFAULT_CONFIG, 'utf-8');\n await writeFile(path.join(yggRoot, '.gitignore'), GITIGNORE_CONTENT, 'utf-8');\n\n const rulesPath = await installRulesForPlatform(projectRoot, platform);\n\n process.stdout.write('✓ Yggdrasil initialized.\\n\\n');\n process.stdout.write('Created:\\n');\n process.stdout.write(' .yggdrasil/yg-config.yaml\\n');\n process.stdout.write(' .yggdrasil/.gitignore\\n');\n process.stdout.write(' .yggdrasil/model/\\n');\n process.stdout.write(' .yggdrasil/aspects/\\n');\n process.stdout.write(' .yggdrasil/flows/\\n');\n process.stdout.write(' .yggdrasil/schemas/ (yg-config, yg-node, yg-aspect, yg-flow)\\n');\n process.stdout.write(` ${path.relative(projectRoot, rulesPath)} (rules)\\n\\n`);\n process.stdout.write('Next steps:\\n');\n process.stdout.write(' 1. Edit .yggdrasil/yg-config.yaml — set name and configure node types\\n');\n process.stdout.write(' 2. Create nodes under .yggdrasil/model/\\n');\n process.stdout.write(' 3. Run: yg validate\\n');\n });\n}\n","export const DEFAULT_CONFIG = `version: \"2.0.0\"\n\nname: \"\"\n\nnode_types:\n module:\n description: \"Business logic unit with clear domain responsibility\"\n service:\n description: \"Component providing functionality to other nodes\"\n library:\n description: \"Shared utility code with no domain knowledge\"\n infrastructure:\n description: \"Guards, middleware, interceptors — invisible in call graphs but affect blast radius\"\n\nartifacts:\n responsibility.md:\n required: always\n description: \"What this node is responsible for, and what it is not\"\n included_in_relations: true\n interface.md:\n required:\n when: has_incoming_relations\n description: \"Public API — methods, parameters, return types, contracts, failure modes, exposed data structures\"\n included_in_relations: true\n internals.md:\n required: never\n description: \"How the node works and why — algorithms, business rules, state machines, design decisions with rejected alternatives\"\n\nquality:\n min_artifact_length: 50\n max_direct_relations: 10\n context_budget:\n warning: 10000\n error: 20000\n`;\n","import { readFile, writeFile, mkdir } from 'node:fs/promises';\nimport path from 'node:path';\nimport { AGENT_RULES_CONTENT } from './rules.js';\n\nconst AGENT_RULES_IMPORT = '@.yggdrasil/agent-rules.md';\nconst YGGDRASIL_START = '<!-- yggdrasil:start -->';\nconst YGGDRASIL_END = '<!-- yggdrasil:end -->';\nconst YGGDRASIL_SECTION = `## Yggdrasil\\n\\n${AGENT_RULES_CONTENT}`;\nconst YGGDRASIL_BLOCK = `${YGGDRASIL_START}\\n${YGGDRASIL_SECTION}\\n${YGGDRASIL_END}`;\n\nexport type Platform =\n | 'cursor'\n | 'claude-code'\n | 'copilot'\n | 'cline'\n | 'roocode'\n | 'codex'\n | 'windsurf'\n | 'aider'\n | 'gemini'\n | 'amp'\n | 'generic';\n\nexport const PLATFORMS: Platform[] = [\n 'cursor',\n 'claude-code',\n 'copilot',\n 'cline',\n 'roocode',\n 'codex',\n 'windsurf',\n 'aider',\n 'gemini',\n 'amp',\n 'generic',\n];\n\nexport async function installRulesForPlatform(\n projectRoot: string,\n platform: Platform,\n): Promise<string> {\n const agentRulesPath = path.join(projectRoot, '.yggdrasil', 'agent-rules.md');\n\n switch (platform) {\n case 'cursor':\n return installForCursor(projectRoot);\n case 'claude-code':\n return installForClaudeCode(projectRoot, agentRulesPath);\n case 'copilot':\n return installForCopilot(projectRoot);\n case 'cline':\n return installForCline(projectRoot);\n case 'roocode':\n return installForRooCode(projectRoot);\n case 'codex':\n return installForCodex(projectRoot);\n case 'windsurf':\n return installForWindsurf(projectRoot);\n case 'aider':\n return installForAider(projectRoot, agentRulesPath);\n case 'gemini':\n return installForGemini(projectRoot, agentRulesPath);\n case 'amp':\n return installForAmp(projectRoot, agentRulesPath);\n case 'generic':\n default:\n return installForGeneric(projectRoot);\n }\n}\n\nasync function ensureAgentRules(agentRulesPath: string): Promise<void> {\n await mkdir(path.dirname(agentRulesPath), { recursive: true });\n await writeFile(agentRulesPath, AGENT_RULES_CONTENT, 'utf-8');\n}\n\nasync function installForCursor(projectRoot: string): Promise<string> {\n const dir = path.join(projectRoot, '.cursor', 'rules');\n await mkdir(dir, { recursive: true });\n const filePath = path.join(dir, 'yggdrasil.mdc');\n const content = `---\ndescription: Yggdrasil — semantic memory of the repository\nalwaysApply: true\n---\n\n${AGENT_RULES_CONTENT}`;\n await writeFile(filePath, content, 'utf-8');\n return filePath;\n}\n\nasync function installForClaudeCode(projectRoot: string, agentRulesPath: string): Promise<string> {\n await ensureAgentRules(agentRulesPath);\n const filePath = path.join(projectRoot, 'CLAUDE.md');\n let existing = '';\n try {\n existing = await readFile(filePath, 'utf-8');\n } catch {\n /* file doesn't exist */\n }\n const importLine = AGENT_RULES_IMPORT;\n if (existing.includes(importLine)) {\n return agentRulesPath;\n }\n const content = existing.trimEnd() ? `${existing.trimEnd()}\\n${importLine}\\n` : `${importLine}\\n`;\n await writeFile(filePath, content, 'utf-8');\n return agentRulesPath;\n}\n\nasync function installForCopilot(projectRoot: string): Promise<string> {\n const dir = path.join(projectRoot, '.github');\n await mkdir(dir, { recursive: true });\n const filePath = path.join(dir, 'copilot-instructions.md');\n let existing = '';\n try {\n existing = await readFile(filePath, 'utf-8');\n } catch {\n /* file doesn't exist */\n }\n let content: string;\n if (existing.includes(YGGDRASIL_START) && existing.includes(YGGDRASIL_END)) {\n content = existing.replace(\n new RegExp(`${escapeRegex(YGGDRASIL_START)}[\\\\s\\\\S]*?${escapeRegex(YGGDRASIL_END)}`, 'g'),\n YGGDRASIL_BLOCK,\n );\n } else {\n content = existing.trimEnd()\n ? `${existing.trimEnd()}\\n\\n${YGGDRASIL_BLOCK}\\n`\n : `${YGGDRASIL_BLOCK}\\n`;\n }\n await writeFile(filePath, content, 'utf-8');\n return filePath;\n}\n\nasync function installForCline(projectRoot: string): Promise<string> {\n const dir = path.join(projectRoot, '.clinerules');\n await mkdir(dir, { recursive: true });\n const filePath = path.join(dir, 'yggdrasil.md');\n await writeFile(filePath, AGENT_RULES_CONTENT, 'utf-8');\n return filePath;\n}\n\nasync function installForRooCode(projectRoot: string): Promise<string> {\n const dir = path.join(projectRoot, '.roo', 'rules');\n await mkdir(dir, { recursive: true });\n const filePath = path.join(dir, 'yggdrasil.md');\n await writeFile(filePath, AGENT_RULES_CONTENT, 'utf-8');\n return filePath;\n}\n\nasync function installForCodex(projectRoot: string): Promise<string> {\n const filePath = path.join(projectRoot, 'AGENTS.md');\n let existing = '';\n try {\n existing = await readFile(filePath, 'utf-8');\n } catch {\n /* file doesn't exist */\n }\n let content: string;\n if (existing.includes(YGGDRASIL_START) && existing.includes(YGGDRASIL_END)) {\n content = existing.replace(\n new RegExp(`${escapeRegex(YGGDRASIL_START)}[\\\\s\\\\S]*?${escapeRegex(YGGDRASIL_END)}`, 'g'),\n YGGDRASIL_BLOCK,\n );\n } else {\n content = existing.trimEnd()\n ? `${existing.trimEnd()}\\n\\n${YGGDRASIL_BLOCK}\\n`\n : `${YGGDRASIL_BLOCK}\\n`;\n }\n await writeFile(filePath, content, 'utf-8');\n return filePath;\n}\n\nasync function installForWindsurf(projectRoot: string): Promise<string> {\n const dir = path.join(projectRoot, '.windsurf', 'rules');\n await mkdir(dir, { recursive: true });\n const filePath = path.join(dir, 'yggdrasil.md');\n await writeFile(filePath, AGENT_RULES_CONTENT, 'utf-8');\n return filePath;\n}\n\nasync function installForAider(projectRoot: string, agentRulesPath: string): Promise<string> {\n await ensureAgentRules(agentRulesPath);\n const filePath = path.join(projectRoot, '.aider.conf.yml');\n const entry = '.yggdrasil/agent-rules.md';\n let existing = '';\n try {\n existing = await readFile(filePath, 'utf-8');\n } catch {\n /* file doesn't exist */\n }\n if (existing.includes(entry)) {\n return agentRulesPath;\n }\n const content = appendAiderReadEntry(existing, entry);\n await writeFile(filePath, content, 'utf-8');\n return agentRulesPath;\n}\n\nfunction appendAiderReadEntry(existing: string, entry: string): string {\n const newItem = ` - ${entry} # added by yg init\\n`;\n const readBlock = /^read:\\s*\\n((?:\\s+-\\s+[^\\n]+\\n)*)/m;\n const match = existing.match(readBlock);\n if (match) {\n return existing.replace(match[0], `read:\\n${match[1]}${newItem}`);\n }\n const readEmpty = /^read:\\s*$/m;\n if (readEmpty.test(existing)) {\n return existing.replace(readEmpty, `read:\\n${newItem}`);\n }\n const trimmed = existing.trimEnd();\n return trimmed ? `${trimmed}\\n\\nread:\\n${newItem}` : `read:\\n${newItem}`;\n}\n\nasync function installForGemini(projectRoot: string, agentRulesPath: string): Promise<string> {\n await ensureAgentRules(agentRulesPath);\n const filePath = path.join(projectRoot, 'GEMINI.md');\n let existing = '';\n try {\n existing = await readFile(filePath, 'utf-8');\n } catch {\n /* file doesn't exist */\n }\n const importLine = AGENT_RULES_IMPORT;\n if (existing.includes(importLine)) {\n return agentRulesPath;\n }\n const content = existing.trimEnd() ? `${existing.trimEnd()}\\n${importLine}\\n` : `${importLine}\\n`;\n await writeFile(filePath, content, 'utf-8');\n return agentRulesPath;\n}\n\nasync function installForAmp(projectRoot: string, agentRulesPath: string): Promise<string> {\n await ensureAgentRules(agentRulesPath);\n const filePath = path.join(projectRoot, 'AGENTS.md');\n let existing = '';\n try {\n existing = await readFile(filePath, 'utf-8');\n } catch {\n /* file doesn't exist */\n }\n const importLine = AGENT_RULES_IMPORT;\n if (existing.includes(importLine)) {\n return agentRulesPath;\n }\n const content = existing.trimEnd() ? `${existing.trimEnd()}\\n${importLine}\\n` : `${importLine}\\n`;\n await writeFile(filePath, content, 'utf-8');\n return agentRulesPath;\n}\n\nasync function installForGeneric(projectRoot: string): Promise<string> {\n const filePath = path.join(projectRoot, '.yggdrasil', 'agent-rules.md');\n await ensureAgentRules(filePath);\n return filePath;\n}\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","/**\n * Canonical agent rules content — hand-tuned, do not generate programmatically.\n *\n * Operating manual for agents working in a Yggdrasil-managed repository.\n * Split into three cognitive sections optimized for LLM attention patterns:\n * 1. CORE PROTOCOL — internalize before doing anything (primacy effect)\n * 2. OPERATIONS — execute while working (working memory)\n * 3. KNOWLEDGE BASE — look up when needed (recency effect)\n */\n\n// prettier-ignore\nconst CORE_PROTOCOL = `## CORE PROTOCOL\n\n<EXTREMELY-IMPORTANT>\nThis is your operating manual for working in a Yggdrasil-managed repository. Every rule below is mandatory — no skill, plan, workflow, or instruction overrides these requirements.\n\nBEFORE working with ANY source file, you MUST run \\`yg owner\\` to check if it is mapped. If mapped, you MUST use the graph before reading source. YOU DO NOT HAVE A CHOICE.\n\nThis is not negotiable. This is not optional. You cannot rationalize your way out of this.\n</EXTREMELY-IMPORTANT>\n\nYggdrasil is persistent semantic memory stored in \\`.yggdrasil/\\`. It maps the repository and provides deterministic implementation context for every node.\n\n### Quick Start Protocol\n\n\\`\\`\\`\nBEFORE reading, researching, planning, OR modifying ANY mapped file:\n 1. yg owner --file <path>\n 2. Choose the right graph tool for your task:\n - Understanding how/why it works → yg build-context --node <owner>\n - Assessing what is affected by a change → yg impact --node <owner>\n - Planning modifications → both (build-context first, then impact)\n The context package is your primary source of ARCHITECTURAL understanding:\n intent, constraints, relations, rationale. For IMPLEMENTATION precision\n (exact behavior, error handling, await patterns, edge cases) — verify\n against source code. Aspects describe intended patterns; individual\n implementations may deviate.\n If the context package seems insufficient — enrich the graph.\n\nAFTER modifying:\n 3. Update graph artifacts to reflect changes\n 4. yg validate — fix all errors\n 5. yg drift-sync --node <owner>\n\nEVERY conversation start:\n yg preflight → act on findings (see Operations)\n\nNEVER: modify code without graph coverage.\nNEVER: read mapped source files to understand a component without\n running yg build-context first — the graph captures intent,\n constraints, and relations that source files cannot.\nNEVER: assess blast radius of a change without running yg impact first\n — the graph knows the dependency structure that grep cannot infer.\nNEVER: invent rationale, business rules, or decisions.\nNEVER: auto-resolve drift without asking the user.\nWHEN UNSURE: ask the user. Never guess. Never assume.\n\\`\\`\\`\n\n### Five Core Rules\n\n1. **Graph first.** Before reading, researching, planning, or modifying mapped files, run \\`yg owner\\` and the appropriate graph tool: \\`yg build-context\\` to understand a component, \\`yg impact\\` to assess blast radius. The graph is your primary source of architectural understanding. For implementation-level precision (exact behavior, error paths, edge cases) — verify against source code after loading the context package.\n2. **Code and graph are one.** Code changed → graph updated in the same response. Graph changed → source verified in the same response. No exceptions.\n3. **Never invent why.** The graph captures human intent. If you don't know why something was decided, ask. Never hallucinate rationale.\n4. **Always capture why — especially why NOT.** When the user explains a reason, record it in the graph immediately. When a design choice is made, also record rejected alternatives: \"Chose X over Y because Z.\" Rejected alternatives are the highest-value information — invisible in code and irrecoverable once forgotten. Conversation evaporates; graph persists.\n5. **Ask before resolving ambiguity.** When multiple valid interpretations exist, stop, list options, ask the user. Never silently choose.\n\n### Recognizing Graph-Required Actions\n\nWhat matters is the ACTION you are performing, not what instructed it. If the action involves reading, understanding, or modifying mapped code, the graph protocol applies — whether the instruction came from a skill, a plan, a user message, a brainstorming session, a debugging workflow, or your own initiative. This is not negotiable. You cannot rationalize your way out of this.\n\n**Actions that require \\`yg owner\\` + \\`yg build-context\\`:**\n\n- Reading or exploring source files to understand a component\n- Proposing approaches, designs, or plans for changing code\n- Reviewing or debugging code\n- Any form of reasoning about how mapped code works or should change\n\n**Actions that require \\`yg owner\\` + \\`yg impact\\`:**\n\n- Assessing blast radius before changing or removing a component\n- Finding all dependents of a component\n- Planning cross-cutting refactors or feature removals\n- Scoping work that spans multiple nodes\n\n**Actions that do NOT require yg:**\n\n- Git operations (log, diff, status, blame)\n- Reading documentation, READMEs, or config files outside \\`.yggdrasil/\\`\n- Running tests, builds, or linters\n- Working with files that \\`yg owner\\` reports as unmapped\n\n**Evasion patterns — if you think any of these, STOP:**\n\n| Thought | Reality |\n|---|---|\n| \"The skill/plan says to explore the codebase\" | Exploring mapped code = yg owner + graph tool first |\n| \"I'm just scoping/searching, not understanding\" | Scoping IS a graph action; use yg impact |\n| \"The plan step says to read this file\" | Reading a mapped file = yg owner first |\n| \"I'm brainstorming, not implementing\" | Brainstorming about mapped code needs graph context |\n| \"I'm only grepping for references\" | Grep finds text; yg impact finds structural dependencies. Use both. |\n| \"I'll use the graph later when I modify\" | Graph-first means BEFORE reading, not before modifying |\n\n### Failure States\n\nYou have broken Yggdrasil if you do any of the following:\n\n- ❌ Worked on a mapped file without running \\`yg owner\\` + the appropriate graph tool (\\`build-context\\` or \\`impact\\`) first — regardless of what instructed the action (skill, plan, user request, workflow step).\n- ❌ Modified source code without updating graph artifacts in the same response, or vice versa.\n- ❌ Resolved a code-graph inconsistency or ambiguity without asking the user first.\n- ❌ Created or edited a graph element without reading its schema in \\`schemas/\\` first.\n- ❌ Ran \\`yg drift-sync\\` before both graph artifacts and source code are current.\n- ❌ Placed a cross-cutting requirement in a local artifact instead of an aspect, or used an aspect id with no \\`aspects/\\` directory.\n- ❌ Invented a rationale, business rule, or decision — or recorded a decision without documenting rejected alternatives and rationale (use \"rationale: unknown\" if unknown).\n- ❌ Used blackbox coverage for greenfield (new) code.\n\n### Escape Hatch\n\nIf the user explicitly requests a code-only change, comply but:\n\n- Warn: \"This creates drift. Run \\`yg drift\\` next session to reconcile.\"\n- Do NOT run \\`yg drift-sync\\` — leave the drift visible.\n\n### Environment Check\n\nBefore preflight:\n\n- Verify \\`yg\\` CLI is available. If not found, inform user and stop.\n- If \\`yg preflight\\` shows 0 nodes → enter BOOTSTRAP MODE (see Operations).\n- If drift report shows >10 drifted nodes → report scope to user, ask which area to prioritize. Do not resolve all at once.\n\n### Delegating to Subagents\n\nWhen you delegate work to a subagent (any subprocess, tool agent, or spawned assistant), the subagent does NOT inherit your Yggdrasil knowledge. Before any other instruction, the subagent MUST:\n\n1. Read \\`.yggdrasil/agent-rules.md\\` — this is the complete operating manual\n2. Follow the Quick Start Protocol from that file before touching any mapped code\n\nInclude this as the FIRST instruction in every subagent prompt:\n\n\\`\\`\\`\nBEFORE doing anything else: read .yggdrasil/agent-rules.md and follow its protocol.\n\\`\\`\\`\n\nA subagent that skips this step will read code without graph context, miss architectural constraints, and produce changes that break graph-code consistency.`;\n\n// prettier-ignore\nconst OPERATIONS = `## OPERATIONS\n\n### Conversation Lifecycle\n\n\\`\\`\\`\nPREFLIGHT (every conversation, before any work):\n - [ ] 1. yg preflight → read unified report\n - [ ] 2. If drift: resolve per Drift Resolution, then yg drift-sync per node\n - [ ] 3. If validation errors: fix, re-run yg validate\n Exception: read-only requests (explain, analyze) — skip preflight.\n\nUNDERSTANDING mapped code (questions, research, OR planning):\n - [ ] 1. yg owner --file <path>\n - [ ] 2. Owner found → yg build-context --node <path>. Use context package as primary source.\n - [ ] 3. Owner not found → use file analysis, state it is not graph-backed.\n Never use grep or raw file reads as primary understanding when graph coverage exists.\n Raw reads supplement the context package — they do not replace it.\n\nWRAP-UP (user signals \"done\", \"wrap up\", \"that's enough\"):\n - [ ] 1. yg drift --drifted-only → resolve\n - [ ] 2. yg validate → fix errors\n - [ ] 3. Report: which nodes and files were changed\n\nBEFORE ENDING ANY RESPONSE (self-audit):\n - [ ] Did I interact with mapped code (read, research, or modify)? If yes → did I use a graph tool BEFORE reading source?\n - [ ] Did I modify source code? If yes → did I update graph artifacts in this same response?\n - [ ] If you broke either rule, you have broken the protocol. Do not finish until both are fixed.\n\\`\\`\\`\n\n### Modify Source Code\n\nYou are not allowed to edit or create source code without establishing graph coverage first.\n\n**Step 1** — Check coverage: \\`yg owner --file <path>\\`\n\n**Step 2a** — Owner found: execute checklist:\n\n- [ ] 1. Read specification: \\`yg build-context --node <node_path>\\`\n- [ ] 2. Assess blast radius: \\`yg impact --node <node_path>\\` — review dependents, descendants, and co-aspect nodes before changing interfaces or shared behavior\n- [ ] 3. Modify source code\n- [ ] 4. Sync graph artifacts — edit artifact files to reflect the changes\n- [ ] 5. Run \\`yg validate\\` — fix all errors (if unfixable after 3 attempts → stop, report to user)\n- [ ] 6. Run \\`yg drift-sync --node <node_path>\\` — only after graph and code are both current\n\n**Step 2b** — Owner not found: establish coverage first. Present options to the user:\n\n*Partially mapped* (file unmapped but inside a mapped module): ask whether to add to existing node or create new one.\n\n*Existing code:*\n\n- Option A — Full node: create node(s), map files, write artifacts from code analysis\n- Option B — Blackbox: create a blackbox node at agreed granularity\n- Option C — Abort\n\n*Greenfield (new code):* Only Option A. Blackbox is forbidden for new code. Follow the graph-first workflow:\n\n1. Create aspects first (cross-cutting requirements the new code must satisfy)\n2. Create flows if the code participates in a business process\n3. Create nodes with full artifacts — responsibility, interface, internals\n4. Review the context package (\\`yg build-context\\`) — it is now the behavioral specification\n5. Implement code that satisfies the specification\n6. The graph specifies WHAT and WHY; the code implements HOW (framework APIs, library choices)\n\nAfter the user chooses, return to Step 1 and follow Step 2a.\n\n### Modify Graph\n\n- [ ] 1. Read the relevant schema from \\`schemas/\\` before touching any YAML\n- [ ] 2. Before changing an aspect or flow, check scope: \\`yg impact --aspect <id>\\` or \\`yg impact --flow <name>\\` — understand which nodes are affected before modifying shared rules or processes\n- [ ] 3. Make changes\n- [ ] 4. Run \\`yg validate\\` immediately — fix all errors\n- [ ] 5. Verify affected source files are consistent — update if needed\n- [ ] 6. Run \\`yg drift-sync\\` for affected nodes\n\n### Reverse Engineering\n\n**Order:** aspects (cross-cutting patterns) → flows (business processes) → model nodes. Never create nodes before aspects and flows are understood.\n\nPer area checklist:\n\n- [ ] 1. \\`yg owner --file <path>\\` — confirm no coverage\n- [ ] 2. Determine node granularity — propose to user if unclear\n- [ ] 3. Create node directory, read \\`schemas/yg-node.yaml\\`, create \\`yg-node.yaml\\`\n- [ ] 4. Analyze source — for each artifact type in \\`yg-config.yaml artifacts\\`: extract content, do not invent\n- [ ] 5. Identify relations — add to \\`yg-node.yaml\\`\n- [ ] 6. Identify cross-cutting requirements — add matching aspects, create if needed\n- [ ] 6b. For each aspect on the node: identify 2-5 code anchors (function names, constants) that evidence the pattern → add as \\`anchors\\` in the aspect entry in \\`yg-node.yaml\\`\n- [ ] 7. Identify business process participation — add to flow, ask user if process unclear\n- [ ] 8. \\`yg validate\\` — fix errors\n- [ ] 9. \\`yg drift-sync --node <path>\\`\n\n**When to ask:**\n\n- Business process unclear: \"This code appears to be part of a larger process. Can you describe what it means from a business perspective?\"\n- Constraint without rationale: \"I see [constraint X]. Do you know why this exists? I want to record the reason, not just the rule.\"\n- Unexplained architectural choice: \"I see [approach X]. What was the reason for this choice?\"\n- Decision without alternatives: \"You chose [X]. What alternatives did you consider, and why did you reject them?\" Record the answer in the Decisions section of \\`internals.md\\`.\n- Decision without known rationale: Record the decision in \\`internals.md\\` with \"rationale: unknown — inferred from code, not confirmed by developer.\" A recorded decision with unknown rationale is infinitely more valuable than no record at all, and safer than an invented rationale.\n\n### Bootstrap Mode\n\nTrigger: \\`yg preflight\\` shows 0 nodes, or no nodes cover the active work area.\n\n- [ ] 1. Identify the active work area (files the user wants to modify)\n- [ ] 2. Scan for cross-cutting patterns → create aspects\n- [ ] 3. Ask user about business processes → create flows if applicable\n- [ ] 4. Propose node structure for the area\n- [ ] 5. Create node(s) with initial artifacts, map files\n- [ ] 6. \\`yg validate\\`, \\`yg drift-sync\\`\n- [ ] 7. Proceed with user's original request\n\nConstraint: Do NOT map the entire repository. Focus on the active area. Expand incrementally.\n\n### Drift Resolution\n\nAlways ask the user before resolving drift. Never auto-resolve.\n\n- **Source drift** (source files changed) → update graph artifacts to match source, then \\`yg drift-sync\\`\n- **Graph drift** (graph artifacts changed) → review affected source, update if needed, then \\`yg drift-sync\\`\n- **Full drift** (both changed) → present both sides to user, ask which direction wins\n- **Missing** → ask: re-materialize or remove mapping?\n- **Unmaterialized** → ask user how to proceed\n\nThreshold: >10 drifted nodes → ask user which area to prioritize. Do not resolve all at once.\n\n**Drift triage:** Prioritize aspects and \\`internals.md\\` (highest decay rate), then \\`responsibility.md\\` and \\`interface.md\\` (most stable).\n\n### Graph Audit\n\nWhen reviewing graph quality (triggered by user or quality improvement):\n\n**Step 1 — Consistency** (catches WRONG information):\n\n- [ ] 1. \\`yg build-context --node <path>\\`\n- [ ] 2. Read mapped source files\n- [ ] 3. For each claim in graph: verify against source code\n- [ ] 4. For each aspect: verify the pattern holds in THIS node. If it deviates, add \\`exceptions\\` to the aspect entry in \\`yg-node.yaml\\`\n- [ ] 5. Report inconsistencies\n\n**Step 2 — Completeness** (catches MISSING information):\n\n- [ ] 1. For each public method: is it in \\`interface.md\\`?\n- [ ] 2. For each error path: is it in \\`interface.md\\` (Failure Modes section)?\n- [ ] 3. For each behavioral invariant: is it in the graph?\n- [ ] 4. Report omissions separately from inconsistencies\n\n### Error Recovery\n\n- **\\`yg\\` not found** → inform user: \"yg CLI is not installed or not in PATH.\" Stop.\n- **Unfixable validate errors** → if not resolved after 3 attempts, stop and report to user. Do not loop.\n- **Budget exceeded** → if \\`yg build-context\\` exits with error (context package exceeds budget), warn user: \"This node should be split.\" Do not proceed with implementation.\n- **Corrupted \\`.yggdrasil/\\` files** → report to user. Do not attempt repair.\n- **Incremental sync** → run \\`yg drift-sync\\` every 3-5 source files during multi-file tasks. Do not defer to end.`;\n\n// prettier-ignore\nconst KNOWLEDGE_BASE = `## KNOWLEDGE BASE\n\n### Graph Structure\n\n\\`\\`\\`\n.yggdrasil/\n yg-config.yaml ← version, vocabulary, node types, artifact rules, required aspects\n model/ ← what exists: nodes, hierarchy, relations, file mappings\n aspects/ ← what must: cross-cutting requirements with rationale and guidance\n flows/ ← why and in what process: business processes with node participation\n schemas/ ← YAML schemas — read before creating any graph element\n .drift-state/ ← generated by CLI; never edit manually\n\\`\\`\\`\n\nKey facts:\n\n- **Hierarchy:** nodes nest in \\`model/\\`. Children inherit parent context. Do not repeat parent content in children.\n- **Aspect id = directory path** under \\`aspects/\\`. Each aspect has \\`yg-aspect.yaml\\` + content \\`.md\\` files. No automatic parent-child — use \\`implies\\` explicitly.\n- **Flows = business processes.** A flow describes what happens in the world, not code sequences. Flow aspects propagate to all participants.\n\n**Node type guidance:** Each type in \\`yg-config.yaml node_types\\` has a \\`description\\` that tells you when to use it. Check the project's config for the full list and descriptions. Common types: \\`module\\` (business logic), \\`service\\` (providing functionality), \\`library\\` (shared utilities), \\`infrastructure\\` (guards, middleware, interceptors — invisible in call graphs but affect blast radius).\n\n### Artifact Structure\n\nThree artifacts capture node knowledge at three levels:\n\n- **responsibility.md** (always required) — WHAT: identity, boundaries, what the node is NOT responsible for.\n- **interface.md** (required when node has consumers) — HOW TO USE: public methods, parameters, return types, contracts, failure modes, exposed data structures. Everything another node needs to interact with this one.\n- **internals.md** (optional, highest value for cross-module nodes) — HOW IT WORKS + WHY: algorithms, control flow, business rules, invariants, state machines, lifecycle, and design decisions with rejected alternatives. Use sections within the file: ## Logic, ## Constraints, ## State, ## Decisions (with \"Chose X over Y because Z\" format).\n\n**Enrichment priority (when adding incrementally):** \\`interface.md\\` first (highest cross-module ROI — contracts enable other nodes to reason about interactions), then \\`responsibility.md\\` (identity and boundaries), then \\`internals.md\\` (depth for complex nodes). A node with only \\`interface.md\\` provides more cross-module value than one with only \\`internals.md\\`.\n\nProjects can define additional artifact types in \\`yg-config.yaml\\` under \\`artifacts\\`. Each custom artifact has a \\`description\\` (tells you what to write), a \\`required\\` condition (\\`always\\`, \\`never\\`, \\`when: has_incoming_relations\\`, \\`when: has_aspect:<id>\\`), and an \\`included_in_relations\\` flag (if true, included in dependency context packages for structural relations). The three standard artifacts are always present in config. Check \\`yg-config.yaml\\` to see all defined artifacts for the project.\n\n### Context Assembly\n\nRun \\`yg build-context --node <path>\\` to get the deterministic context package for a node. The package assembles global project identity, hierarchy, own artifacts, aspects, and relational context. It is your architectural map. For implementation-level claims (exact call patterns, error handling, await vs fire-and-forget) — verify against source code. If the package is insufficient, enrich the graph.\n\n### Information Routing\n\nWhen you encounter information, route it to the correct location:\n\n- **Specific to this node** → local node artifact (check \\`yg-config.yaml artifacts\\` for available types)\n- **Rule for many nodes** → aspect (\\`aspects/<id>/\\` with \\`yg-aspect.yaml\\` + content \\`.md\\` files). If applies to ALL nodes of a type → \\`node_types.<type>.required_aspects\\` in \\`yg-config.yaml\\`\n- **Business process** → flow (\\`flows/<name>/\\` with \\`yg-flow.yaml\\` + \\`description.md\\`). Ask user if process unclear.\n- **Shared across a domain** → parent node artifact. Children receive it through hierarchy.\n- **Technology stack or standard** → node artifact at the appropriate hierarchy level (e.g., root node's \\`responsibility.md\\` for single-stack repos, or deployment unit node for monorepos)\n- **Decision (why + why NOT):** one node → Decisions section of \\`internals.md\\` with format \"Chose X over Y because Z\"; category of nodes → aspect content files; tech choice → node artifact at the level where the technology applies. Always include rejected alternatives — they are the highest-value graph content. If the rationale is unknown: record the decision with \"rationale: unknown\" and note what CAN be observed from the code. Never invent a plausible-sounding rationale.\n\n### Creating Aspects\n\n- [ ] 1. Read \\`schemas/yg-aspect.yaml\\`\n- [ ] 2. Create \\`aspects/<id>/\\` directory\n- [ ] 3. Write \\`yg-aspect.yaml\\` — name, optional description, optional implies\n- [ ] 4. Write content \\`.md\\` files: WHAT must be satisfied + WHY (user's words, do not invent)\n- [ ] 5. \\`yg validate\\`\n\nTest: \"Does this requirement apply to more than one node?\" Yes → aspect. No → local artifact.\n\n**Aspect identification heuristic:** If the same pattern, constraint, or rule appears in 3+ places, it is a candidate aspect. Aspects fall into natural categories:\n\n- **Domain-specific:** Business rules that cross module boundaries (e.g., timezone handling, booking periods, currency rounding)\n- **Architectural:** Structural patterns with rationale (e.g., dual-rollback on provider failure, idempotency via key generation, fire-and-forget dispatch)\n- **Concurrency:** Shared concurrency strategies (e.g., pessimistic locking, retry-on-deadlock, optimistic versioning)\n\nWhen a node follows an aspect's pattern with exceptions, record them in the \\`exceptions\\` field of the aspect entry in \\`yg-node.yaml\\`. Example: aspect says \"fire-and-forget\" but this node awaits the publish call — add \\`exceptions: [\"awaits publish call instead of fire-and-forget because...\"]\\`. Exceptions appear in the context package next to the aspect content, preventing abstractions from masking implementation details.\n\n**Aspect lifecycle warning.** Aspects decay CATASTROPHICALLY — a pattern either exists or it doesn't. When a pattern changes, ALL aspect claims become wrong at once. This differs from other artifacts: \\`interface.md\\` and \\`responsibility.md\\` are most stable (~9-year half-life); \\`internals.md\\` has moderate stability (~2.5-year half-life); aspects are least stable (~2.4-year half-life, binary decay). After any significant feature addition, review ALL aspects touching the affected area. Don't wait for drift — aspects can be 100% wrong without any mapped file changing.\n\n**Aspect stability tiers.** If an aspect has a \\`stability\\` field in \\`yg-aspect.yaml\\`, use it to calibrate review urgency:\n\n- \\`schema\\` — enforced by data model; review only when data model changes (most stable)\n- \\`protocol\\` — contractual pattern; review when contracts or interfaces change\n- \\`implementation\\` — specific mechanism; review after ANY significant code change (least stable)\n\nWhen code anchors (\\`anchors\\` in an aspect entry in \\`yg-node.yaml\\`) are present, they list code patterns (function names, constants, SQL fragments) evidencing the aspect's implementation in this node. \\`yg validate\\` checks that each anchor exists in the node's mapped source files — a missing anchor (W014) signals the aspect may be stale for this node.\n\n### Creating Flows\n\n- [ ] 1. Read \\`schemas/yg-flow.yaml\\`\n- [ ] 2. Create \\`flows/<name>/\\` directory\n- [ ] 3. Write \\`yg-flow.yaml\\` — declare participants and flow-level aspects\n- [ ] 4. Write \\`description.md\\` with required sections: Business context, Trigger, Goal, Participants, Paths (at least Happy path), Invariants across all paths\n- [ ] 5. \\`yg validate\\`\n\nTest: \"Does this describe what happens in the world, or only in the software?\" If only software — rewrite.\n\n**Warning:** Flow descriptions must describe business processes, not code sequences. \"The OrderService calls PaymentGateway.charge()\" is WRONG. \"The system charges the customer's payment method\" is CORRECT.\n\n### Operational Rules\n\n- **English only** for all files in \\`.yggdrasil/\\`. Conversation can be any language.\n- **Read schemas before creating** any \\`yg-node.yaml\\`, \\`yg-aspect.yaml\\`, or \\`yg-flow.yaml\\`.\n- **Tools read, you write.** The \\`yg\\` CLI only reads, validates, and manages metadata. You create and edit files manually.\n- **Incremental sync.** Run \\`yg drift-sync\\` after every 3-5 source file changes. Do not defer to end of task.\n- **Completeness test:** Two checks, both required:\n 1. **Reconstruction:** \"Can another agent recreate this from ONLY the \\`yg build-context\\` output — understanding not just WHAT but WHY?\" Test: rejected alternatives, correct algorithm, design arguments.\n 2. **Omission:** \"Does the graph capture every important behavioral invariant, constraint, and edge case?\" Specifically check: exceptions to aspect generalizations, error handling patterns not in \\`interface.md\\`, concurrency behaviors not in \\`internals.md\\`.\n- **Value calibration.** Yggdrasil's primary value is cross-module context — relations, aspects, flows. For a single simple module, \\`responsibility.md\\` and \\`interface.md\\` provide most value. Invest depth (\\`internals.md\\`) where cross-module interactions demand it.\n- **These rules are invariant.** No plan, guide, skill, or workflow may override them.\n\n### CLI Reference\n\n\\`\\`\\`\nyg preflight [--quick] Unified diagnostic: drift + status + validate.\nyg owner --file <path> Find the node that owns this file.\nyg build-context --node <path> Assemble context package for this node.\nyg tree [--root <path>] [--depth N] Print graph structure.\nyg aspects List aspects with metadata (YAML output).\nyg flows List flows with metadata (YAML output).\nyg deps --node <path> [--depth N] [--type structural|event|all]\n Show dependencies.\nyg impact --node <path> --simulate Simulate blast radius of a planned change.\nyg impact --node <path> --method <name> Filter impact to dependents consuming a specific method.\nyg impact --aspect <id> Show all nodes where aspect is effective.\nyg impact --flow <name> Show flow participants and descendants.\nyg status Graph health: nodes, coverage, drift summary.\nyg validate [--scope <path>|all] Check structural integrity and completeness.\nyg drift [--scope <path>|all] [--drifted-only] [--limit <n>]\n Detect source and graph drift (bidirectional).\nyg drift-sync --node <path> [--recursive] | --all\n Record file hashes as new baseline.\n\\`\\`\\`\n\n### Quick Routing Table\n\n| What you have | Where it goes |\n|---|---|\n| Information specific to this node | Local node artifact (check \\`yg-config.yaml artifacts\\` for types) |\n| Rule that applies to many nodes | Aspect (content \\`.md\\` files in \\`aspects/<id>/\\`) |\n| Architectural invariant for a node type | Required aspect in \\`yg-config.yaml node_types\\` |\n| Business process participation | Flow (\\`yg-flow.yaml participants\\`) |\n| Process-level requirement | Flow \\`aspects\\` + aspect directory |\n| Context shared across a domain | Parent node artifact |\n| Technology stack | Node artifact at appropriate hierarchy level |\n| Coding standards | Node artifact at appropriate hierarchy level |`;\n\nexport const AGENT_RULES_CONTENT = [CORE_PROTOCOL, OPERATIONS, KNOWLEDGE_BASE].join('\\n\\n---\\n\\n') + '\\n';\n","import { readFile, access } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport { gt, valid, compare } from 'semver';\n\nexport interface Migration {\n to: string;\n description: string;\n run(yggRoot: string): Promise<MigrationResult>;\n}\n\nexport interface MigrationResult {\n actions: string[];\n warnings: string[];\n}\n\n/**\n * Detect the Yggdrasil version of a project.\n * Returns semver string, '1.4.3' for pre-version projects, or null if no config found.\n * Version field validation is intentionally deferred to the migration runner, not the config parser,\n * since migrating old configs is exactly the purpose of this module.\n */\nexport async function detectVersion(yggRoot: string): Promise<string | null> {\n // Try yg-config.yaml first\n const newConfigPath = path.join(yggRoot, 'yg-config.yaml');\n try {\n const content = await readFile(newConfigPath, 'utf-8');\n const raw = parseYaml(content) as Record<string, unknown>;\n if (raw && typeof raw === 'object' && typeof raw.version === 'string') {\n return raw.version.trim();\n }\n return '1.4.3'; // yg-config.yaml exists but no version field → pre-2.0.0\n } catch {\n // yg-config.yaml not found\n }\n\n // Try old config.yaml (1.x format)\n const oldConfigPath = path.join(yggRoot, 'config.yaml');\n try {\n await access(oldConfigPath);\n return '1.4.3';\n } catch {\n return null;\n }\n}\n\n/**\n * Run all applicable migrations sequentially.\n * A migration is applicable when its target version is strictly greater than currentVersion.\n * Migrations are sorted by target version ascending before running.\n */\nexport async function runMigrations(\n currentVersion: string,\n migrations: Migration[],\n yggRoot: string,\n): Promise<MigrationResult[]> {\n const cVer = valid(currentVersion);\n if (!cVer) return [];\n\n const applicable = migrations\n .filter((m) => {\n const mVer = valid(m.to);\n if (!mVer) return false;\n return gt(mVer, cVer);\n })\n .sort((a, b) => compare(valid(a.to)!, valid(b.to)!));\n\n const results: MigrationResult[] = [];\n for (const migration of applicable) {\n const result = await migration.run(yggRoot);\n results.push(result);\n }\n return results;\n}\n","import { readFile, writeFile, rename, readdir, rm, stat } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse as parseYaml, stringify as stringifyYaml } from 'yaml';\nimport type { MigrationResult } from '../core/migrator.js';\n\nconst KNOWN_TYPE_DESCRIPTIONS: Record<string, string> = {\n module: 'Business logic unit with clear domain responsibility',\n service: 'Component providing functionality to other nodes',\n library: 'Shared utility code with no domain knowledge',\n infrastructure: 'Guards, middleware, interceptors — invisible in call graphs but affect blast radius',\n};\n\nconst STANDARD_ARTIFACTS = {\n 'responsibility.md': {\n required: 'always' as const,\n description: 'What this node is responsible for, and what it is not',\n included_in_relations: true,\n },\n 'interface.md': {\n required: { when: 'has_incoming_relations' },\n description: 'Public API — methods, parameters, return types, contracts, failure modes, exposed data structures',\n included_in_relations: true,\n },\n 'internals.md': {\n required: 'never' as const,\n description: 'How the node works and why — algorithms, business rules, state machines, design decisions with rejected alternatives',\n },\n};\n\nexport async function migrateTo2(yggRoot: string): Promise<MigrationResult> {\n const actions: string[] = [];\n const warnings: string[] = [];\n\n // Step 1: Read and rename config (idempotent: fallback to yg-config.yaml if already renamed)\n const oldConfigPath = path.join(yggRoot, 'config.yaml');\n const newConfigPath = path.join(yggRoot, 'yg-config.yaml');\n let configContent: string;\n\n const oldConfigExists = await fileExists(oldConfigPath);\n if (oldConfigExists) {\n configContent = await readFile(oldConfigPath, 'utf-8');\n await rename(oldConfigPath, newConfigPath);\n actions.push('Renamed config.yaml → yg-config.yaml');\n } else {\n // Already renamed (idempotent)\n configContent = await readFile(newConfigPath, 'utf-8');\n }\n\n const raw = parseYaml(configContent) as Record<string, unknown>;\n\n // Step 2: Transform node_types\n const nodeTypesRaw = raw.node_types;\n const nodeTypes: Record<string, { description: string; required_aspects?: string[] }> = {};\n\n if (Array.isArray(nodeTypesRaw)) {\n for (const typeName of nodeTypesRaw) {\n if (typeof typeName === 'string') {\n const desc = KNOWN_TYPE_DESCRIPTIONS[typeName];\n if (desc) {\n nodeTypes[typeName] = { description: desc };\n } else {\n nodeTypes[typeName] = { description: 'TODO: add description' };\n warnings.push(`Unknown node type '${typeName}' — needs a description`);\n }\n }\n }\n actions.push('Converted node_types from array to object format');\n } else if (nodeTypesRaw && typeof nodeTypesRaw === 'object') {\n for (const [name, val] of Object.entries(nodeTypesRaw as Record<string, unknown>)) {\n const entry = val as Record<string, unknown>;\n const desc = KNOWN_TYPE_DESCRIPTIONS[name] ?? (typeof entry?.description === 'string' ? entry.description : 'TODO: add description');\n nodeTypes[name] = { description: desc };\n if (entry?.required_aspects) {\n nodeTypes[name].required_aspects = entry.required_aspects as string[];\n }\n if (!KNOWN_TYPE_DESCRIPTIONS[name] && (!entry?.description || entry.description === 'TODO: add description')) {\n warnings.push(`Unknown node type '${name}' — needs a description`);\n }\n }\n }\n\n // Add infrastructure if missing\n if (!nodeTypes.infrastructure) {\n nodeTypes.infrastructure = { description: KNOWN_TYPE_DESCRIPTIONS.infrastructure };\n actions.push('Added infrastructure node type');\n }\n\n // Step 3: Migrate stack/standards to root node internals.md (idempotent: checks for existing section)\n const stackRaw = raw.stack as Record<string, string> | undefined;\n const standardsRaw = raw.standards as string | undefined;\n\n if (stackRaw || standardsRaw) {\n await migrateStackStandards(yggRoot, stackRaw, standardsRaw, actions);\n }\n\n // Step 4: Write new config (always overwrite — idempotent since output is deterministic)\n const newConfig: Record<string, unknown> = {\n version: '2.0.0',\n name: raw.name,\n node_types: nodeTypes,\n artifacts: STANDARD_ARTIFACTS,\n };\n if (raw.quality) {\n newConfig.quality = raw.quality;\n }\n await writeFile(newConfigPath, stringifyYaml(newConfig, { lineWidth: 120 }), 'utf-8');\n actions.push('Updated config: version, artifacts, removed stack/standards');\n\n // Step 5: Rename and transform model files\n const modelDir = path.join(yggRoot, 'model');\n if (await fileExists(modelDir)) {\n // Rename must happen before transform — transformNodeFiles only processes yg-node.yaml\n await renameFilesRecursively(modelDir, 'node.yaml', 'yg-node.yaml', actions);\n await transformNodeFiles(modelDir, actions, warnings);\n }\n\n // Step 6: Rename aspect files\n const aspectsDir = path.join(yggRoot, 'aspects');\n if (await fileExists(aspectsDir)) {\n await renameFilesRecursively(aspectsDir, 'aspect.yaml', 'yg-aspect.yaml', actions);\n }\n\n // Step 7: Rename flow files\n const flowsDir = path.join(yggRoot, 'flows');\n if (await fileExists(flowsDir)) {\n await renameFilesRecursively(flowsDir, 'flow.yaml', 'yg-flow.yaml', actions);\n }\n\n // Step 8: Rename schema files (idempotent: skip if source missing or destination exists)\n const schemasDir = path.join(yggRoot, 'schemas');\n if (await fileExists(schemasDir)) {\n for (const name of ['config.yaml', 'node.yaml', 'aspect.yaml', 'flow.yaml']) {\n const oldPath = path.join(schemasDir, name);\n const newPath = path.join(schemasDir, `yg-${name}`);\n if ((await fileExists(oldPath)) && !(await fileExists(newPath))) {\n await rename(oldPath, newPath);\n actions.push(`Renamed schemas/${name} → yg-${name}`);\n }\n }\n }\n\n // Step 9: Delete drift state (idempotent: silently skip if already gone)\n const driftStatePath = path.join(yggRoot, '.drift-state');\n if (await fileExists(driftStatePath)) {\n await rm(driftStatePath);\n actions.push('Deleted .drift-state (requires fresh yg drift-sync --all)');\n }\n\n return { actions, warnings };\n}\n\nasync function fileExists(p: string): Promise<boolean> {\n try { await stat(p); return true; } catch { return false; }\n}\n\nasync function migrateStackStandards(\n yggRoot: string,\n stack: Record<string, string> | undefined,\n standards: string | undefined,\n actions: string[],\n): Promise<void> {\n const modelDir = path.join(yggRoot, 'model');\n if (!(await fileExists(modelDir))) return;\n\n const lines: string[] = [];\n if (stack && Object.keys(stack).length > 0) {\n lines.push('## Technology Stack');\n lines.push('');\n for (const [key, value] of Object.entries(stack)) {\n lines.push(`- **${key}:** ${value}`);\n }\n lines.push('');\n }\n if (standards) {\n lines.push('## Standards');\n lines.push('');\n lines.push(standards);\n lines.push('');\n }\n\n if (lines.length === 0) return;\n\n // Check if root node exists; create if not\n const rootNodeYgPath = path.join(modelDir, 'yg-node.yaml');\n const rootNodeOldPath = path.join(modelDir, 'node.yaml');\n const hasRootNode = (await fileExists(rootNodeYgPath)) || (await fileExists(rootNodeOldPath));\n\n if (!hasRootNode) {\n await writeFile(rootNodeYgPath, stringifyYaml({ name: 'Root', type: 'module' }), 'utf-8');\n await writeFile(path.join(modelDir, 'responsibility.md'), 'TBD\\n', 'utf-8');\n actions.push('Created root node in model/ for stack/standards migration');\n }\n\n // Write internals.md — idempotent: skip if marker already present\n const internalsPath = path.join(modelDir, 'internals.md');\n const existingInternals = (await fileExists(internalsPath)) ? await readFile(internalsPath, 'utf-8') : '';\n\n // Unique HTML comment marker — invisible in rendered Markdown, never false-triggers\n const MIGRATION_MARKER = '<!-- migrated-stack-standards-v2 -->';\n if (existingInternals.includes(MIGRATION_MARKER)) {\n return;\n }\n const markerLine = MIGRATION_MARKER + '\\n';\n const newContent = existingInternals\n ? existingInternals.trimEnd() + '\\n\\n' + markerLine + lines.join('\\n')\n : markerLine + lines.join('\\n');\n await writeFile(internalsPath, newContent, 'utf-8');\n actions.push('Migrated stack/standards to model/internals.md');\n}\n\nasync function renameFilesRecursively(\n dir: string,\n oldName: string,\n newName: string,\n actions: string[],\n): Promise<void> {\n let entries;\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n await renameFilesRecursively(fullPath, oldName, newName, actions);\n } else if (entry.name === oldName) {\n const destPath = path.join(dir, newName);\n // Idempotent: skip if destination already exists (previous run)\n if (!(await fileExists(destPath))) {\n await rename(fullPath, destPath);\n actions.push(`Renamed ${oldName} → ${newName} in ${dir}`);\n }\n }\n }\n}\n\nasync function transformNodeFiles(dir: string, actions: string[], warnings: string[]): Promise<void> {\n let entries;\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n await transformNodeFiles(fullPath, actions, warnings);\n } else if (entry.name === 'yg-node.yaml') {\n await transformSingleNode(fullPath, actions, warnings);\n }\n }\n}\n\nasync function transformSingleNode(filePath: string, actions: string[], warnings: string[]): Promise<void> {\n const content = await readFile(filePath, 'utf-8');\n const raw = parseYaml(content) as Record<string, unknown>;\n if (!raw || typeof raw !== 'object') {\n warnings.push(`Skipped ${filePath}: not a valid YAML object`);\n return;\n }\n\n let changed = false;\n\n // Convert aspects from string array to object array (idempotent: check first element type)\n if (Array.isArray(raw.aspects) && raw.aspects.length > 0 && typeof raw.aspects[0] === 'string') {\n const aspectExceptions = (raw.aspect_exceptions ?? {}) as Record<string, string[]>;\n const anchors = (raw.anchors ?? {}) as Record<string, string[]>;\n\n raw.aspects = (raw.aspects as string[]).map((id) => {\n const entry: Record<string, unknown> = { aspect: id };\n if (aspectExceptions[id]) entry.exceptions = aspectExceptions[id];\n if (anchors[id]) entry.anchors = anchors[id];\n return entry;\n });\n\n delete raw.aspect_exceptions;\n delete raw.anchors;\n changed = true;\n }\n\n // Remove tags (idempotent: only if present)\n if (raw.tags !== undefined) {\n delete raw.tags;\n changed = true;\n }\n\n if (changed) {\n await writeFile(filePath, stringifyYaml(raw, { lineWidth: 120 }), 'utf-8');\n actions.push(`Transformed ${path.basename(path.dirname(filePath))}/yg-node.yaml`);\n }\n}\n","import type { Migration } from '../core/migrator.js';\nimport { migrateTo2 } from './to-2.0.0.js';\n\nexport const MIGRATIONS: Migration[] = [\n {\n to: '2.0.0',\n description: 'Rename YAML files to yg-* prefix, restructure config, convert aspects format',\n run: migrateTo2,\n },\n];\n","import { readdir, readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type {\n Graph,\n GraphNode,\n AspectDef,\n FlowDef,\n SchemaDef,\n YggConfig,\n} from '../model/types.js';\nimport { parseConfig } from '../io/config-parser.js';\nimport { parseNodeYaml } from '../io/node-parser.js';\nimport { parseAspect } from '../io/aspect-parser.js';\nimport { parseFlow } from '../io/flow-parser.js';\nimport { parseSchema } from '../io/schema-parser.js';\nimport { readArtifacts } from '../io/artifact-reader.js';\nimport { findYggRoot } from '../utils/paths.js';\n\nfunction toModelPath(absolutePath: string, modelDir: string): string {\n return path.relative(modelDir, absolutePath).split(path.sep).join('/');\n}\n\nconst FALLBACK_CONFIG: YggConfig = {\n name: '',\n node_types: {},\n artifacts: {},\n};\n\nexport async function loadGraph(\n projectRoot: string,\n options: { tolerateInvalidConfig?: boolean } = {},\n): Promise<Graph> {\n const yggRoot = await findYggRoot(projectRoot);\n let configError: string | undefined;\n let config = FALLBACK_CONFIG;\n try {\n config = await parseConfig(path.join(yggRoot, 'yg-config.yaml'));\n } catch (error) {\n if (!options.tolerateInvalidConfig) {\n throw error;\n }\n configError = (error as Error).message;\n }\n\n const modelDir = path.join(yggRoot, 'model');\n const nodes = new Map<string, GraphNode>();\n const nodeParseErrors: Array<{ nodePath: string; message: string }> = [];\n const artifactFilenames = Object.keys(config.artifacts ?? {});\n try {\n await scanModelDirectory(modelDir, modelDir, null, nodes, nodeParseErrors, artifactFilenames);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new Error(`Directory .yggdrasil/model/ does not exist. Run 'yg init' first.`, {\n cause: err,\n });\n }\n throw err;\n }\n\n const aspects = await loadAspects(path.join(yggRoot, 'aspects'));\n const flows = await loadFlows(path.join(yggRoot, 'flows'));\n const schemas = await loadSchemas(path.join(yggRoot, 'schemas'));\n\n return {\n config,\n configError,\n nodeParseErrors: nodeParseErrors.length > 0 ? nodeParseErrors : undefined,\n nodes,\n aspects,\n flows,\n schemas,\n rootPath: yggRoot,\n };\n}\n\nasync function scanModelDirectory(\n dirPath: string,\n modelDir: string,\n parent: GraphNode | null,\n nodes: Map<string, GraphNode>,\n nodeParseErrors: Array<{ nodePath: string; message: string }>,\n artifactFilenames: string[],\n): Promise<void> {\n const entries = await readdir(dirPath, { withFileTypes: true });\n const hasNodeYaml = entries.some((e) => e.isFile() && e.name === 'yg-node.yaml');\n\n if (!hasNodeYaml && dirPath !== modelDir) {\n return;\n }\n\n if (hasNodeYaml) {\n const graphPath = toModelPath(dirPath, modelDir);\n const nodeYamlPath = path.join(dirPath, 'yg-node.yaml');\n let meta;\n let nodeYamlRaw: string | undefined;\n try {\n nodeYamlRaw = await readFile(nodeYamlPath, 'utf-8');\n meta = await parseNodeYaml(nodeYamlPath);\n } catch (err) {\n nodeParseErrors.push({\n nodePath: graphPath,\n message: (err as Error).message,\n });\n return;\n }\n const artifacts = await readArtifacts(dirPath, ['yg-node.yaml'], artifactFilenames);\n\n const node: GraphNode = {\n path: graphPath,\n meta,\n nodeYamlRaw,\n artifacts,\n children: [],\n parent,\n };\n\n nodes.set(graphPath, node);\n if (parent) {\n parent.children.push(node);\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n if (entry.name.startsWith('.')) continue;\n\n await scanModelDirectory(\n path.join(dirPath, entry.name),\n modelDir,\n node,\n nodes,\n nodeParseErrors,\n artifactFilenames,\n );\n }\n } else {\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n if (entry.name.startsWith('.')) continue;\n\n await scanModelDirectory(\n path.join(dirPath, entry.name),\n modelDir,\n null,\n nodes,\n nodeParseErrors,\n artifactFilenames,\n );\n }\n }\n}\n\nasync function loadAspects(aspectsDir: string): Promise<AspectDef[]> {\n try {\n const aspects: AspectDef[] = [];\n await scanAspectsDirectory(aspectsDir, aspectsDir, aspects);\n return aspects;\n } catch {\n return [];\n }\n}\n\nasync function scanAspectsDirectory(\n dirPath: string,\n aspectsRoot: string,\n aspects: AspectDef[],\n): Promise<void> {\n const entries = await readdir(dirPath, { withFileTypes: true });\n const hasAspectYaml = entries.some((e) => e.isFile() && e.name === 'yg-aspect.yaml');\n\n if (hasAspectYaml) {\n const id = path.relative(aspectsRoot, dirPath).split(path.sep).join('/');\n const aspectYamlPath = path.join(dirPath, 'yg-aspect.yaml');\n const aspect = await parseAspect(dirPath, aspectYamlPath, id);\n aspects.push(aspect);\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n if (entry.name.startsWith('.')) continue;\n await scanAspectsDirectory(path.join(dirPath, entry.name), aspectsRoot, aspects);\n }\n}\n\nasync function loadFlows(flowsDir: string): Promise<FlowDef[]> {\n try {\n const entries = await readdir(flowsDir, { withFileTypes: true });\n const flows: FlowDef[] = [];\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const flowYamlPath = path.join(flowsDir, entry.name, 'yg-flow.yaml');\n const flow = await parseFlow(path.join(flowsDir, entry.name), flowYamlPath);\n flows.push(flow);\n }\n return flows;\n } catch {\n return [];\n }\n}\n\nasync function loadSchemas(schemasDir: string): Promise<SchemaDef[]> {\n try {\n const entries = await readdir(schemasDir, { withFileTypes: true });\n const schemas: SchemaDef[] = [];\n for (const entry of entries) {\n if (!entry.isFile()) continue;\n if (!entry.name.endsWith('.yaml') && !entry.name.endsWith('.yml')) continue;\n const s = await parseSchema(path.join(schemasDir, entry.name));\n schemas.push(s);\n }\n return schemas;\n } catch {\n return [];\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { parse as parseYaml } from 'yaml';\nimport type {\n YggConfig,\n ArtifactConfig,\n QualityConfig,\n NodeTypeConfig,\n} from '../model/types.js';\n\nconst DEFAULT_QUALITY: QualityConfig = {\n min_artifact_length: 50,\n max_direct_relations: 10,\n context_budget: { warning: 10000, error: 20000 },\n};\n\nexport async function parseConfig(filePath: string): Promise<YggConfig> {\n const content = await readFile(filePath, 'utf-8');\n const raw = parseYaml(content) as Record<string, unknown>;\n\n if (!raw || typeof raw !== 'object') {\n throw new Error(`yg-config.yaml: file is empty or not a valid YAML mapping`);\n }\n\n const version = typeof raw.version === 'string' ? raw.version.trim() : undefined;\n\n if (!raw.name || typeof raw.name !== 'string' || raw.name.trim() === '') {\n throw new Error(`yg-config.yaml: missing or invalid 'name' field`);\n }\n\n const nodeTypesRaw = raw.node_types;\n if (\n !nodeTypesRaw ||\n typeof nodeTypesRaw !== 'object' ||\n Array.isArray(nodeTypesRaw) ||\n Object.keys(nodeTypesRaw).length === 0\n ) {\n throw new Error(`yg-config.yaml: 'node_types' must be a non-empty object`);\n }\n\n const nodeTypes: Record<string, NodeTypeConfig> = {};\n for (const [typeName, val] of Object.entries(nodeTypesRaw)) {\n const entry = val as Record<string, unknown>;\n if (!entry || typeof entry !== 'object' || typeof entry.description !== 'string' || entry.description.trim() === '') {\n throw new Error(\n `yg-config.yaml: node_types.${typeName} must have a non-empty 'description' string`,\n );\n }\n const requiredAspects = Array.isArray(entry.required_aspects)\n ? (entry.required_aspects as unknown[]).filter((t): t is string => typeof t === 'string')\n : undefined;\n nodeTypes[typeName] = {\n description: entry.description as string,\n required_aspects: requiredAspects && requiredAspects.length > 0 ? requiredAspects : undefined,\n };\n }\n\n const artifacts = raw.artifacts;\n if (\n !artifacts ||\n typeof artifacts !== 'object' ||\n Array.isArray(artifacts) ||\n Object.keys(artifacts).length === 0\n ) {\n throw new Error(`yg-config.yaml: 'artifacts' must be a non-empty object`);\n }\n\n const artifactsMap: Record<string, ArtifactConfig> = {};\n for (const [key, val] of Object.entries(artifacts)) {\n if (key === 'yg-node.yaml') {\n throw new Error(`yg-config.yaml: artifact name 'yg-node.yaml' is reserved`);\n }\n const a = val as Record<string, unknown>;\n const required = a.required;\n if (\n required !== 'always' &&\n required !== 'never' &&\n (typeof required !== 'object' || !required || !('when' in required))\n ) {\n throw new Error(`yg-config.yaml: artifact '${key}' has invalid 'required' field`);\n }\n if (typeof required === 'object' && required && 'when' in required) {\n const when = (required as { when: string }).when;\n const validWhen =\n when === 'has_incoming_relations' ||\n when === 'has_outgoing_relations' ||\n (typeof when === 'string' &&\n (when.startsWith('has_aspect:') || when.startsWith('has_tag:')));\n if (!validWhen) {\n throw new Error(\n `yg-config.yaml: artifact '${key}' has invalid 'required.when': must be has_incoming_relations, has_outgoing_relations, or has_aspect:<name>`,\n );\n }\n }\n artifactsMap[key] = {\n required: required as ArtifactConfig['required'],\n description: (a.description as string) ?? '',\n included_in_relations: (a.included_in_relations as boolean) ?? false,\n };\n }\n\n const qualityRaw = raw.quality as Record<string, unknown> | undefined;\n const quality: QualityConfig = qualityRaw\n ? {\n min_artifact_length:\n (qualityRaw.min_artifact_length as number) ?? DEFAULT_QUALITY.min_artifact_length,\n max_direct_relations:\n (qualityRaw.max_direct_relations as number) ?? DEFAULT_QUALITY.max_direct_relations,\n context_budget: {\n warning:\n (qualityRaw.context_budget as Record<string, number>)?.warning ??\n DEFAULT_QUALITY.context_budget.warning,\n error:\n (qualityRaw.context_budget as Record<string, number>)?.error ??\n DEFAULT_QUALITY.context_budget.error,\n },\n }\n : DEFAULT_QUALITY;\n\n if (quality.context_budget.error < quality.context_budget.warning) {\n throw new Error(\n `yg-config.yaml: quality.context_budget.error (${quality.context_budget.error}) must be >= warning (${quality.context_budget.warning})`,\n );\n }\n\n return {\n version,\n name: (raw.name as string).trim(),\n node_types: nodeTypes,\n artifacts: artifactsMap,\n quality,\n };\n}\n","import { readFile } from 'node:fs/promises';\nimport { parse as parseYaml } from 'yaml';\nimport type { NodeAspectEntry, NodeMeta, NodeMapping, Relation, RelationType } from '../model/types.js';\n\nconst RELATION_TYPES: RelationType[] = [\n 'uses',\n 'calls',\n 'extends',\n 'implements',\n 'emits',\n 'listens',\n];\n\nfunction isValidRelationType(t: unknown): t is RelationType {\n return typeof t === 'string' && RELATION_TYPES.includes(t as RelationType);\n}\n\nexport async function parseNodeYaml(filePath: string): Promise<NodeMeta> {\n const content = await readFile(filePath, 'utf-8');\n const raw = parseYaml(content) as Record<string, unknown>;\n\n if (!raw || typeof raw !== 'object') {\n throw new Error(`yg-node.yaml at ${filePath}: file is empty or not a valid YAML mapping`);\n }\n\n if (!raw.name || typeof raw.name !== 'string' || raw.name.trim() === '') {\n throw new Error(`yg-node.yaml at ${filePath}: missing or empty 'name'`);\n }\n if (!raw.type || typeof raw.type !== 'string' || raw.type.trim() === '') {\n throw new Error(`yg-node.yaml at ${filePath}: missing or empty 'type'`);\n }\n\n const relations = parseRelations(raw.relations, filePath);\n const mapping = parseMapping(raw.mapping, filePath);\n const aspects = parseAspects(raw.aspects, filePath);\n\n return {\n name: (raw.name as string).trim(),\n type: (raw.type as string).trim(),\n aspects,\n blackbox: (raw.blackbox as boolean) ?? false,\n relations: relations.length > 0 ? relations : undefined,\n mapping,\n };\n}\n\nfunction parseAspects(raw: unknown, filePath: string): NodeAspectEntry[] | undefined {\n if (raw === undefined || raw === null) return undefined;\n if (!Array.isArray(raw)) {\n throw new Error(`yg-node.yaml at ${filePath}: 'aspects' must be an array`);\n }\n if (raw.length === 0) return undefined;\n\n const result: NodeAspectEntry[] = [];\n const seenAspects = new Set<string>();\n\n for (let i = 0; i < raw.length; i++) {\n const item = raw[i];\n if (typeof item !== 'object' || item === null) {\n throw new Error(`yg-node.yaml at ${filePath}: aspects[${i}] must be an object with 'aspect' key`);\n }\n const obj = item as Record<string, unknown>;\n\n if (typeof obj.aspect !== 'string' || obj.aspect.trim() === '') {\n throw new Error(\n `yg-node.yaml at ${filePath}: aspects[${i}].aspect must be a non-empty string`,\n );\n }\n\n const aspectId = obj.aspect.trim();\n if (seenAspects.has(aspectId)) {\n throw new Error(\n `yg-node.yaml at ${filePath}: duplicate aspect '${aspectId}' in aspects list`,\n );\n }\n seenAspects.add(aspectId);\n\n const entry: NodeAspectEntry = { aspect: aspectId };\n\n // Parse exceptions (optional string[])\n if (obj.exceptions !== undefined && obj.exceptions !== null) {\n if (!Array.isArray(obj.exceptions)) {\n throw new Error(\n `yg-node.yaml at ${filePath}: aspects[${i}].exceptions must be an array of strings`,\n );\n }\n const exceptions = obj.exceptions.filter((e): e is string => typeof e === 'string' && e.trim() !== '');\n if (exceptions.length > 0) {\n entry.exceptions = exceptions;\n }\n }\n\n // Parse anchors (optional string[])\n if (obj.anchors !== undefined && obj.anchors !== null) {\n if (!Array.isArray(obj.anchors)) {\n throw new Error(\n `yg-node.yaml at ${filePath}: aspects[${i}].anchors must be an array of strings`,\n );\n }\n const anchors = obj.anchors.filter((a): a is string => typeof a === 'string' && a.trim() !== '');\n if (anchors.length > 0) {\n entry.anchors = anchors;\n }\n }\n\n result.push(entry);\n }\n\n return result.length > 0 ? result : undefined;\n}\n\nfunction parseRelations(raw: unknown, filePath: string): Relation[] {\n if (raw === undefined) return [];\n if (!Array.isArray(raw)) {\n throw new Error(`yg-node.yaml at ${filePath}: 'relations' must be an array`);\n }\n\n const result: Relation[] = [];\n for (let index = 0; index < raw.length; index++) {\n const r = raw[index];\n if (typeof r !== 'object' || r === null) {\n throw new Error(`yg-node.yaml at ${filePath}: relations[${index}] must be an object`);\n }\n const obj = r as Record<string, unknown>;\n const target = obj.target;\n const type = obj.type;\n\n if (typeof target !== 'string' || target.trim() === '') {\n throw new Error(\n `yg-node.yaml at ${filePath}: relations[${index}].target must be a non-empty string`,\n );\n }\n if (!isValidRelationType(type)) {\n throw new Error(`yg-node.yaml at ${filePath}: relations[${index}].type is invalid`);\n }\n\n const rel: Relation = {\n target: target.trim(),\n type: type as RelationType,\n };\n if (Array.isArray(obj.consumes)) {\n rel.consumes = (obj.consumes as unknown[]).filter((c): c is string => typeof c === 'string');\n }\n if (typeof obj.failure === 'string') {\n rel.failure = obj.failure;\n }\n if (typeof obj.event_name === 'string' && obj.event_name.trim()) {\n rel.event_name = obj.event_name.trim();\n }\n result.push(rel);\n }\n return result;\n}\n\nfunction validateRelativePath(pathValue: string, filePath: string, fieldName: string): string {\n const normalized = pathValue.trim();\n if (normalized === '') {\n throw new Error(`yg-node.yaml at ${filePath}: '${fieldName}' must be non-empty`);\n }\n if (normalized.startsWith('/')) {\n throw new Error(`yg-node.yaml at ${filePath}: '${fieldName}' must be relative to repository root`);\n }\n return normalized;\n}\n\nfunction parseMapping(rawMapping: unknown, filePath: string): NodeMapping | undefined {\n if (!rawMapping || typeof rawMapping !== 'object') return undefined;\n\n const obj = rawMapping as Record<string, unknown>;\n\n // Unified format: mapping.paths — list of files and/or directories (type auto-detected at runtime)\n if (Array.isArray(obj.paths) && obj.paths.length > 0) {\n const paths = (obj.paths as unknown[])\n .filter((p): p is string => typeof p === 'string')\n .map((p) => validateRelativePath(p, filePath, 'mapping.paths[]'));\n if (paths.length === 0) {\n throw new Error(`yg-node.yaml at ${filePath}: mapping.paths must be a non-empty array`);\n }\n return { paths };\n }\n\n if (obj.paths !== undefined || obj.type !== undefined || obj.path !== undefined) {\n throw new Error(\n `yg-node.yaml at ${filePath}: mapping must have paths (array of file/directory paths)`,\n );\n }\n\n return undefined;\n}\n","import { readFile } from 'node:fs/promises';\nimport { parse as parseYaml } from 'yaml';\nimport type { AspectDef, AspectStability } from '../model/types.js';\nimport { readArtifacts } from './artifact-reader.js';\n\nconst VALID_STABILITY_VALUES: AspectStability[] = ['schema', 'protocol', 'implementation'];\n\nexport async function parseAspect(\n aspectDir: string,\n aspectYamlPath: string,\n id: string,\n): Promise<AspectDef> {\n const idTrimmed = id?.trim() ?? '';\n if (!idTrimmed) {\n throw new Error(`Aspect id must be non-empty (relative path in aspects/)`);\n }\n const content = await readFile(aspectYamlPath, 'utf-8');\n const raw = parseYaml(content) as Record<string, unknown>;\n\n if (!raw || typeof raw !== 'object') {\n throw new Error(`Aspect file ${aspectYamlPath}: file is empty or not a valid YAML mapping`);\n }\n\n if (!raw.name || typeof raw.name !== 'string' || raw.name.trim() === '') {\n throw new Error(`Aspect file ${aspectYamlPath}: missing or empty 'name'`);\n }\n\n const description = typeof raw.description === 'string' ? raw.description.trim() : undefined;\n\n const artifacts = await readArtifacts(aspectDir, ['yg-aspect.yaml']);\n\n let implies: string[] | undefined;\n if (raw.implies !== undefined) {\n if (!Array.isArray(raw.implies)) {\n throw new Error(`Aspect file ${aspectYamlPath}: 'implies' must be an array of strings`);\n }\n implies = (raw.implies as unknown[]).filter((t): t is string => typeof t === 'string');\n }\n\n let stability: AspectStability | undefined;\n if (raw.stability !== undefined) {\n if (typeof raw.stability !== 'string' || !VALID_STABILITY_VALUES.includes(raw.stability as AspectStability)) {\n throw new Error(\n `Aspect file ${aspectYamlPath}: 'stability' must be one of: ${VALID_STABILITY_VALUES.join(', ')}`,\n );\n }\n stability = raw.stability as AspectStability;\n }\n\n return {\n name: (raw.name as string).trim(),\n id: idTrimmed,\n description,\n implies,\n stability,\n artifacts,\n };\n}\n","import { readFile, readdir } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Artifact } from '../model/types.js';\n\nexport async function readArtifacts(\n dirPath: string,\n excludeFiles: string[] = ['yg-node.yaml'],\n includeFiles?: string[],\n): Promise<Artifact[]> {\n const entries = await readdir(dirPath, { withFileTypes: true });\n const artifacts: Artifact[] = [];\n const includeSet = includeFiles && includeFiles.length > 0 ? new Set(includeFiles) : null;\n\n for (const entry of entries) {\n if (!entry.isFile()) continue;\n if (excludeFiles.includes(entry.name)) continue;\n if (includeSet && !includeSet.has(entry.name)) continue;\n\n const filePath = path.join(dirPath, entry.name);\n const content = await readFile(filePath, 'utf-8');\n artifacts.push({ filename: entry.name, content });\n }\n\n // Sort by filename for deterministic output\n artifacts.sort((a, b) => a.filename.localeCompare(b.filename));\n return artifacts;\n}\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport type { FlowDef } from '../model/types.js';\nimport { readArtifacts } from './artifact-reader.js';\n\nexport async function parseFlow(flowDir: string, flowYamlPath: string): Promise<FlowDef> {\n const content = await readFile(flowYamlPath, 'utf-8');\n const raw = parseYaml(content) as Record<string, unknown>;\n\n if (!raw || typeof raw !== 'object') {\n throw new Error(`yg-flow.yaml at ${flowYamlPath}: file is empty or not a valid YAML mapping`);\n }\n\n if (!raw.name || typeof raw.name !== 'string' || raw.name.trim() === '') {\n throw new Error(`yg-flow.yaml at ${flowYamlPath}: missing or empty 'name'`);\n }\n\n const nodes = raw.nodes;\n if (!Array.isArray(nodes) || nodes.length === 0) {\n throw new Error(`yg-flow.yaml at ${flowYamlPath}: 'nodes' must be a non-empty array`);\n }\n\n const nodePaths = (nodes as unknown[]).filter((n): n is string => typeof n === 'string');\n if (nodePaths.length === 0) {\n throw new Error(`yg-flow.yaml at ${flowYamlPath}: 'nodes' must contain string node paths`);\n }\n\n let aspects: string[] | undefined;\n if (raw.aspects !== undefined) {\n if (!Array.isArray(raw.aspects)) {\n throw new Error(`yg-flow.yaml at ${flowYamlPath}: 'aspects' must be an array of strings`);\n }\n const aspectTags = (raw.aspects as unknown[]).filter((a): a is string => typeof a === 'string');\n aspects = aspectTags.length > 0 ? aspectTags : [];\n }\n\n const artifacts = await readArtifacts(flowDir, ['yg-flow.yaml']);\n\n return {\n path: path.basename(flowDir),\n name: (raw.name as string).trim(),\n nodes: nodePaths,\n ...(aspects !== undefined && { aspects }),\n artifacts,\n };\n}\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport type { SchemaDef } from '../model/types.js';\n\nexport async function parseSchema(filePath: string): Promise<SchemaDef> {\n const content = await readFile(filePath, 'utf-8');\n parseYaml(content); // validate YAML is parseable\n const rawName = path.basename(filePath, path.extname(filePath));\n const schemaType = rawName.startsWith('yg-') ? rawName.slice(3) : rawName;\n return { schemaType };\n}\n","import path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { stat } from 'node:fs/promises';\n\n/**\n * Directory containing the CLI package (dist/ when bundled).\n * Uses import.meta.url so it works when installed globally.\n */\nexport function getPackageRoot(): string {\n return path.dirname(fileURLToPath(import.meta.url));\n}\n\n/**\n * Find the .yggdrasil/ directory starting from projectRoot.\n * Searches upward through parent directories until found or filesystem root.\n * Returns the absolute path to the .yggdrasil/ directory.\n */\nexport async function findYggRoot(projectRoot: string): Promise<string> {\n let current = path.resolve(projectRoot);\n const root = path.parse(current).root;\n\n while (true) {\n const yggPath = path.join(current, '.yggdrasil');\n try {\n const st = await stat(yggPath);\n if (!st.isDirectory()) {\n throw new Error(\n `.yggdrasil exists but is not a directory (${yggPath}). Run 'yg init' in a clean location.`,\n );\n }\n return yggPath;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n if (current === root) {\n throw new Error(`No .yggdrasil/ directory found. Run 'yg init' first.`, { cause: err });\n }\n current = path.dirname(current);\n continue;\n }\n throw err;\n }\n }\n}\n\nimport type { NodeMapping } from '../model/types.js';\n\n/**\n * Normalize a mapping to always return an array of paths (relative to project root).\n * Each path can be a file or directory — type is detected at runtime by hash/owner.\n */\nexport function normalizeMappingPaths(mapping: NodeMapping | undefined): string[] {\n if (!mapping?.paths?.length) return [];\n return mapping.paths.map((p) => p.trim()).filter(Boolean);\n}\n\n/**\n * Convert a node's directory path to its graph path.\n * E.g., \"/abs/path/.yggdrasil/orders/order-service\" → \"orders/order-service\"\n */\nexport function toGraphPath(absolutePath: string, yggRoot: string): string {\n return path.relative(yggRoot, absolutePath).split(path.sep).join('/');\n}\n\n/**\n * Normalize a user-provided path to project-relative POSIX form.\n * Throws when the target path points outside the project root.\n */\nexport function normalizeProjectRelativePath(projectRoot: string, rawPath: string): string {\n const normalizedInput = rawPath.trim().replace(/\\\\/g, '/');\n if (normalizedInput.length === 0) {\n throw new Error('Path cannot be empty');\n }\n\n const absolute = path.resolve(projectRoot, normalizedInput);\n const relative = path.relative(projectRoot, absolute);\n const isOutside = relative.startsWith('..') || path.isAbsolute(relative);\n if (isOutside) {\n throw new Error(`Path is outside project root: ${rawPath}`);\n }\n\n return relative.split(path.sep).join('/');\n}\n\n/**\n * Normalize a --node path argument: strip leading ./ and trailing /.\n */\nexport function normalizeNodePath(rawPath: string): string {\n return rawPath.trim().replace(/^\\.\\//, '').replace(/\\/+$/, '');\n}\n\n/**\n * Derive the actual project root (repo root) from the graph's .yggdrasil/ path.\n */\nexport function projectRootFromGraph(yggRootPath: string): string {\n return path.dirname(yggRootPath);\n}\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type {\n Graph,\n GraphNode,\n ContextPackage,\n ContextLayer,\n ContextSection,\n YggConfig,\n AspectDef,\n FlowDef,\n Relation,\n} from '../model/types.js';\nimport { normalizeMappingPaths } from '../utils/paths.js';\nimport { estimateTokens } from '../utils/tokens.js';\n\nconst STRUCTURAL_RELATION_TYPES = new Set(['uses', 'calls', 'extends', 'implements']);\nconst EVENT_RELATION_TYPES = new Set(['emits', 'listens']);\n\nexport async function buildContext(graph: Graph, nodePath: string): Promise<ContextPackage> {\n const node = graph.nodes.get(nodePath);\n if (!node) {\n throw new Error(`Node not found: ${nodePath}`);\n }\n\n const layers: ContextLayer[] = [];\n\n // 1. Global\n layers.push(buildGlobalLayer(graph.config));\n\n // 2. Hierarchy (only configured artifacts that exist in ancestor's directory)\n const ancestors = collectAncestors(node);\n for (const ancestor of ancestors) {\n layers.push(buildHierarchyLayer(ancestor, graph.config, graph));\n }\n\n // 3. Own (yg-node.yaml + configured artifacts)\n layers.push(await buildOwnLayer(node, graph.config, graph.rootPath, graph));\n\n // 4. Relational (structural + event, with consumes/failure)\n // Skip relations targeting ancestors — their context is already in hierarchy layers.\n const ancestorPaths = new Set(ancestors.map((a) => a.path));\n for (const relation of node.meta.relations ?? []) {\n const target = graph.nodes.get(relation.target);\n if (!target) {\n throw new Error(`Broken relation: ${nodePath} -> ${relation.target} (target not found)`);\n }\n if (ancestorPaths.has(relation.target)) continue;\n if (STRUCTURAL_RELATION_TYPES.has(relation.type)) {\n layers.push(buildStructuralRelationLayer(target, relation, graph.config));\n } else if (EVENT_RELATION_TYPES.has(relation.type)) {\n layers.push(buildEventRelationLayer(target, relation));\n }\n }\n\n // 5. Flows (node + all ancestors) — built before aspects so we can collect flow aspect ids\n for (const flow of collectParticipatingFlows(graph, node)) {\n layers.push(buildFlowLayer(flow, graph));\n }\n\n // 6. Aspects: union of aspect ids from hierarchy + own + flow layers\n const allAspectIds = new Set<string>();\n for (const l of layers) {\n const aspects = l.attrs?.aspects;\n if (aspects) {\n for (const id of aspects.split(',').map((t) => t.trim()).filter(Boolean)) {\n allAspectIds.add(id);\n }\n }\n }\n const aspectsToInclude = resolveAspects(allAspectIds, graph.aspects);\n for (const aspect of aspectsToInclude) {\n const entry = node.meta.aspects?.find(a => a.aspect === aspect.id);\n const exceptionNote = entry?.exceptions?.join('; ');\n layers.push(buildAspectLayer(aspect, exceptionNote));\n }\n\n const fullText = layers.map((l) => l.content).join('\\n\\n');\n const tokenCount = estimateTokens(fullText);\n const mapping = normalizeMappingPaths(node.meta.mapping);\n const sections = buildSections(layers, mapping.length > 0 ? mapping : null);\n\n return {\n nodePath,\n nodeName: node.meta.name,\n layers,\n sections,\n mapping: mapping.length > 0 ? mapping : null,\n tokenCount,\n };\n}\n\nfunction collectParticipatingFlows(graph: Graph, node: GraphNode): FlowDef[] {\n const paths = new Set<string>([node.path, ...collectAncestors(node).map((a) => a.path)]);\n return graph.flows.filter((f) => f.nodes.some((n) => paths.has(n)));\n}\n\n/** Expand aspect ids to include implied ids recursively. Returns unique list. */\nexport function expandAspects(aspectIds: string[], aspects: AspectDef[]): string[] {\n const idToAspect = new Map<string, AspectDef>();\n for (const a of aspects) {\n idToAspect.set(a.id, a);\n }\n const result: string[] = [];\n const visited = new Set<string>();\n const stack = new Set<string>();\n\n function collect(id: string): void {\n if (stack.has(id)) {\n throw new Error(`Aspect implies cycle detected involving aspect '${id}'`);\n }\n if (visited.has(id)) return;\n stack.add(id);\n visited.add(id);\n result.push(id);\n const aspect = idToAspect.get(id);\n if (aspect) {\n for (const implied of aspect.implies ?? []) {\n collect(implied);\n }\n }\n stack.delete(id);\n }\n\n for (const id of aspectIds) {\n collect(id);\n }\n return result;\n}\n\n/** Expand aspect ids to AspectDefs including implied (recursive, with cycle detection). */\nexport function resolveAspects(\n aspectIds: Iterable<string>,\n aspects: AspectDef[],\n): AspectDef[] {\n const idToAspect = new Map<string, AspectDef>();\n for (const a of aspects) {\n idToAspect.set(a.id, a);\n }\n const expandedIds = expandAspects([...aspectIds], aspects);\n return expandedIds\n .map((id) => idToAspect.get(id))\n .filter((a): a is AspectDef => a !== undefined);\n}\n\n// --- backward-compat aliases (used by tests / external callers) ---\nexport const expandTags = expandAspects;\nexport const expandAspectsForTags = resolveAspects;\n\n// --- Layer builders (exported for testing) ---\n\nexport function buildGlobalLayer(config: YggConfig): ContextLayer {\n const content = `**Project:** ${config.name}\\n`;\n return { type: 'global', label: 'Global Context', content };\n}\n\nfunction filterArtifactsByConfig(\n artifacts: Array<{ filename: string; content: string }>,\n config: YggConfig,\n): Array<{ filename: string; content: string }> {\n const allowed = new Set(Object.keys(config.artifacts ?? {}));\n return artifacts.filter((a) => allowed.has(a.filename));\n}\n\nexport function buildHierarchyLayer(\n ancestor: GraphNode,\n config: YggConfig,\n graph: Graph,\n): ContextLayer {\n const filtered = filterArtifactsByConfig(ancestor.artifacts, config);\n const content = filtered.map((a) => `### ${a.filename}\\n${a.content}`).join('\\n\\n');\n const nodeAspects = (ancestor.meta.aspects ?? []).map(a => a.aspect);\n const expanded = expandAspects(nodeAspects, graph.aspects);\n const attrs: Record<string, string> | undefined =\n expanded.length > 0 ? { aspects: expanded.join(',') } : undefined;\n return {\n type: 'hierarchy',\n label: `Module Context (${ancestor.path}/)`,\n content,\n attrs,\n };\n}\n\nexport async function buildOwnLayer(\n node: GraphNode,\n config: YggConfig,\n graphRootPath: string,\n graph: Graph,\n): Promise<ContextLayer> {\n const parts: string[] = [];\n\n if (node.nodeYamlRaw) {\n parts.push(`### yg-node.yaml\\n${node.nodeYamlRaw.trim()}`);\n } else {\n const nodeYamlPath = path.join(graphRootPath, 'model', node.path, 'yg-node.yaml');\n try {\n const nodeYamlContent = await readFile(nodeYamlPath, 'utf-8');\n parts.push(`### yg-node.yaml\\n${nodeYamlContent.trim()}`);\n } catch {\n parts.push(`### yg-node.yaml\\n(not found)`);\n }\n }\n\n const filtered = filterArtifactsByConfig(node.artifacts, config);\n for (const a of filtered) {\n parts.push(`### ${a.filename}\\n${a.content}`);\n }\n\n const content = parts.join('\\n\\n');\n const nodeAspects = (node.meta.aspects ?? []).map(a => a.aspect);\n const expanded = expandAspects(nodeAspects, graph.aspects);\n const attrs: Record<string, string> | undefined =\n expanded.length > 0 ? { aspects: expanded.join(',') } : undefined;\n return {\n type: 'own',\n label: `Node: ${node.meta.name}`,\n content,\n attrs,\n };\n}\n\nexport function buildStructuralRelationLayer(\n target: GraphNode,\n relation: Relation,\n config: YggConfig,\n): ContextLayer {\n let content = '';\n if (relation.consumes?.length) {\n content += `Consumes: ${relation.consumes.join(', ')}\\n\\n`;\n }\n if (relation.failure) {\n content += `On failure: ${relation.failure}\\n\\n`;\n }\n\n const structuralArtifactFilenames = Object.entries(config.artifacts ?? {})\n .filter(([, c]) => c.included_in_relations)\n .map(([filename]) => filename);\n\n const structuralArts = structuralArtifactFilenames\n .map((filename) => {\n const art = target.artifacts.find((a) => a.filename === filename);\n return art ? { filename: art.filename, content: art.content } : null;\n })\n .filter((a): a is { filename: string; content: string } => a !== null);\n\n if (structuralArts.length > 0) {\n content += structuralArts.map((a) => `### ${a.filename}\\n${a.content}`).join('\\n\\n');\n } else {\n const filtered = filterArtifactsByConfig(target.artifacts, config);\n content += filtered.map((a) => `### ${a.filename}\\n${a.content}`).join('\\n\\n');\n }\n\n const attrs: Record<string, string> = {\n target: target.path,\n type: relation.type,\n };\n if (relation.consumes?.length) attrs.consumes = relation.consumes.join(', ');\n if (relation.failure) attrs.failure = relation.failure;\n\n return {\n type: 'relational',\n label: `Dependency: ${target.meta.name} (${relation.type}) — ${target.path}`,\n content: content.trim(),\n attrs,\n };\n}\n\nexport function buildEventRelationLayer(target: GraphNode, relation: Relation): ContextLayer {\n const eventName = relation.event_name ?? target.meta.name;\n const isEmit = relation.type === 'emits';\n let content = isEmit\n ? `Target: ${target.path}\\nYou publish ${eventName}.`\n : `Source: ${target.path}\\nYou listen for ${eventName}.`;\n if (relation.consumes?.length) {\n content += `\\nConsumes: ${relation.consumes.join(', ')}`;\n }\n const attrs: Record<string, string> = {\n target: target.path,\n type: relation.type,\n 'event-name': eventName,\n };\n if (relation.consumes?.length) attrs.consumes = relation.consumes.join(', ');\n\n return {\n type: 'relational',\n label: `Event: ${eventName} [${relation.type}]`,\n content,\n attrs,\n };\n}\n\nexport function buildAspectLayer(aspect: AspectDef, exceptionNote?: string): ContextLayer {\n let content = aspect.artifacts.map((a) => `### ${a.filename}\\n${a.content}`).join('\\n\\n');\n if (aspect.stability) {\n content += `\\n**Stability tier:** ${aspect.stability}`;\n }\n if (exceptionNote) {\n content += `\\n\\n⚠ **Exception for this node:** ${exceptionNote}`;\n }\n return {\n type: 'aspects',\n label: `${aspect.name} (aspect: ${aspect.id})`,\n content,\n };\n}\n\nfunction buildFlowLayer(flow: FlowDef, graph: Graph): ContextLayer {\n const content = flow.artifacts.map((a) => `### ${a.filename}\\n${a.content}`).join('\\n\\n');\n const flowAspects = flow.aspects ?? [];\n const expanded = expandAspects(flowAspects, graph.aspects);\n const attrs: Record<string, string> | undefined =\n expanded.length > 0 ? { aspects: expanded.join(',') } : undefined;\n return {\n type: 'flows',\n label: `Flow: ${flow.name}`,\n content: content || '(no artifacts)',\n attrs,\n };\n}\n\nfunction buildSections(layers: ContextLayer[], mapping: string[] | null): ContextSection[] {\n const ownLayers = layers.filter((layer) => layer.type === 'own');\n if (mapping && mapping.length > 0) {\n ownLayers.push({\n type: 'own',\n label: 'Materialization Target',\n content: mapping.join(', '),\n });\n }\n\n return [\n { key: 'Global', layers: layers.filter((l) => l.type === 'global') },\n { key: 'Hierarchy', layers: layers.filter((l) => l.type === 'hierarchy') },\n { key: 'OwnArtifacts', layers: ownLayers },\n { key: 'Aspects', layers: layers.filter((l) => l.type === 'aspects') },\n {\n key: 'Relational',\n layers: [\n ...layers.filter((l) => l.type === 'relational'),\n ...layers.filter((l) => l.type === 'flows'),\n ],\n },\n ];\n}\n\n// --- Helpers (exported for testing) ---\n\nexport function collectAncestors(node: GraphNode): GraphNode[] {\n const ancestors: GraphNode[] = [];\n let current = node.parent;\n while (current) {\n ancestors.unshift(current);\n current = current.parent;\n }\n return ancestors;\n}\n\n/** Compute effective aspect ids for a node: own + hierarchy + flow + implies expanded. */\nexport function collectEffectiveAspectIds(graph: Graph, nodePath: string): Set<string> {\n const node = graph.nodes.get(nodePath);\n if (!node) return new Set();\n\n const raw = new Set<string>((node.meta.aspects ?? []).map(a => a.aspect));\n\n // Hierarchy aspects\n let ancestor = node.parent;\n while (ancestor) {\n for (const entry of ancestor.meta.aspects ?? []) raw.add(entry.aspect);\n ancestor = ancestor.parent;\n }\n\n // Flow aspects (flows where node or ancestor participates)\n const ancestorPaths = new Set([nodePath, ...collectAncestors(node).map((a) => a.path)]);\n for (const flow of graph.flows) {\n if (flow.nodes.some((n) => ancestorPaths.has(n))) {\n for (const id of flow.aspects ?? []) raw.add(id);\n }\n }\n\n // Expand implies\n return new Set(expandAspects([...raw], graph.aspects));\n}\n","/**\n * Estimate token count for a string.\n * Heuristic: ~4 characters per token (no tokenizer dependency).\n */\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n","import { readdir, readFile, stat } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Graph, ValidationResult, ValidationIssue, ArtifactConfig, NodeAspectEntry } from '../model/types.js';\nimport { buildContext, resolveAspects } from './context-builder.js';\nimport { normalizeMappingPaths } from '../utils/paths.js';\n\n/** Extract flat aspect id list from unified aspect entries */\nfunction getAspectIds(aspects: NodeAspectEntry[] | undefined): string[] {\n return (aspects ?? []).map(a => a.aspect);\n}\n\n/** Reserved directories that are NOT nodes (within model/) */\nconst RESERVED_DIRS = new Set<string>();\n\nexport async function validate(graph: Graph, scope: string = 'all'): Promise<ValidationResult> {\n const issues: ValidationIssue[] = [];\n\n if (graph.configError) {\n issues.push({\n severity: 'error',\n code: 'E012',\n rule: 'invalid-config',\n message: graph.configError,\n });\n }\n\n for (const { nodePath, message } of graph.nodeParseErrors ?? []) {\n issues.push({\n severity: 'error',\n code: 'E001',\n rule: 'invalid-node-yaml',\n message,\n nodePath,\n });\n }\n\n if (!graph.configError) {\n issues.push(...checkNodeTypes(graph));\n issues.push(...checkAspectsDefined(graph));\n issues.push(...checkAspectIds(graph));\n issues.push(...checkAspectIdUniqueness(graph));\n issues.push(...checkImpliedAspectsExist(graph));\n issues.push(...checkImpliesNoCycles(graph));\n issues.push(...checkRequiredAspectsCoverage(graph));\n issues.push(...(await checkAnchorPresence(graph)));\n issues.push(...checkRequiredArtifacts(graph));\n issues.push(...checkInvalidArtifactConditions(graph));\n issues.push(...(await checkContextBudget(graph)));\n issues.push(...checkHighFanOut(graph));\n }\n\n issues.push(...checkSchemas(graph));\n issues.push(...checkRelationTargets(graph));\n issues.push(...checkNoCycles(graph));\n issues.push(...checkMappingOverlap(graph));\n issues.push(...(await checkMappingPathsExist(graph)));\n issues.push(...checkBrokenFlowRefs(graph));\n issues.push(...checkFlowAspectIds(graph));\n issues.push(...(await checkDirectoriesHaveNodeYaml(graph)));\n issues.push(...(await checkShallowArtifacts(graph)));\n issues.push(...checkUnpairedEvents(graph));\n\n let filtered = issues;\n let nodesScanned = graph.nodes.size;\n if (scope !== 'all' && scope.trim()) {\n if (!graph.nodes.has(scope)) {\n // Check if the node exists but has a parse error\n const parseError = (graph.nodeParseErrors ?? []).find(\n (e) => e.nodePath === scope || scope.startsWith(e.nodePath + '/'),\n );\n if (parseError) {\n return {\n issues: [{\n severity: 'error',\n code: 'E001',\n rule: 'invalid-node-yaml',\n message: parseError.message,\n nodePath: parseError.nodePath,\n }],\n nodesScanned: 0,\n };\n }\n return {\n issues: [{ severity: 'error', rule: 'invalid-scope', message: `Node not found: ${scope}` }],\n nodesScanned: 0,\n };\n }\n const scopePrefix = scope + '/';\n filtered = issues.filter((i) => !i.nodePath || i.nodePath === scope || i.nodePath.startsWith(scopePrefix));\n nodesScanned = [...graph.nodes.keys()].filter((p) => p === scope || p.startsWith(scopePrefix)).length;\n }\n\n return { issues: filtered, nodesScanned };\n}\n\n// --- Rule 0: Node types from config ---\n\nfunction checkNodeTypes(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const allowedTypes = new Set(Object.keys(graph.config.node_types ?? {}));\n for (const [nodePath, node] of graph.nodes) {\n if (!allowedTypes.has(node.meta.type)) {\n issues.push({\n severity: 'error',\n code: 'E002',\n rule: 'unknown-node-type',\n message: `Node type '${node.meta.type}' not in config.node_types (${[...allowedTypes].join(', ')})`,\n nodePath,\n });\n }\n }\n return issues;\n}\n\n// --- Rule 1: Relation targets exist ---\n\nfunction findSimilar(target: string, candidates: string[]): string | null {\n if (candidates.length === 0) return null;\n\n let best: string | null = null;\n let bestScore = -1;\n\n for (const c of candidates) {\n if (c === target) return c;\n // Simple similarity: shared path segments\n const targetParts = target.split('/');\n const candParts = c.split('/');\n let score = 0;\n for (let i = 0; i < Math.min(targetParts.length, candParts.length); i++) {\n if (targetParts[i] === candParts[i]) score++;\n else break;\n }\n if (score > bestScore && score > 0) {\n bestScore = score;\n best = c;\n }\n }\n return best;\n}\n\nfunction checkRelationTargets(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const nodePaths = [...graph.nodes.keys()];\n for (const [nodePath, node] of graph.nodes) {\n for (const rel of node.meta.relations ?? []) {\n if (!graph.nodes.has(rel.target)) {\n const suggestion = findSimilar(rel.target, nodePaths);\n const parts = rel.target.split('/');\n const parentPrefix = parts.length > 1 ? parts.slice(0, -1).join('/') + '/' : '';\n const existingInParent = nodePaths\n .filter((p) => p.startsWith(parentPrefix) && p !== rel.target)\n .map((p) => {\n const rest = p.slice(parentPrefix.length);\n return rest.split('/')[0];\n })\n .filter((v, i, a) => a.indexOf(v) === i)\n .sort();\n const existingLine =\n existingInParent.length > 0\n ? `\\n Existing nodes in ${parentPrefix || 'model/'}: ${existingInParent.join(', ')}`\n : '';\n const hint = suggestion ? `\\n Did you mean '${suggestion}'?` : '';\n issues.push({\n severity: 'error',\n code: 'E004',\n rule: 'broken-relation',\n message: `Relation target '${rel.target}' does not exist${existingLine}${hint}`,\n nodePath,\n });\n }\n }\n }\n return issues;\n}\n\n// --- Rule 2: Node aspects must reference a defined aspect ---\n\nfunction checkAspectsDefined(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const validAspectIds = new Set(graph.aspects.map((a) => a.id));\n for (const [nodePath, node] of graph.nodes) {\n for (const aspectId of getAspectIds(node.meta.aspects)) {\n if (!validAspectIds.has(aspectId)) {\n issues.push({\n severity: 'error',\n code: 'E003',\n rule: 'unknown-aspect',\n message: `Aspect '${aspectId}' has no corresponding directory in aspects/`,\n nodePath,\n });\n }\n }\n }\n return issues;\n}\n\n// --- Rule 3: Aspect ids (derived from directory path) — always valid when aspect exists ---\n\nfunction checkAspectIds(_graph: Graph): ValidationIssue[] {\n // validAspectIds = graph.aspects.map(a => a.id), so every aspect's id is valid by definition\n return [];\n}\n\nfunction checkAspectIdUniqueness(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const byId = new Map<string, string[]>();\n for (const aspect of graph.aspects) {\n const names = byId.get(aspect.id) ?? [];\n names.push(aspect.name);\n byId.set(aspect.id, names);\n }\n for (const [id, names] of byId) {\n if (names.length <= 1) continue;\n issues.push({\n severity: 'error',\n code: 'E014',\n rule: 'duplicate-aspect-binding',\n message: `Aspect '${id}' is bound to multiple aspects (${names.join(', ')})`,\n });\n }\n return issues;\n}\n\n// --- Rule: Implied aspects exist ---\n\nfunction checkImpliedAspectsExist(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const idToAspect = new Map<string, { name: string }>();\n for (const a of graph.aspects) {\n idToAspect.set(a.id, { name: a.name });\n }\n for (const aspect of graph.aspects) {\n for (const impliedId of aspect.implies ?? []) {\n if (!idToAspect.has(impliedId)) {\n issues.push({\n severity: 'error',\n code: 'E016',\n rule: 'implied-aspect-missing',\n message: `Aspect '${aspect.name}' implies '${impliedId}' but no aspect with that id exists in aspects/`,\n });\n }\n }\n }\n return issues;\n}\n\n// --- Rule: No cycles in aspect implies graph ---\n\nfunction checkImpliesNoCycles(graph: Graph): ValidationIssue[] {\n const idToAspect = new Map<string, { implies?: string[] }>();\n for (const a of graph.aspects) {\n idToAspect.set(a.id, { implies: a.implies });\n }\n const WHITE = 0;\n const GRAY = 1;\n const BLACK = 2;\n const color = new Map<string, number>();\n for (const id of idToAspect.keys()) color.set(id, WHITE);\n\n const issues: ValidationIssue[] = [];\n\n function dfs(id: string, pathArr: string[]): boolean {\n color.set(id, GRAY);\n pathArr.push(id);\n const aspect = idToAspect.get(id);\n for (const implied of aspect?.implies ?? []) {\n if (color.get(implied) === GRAY) {\n const cycle = pathArr.slice(pathArr.indexOf(implied)).concat(implied);\n issues.push({\n severity: 'error',\n code: 'E017',\n rule: 'aspect-implies-cycle',\n message: `Aspect implies cycle: ${cycle.join(' → ')}`,\n });\n pathArr.pop();\n color.set(id, BLACK);\n return true;\n }\n if (color.get(implied) === WHITE && dfs(implied, pathArr)) {\n pathArr.pop();\n color.set(id, BLACK);\n return true;\n }\n }\n pathArr.pop();\n color.set(id, BLACK);\n return false;\n }\n\n for (const id of idToAspect.keys()) {\n if (color.get(id) === WHITE) {\n dfs(id, []);\n }\n }\n return issues;\n}\n\n// --- Rule: Required aspects coverage per node type ---\n\nfunction checkRequiredAspectsCoverage(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const typeConfig = new Map(\n Object.entries(graph.config.node_types ?? {}).map(([name, cfg]) => [name, cfg.required_aspects ?? []]),\n );\n for (const [nodePath, node] of graph.nodes) {\n if (node.meta.blackbox) continue;\n const requiredAspects = typeConfig.get(node.meta.type);\n if (!requiredAspects || requiredAspects.length === 0) continue;\n\n const nodeAspectIds = getAspectIds(node.meta.aspects);\n let effectiveAspects;\n try {\n effectiveAspects = resolveAspects(nodeAspectIds, graph.aspects);\n } catch {\n continue;\n }\n const effectiveAspectIds = new Set(effectiveAspects.map((a) => a.id));\n\n for (const required of requiredAspects) {\n if (!effectiveAspectIds.has(required)) {\n issues.push({\n severity: 'warning',\n code: 'W011',\n rule: 'missing-required-aspect-coverage',\n message: `Node '${nodePath}' (type: ${node.meta.type}) missing required aspect coverage for '${required}'`,\n nodePath,\n });\n }\n }\n }\n return issues;\n}\n\n// --- Rule 4: No circular dependencies (cycles involving blackbox are tolerated) ---\n\nfunction checkNoCycles(graph: Graph): ValidationIssue[] {\n const WHITE = 0;\n const GRAY = 1;\n const BLACK = 2;\n const color = new Map<string, number>();\n for (const p of graph.nodes.keys()) color.set(p, WHITE);\n\n const issues: ValidationIssue[] = [];\n\n function dfs(nodePath: string, pathSegments: string[]): boolean {\n color.set(nodePath, GRAY);\n const node = graph.nodes.get(nodePath)!;\n const structuralTypes = new Set(['uses', 'calls', 'extends', 'implements']);\n for (const rel of node.meta.relations ?? []) {\n const targetNode = graph.nodes.get(rel.target);\n if (!targetNode) continue;\n if (!structuralTypes.has(rel.type)) continue;\n if (color.get(rel.target) === GRAY) {\n const cyclePath = [...pathSegments, nodePath, rel.target];\n const cycleNodes = pathSegments.slice(pathSegments.indexOf(rel.target)).concat(nodePath);\n const hasBlackboxInCycle = cycleNodes.some(\n (p) => graph.nodes.get(p)?.meta.blackbox === true,\n );\n if (!hasBlackboxInCycle) {\n issues.push({\n severity: 'error',\n code: 'E010',\n rule: 'structural-cycle',\n message: `Circular dependency: ${cyclePath.join(' -> ')}`,\n });\n }\n return true;\n }\n if (color.get(rel.target) === WHITE) {\n if (dfs(rel.target, [...pathSegments, nodePath])) return true;\n }\n }\n color.set(nodePath, BLACK);\n return false;\n }\n\n for (const nodePath of graph.nodes.keys()) {\n if (color.get(nodePath) === WHITE) {\n dfs(nodePath, []);\n }\n }\n\n return issues;\n}\n\n// --- Rule 5: Mapping ownership overlap ---\n\nfunction normalizePathForCompare(mappingPath: string): string {\n return mappingPath.replace(/\\\\/g, '/').replace(/\\/+$/, '');\n}\n\nfunction arePathsOverlapping(pathA: string, pathB: string): boolean {\n if (pathA === pathB) return true;\n return pathA.startsWith(pathB + '/') || pathB.startsWith(pathA + '/');\n}\n\nfunction isAncestorNode(possibleAncestor: string, possibleDescendant: string): boolean {\n return possibleDescendant.startsWith(possibleAncestor + '/');\n}\n\nfunction checkMappingOverlap(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const ownership: Array<{ nodePath: string; mappingPath: string }> = [];\n\n for (const [nodePath, node] of graph.nodes) {\n const mappingPaths = normalizeMappingPaths(node.meta.mapping)\n .map(normalizePathForCompare)\n .filter((mappingPath) => mappingPath.length > 0);\n for (const mappingPath of mappingPaths) {\n ownership.push({ nodePath, mappingPath });\n }\n }\n\n for (let index = 0; index < ownership.length; index++) {\n const current = ownership[index];\n for (let nestedIndex = index + 1; nestedIndex < ownership.length; nestedIndex++) {\n const candidate = ownership[nestedIndex];\n if (current.nodePath === candidate.nodePath) continue;\n if (!arePathsOverlapping(current.mappingPath, candidate.mappingPath)) continue;\n\n // Allow containment overlaps between ancestor-descendant nodes (\"child wins\" model).\n // Exact duplicates (same path) are always errors regardless of hierarchy.\n const isContainment = current.mappingPath !== candidate.mappingPath;\n const isHierarchical =\n isAncestorNode(current.nodePath, candidate.nodePath) ||\n isAncestorNode(candidate.nodePath, current.nodePath);\n\n if (isContainment && isHierarchical) continue;\n\n issues.push({\n severity: 'error',\n code: 'E009',\n rule: 'overlapping-mapping',\n message:\n `Mapping paths '${current.mappingPath}' (${current.nodePath}) and ` +\n `'${candidate.mappingPath}' (${candidate.nodePath}) overlap. ` +\n `Keep one owner mapping and model other concerns via relations.`,\n nodePath: candidate.nodePath,\n });\n }\n }\n\n return issues;\n}\n\n// --- Rule: Mapping paths should exist on disk (W012) ---\n\nasync function checkMappingPathsExist(graph: Graph): Promise<ValidationIssue[]> {\n const issues: ValidationIssue[] = [];\n const projectRoot = path.dirname(graph.rootPath);\n const { access } = await import('node:fs/promises');\n\n for (const [nodePath, node] of graph.nodes) {\n const mappingPaths = normalizeMappingPaths(node.meta.mapping);\n for (const mp of mappingPaths) {\n const absPath = path.join(projectRoot, mp);\n try {\n await access(absPath);\n } catch {\n issues.push({\n severity: 'warning',\n code: 'W012',\n rule: 'mapping-path-missing',\n message: `Mapping path '${mp}' does not exist on disk`,\n nodePath,\n });\n }\n }\n }\n return issues;\n}\n\n// --- Rule 6: Required artifacts per config.artifacts (W001) ---\n\nfunction getIncomingRelationSources(graph: Graph, nodePath: string): string[] {\n const sources: string[] = [];\n for (const [srcPath, node] of graph.nodes) {\n for (const rel of node.meta.relations ?? []) {\n if (rel.target === nodePath) sources.push(srcPath);\n }\n }\n return sources;\n}\n\nfunction artifactRequiredReason(\n graph: Graph,\n nodePath: string,\n node: {\n meta: { relations?: Array<{ target: string }>; aspects?: NodeAspectEntry[]; blackbox?: boolean };\n artifacts: Array<{ filename: string }>;\n },\n required: ArtifactConfig['required'],\n): string | null {\n if (required === 'never') return null;\n if (required === 'always') {\n return node.meta.blackbox ? null : 'required: always';\n }\n const when = (required as { when: string }).when;\n if (when === 'has_incoming_relations') {\n const sources = getIncomingRelationSources(graph, nodePath);\n return sources.length > 0\n ? `${sources.length} incoming relation(s): ${sources.join(', ')}`\n : null;\n }\n if (when === 'has_outgoing_relations') {\n const count = node.meta.relations?.length ?? 0;\n return count > 0 ? `${count} outgoing relation(s)` : null;\n }\n if (when.startsWith('has_aspect:') || when.startsWith('has_tag:')) {\n const prefix = when.startsWith('has_aspect:') ? 'has_aspect:' : 'has_tag:';\n const aspectId = when.slice(prefix.length);\n return (node.meta.aspects ?? []).some(a => a.aspect === aspectId) ? `node has aspect '${aspectId}'` : null;\n }\n return null;\n}\n\nfunction getIncomingRelations(graph: Graph, nodePath: string): string[] {\n const incoming: string[] = [];\n for (const [fromPath, node] of graph.nodes) {\n for (const rel of node.meta.relations ?? []) {\n if (rel.target === nodePath) {\n incoming.push(fromPath);\n break;\n }\n }\n }\n return incoming.sort();\n}\n\nfunction checkRequiredArtifacts(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const artifacts = graph.config.artifacts ?? {};\n\n for (const [nodePath, node] of graph.nodes) {\n for (const [filename, config] of Object.entries(artifacts)) {\n const hasArtifact = node.artifacts.some((a) => a.filename === filename);\n const reason = artifactRequiredReason(graph, nodePath, node, config.required);\n\n if (reason && !hasArtifact) {\n const action = config.description ?? '';\n const incoming = getIncomingRelations(graph, nodePath);\n const incomingStr =\n incoming.length > 0\n ? ` Node has ${incoming.length} incoming relation(s): ${incoming.slice(0, 5).join(', ')}${incoming.length > 5 ? '...' : ''}.`\n : '';\n const msg = action\n ? `Missing required artifact '${filename}' (${reason}).${incomingStr} ${action}`\n : `Missing required artifact '${filename}' (${reason}).${incomingStr}`;\n issues.push({\n severity: 'warning',\n code: 'W001',\n rule: 'missing-artifact',\n message: msg.trim(),\n nodePath,\n });\n }\n }\n }\n\n return issues;\n}\n\n// --- E006: Broken flow refs (flow.nodes) ---\n\nfunction checkBrokenFlowRefs(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const nodePaths = new Set(graph.nodes.keys());\n for (const flow of graph.flows) {\n for (const n of flow.nodes) {\n if (!nodePaths.has(n)) {\n issues.push({\n severity: 'error',\n code: 'E006',\n rule: 'broken-flow-ref',\n message: `Flow '${flow.name}' references non-existent node '${n}'`,\n });\n }\n }\n }\n return issues;\n}\n\n// --- E007: Flow aspect ids must have corresponding aspect ---\n\nfunction checkFlowAspectIds(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const validAspectIds = new Set(graph.aspects.map((a) => a.id));\n\n for (const flow of graph.flows) {\n for (const aspectId of flow.aspects ?? []) {\n if (!validAspectIds.has(aspectId)) {\n issues.push({\n severity: 'error',\n code: 'E007',\n rule: 'broken-aspect-ref',\n message: `Flow '${flow.name}' references aspect '${aspectId}' but no aspect with that id exists in aspects/`,\n });\n }\n }\n }\n return issues;\n}\n\n// --- E013: Invalid artifact condition (has_aspect:X where X has no aspect) ---\n\nfunction checkInvalidArtifactConditions(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const validAspectIds = new Set(graph.aspects.map((a) => a.id));\n const artifacts = graph.config.artifacts ?? {};\n for (const [artifactName, config] of Object.entries(artifacts)) {\n const required = config.required;\n if (typeof required === 'object' && required && 'when' in required) {\n const when = (required as { when: string }).when;\n if (when.startsWith('has_aspect:') || when.startsWith('has_tag:')) {\n const prefix = when.startsWith('has_aspect:') ? 'has_aspect:' : 'has_tag:';\n const aspectId = when.slice(prefix.length);\n if (!validAspectIds.has(aspectId)) {\n issues.push({\n severity: 'error',\n code: 'E013',\n rule: 'invalid-artifact-condition',\n message: `Artifact '${artifactName}' condition has_aspect:${aspectId} has no corresponding aspect in aspects/`,\n });\n }\n }\n }\n }\n return issues;\n}\n\n// --- W002: Shallow artifacts (below min_artifact_length) ---\n\nasync function checkShallowArtifacts(graph: Graph): Promise<ValidationIssue[]> {\n const issues: ValidationIssue[] = [];\n const minLen = graph.config.quality?.min_artifact_length ?? 50;\n for (const [nodePath, node] of graph.nodes) {\n for (const art of node.artifacts) {\n if (art.content.trim().length < minLen) {\n issues.push({\n severity: 'warning',\n code: 'W002',\n rule: 'shallow-artifact',\n message: `Artifact '${art.filename}' is below minimum length (${art.content.trim().length} < ${minLen})`,\n nodePath,\n });\n }\n }\n }\n return issues;\n}\n\n// --- W007: High fan-out (exceeds max_direct_relations) ---\n\nfunction checkHighFanOut(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const maxRel = graph.config.quality?.max_direct_relations ?? 10;\n for (const [nodePath, node] of graph.nodes) {\n const count = node.meta.relations?.length ?? 0;\n if (count > maxRel) {\n issues.push({\n severity: 'warning',\n code: 'W007',\n rule: 'high-fan-out',\n message: `Node has ${count} direct relations (max: ${maxRel})`,\n nodePath,\n });\n }\n }\n return issues;\n}\n\n// --- W009: Unpaired event relations (emits without listens or vice versa) ---\n\nfunction checkUnpairedEvents(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const emitsTo = new Map<string, Set<string>>();\n const listensFrom = new Map<string, Set<string>>();\n for (const [nodePath, node] of graph.nodes) {\n for (const rel of node.meta.relations ?? []) {\n if (rel.type === 'emits') {\n const set = emitsTo.get(nodePath) ?? new Set();\n set.add(rel.target);\n emitsTo.set(nodePath, set);\n }\n if (rel.type === 'listens') {\n const set = listensFrom.get(nodePath) ?? new Set();\n set.add(rel.target);\n listensFrom.set(nodePath, set);\n }\n }\n }\n for (const [emitter, targets] of emitsTo) {\n for (const target of targets) {\n const listenerSet = listensFrom.get(target);\n if (!listenerSet?.has(emitter)) {\n issues.push({\n severity: 'warning',\n code: 'W009',\n rule: 'unpaired-event',\n message: `Node '${emitter}' emits to '${target}' but '${target}' has no listens from '${emitter}'`,\n nodePath: emitter,\n });\n }\n }\n }\n for (const [listener, sources] of listensFrom) {\n for (const source of sources) {\n const emitterSet = emitsTo.get(source);\n if (!emitterSet?.has(listener)) {\n issues.push({\n severity: 'warning',\n code: 'W009',\n rule: 'unpaired-event',\n message: `Node '${listener}' listens from '${source}' but '${source}' has no emits to '${listener}'`,\n nodePath: listener,\n });\n }\n }\n }\n return issues;\n}\n\n// --- Schema validation (required graph-layer schemas present in schemas/) ---\n\nconst REQUIRED_SCHEMAS = ['node', 'aspect', 'flow'] as const;\n\nfunction checkSchemas(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const present = new Set(graph.schemas.map((s) => s.schemaType));\n\n for (const required of REQUIRED_SCHEMAS) {\n if (!present.has(required)) {\n issues.push({\n severity: 'warning',\n code: 'W010',\n rule: 'missing-schema',\n message: `Schema 'yg-${required}.yaml' missing from .yggdrasil/schemas/`,\n });\n }\n }\n\n return issues;\n}\n\n// --- Directories have yg-node.yaml ---\n\nasync function checkDirectoriesHaveNodeYaml(graph: Graph): Promise<ValidationIssue[]> {\n const issues: ValidationIssue[] = [];\n const modelDir = path.join(graph.rootPath, 'model');\n\n async function scanDir(dirPath: string, segments: string[]): Promise<void> {\n const entries = await readdir(dirPath, { withFileTypes: true });\n const hasNodeYaml = entries.some((e) => e.isFile() && e.name === 'yg-node.yaml');\n const dirName = path.basename(dirPath);\n\n if (RESERVED_DIRS.has(dirName)) return;\n\n const hasFiles = entries.some((e) => e.isFile());\n const hasSubdirs = entries.some((e) => e.isDirectory() && !RESERVED_DIRS.has(e.name) && !e.name.startsWith('.'));\n const graphPath = segments.join('/');\n\n if (!hasNodeYaml && graphPath !== '') {\n if (hasFiles) {\n issues.push({\n severity: 'error',\n code: 'E015',\n rule: 'missing-node-yaml',\n message: `Directory '${graphPath}' has files but no yg-node.yaml`,\n nodePath: graphPath,\n });\n } else if (hasSubdirs) {\n issues.push({\n severity: 'warning',\n code: 'W013',\n rule: 'directory-without-node',\n message: `Directory '${graphPath}' has subdirectories but no yg-node.yaml — consider creating a node`,\n nodePath: graphPath,\n });\n }\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n if (RESERVED_DIRS.has(entry.name)) continue;\n if (entry.name.startsWith('.')) continue;\n await scanDir(path.join(dirPath, entry.name), [...segments, entry.name]);\n }\n }\n\n try {\n const rootEntries = await readdir(modelDir, { withFileTypes: true });\n for (const entry of rootEntries) {\n if (!entry.isDirectory()) continue;\n if (entry.name.startsWith('.')) continue;\n await scanDir(path.join(modelDir, entry.name), [entry.name]);\n }\n } catch {\n // model/ may not exist\n }\n\n return issues;\n}\n\n// --- Anchor validation (E019, W014) ---\n\nasync function expandMappingToFiles(projectRoot: string, mappingPaths: string[]): Promise<string[]> {\n const files: string[] = [];\n\n async function collectFiles(absPath: string): Promise<void> {\n try {\n const s = await stat(absPath);\n if (s.isFile()) {\n files.push(absPath);\n } else if (s.isDirectory()) {\n const entries = await readdir(absPath, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.name.startsWith('.') || entry.name === 'node_modules') continue;\n const entryPath = path.join(absPath, entry.name);\n if (entry.isFile()) {\n files.push(entryPath);\n } else if (entry.isDirectory()) {\n await collectFiles(entryPath);\n }\n }\n }\n } catch {\n // Skip inaccessible paths\n }\n }\n\n for (const mp of mappingPaths) {\n await collectFiles(path.join(projectRoot, mp));\n }\n return files;\n}\n\nasync function checkAnchorPresence(graph: Graph): Promise<ValidationIssue[]> {\n const issues: ValidationIssue[] = [];\n const projectRoot = path.dirname(graph.rootPath);\n\n for (const [nodePath, node] of graph.nodes) {\n const aspectsWithAnchors = (node.meta.aspects ?? []).filter(a => a.anchors && a.anchors.length > 0);\n if (aspectsWithAnchors.length === 0) continue;\n\n // W014: check anchor strings exist in source files\n const mappingPaths = normalizeMappingPaths(node.meta.mapping);\n if (mappingPaths.length === 0) continue;\n\n const sourceFiles = await expandMappingToFiles(projectRoot, mappingPaths);\n if (sourceFiles.length === 0) continue;\n\n const fileContents: string[] = [];\n for (const filePath of sourceFiles) {\n try {\n const content = await readFile(filePath, 'utf-8');\n fileContents.push(content);\n } catch {\n // Skip unreadable files\n }\n }\n\n for (const entry of aspectsWithAnchors) {\n for (const anchor of entry.anchors!) {\n const found = fileContents.some((content) => content.includes(anchor));\n if (!found) {\n issues.push({\n severity: 'warning',\n code: 'W014',\n rule: 'anchor-not-found',\n message: `Anchor '${anchor}' for aspect '${entry.aspect}' not found in mapped source files`,\n nodePath,\n });\n }\n }\n }\n }\n\n return issues;\n}\n\n// --- Context budget (W005 warning, W006 error) ---\n\nasync function checkContextBudget(graph: Graph): Promise<ValidationIssue[]> {\n const issues: ValidationIssue[] = [];\n const warningThreshold = graph.config.quality?.context_budget.warning ?? 10000;\n const errorThreshold = graph.config.quality?.context_budget.error ?? 20000;\n\n for (const [nodePath, node] of graph.nodes) {\n if (node.meta.blackbox) continue;\n try {\n const pkg = await buildContext(graph, nodePath);\n if (pkg.tokenCount >= errorThreshold) {\n issues.push({\n severity: 'warning',\n code: 'W006',\n rule: 'budget-error',\n message: `Context is ${pkg.tokenCount.toLocaleString()} tokens (error threshold: ${errorThreshold.toLocaleString()}) — blocks materialization, node must be split`,\n nodePath,\n });\n } else if (pkg.tokenCount >= warningThreshold) {\n issues.push({\n severity: 'warning',\n code: 'W005',\n rule: 'budget-warning',\n message: `Context is ${pkg.tokenCount.toLocaleString()} tokens (warning threshold: ${warningThreshold.toLocaleString()}). Consider splitting the node or reducing dependencies.`,\n nodePath,\n });\n }\n } catch {\n // If context building fails, other rules will catch it\n }\n }\n return issues;\n}\n","import type { ContextPackage, ContextLayer } from '../model/types.js';\n\nfunction escapeAttr(val: string): string {\n return val.replace(/\"/g, '&quot;');\n}\n\nfunction formatLayer(layer: ContextLayer): string {\n switch (layer.type) {\n case 'global':\n return `<global>\\n${layer.content}\\n</global>`;\n case 'hierarchy': {\n const pathMatch = layer.label.match(/\\((.+)\\/\\)/);\n const pathAttr = pathMatch ? ` path=\"${escapeAttr(pathMatch[1])}\"` : '';\n const aspectsAttr = layer.attrs?.aspects ? ` aspects=\"${escapeAttr(layer.attrs.aspects)}\"` : '';\n return `<hierarchy${pathAttr}${aspectsAttr}>\\n${layer.content}\\n</hierarchy>`;\n }\n case 'own': {\n if (layer.label === 'Materialization Target') {\n return `<materialization-target paths=\"${escapeAttr(layer.content)}\" />`;\n }\n const ownAspectsAttr = layer.attrs?.aspects ? ` aspects=\"${escapeAttr(layer.attrs.aspects)}\"` : '';\n return `<own-artifacts${ownAspectsAttr}>\\n${layer.content}\\n</own-artifacts>`;\n }\n case 'aspects': {\n const nameMatch = layer.label.match(/^(.+?) \\(aspect: (.+)\\)$/);\n const name = nameMatch ? escapeAttr(nameMatch[1]) : '';\n const id = nameMatch ? escapeAttr(nameMatch[2]) : '';\n return `<aspect name=\"${name}\" id=\"${id}\">\\n${layer.content}\\n</aspect>`;\n }\n case 'relational': {\n const attrs = layer.attrs ?? {};\n const attrStr = Object.entries(attrs)\n .map(([k, v]) => ` ${k}=\"${escapeAttr(v)}\"`)\n .join('');\n const tagName = attrs.type && ['emits', 'listens'].includes(attrs.type) ? 'event' : 'dependency';\n return `<${tagName}${attrStr}>\\n${layer.content}\\n</${tagName}>`;\n }\n case 'flows': {\n const flowName = layer.label.replace(/^Flow: /, '').trim();\n const flowAspectsAttr = layer.attrs?.aspects ? ` aspects=\"${escapeAttr(layer.attrs.aspects)}\"` : '';\n return `<flow name=\"${escapeAttr(flowName)}\"${flowAspectsAttr}>\\n${layer.content}\\n</flow>`;\n }\n default:\n return layer.content;\n }\n}\n\nexport function formatContextText(pkg: ContextPackage): string {\n const attrs = [\n `node-path=\"${escapeAttr(pkg.nodePath)}\"`,\n `node-name=\"${escapeAttr(pkg.nodeName)}\"`,\n `token-count=\"${pkg.tokenCount}\"`,\n ].join(' ');\n\n let out = `<context-package ${attrs}>\\n\\n`;\n\n for (const section of pkg.sections) {\n for (const layer of section.layers) {\n out += formatLayer(layer) + '\\n\\n';\n }\n }\n\n out += '</context-package>';\n return out;\n}\n","import { Command } from 'commander';\nimport { loadGraph } from '../core/graph-loader.js';\nimport { buildContext, collectAncestors } from '../core/context-builder.js';\nimport { validate } from '../core/validator.js';\nimport { formatContextText } from '../formatters/context-text.js';\nimport type { Graph } from '../model/types.js';\n\n/**\n * Collect the set of node paths that participate in context assembly for a given node:\n * the node itself, its ancestors, and its direct relation targets.\n */\nfunction collectRelevantNodePaths(graph: Graph, nodePath: string): Set<string> {\n const relevant = new Set<string>();\n const node = graph.nodes.get(nodePath);\n if (!node) return relevant;\n\n relevant.add(nodePath);\n\n // Ancestors (hierarchy)\n for (const ancestor of collectAncestors(node)) {\n relevant.add(ancestor.path);\n }\n\n // Direct relation targets\n for (const rel of node.meta.relations ?? []) {\n relevant.add(rel.target);\n }\n\n return relevant;\n}\n\nexport function registerBuildCommand(program: Command): void {\n program\n .command('build-context')\n .description('Assemble a context package for one node')\n .requiredOption('--node <node-path>', 'Node path relative to .yggdrasil/model/')\n .action(async (options: { node: string }) => {\n try {\n const graph = await loadGraph(process.cwd());\n const nodePath = options.node.trim().replace(/^\\.\\//, '').replace(/\\/$/, '');\n\n // Collect nodes relevant to this context assembly\n const relevantNodes = collectRelevantNodePaths(graph, nodePath);\n\n // Validate but only block on errors relevant to this node's context\n const validationResult = await validate(graph, 'all');\n const relevantErrors = validationResult.issues.filter(\n (issue) =>\n issue.severity === 'error' &&\n // Global errors (no nodePath) always block — e.g., E012 invalid config\n (!issue.nodePath || relevantNodes.has(issue.nodePath)),\n );\n if (relevantErrors.length > 0) {\n const totalErrors = validationResult.issues.filter((i) => i.severity === 'error').length;\n const skippedErrors = totalErrors - relevantErrors.length;\n let msg = `Error: build-context blocked by ${relevantErrors.length} error(s) affecting this node's context.\\n`;\n if (skippedErrors > 0) {\n msg += `(${skippedErrors} unrelated error(s) in other nodes ignored.)\\n`;\n }\n for (const err of relevantErrors) {\n const loc = err.nodePath ? `${err.nodePath}: ` : '';\n msg += ` ${err.code ?? ''} ${loc}${err.message}\\n`;\n }\n process.stderr.write(msg);\n process.exit(1);\n }\n\n const pkg = await buildContext(graph, nodePath);\n const warningThreshold = graph.config.quality?.context_budget.warning ?? 10000;\n const errorThreshold = graph.config.quality?.context_budget.error ?? 20000;\n const budgetStatus =\n pkg.tokenCount >= errorThreshold\n ? 'error'\n : pkg.tokenCount >= warningThreshold\n ? 'warning'\n : 'ok';\n\n let output = formatContextText(pkg);\n output += `Budget status: ${budgetStatus}\\n`;\n process.stdout.write(output);\n\n if (budgetStatus === 'error') {\n process.stderr.write(\n `Warning: context package exceeds error budget (${pkg.tokenCount} >= ${errorThreshold}). Consider splitting the node.\\n`,\n );\n }\n } catch (error) {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n process.exit(1);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { loadGraph } from '../core/graph-loader.js';\nimport { validate } from '../core/validator.js';\n\nexport function registerValidateCommand(program: Command): void {\n program\n .command('validate')\n .description('Validate graph structural integrity and completeness signals')\n .option('--scope <scope>', 'Scope: all or node-path (default: all)', 'all')\n .action(async (options: { scope: string }) => {\n try {\n const graph = await loadGraph(process.cwd(), { tolerateInvalidConfig: true });\n const rawScope = (options.scope ?? 'all').trim() || 'all';\n const scope = rawScope === 'all' ? 'all' : rawScope.replace(/^\\.\\//, '').replace(/\\/+$/, '');\n const result = await validate(graph, scope);\n process.stdout.write(`${result.nodesScanned} nodes scanned\\n\\n`);\n const errors = result.issues.filter((i) => i.severity === 'error');\n const warnings = result.issues.filter((i) => i.severity === 'warning');\n for (const issue of errors) {\n const code = issue.code ?? '';\n const loc = issue.nodePath ?? '';\n const prefix = loc ? `${code} ${loc} -> ` : `${code} `;\n process.stdout.write(chalk.red(`✗ ${prefix}${issue.message}\\n`));\n }\n for (const issue of warnings) {\n const code = issue.code ?? '';\n const loc = issue.nodePath ?? '';\n const prefix = loc ? `${code} ${loc} -> ` : `${code} `;\n process.stdout.write(chalk.yellow(`⚠ ${prefix}${issue.message}\\n`));\n }\n if (errors.length === 0 && warnings.length === 0) {\n process.stdout.write(chalk.green('✓ No issues found.\\n'));\n } else {\n process.stdout.write(`\\n${errors.length} errors, ${warnings.length} warnings.\\n`);\n }\n\n const hasErrors = result.issues.some((i) => i.severity === 'error');\n process.exit(hasErrors ? 1 : 0);\n } catch (error) {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n process.exit(1);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { loadGraph } from '../core/graph-loader.js';\nimport { detectDrift } from '../core/drift-detector.js';\nimport type { DriftEntry, DriftReport } from '../model/types.js';\n\nexport function registerDriftCommand(program: Command): void {\n program\n .command('drift')\n .description('Detect divergences between graph and mapped files')\n .option('--scope <scope>', 'Scope: \"all\" or node path', 'all')\n .option('--drifted-only', 'Show only nodes with drift (hide ok entries)')\n .option('--limit <n>', 'Maximum number of entries to show per section', parseInt)\n .action(async (opts: { scope: string; driftedOnly?: boolean; limit?: number }) => {\n try {\n const graph = await loadGraph(process.cwd());\n const rawScope = (opts.scope ?? 'all').trim() || 'all';\n const scope = rawScope === 'all' ? 'all' : rawScope.replace(/^\\.\\//, '').replace(/\\/+$/, '');\n\n if (scope !== 'all') {\n const node = graph.nodes.get(scope);\n if (!node) {\n process.stderr.write(`Error: Node not found: ${scope}\\n`);\n process.exit(1);\n }\n // Check if scope or any descendant has a mapping\n const hasAnyMapping = node.meta.mapping ||\n [...graph.nodes.entries()].some(([p, n]) => p.startsWith(scope + '/') && n.meta.mapping);\n if (!hasAnyMapping) {\n process.stderr.write(`Error: Node has no mapping: ${scope}\\n`);\n process.exit(1);\n }\n }\n\n const scopeNode = scope === 'all' ? undefined : scope;\n const report = await detectDrift(graph, scopeNode);\n printReport(report, opts.driftedOnly ?? false, opts.limit);\n\n const hasIssues =\n report.sourceDriftCount > 0 ||\n report.graphDriftCount > 0 ||\n report.fullDriftCount > 0 ||\n report.missingCount > 0 ||\n report.unmaterializedCount > 0;\n process.exit(hasIssues ? 1 : 0);\n } catch (error) {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n process.exit(1);\n }\n });\n}\n\nfunction printReport(report: DriftReport, driftedOnly: boolean, limit?: number): void {\n const sourceEntries = classifyForSection(report.entries, 'source', driftedOnly);\n const graphEntries = classifyForSection(report.entries, 'graph', driftedOnly);\n\n const sourceShown = limit !== undefined ? sourceEntries.slice(0, limit) : sourceEntries;\n const graphShown = limit !== undefined ? graphEntries.slice(0, limit) : graphEntries;\n\n process.stdout.write('Source drift:\\n');\n printSectionEntries(sourceShown, 'source');\n if (limit !== undefined && sourceEntries.length > limit) {\n process.stdout.write(chalk.dim(` ... ${sourceEntries.length - limit} more (${sourceEntries.length} total)\\n`));\n }\n\n process.stdout.write('\\nGraph drift:\\n');\n printSectionEntries(graphShown, 'graph');\n if (limit !== undefined && graphEntries.length > limit) {\n process.stdout.write(chalk.dim(` ... ${graphEntries.length - limit} more (${graphEntries.length} total)\\n`));\n }\n\n // Summary line\n const parts: string[] = [\n `${report.sourceDriftCount} source-drift`,\n `${report.graphDriftCount} graph-drift`,\n `${report.fullDriftCount} full-drift`,\n `${report.missingCount} missing`,\n `${report.unmaterializedCount} unmaterialized`,\n ];\n\n let summary = `\\nSummary: ${parts.join(', ')}`;\n if (driftedOnly && report.okCount > 0) {\n summary += ` (${report.okCount} ok hidden)`;\n } else {\n summary += `, ${report.okCount} ok`;\n }\n process.stdout.write(summary + '\\n');\n}\n\n/**\n * Classify entries for a given section (source or graph).\n * Source section shows: source-drift, full-drift, missing, unmaterialized, ok\n * Graph section shows: graph-drift, full-drift, ok\n */\nfunction classifyForSection(\n entries: DriftEntry[],\n section: 'source' | 'graph',\n driftedOnly: boolean,\n): DriftEntry[] {\n return entries.filter((entry) => {\n if (section === 'source') {\n // Source section: source-drift, full-drift, missing, unmaterialized, ok\n if (entry.status === 'graph-drift') return false;\n if (entry.status === 'ok' && driftedOnly) return false;\n return true;\n } else {\n // Graph section: graph-drift, full-drift, ok\n if (\n entry.status === 'source-drift' ||\n entry.status === 'missing' ||\n entry.status === 'unmaterialized'\n )\n return false;\n if (entry.status === 'ok' && driftedOnly) return false;\n return true;\n }\n });\n}\n\nfunction printSectionEntries(entries: DriftEntry[], section: 'source' | 'graph'): void {\n if (entries.length === 0) {\n process.stdout.write(chalk.dim(' (none)\\n'));\n return;\n }\n\n for (const entry of entries) {\n printEntryLine(entry);\n printChangedFiles(entry, section);\n }\n}\n\nfunction printEntryLine(entry: DriftEntry): void {\n const pad = 13; // width for status label column\n switch (entry.status) {\n case 'ok':\n process.stdout.write(chalk.green(` ${'[ok]'.padEnd(pad)}${entry.nodePath}\\n`));\n break;\n case 'source-drift':\n process.stdout.write(chalk.red(` ${'[drift]'.padEnd(pad)}${entry.nodePath}\\n`));\n break;\n case 'graph-drift':\n process.stdout.write(chalk.magenta(` ${'[drift]'.padEnd(pad)}${entry.nodePath}\\n`));\n break;\n case 'full-drift':\n process.stdout.write(chalk.red(` ${'[drift]'.padEnd(pad)}${entry.nodePath}\\n`));\n break;\n case 'missing':\n process.stdout.write(chalk.yellow(` ${'[missing]'.padEnd(pad)}${entry.nodePath}\\n`));\n break;\n case 'unmaterialized':\n process.stdout.write(chalk.dim(` ${'[unmat.]'.padEnd(pad)}${entry.nodePath}\\n`));\n break;\n }\n}\n\nfunction printChangedFiles(entry: DriftEntry, section: 'source' | 'graph'): void {\n if (!entry.changedFiles || entry.changedFiles.length === 0) return;\n\n const indent = ' '.repeat(15); // align under node path\n const relevantFiles = entry.changedFiles.filter((f) => {\n if (section === 'source') return f.category === 'source';\n return f.category === 'graph';\n });\n\n for (const file of relevantFiles) {\n process.stdout.write(chalk.dim(`${indent}${file.filePath} (changed)\\n`));\n }\n}\n","import { readFile, writeFile, stat, readdir, mkdir, rm } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse as yamlParse } from 'yaml';\nimport type { DriftState, DriftNodeState } from '../model/types.js';\n\nconst DRIFT_STATE_DIR = '.drift-state';\n\n/** Convert node path to per-node state file path under .drift-state/ */\nfunction nodeStatePath(yggRoot: string, nodePath: string): string {\n return path.join(yggRoot, DRIFT_STATE_DIR, `${nodePath}.json`);\n}\n\n/**\n * Recursively scan a directory for .json files.\n * Returns array of paths relative to baseDir (without .json extension).\n */\nasync function scanJsonFiles(dir: string, baseDir: string): Promise<string[]> {\n const results: string[] = [];\n let entries;\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n return results;\n }\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n const nested = await scanJsonFiles(fullPath, baseDir);\n results.push(...nested);\n } else if (entry.isFile() && entry.name.endsWith('.json')) {\n const relPath = path.relative(baseDir, fullPath);\n // Remove .json extension and normalize to posix\n const nodePath = relPath.replace(/\\\\/g, '/').replace(/\\.json$/, '');\n results.push(nodePath);\n }\n }\n return results;\n}\n\n/**\n * Remove empty directories walking up from filePath to (but not including) stopDir.\n */\nasync function removeEmptyParents(filePath: string, stopDir: string): Promise<void> {\n let dir = path.dirname(filePath);\n while (dir !== stopDir && dir.startsWith(stopDir)) {\n try {\n const entries = await readdir(dir);\n if (entries.length === 0) {\n await rm(dir, { recursive: true });\n dir = path.dirname(dir);\n } else {\n break;\n }\n } catch {\n break;\n }\n }\n}\n\n/** Read a single node's drift state from .drift-state/<nodePath>.json */\nexport async function readNodeDriftState(\n yggRoot: string,\n nodePath: string,\n): Promise<DriftNodeState | undefined> {\n try {\n const filePath = nodeStatePath(yggRoot, nodePath);\n const content = await readFile(filePath, 'utf-8');\n const parsed = JSON.parse(content) as DriftNodeState;\n return parsed;\n } catch {\n return undefined;\n }\n}\n\n/** Write a single node's drift state to .drift-state/<nodePath>.json */\nexport async function writeNodeDriftState(\n yggRoot: string,\n nodePath: string,\n nodeState: DriftNodeState,\n): Promise<void> {\n const filePath = nodeStatePath(yggRoot, nodePath);\n await mkdir(path.dirname(filePath), { recursive: true });\n const content = JSON.stringify(nodeState, null, 2) + '\\n';\n await writeFile(filePath, content, 'utf-8');\n}\n\n/**\n * Garbage-collect drift state: remove .json files for node paths NOT in validNodePaths.\n * Cleans up empty parent directories after removal.\n * Returns sorted list of removed node paths.\n */\nexport async function garbageCollectDriftState(\n yggRoot: string,\n validNodePaths: Set<string>,\n): Promise<string[]> {\n const driftDir = path.join(yggRoot, DRIFT_STATE_DIR);\n const allNodePaths = await scanJsonFiles(driftDir, driftDir);\n const removed: string[] = [];\n\n for (const nodePath of allNodePaths) {\n if (!validNodePaths.has(nodePath)) {\n const filePath = nodeStatePath(yggRoot, nodePath);\n await rm(filePath);\n await removeEmptyParents(filePath, driftDir);\n removed.push(nodePath);\n }\n }\n\n return removed.sort();\n}\n\n/**\n * Read full drift state.\n * - If .drift-state is a directory: scan for per-node .json files.\n * - If .drift-state is a file (legacy): parse it, migrate to per-node files, delete old file.\n * - If .drift-state doesn't exist: return {}.\n */\nexport async function readDriftState(yggRoot: string): Promise<DriftState> {\n const driftPath = path.join(yggRoot, DRIFT_STATE_DIR);\n\n let driftStat;\n try {\n driftStat = await stat(driftPath);\n } catch {\n return {};\n }\n\n // Legacy single-file format: migrate to per-node files\n if (driftStat.isFile()) {\n const content = await readFile(driftPath, 'utf-8');\n let raw: unknown;\n try {\n raw = JSON.parse(content);\n } catch {\n raw = yamlParse(content);\n }\n\n if (!raw || typeof raw !== 'object') return {};\n\n const state: DriftState = {};\n for (const [key, value] of Object.entries(raw)) {\n if (typeof value === 'object' && value !== null && 'hash' in value) {\n state[key] = value as DriftNodeState;\n }\n // Skip legacy string entries silently\n }\n\n // Migrate: delete old file, write per-node files\n await rm(driftPath);\n for (const [nodePath, nodeState] of Object.entries(state)) {\n await writeNodeDriftState(yggRoot, nodePath, nodeState);\n }\n\n return state;\n }\n\n // Directory format: scan for per-node .json files\n const nodePaths = await scanJsonFiles(driftPath, driftPath);\n const state: DriftState = {};\n for (const nodePath of nodePaths) {\n const nodeState = await readNodeDriftState(yggRoot, nodePath);\n if (nodeState) {\n state[nodePath] = nodeState;\n }\n }\n return state;\n}\n\n/**\n * Write full drift state as per-node files.\n * Each entry is written as a separate .json file under .drift-state/.\n */\nexport async function writeDriftState(yggRoot: string, state: DriftState): Promise<void> {\n for (const [nodePath, nodeState] of Object.entries(state)) {\n await writeNodeDriftState(yggRoot, nodePath, nodeState);\n }\n}\n","import { readFile, readdir, stat } from 'node:fs/promises';\nimport path from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { createRequire } from 'node:module';\nimport { type Ignore, type Options as IgnoreOptions } from 'ignore';\nimport type { TrackedFile } from '../core/context-files.js';\n\nconst require = createRequire(import.meta.url);\nconst ignoreFactory = require('ignore') as (options?: IgnoreOptions) => Ignore;\n\ntype HashPathOptions = {\n projectRoot?: string;\n};\n\ntype GitignoreEntry = { basePath: string; matcher: Ignore };\n\nexport async function hashFile(filePath: string): Promise<string> {\n const content = await readFile(filePath);\n return createHash('sha256').update(content).digest('hex');\n}\n\nexport async function hashPath(targetPath: string, options: HashPathOptions = {}): Promise<string> {\n const projectRoot = options.projectRoot ? path.resolve(options.projectRoot) : undefined;\n const gitignoreStack = await loadRootGitignoreStack(projectRoot);\n const targetStat = await stat(targetPath);\n\n if (targetStat.isFile()) {\n // Mapped files are always hashed — gitignore only applies to directory scans.\n return hashFile(targetPath);\n }\n\n if (targetStat.isDirectory()) {\n const fileHashes = await collectDirectoryFileHashes(targetPath, targetPath, {\n projectRoot,\n gitignoreStack,\n });\n const digestInput = fileHashes\n .sort((a, b) => a.path.localeCompare(b.path))\n .map((entry) => `${entry.path}:${entry.hash}`)\n .join('\\n');\n return hashString(digestInput);\n }\n\n throw new Error(`Unsupported mapping path type: ${targetPath}`);\n}\n\nasync function collectDirectoryFileHashes(\n directoryPath: string,\n rootDirectoryPath: string,\n options: { projectRoot?: string; gitignoreStack?: GitignoreEntry[] },\n): Promise<Array<{ path: string; hash: string }>> {\n const filePaths = await collectDirectoryFilePaths(directoryPath, rootDirectoryPath, options);\n const result: Array<{ path: string; hash: string }> = [];\n for (const entry of filePaths) {\n result.push({ path: entry.relPath, hash: await hashFile(entry.absPath) });\n }\n return result;\n}\n\nasync function loadRootGitignoreStack(projectRoot?: string): Promise<GitignoreEntry[]> {\n if (!projectRoot) return [];\n try {\n const content = await readFile(path.join(projectRoot, '.gitignore'), 'utf-8');\n const matcher = ignoreFactory();\n matcher.add(content);\n return [{ basePath: projectRoot, matcher }];\n } catch {\n return [];\n }\n}\n\nfunction isIgnoredByStack(candidatePath: string, stack: GitignoreEntry[]): boolean {\n for (const { basePath, matcher } of stack) {\n const relativePath = path.relative(basePath, candidatePath);\n if (relativePath === '' || relativePath.startsWith('..')) continue;\n if (matcher.ignores(relativePath) || matcher.ignores(relativePath + '/')) return true;\n }\n return false;\n}\n\nexport function hashString(content: string): string {\n return createHash('sha256').update(content).digest('hex');\n}\n\n/** Compute per-file hashes for a mapping. Used for diagnostics (which files changed). */\nexport async function perFileHashes(\n projectRoot: string,\n mapping: { paths?: string[] },\n): Promise<Array<{ path: string; hash: string }>> {\n const root = path.resolve(projectRoot);\n const paths = mapping.paths ?? [];\n if (paths.length === 0) return [];\n\n const result: Array<{ path: string; hash: string }> = [];\n const gitignoreStack = await loadRootGitignoreStack(root);\n\n for (const p of paths) {\n const absPath = path.join(root, p);\n const st = await stat(absPath);\n if (st.isFile()) {\n result.push({ path: p, hash: await hashFile(absPath) });\n } else if (st.isDirectory()) {\n const hashes = await collectDirectoryFileHashes(absPath, absPath, {\n projectRoot: root,\n gitignoreStack,\n });\n for (const h of hashes) {\n result.push({\n path: path.join(p, h.path).split(path.sep).join('/'),\n hash: h.hash,\n });\n }\n }\n }\n\n return result;\n}\n\n/** Compute drift hash for a node mapping. Returns hex. */\nexport async function hashForMapping(\n projectRoot: string,\n mapping: { paths?: string[] },\n): Promise<string> {\n const root = path.resolve(projectRoot);\n const paths = mapping.paths ?? [];\n if (paths.length === 0) throw new Error('Invalid mapping for hash: no paths');\n\n const pairs: Array<{ path: string; hash: string }> = [];\n\n for (const p of paths) {\n const absPath = path.join(root, p);\n const st = await stat(absPath);\n if (st.isFile()) {\n pairs.push({ path: p, hash: await hashFile(absPath) });\n } else if (st.isDirectory()) {\n const dirHash = await hashPath(absPath, { projectRoot: root });\n pairs.push({ path: p, hash: dirHash });\n }\n }\n\n const digestInput = pairs\n .sort((a, b) => a.path.localeCompare(b.path))\n .map((e) => `${e.path}:${e.hash}`)\n .join('\\n');\n return createHash('sha256').update(digestInput).digest('hex');\n}\n\n/** Stored file data for mtime-based drift optimization. */\nexport interface StoredFileData {\n hashes: Record<string, string>;\n mtimes: Record<string, number>;\n}\n\n/**\n * Hash all tracked files (source + graph) for bidirectional drift detection.\n * Directories in the tracked list are expanded to their contained files.\n * Returns a canonical hash (sorted path:hash digest), per-file hashes, and mtimes.\n *\n * When `storedFileData` is provided, files whose mtime has not changed since\n * the last sync will reuse the stored hash instead of re-reading and hashing.\n * This makes the common case (no changes) nearly instant even for large mappings.\n */\nexport async function hashTrackedFiles(\n projectRoot: string,\n trackedFiles: TrackedFile[],\n storedFileData?: StoredFileData,\n excludePrefixes?: string[],\n): Promise<{ canonicalHash: string; fileHashes: Record<string, string>; fileMtimes: Record<string, number> }> {\n const fileHashes: Record<string, string> = {};\n const fileMtimes: Record<string, number> = {};\n const gitignoreStack = await loadRootGitignoreStack(projectRoot);\n\n // Collect all file entries (expanding directories) with their metadata\n type FileEntry = { relPath: string; absPath: string; mtimeMs: number };\n const allFiles: FileEntry[] = [];\n\n for (const tf of trackedFiles) {\n const absPath = path.join(projectRoot, tf.path);\n try {\n const st = await stat(absPath);\n if (st.isDirectory()) {\n const dirEntries = await collectDirectoryFilePaths(absPath, absPath, {\n projectRoot,\n gitignoreStack,\n });\n for (const entry of dirEntries) {\n allFiles.push({\n relPath: path.join(tf.path, entry.relPath).replace(/\\\\/g, '/'),\n absPath: entry.absPath,\n mtimeMs: entry.mtimeMs,\n });\n }\n } else {\n allFiles.push({ relPath: tf.path, absPath, mtimeMs: st.mtimeMs });\n }\n } catch {\n continue;\n }\n }\n\n // Exclude files owned by descendant nodes (child-wins model)\n const filtered = excludePrefixes?.length\n ? allFiles.filter((entry) =>\n !excludePrefixes.some((prefix) =>\n entry.relPath === prefix || entry.relPath.startsWith(prefix + '/')))\n : allFiles;\n\n // Separate files into cached (mtime match) and dirty (need hashing)\n const dirty: FileEntry[] = [];\n for (const entry of filtered) {\n const storedMtime = storedFileData?.mtimes[entry.relPath];\n const storedHash = storedFileData?.hashes[entry.relPath];\n if (storedMtime !== undefined && storedHash !== undefined && entry.mtimeMs === storedMtime) {\n fileHashes[entry.relPath] = storedHash;\n } else {\n dirty.push(entry);\n }\n fileMtimes[entry.relPath] = entry.mtimeMs;\n }\n\n // Hash dirty files in parallel batches to avoid overwhelming file descriptors\n const BATCH_SIZE = 256;\n for (let i = 0; i < dirty.length; i += BATCH_SIZE) {\n const batch = dirty.slice(i, i + BATCH_SIZE);\n const hashes = await Promise.all(batch.map((e) => hashFile(e.absPath)));\n for (let j = 0; j < batch.length; j++) {\n fileHashes[batch[j].relPath] = hashes[j];\n }\n }\n\n // Canonical hash: sorted path:hash pairs\n const sorted = Object.entries(fileHashes).sort(([a], [b]) => a.localeCompare(b));\n const digest = sorted.map(([p, h]) => `${p}:${h}`).join('\\n');\n const canonicalHash = hashString(digest);\n\n return { canonicalHash, fileHashes, fileMtimes };\n}\n\n/**\n * Collect file paths and mtimes from a directory without hashing.\n * Used by hashTrackedFiles to separate discovery from hashing,\n * enabling mtime-based optimization.\n *\n * Directory recursion and file stat() calls are parallelized for performance.\n */\nasync function collectDirectoryFilePaths(\n directoryPath: string,\n rootDirectoryPath: string,\n options: { projectRoot?: string; gitignoreStack?: GitignoreEntry[] },\n): Promise<Array<{ relPath: string; absPath: string; mtimeMs: number }>> {\n let stack = options.gitignoreStack ?? [];\n try {\n const localContent = await readFile(path.join(directoryPath, '.gitignore'), 'utf-8');\n const localMatcher = ignoreFactory();\n localMatcher.add(localContent);\n stack = [...stack, { basePath: directoryPath, matcher: localMatcher }];\n } catch {\n // No local .gitignore\n }\n\n const entries = await readdir(directoryPath, { withFileTypes: true });\n const dirs: string[] = [];\n const files: string[] = [];\n\n for (const entry of entries) {\n const absoluteChildPath = path.join(directoryPath, entry.name);\n if (isIgnoredByStack(absoluteChildPath, stack)) continue;\n if (entry.isDirectory()) dirs.push(absoluteChildPath);\n else if (entry.isFile()) files.push(absoluteChildPath);\n }\n\n // Parallel: recurse into directories AND stat files concurrently\n const [dirResults, fileStats] = await Promise.all([\n Promise.all(dirs.map((d) => collectDirectoryFilePaths(d, rootDirectoryPath, {\n projectRoot: options.projectRoot,\n gitignoreStack: stack,\n }))),\n Promise.all(files.map(async (f) => {\n const fileStat = await stat(f);\n return {\n relPath: path.relative(rootDirectoryPath, f),\n absPath: f,\n mtimeMs: fileStat.mtimeMs,\n };\n })),\n ]);\n\n const result: Array<{ relPath: string; absPath: string; mtimeMs: number }> = [];\n for (const nested of dirResults) result.push(...nested);\n result.push(...fileStats);\n return result;\n}\n","import path from 'node:path';\nimport type { Graph, GraphNode, DriftCategory, FlowDef } from '../model/types.js';\nimport { normalizeMappingPaths } from '../utils/paths.js';\nimport { collectAncestors, resolveAspects } from './context-builder.js';\n\nexport interface TrackedFile {\n path: string; // relative to project root\n category: DriftCategory; // 'source' or 'graph'\n}\n\nconst STRUCTURAL_RELATION_TYPES = new Set(['uses', 'calls', 'extends', 'implements']);\n\n/**\n * Collect all files tracked by a node's context package.\n * Mirrors the traversal of build-context but returns file paths\n * instead of rendered content. This is the core function for\n * bidirectional drift detection.\n *\n * Synchronous — no I/O needed; all data comes from the loaded Graph.\n */\nexport function collectTrackedFiles(node: GraphNode, graph: Graph): TrackedFile[] {\n const seen = new Set<string>();\n const result: TrackedFile[] = [];\n\n // Compute the .yggdrasil prefix relative to project root.\n // graph.rootPath is absolute path to .yggdrasil/; project root is its parent.\n const projectRoot = path.dirname(graph.rootPath);\n const yggPrefix = path.relative(projectRoot, graph.rootPath);\n // Normalize to forward slashes for consistency\n const yggPrefixNormalized = yggPrefix.split(path.sep).join('/');\n\n const configArtifactKeys = new Set(Object.keys(graph.config.artifacts ?? {}));\n\n function addFile(filePath: string, category: DriftCategory): void {\n if (seen.has(filePath)) return;\n seen.add(filePath);\n result.push({ path: filePath, category });\n }\n\n function graphPath(...segments: string[]): string {\n return [yggPrefixNormalized, ...segments].join('/');\n }\n\n function addNodeFiles(n: GraphNode): void {\n // yg-node.yaml\n addFile(graphPath('model', n.path, 'yg-node.yaml'), 'graph');\n // artifacts filtered by config\n for (const art of n.artifacts) {\n if (configArtifactKeys.has(art.filename)) {\n addFile(graphPath('model', n.path, art.filename), 'graph');\n }\n }\n }\n\n // 1. OWN — yg-node.yaml + config-filtered artifacts\n addNodeFiles(node);\n\n // 2. HIERARCHICAL — ancestors from root to parent\n const ancestors = collectAncestors(node);\n for (const ancestor of ancestors) {\n addNodeFiles(ancestor);\n }\n\n // 3. ASPECTS — resolve all aspects from own + ancestors + flows (with recursive implies)\n // First, collect all aspect ids from own node and ancestors\n const allAspectIds = new Set<string>();\n\n for (const entry of node.meta.aspects ?? []) {\n allAspectIds.add(entry.aspect);\n }\n for (const ancestor of ancestors) {\n for (const entry of ancestor.meta.aspects ?? []) {\n allAspectIds.add(entry.aspect);\n }\n }\n\n // Collect participating flows (same logic as build-context)\n const participatingFlows = collectParticipatingFlows(graph, node, ancestors);\n\n // Add flow-propagated aspects\n for (const flow of participatingFlows) {\n for (const id of flow.aspects ?? []) {\n allAspectIds.add(id);\n }\n }\n\n // Resolve with recursive implies\n const resolvedAspects = resolveAspects(allAspectIds, graph.aspects);\n for (const aspect of resolvedAspects) {\n addFile(graphPath('aspects', aspect.id, 'yg-aspect.yaml'), 'graph');\n for (const art of aspect.artifacts) {\n addFile(graphPath('aspects', aspect.id, art.filename), 'graph');\n }\n }\n\n // 4. RELATIONAL-DEPS — structural relations (uses/calls/extends/implements)\n for (const relation of node.meta.relations ?? []) {\n if (!STRUCTURAL_RELATION_TYPES.has(relation.type)) continue;\n const target = graph.nodes.get(relation.target);\n if (!target) continue;\n\n // Determine which artifacts to include from the target\n const structuralFilenames = Object.entries(graph.config.artifacts ?? {})\n .filter(([, c]) => c.included_in_relations)\n .map(([filename]) => filename);\n\n // Check if the target actually has any of the included_in_relations artifacts\n const structuralArts = structuralFilenames.filter((filename) =>\n target.artifacts.some((a) => a.filename === filename),\n );\n\n if (structuralArts.length > 0) {\n // Use only included_in_relations artifacts that exist on target\n for (const filename of structuralArts) {\n addFile(graphPath('model', target.path, filename), 'graph');\n }\n } else {\n // Fallback: all config-allowed artifacts\n for (const art of target.artifacts) {\n if (configArtifactKeys.has(art.filename)) {\n addFile(graphPath('model', target.path, art.filename), 'graph');\n }\n }\n }\n }\n\n // 5. RELATIONAL-FLOWS — yg-flow.yaml + flow artifacts for participating flows\n for (const flow of participatingFlows) {\n addFile(graphPath('flows', flow.path, 'yg-flow.yaml'), 'graph');\n for (const art of flow.artifacts) {\n addFile(graphPath('flows', flow.path, art.filename), 'graph');\n }\n }\n\n // 6. SOURCE — files from mapping.paths\n const mappingPaths = normalizeMappingPaths(node.meta.mapping);\n for (const p of mappingPaths) {\n addFile(p, 'source');\n }\n\n return result;\n}\n\n/**\n * Find all flows where the node or any of its ancestors is a participant.\n * Same logic as collectParticipatingFlows in context-builder.ts.\n */\nfunction collectParticipatingFlows(\n graph: Graph,\n node: GraphNode,\n ancestors: GraphNode[],\n): FlowDef[] {\n const paths = new Set<string>([node.path, ...ancestors.map((a) => a.path)]);\n return graph.flows.filter((f) => f.nodes.some((n) => paths.has(n)));\n}\n","import type {\n Graph,\n DriftReport,\n DriftEntry,\n DriftStatus,\n DriftFileChange,\n DriftCategory,\n} from '../model/types.js';\nimport {\n readDriftState,\n readNodeDriftState,\n writeNodeDriftState,\n} from '../io/drift-state-store.js';\nimport { hashTrackedFiles } from '../utils/hash.js';\nimport { collectTrackedFiles } from './context-files.js';\nimport { normalizeMappingPaths } from '../utils/paths.js';\nimport { access } from 'node:fs/promises';\nimport path from 'node:path';\n\n/**\n * Compute mapping paths owned by descendant nodes that overlap with a node's own\n * mapping paths. Used to exclude child-owned files from parent drift hashing\n * (\"child wins\" model).\n */\nfunction getChildMappingExclusions(graph: Graph, nodePath: string): string[] {\n const node = graph.nodes.get(nodePath);\n if (!node) return [];\n const parentMappings = normalizeMappingPaths(node.meta.mapping);\n if (parentMappings.length === 0) return [];\n\n const exclusions: string[] = [];\n for (const [childPath, childNode] of graph.nodes) {\n if (childPath === nodePath) continue;\n if (!childPath.startsWith(nodePath + '/')) continue; // not a descendant\n const childMappings = normalizeMappingPaths(childNode.meta.mapping);\n for (const cm of childMappings) {\n for (const pm of parentMappings) {\n if (cm === pm || cm.startsWith(pm + '/')) {\n exclusions.push(cm);\n }\n }\n }\n }\n return exclusions;\n}\n\nexport async function detectDrift(graph: Graph, filterNodePath?: string): Promise<DriftReport> {\n const projectRoot = path.dirname(graph.rootPath);\n const driftState = await readDriftState(graph.rootPath);\n const entries: DriftEntry[] = [];\n\n for (const [nodePath, node] of graph.nodes) {\n if (filterNodePath && nodePath !== filterNodePath && !nodePath.startsWith(filterNodePath + '/')) continue;\n const mapping = node.meta.mapping;\n if (!mapping) continue;\n\n const mappingPaths = normalizeMappingPaths(mapping);\n if (mappingPaths.length === 0) continue;\n\n const storedEntry = driftState[nodePath];\n\n if (!storedEntry) {\n const allMissing = await allPathsMissing(projectRoot, mappingPaths);\n entries.push({\n nodePath,\n status: allMissing ? 'unmaterialized' : 'source-drift',\n details: allMissing\n ? 'No drift state recorded, files do not exist'\n : 'No drift state recorded, files exist (run drift-sync after materialization)',\n });\n continue;\n }\n\n // Check if source files are entirely missing (all mapping paths gone)\n // This must happen BEFORE hash comparison — a node whose source files\n // are all gone is 'missing' regardless of whether graph-only hashes match.\n const sourceFilesMissing = await allPathsMissing(projectRoot, mappingPaths);\n if (sourceFilesMissing) {\n entries.push({\n nodePath,\n status: 'missing',\n details: 'All source mapping paths are missing',\n });\n continue;\n }\n\n // Collect all tracked files (source + graph) for this node\n const trackedFiles = collectTrackedFiles(node, graph);\n // Exclude files owned by descendant nodes (child-wins model)\n const excludePrefixes = getChildMappingExclusions(graph, nodePath);\n // Pass stored file data for mtime-based optimization: skip hashing files whose\n // modification time has not changed since the last drift-sync.\n const storedFileData = storedEntry.files\n ? { hashes: storedEntry.files, mtimes: storedEntry.mtimes ?? {} }\n : undefined;\n const { canonicalHash, fileHashes } = await hashTrackedFiles(projectRoot, trackedFiles, storedFileData, excludePrefixes);\n\n if (canonicalHash === storedEntry.hash) {\n entries.push({ nodePath, status: 'ok' });\n continue;\n }\n\n // Something changed — determine what\n const changedFiles: DriftFileChange[] = [];\n const storedFiles = storedEntry.files;\n\n // Check current files against stored\n for (const [filePath, hash] of Object.entries(fileHashes)) {\n const storedHash = storedFiles[filePath];\n if (!storedHash || storedHash !== hash) {\n changedFiles.push({\n filePath,\n category: categorizeFile(filePath, graph.rootPath, projectRoot),\n });\n }\n }\n\n // Check for deleted files (in stored but not in current)\n for (const storedPath of Object.keys(storedFiles)) {\n if (!(storedPath in fileHashes)) {\n changedFiles.push({\n filePath: `${storedPath} (deleted)`,\n category: categorizeFile(storedPath, graph.rootPath, projectRoot),\n });\n }\n }\n\n // Determine drift status from changed file categories\n const hasSourceChanges = changedFiles.some((f) => f.category === 'source');\n const hasGraphChanges = changedFiles.some((f) => f.category === 'graph');\n\n let status: DriftStatus;\n if (hasSourceChanges && hasGraphChanges) {\n status = 'full-drift';\n } else if (hasGraphChanges) {\n status = 'graph-drift';\n } else if (hasSourceChanges) {\n status = 'source-drift';\n } else {\n // Hash changed but no individual file identified — fallback\n status = 'source-drift';\n }\n\n const details =\n changedFiles.length > 0\n ? `Changed files: ${changedFiles.map((f) => f.filePath).join(', ')}`\n : 'File(s) modified since last sync';\n\n entries.push({ nodePath, status, details, changedFiles });\n }\n\n return {\n entries,\n totalChecked: entries.length,\n okCount: entries.filter((e) => e.status === 'ok').length,\n sourceDriftCount: entries.filter((e) => e.status === 'source-drift').length,\n graphDriftCount: entries.filter((e) => e.status === 'graph-drift').length,\n fullDriftCount: entries.filter((e) => e.status === 'full-drift').length,\n missingCount: entries.filter((e) => e.status === 'missing').length,\n unmaterializedCount: entries.filter((e) => e.status === 'unmaterialized').length,\n };\n}\n\n/**\n * Categorize a file path as 'source' or 'graph' based on whether it lives\n * under the .yggdrasil/ directory.\n */\nfunction categorizeFile(filePath: string, _rootPath: string, projectRoot: string): DriftCategory {\n const yggPrefix = path.relative(projectRoot, _rootPath);\n const normalizedPrefix = yggPrefix.split(path.sep).join('/');\n const normalizedFilePath = filePath.replace(/\\\\/g, '/');\n return normalizedFilePath.startsWith(normalizedPrefix) ? 'graph' : 'source';\n}\n\nasync function allPathsMissing(projectRoot: string, mappingPaths: string[]): Promise<boolean> {\n for (const mp of mappingPaths) {\n const absPath = path.join(projectRoot, mp);\n try {\n await access(absPath);\n return false;\n } catch {\n // path missing\n }\n }\n return true;\n}\n\nexport async function syncDriftState(\n graph: Graph,\n nodePath: string,\n): Promise<{ previousHash?: string; currentHash: string }> {\n const projectRoot = path.dirname(graph.rootPath);\n const node = graph.nodes.get(nodePath);\n if (!node) throw new Error(`Node not found: ${nodePath}`);\n if (!node.meta.mapping) throw new Error(`Node has no mapping: ${nodePath}`);\n\n const trackedFiles = collectTrackedFiles(node, graph);\n const excludePrefixes = getChildMappingExclusions(graph, nodePath);\n // For sync, pass stored data so unchanged files can reuse cached hashes.\n const existingEntry = await readNodeDriftState(graph.rootPath, nodePath);\n const storedFileData = existingEntry?.files\n ? { hashes: existingEntry.files, mtimes: existingEntry.mtimes ?? {} }\n : undefined;\n const { canonicalHash, fileHashes, fileMtimes } = await hashTrackedFiles(projectRoot, trackedFiles, storedFileData, excludePrefixes);\n\n const previousHash = existingEntry?.hash;\n\n await writeNodeDriftState(graph.rootPath, nodePath, {\n hash: canonicalHash,\n files: fileHashes,\n mtimes: fileMtimes,\n });\n\n return { previousHash, currentHash: canonicalHash };\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { loadGraph } from '../core/graph-loader.js';\nimport { syncDriftState } from '../core/drift-detector.js';\nimport { garbageCollectDriftState } from '../io/drift-state-store.js';\nimport { normalizeMappingPaths } from '../utils/paths.js';\n\nexport function registerDriftSyncCommand(program: Command): void {\n program\n .command('drift-sync')\n .description('Record current file hash after resolving drift')\n .option('--node <path>', 'Node path to sync')\n .option('--recursive', 'Also sync all descendant nodes')\n .option('--all', 'Sync all nodes with mappings')\n .action(async (options: { node?: string; recursive?: boolean; all?: boolean }) => {\n try {\n if (!options.node && !options.all) {\n process.stderr.write(\"Error: either '--node <path>' or '--all' is required\\n\");\n process.exit(1);\n }\n\n const graph = await loadGraph(process.cwd());\n\n let nodesToSync: string[];\n\n if (options.all) {\n nodesToSync = [...graph.nodes.entries()]\n .filter(([, n]) => normalizeMappingPaths(n.meta.mapping).length > 0)\n .map(([p]) => p)\n .sort();\n } else {\n const nodePath = options.node!.trim().replace(/^\\.\\//, '').replace(/\\/+$/, '');\n\n if (!graph.nodes.has(nodePath)) {\n await syncDriftState(graph, nodePath); // will throw with proper error\n return;\n }\n\n nodesToSync = [nodePath];\n if (options.recursive) {\n const prefix = nodePath + '/';\n for (const [p] of graph.nodes) {\n if (p.startsWith(prefix)) {\n nodesToSync.push(p);\n }\n }\n nodesToSync.sort();\n }\n }\n\n for (const np of nodesToSync) {\n const node = graph.nodes.get(np)!;\n if (normalizeMappingPaths(node.meta.mapping).length === 0) {\n if (!options.all && !options.recursive && np === options.node) {\n await syncDriftState(graph, np); // will throw with proper error\n }\n continue;\n }\n const { previousHash, currentHash } = await syncDriftState(graph, np);\n process.stdout.write(chalk.green(`Synchronized: ${np}\\n`));\n process.stdout.write(\n ` Hash: ${previousHash ? previousHash.slice(0, 8) : 'none'} -> ${currentHash.slice(0, 8)}\\n`,\n );\n }\n\n // Garbage collect orphaned drift state files after --all sync\n if (options.all) {\n const validPaths = new Set(nodesToSync);\n const removed = await garbageCollectDriftState(graph.rootPath, validPaths);\n for (const r of removed) {\n process.stdout.write(chalk.dim(`Removed orphaned drift state: ${r}\\n`));\n }\n }\n } catch (error) {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n process.exit(1);\n }\n });\n}\n","import { Command } from 'commander';\nimport { loadGraph } from '../core/graph-loader.js';\nimport { detectDrift } from '../core/drift-detector.js';\nimport { validate } from '../core/validator.js';\nimport { collectEffectiveAspectIds } from '../core/context-builder.js';\nimport { normalizeMappingPaths } from '../utils/paths.js';\n\nexport function registerStatusCommand(program: Command): void {\n program\n .command('status')\n .description('Show graph summary')\n .action(async () => {\n try {\n const graph = await loadGraph(process.cwd());\n\n // Count nodes by type\n const typeCounts = new Map<string, number>();\n let blackboxCount = 0;\n\n for (const node of graph.nodes.values()) {\n typeCounts.set(node.meta.type, (typeCounts.get(node.meta.type) ?? 0) + 1);\n if (node.meta.blackbox) blackboxCount++;\n }\n\n // Count relations\n let structuralRelations = 0;\n let eventRelations = 0;\n const structuralTypes = new Set(['uses', 'calls', 'extends', 'implements']);\n let maxRelCount = 0;\n let maxRelNode = '';\n for (const node of graph.nodes.values()) {\n const relCount = (node.meta.relations ?? []).length;\n if (relCount > maxRelCount) {\n maxRelCount = relCount;\n maxRelNode = node.path;\n }\n for (const rel of node.meta.relations ?? []) {\n if (structuralTypes.has(rel.type)) structuralRelations += 1;\n else eventRelations += 1;\n }\n }\n\n const flowCount = graph.flows.length;\n\n const drift = await detectDrift(graph);\n const validation = await validate(graph, 'all');\n const errorCount = validation.issues.filter((issue) => issue.severity === 'error').length;\n const warningCount = validation.issues.filter(\n (issue) => issue.severity === 'warning',\n ).length;\n\n // Quality metrics\n const configuredArtifactTypes = Object.keys(graph.config.artifacts ?? {});\n const totalSlots = graph.nodes.size * configuredArtifactTypes.length;\n let filledSlots = 0;\n let mappedNodeCount = 0;\n\n for (const node of graph.nodes.values()) {\n const allowed = new Set(configuredArtifactTypes);\n filledSlots += node.artifacts.filter((a) => allowed.has(a.filename)).length;\n if (normalizeMappingPaths(node.meta.mapping).length > 0) mappedNodeCount++;\n }\n\n let aspectCoveredNodes = 0;\n for (const node of graph.nodes.values()) {\n const effective = collectEffectiveAspectIds(graph, node.path);\n if (effective.size > 0) aspectCoveredNodes++;\n }\n\n process.stdout.write(`Graph: ${graph.config.name}\\n`);\n const pluralize = (word: string, count: number) =>\n count === 1 ? word : word.endsWith('y') ? word.slice(0, -1) + 'ies' : word + 's';\n const typeStr = [...typeCounts.entries()]\n .map(([t, c]) => `${c} ${pluralize(t, c)}`)\n .join(', ');\n process.stdout.write(\n `Nodes: ${graph.nodes.size} (${typeStr}) + ${blackboxCount} blackbox\\n`,\n );\n process.stdout.write(\n `Relations: ${structuralRelations} structural, ${eventRelations} event\\n`,\n );\n process.stdout.write(\n `Aspects: ${graph.aspects.length} Flows: ${flowCount}\\n`,\n );\n process.stdout.write(\n `Drift: ${drift.sourceDriftCount} source-drift, ${drift.graphDriftCount} graph-drift, ${drift.fullDriftCount} full-drift, ${drift.missingCount} missing, ${drift.unmaterializedCount} unmaterialized, ${drift.okCount} ok\\n`,\n );\n process.stdout.write(`Validation: ${errorCount} errors, ${warningCount} warnings\\n`);\n\n // Quality section\n const fillPct = totalSlots > 0 ? Math.round((filledSlots / totalSlots) * 100) : 0;\n const totalRelations = structuralRelations + eventRelations;\n const avgRel = graph.nodes.size > 0 ? (totalRelations / graph.nodes.size).toFixed(1) : '0';\n process.stdout.write(`\\nQuality:\\n`);\n process.stdout.write(\n ` Artifacts: ${filledSlots}/${totalSlots} slots filled (${fillPct}%) — ${configuredArtifactTypes.length} types × ${graph.nodes.size} nodes\\n`,\n );\n process.stdout.write(\n ` Relations: avg ${avgRel}/node, max ${maxRelCount}${maxRelNode ? ` (${maxRelNode})` : ''}\\n`,\n );\n process.stdout.write(\n ` Mapping: ${mappedNodeCount}/${graph.nodes.size} nodes mapped to source\\n`,\n );\n process.stdout.write(\n ` Aspects: ${aspectCoveredNodes}/${graph.nodes.size} nodes have aspect coverage\\n`,\n );\n } catch (error) {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n process.exit(1);\n }\n });\n}\n","import { Command } from 'commander';\nimport { loadGraph } from '../core/graph-loader.js';\nimport type { GraphNode } from '../model/types.js';\n\nexport function registerTreeCommand(program: Command): void {\n program\n .command('tree')\n .description('Display graph structure as a tree')\n .option('--root <path>', 'Show only subtree rooted at this path')\n .option('--depth <n>', 'Maximum depth', (v) => parseInt(v, 10))\n .action(async (options: { root?: string; depth?: number }) => {\n try {\n const graph = await loadGraph(process.cwd());\n\n let roots: GraphNode[];\n let showProjectName: boolean;\n\n if (options.root?.trim()) {\n const path = options.root.trim().replace(/\\/$/, '');\n const node = graph.nodes.get(path);\n if (!node) {\n process.stderr.write(`Error: path '${path}' not found\\n`);\n process.exit(1);\n }\n roots = [node];\n showProjectName = false;\n } else {\n roots = [...graph.nodes.values()]\n .filter((n) => n.parent === null)\n .sort((a, b) => a.path.localeCompare(b.path));\n showProjectName = true;\n }\n\n if (showProjectName) {\n process.stdout.write('model/\\n');\n }\n\n for (let i = 0; i < roots.length; i++) {\n const isLast = i === roots.length - 1;\n printNode(roots[i], '', isLast, 1, options.depth);\n }\n } catch (error) {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n process.exit(1);\n }\n });\n}\n\nfunction printNode(\n node: GraphNode,\n prefix: string,\n isLast: boolean,\n depth: number,\n maxDepth: number | undefined,\n): void {\n const connector = isLast ? '└── ' : '├── ';\n const name = node.path.split('/').pop() ?? node.path;\n const type = `[${node.meta.type}]`;\n const tags = node.meta.aspects?.length ? ` aspects:${node.meta.aspects.join(',')}` : '';\n const blackbox = node.meta.blackbox ? ' ■ blackbox' : '';\n const relationCount = node.meta.relations?.length ?? 0;\n\n process.stdout.write(\n `${prefix}${connector}${name}/ ${type}${tags}${blackbox} -> ${relationCount} relations\\n`,\n );\n\n const childPrefix = prefix + (isLast ? ' ' : '│ ');\n\n // Recurse into children\n if (maxDepth !== undefined && depth >= maxDepth) return;\n\n const children = [...node.children].sort((a, b) => a.path.localeCompare(b.path));\n for (let i = 0; i < children.length; i++) {\n printNode(children[i], childPrefix, i === children.length - 1, depth + 1, maxDepth);\n }\n}\n","import path from 'node:path';\nimport { access } from 'node:fs/promises';\nimport { Command } from 'commander';\nimport { loadGraph } from '../core/graph-loader.js';\nimport type { Graph, OwnerResult } from '../model/types.js';\nimport { normalizeMappingPaths, normalizeProjectRelativePath, projectRootFromGraph } from '../utils/paths.js';\n\nfunction normalizeForMatch(inputPath: string): string {\n return inputPath.replace(/\\\\/g, '/').replace(/\\/+$/, '');\n}\n\nexport function findOwner(graph: Graph, projectRoot: string, rawPath: string): OwnerResult {\n const file = normalizeForMatch(normalizeProjectRelativePath(projectRoot, rawPath));\n let best: { nodePath: string; mappingPath: string; exact: boolean } | null = null;\n\n for (const [nodePath, node] of graph.nodes) {\n const mappingPaths = normalizeMappingPaths(node.meta.mapping)\n .map(normalizeForMatch)\n .filter((mappingPath) => mappingPath.length > 0);\n\n for (const mappingPath of mappingPaths) {\n if (file === mappingPath) {\n return { file, nodePath, mappingPath, direct: true };\n }\n if (file.startsWith(mappingPath + '/')) {\n if (!best || (best && mappingPath.length > best.mappingPath.length)) {\n best = { nodePath, mappingPath, exact: false };\n }\n }\n }\n }\n\n return best\n ? { file, nodePath: best.nodePath, mappingPath: best.mappingPath, direct: false }\n : { file, nodePath: null };\n}\n\nexport function registerOwnerCommand(program: Command): void {\n program\n .command('owner')\n .description('Find which graph node owns a source file')\n .requiredOption('--file <path>', 'File path (relative to repository root)')\n .action(async (options: { file: string }) => {\n try {\n const cwd = process.cwd();\n const graph = await loadGraph(cwd);\n // Resolve the file path relative to CWD (so subdirectory-relative paths work),\n // then make it relative to the actual repo root (where .yggdrasil/ lives).\n const repoRoot = projectRootFromGraph(graph.rootPath);\n const rawPath = options.file.trim();\n const absolute = path.resolve(cwd, rawPath);\n const repoRelative = path.relative(repoRoot, absolute).split(path.sep).join('/');\n const result = findOwner(graph, repoRoot, repoRelative);\n\n if (!result.nodePath) {\n // Distinguish \"file doesn't exist\" from \"file exists but not mapped\"\n const absPath = path.resolve(repoRoot, result.file);\n let exists = true;\n try { await access(absPath); } catch { exists = false; }\n if (exists) {\n process.stdout.write(`${result.file} -> no graph coverage\\n`);\n } else {\n process.stdout.write(`${result.file} -> no graph coverage (file not found)\\n`);\n }\n } else {\n process.stdout.write(`${result.file} -> ${result.nodePath}\\n`);\n if (result.direct === false && result.mappingPath) {\n process.stdout.write(\n ` Plik nie ma własnego mapowania; kontekst pochodzi z nadrzędnego katalogu ${result.mappingPath}. Użyj: yg build-context --node ${result.nodePath}\\n`,\n );\n }\n }\n } catch (error) {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n process.exit(1);\n }\n });\n}\n","import type { Graph, Stage } from '../model/types.js';\nimport { execSync } from 'node:child_process';\nimport path from 'node:path';\n\nexport interface ResolveOptions {\n mode: 'all' | 'changed' | 'node';\n nodePath?: string; // required when mode === 'node'\n ref?: string; // git ref for --changed mode (default: HEAD)\n depth?: number; // max depth for tree (when mode === 'node')\n relationType?: 'structural' | 'event' | 'all'; // filter for tree\n}\n\nconst STRUCTURAL_RELATION_TYPES = new Set(['uses', 'calls', 'extends', 'implements']);\nconst EVENT_RELATION_TYPES = new Set(['emits', 'listens']);\n\n/** Expand changed set with direct dependents only (one level, no cascade) */\nfunction expandWithDependents(graph: Graph, changed: string[]): string[] {\n const dependents = new Map<string, string[]>();\n for (const [nodePath, node] of graph.nodes) {\n for (const rel of node.meta.relations ?? []) {\n if (!STRUCTURAL_RELATION_TYPES.has(rel.type)) continue;\n const deps = dependents.get(rel.target) ?? [];\n deps.push(nodePath);\n dependents.set(rel.target, deps);\n }\n }\n\n const result = new Set<string>(changed);\n for (const node of changed) {\n for (const dep of dependents.get(node) ?? []) {\n result.add(dep);\n }\n }\n\n return [...result];\n}\n\n/** Find nodes whose graph files have changed according to git */\nexport function findChangedNodes(graph: Graph, ref?: string): string[] {\n const gitRef = ref ?? 'HEAD';\n const yggDirName = path.basename(graph.rootPath);\n const projectRoot = path.dirname(graph.rootPath);\n\n let changedFiles: string[];\n try {\n const output = execSync(`git diff --name-only ${gitRef} -- ${yggDirName}/`, {\n cwd: projectRoot,\n encoding: 'utf-8',\n }).trim();\n changedFiles = output ? output.split('\\n') : [];\n } catch {\n // If git diff fails (no commits, not a repo, etc.), fall back to empty\n changedFiles = [];\n }\n\n // Map changed file paths back to node paths\n const changedNodePaths = new Set<string>();\n for (const filePath of changedFiles) {\n // filePath is like \".yggdrasil/auth/login-service/yg-node.yaml\"\n // Strip the yggdrasil dir prefix to get \"auth/login-service/yg-node.yaml\"\n const relative = filePath.startsWith(yggDirName + '/')\n ? filePath.slice(yggDirName.length + 1)\n : filePath;\n\n // Walk up directories to find matching node paths (nodes are under model/)\n const parts = relative.split('/');\n const modelIdx = parts.indexOf('model');\n const startIdx = modelIdx >= 0 ? modelIdx + 1 : 0;\n for (let i = parts.length - 1; i >= startIdx + 1; i--) {\n const candidate = parts.slice(startIdx, i).join('/');\n if (graph.nodes.has(candidate)) {\n changedNodePaths.add(candidate);\n break;\n }\n }\n }\n\n return expandWithDependents(graph, [...changedNodePaths]);\n}\n\n/** Collect node and its transitive dependencies (for --node mode) */\nexport function collectTransitiveDeps(graph: Graph, nodePath: string): string[] {\n return collectTransitiveDepsFiltered(graph, nodePath, undefined, 'structural');\n}\n\n/** Filter relation types for inclusion */\nfunction filterRelationType(relType: string, filter: 'structural' | 'event' | 'all'): boolean {\n if (filter === 'all') return true;\n if (filter === 'structural') return STRUCTURAL_RELATION_TYPES.has(relType);\n if (filter === 'event') return EVENT_RELATION_TYPES.has(relType);\n return false;\n}\n\n/** Collect transitive deps with depth and type filter */\nfunction collectTransitiveDepsFiltered(\n graph: Graph,\n nodePath: string,\n maxDepth: number | undefined,\n relationType: 'structural' | 'event' | 'all',\n): string[] {\n const node = graph.nodes.get(nodePath);\n if (!node) {\n throw new Error(`Node not found: ${nodePath}`);\n }\n\n const result = new Set<string>();\n const queue: Array<{ path: string; depth: number }> = [{ path: nodePath, depth: 0 }];\n\n while (queue.length > 0) {\n const { path: p, depth } = queue.shift()!;\n if (result.has(p)) continue;\n result.add(p);\n if (maxDepth !== undefined && depth >= maxDepth) continue;\n\n const n = graph.nodes.get(p)!;\n for (const rel of n.meta.relations ?? []) {\n if (!filterRelationType(rel.type, relationType)) continue;\n if (!graph.nodes.has(rel.target)) {\n throw new Error(`Relation target not found: ${rel.target}`);\n }\n if (!result.has(rel.target)) {\n queue.push({ path: rel.target, depth: depth + 1 });\n }\n }\n }\n\n return [...result];\n}\n\n/** Tree node for dependency tree output */\nexport interface DepTreeNode {\n nodePath: string;\n relationType: string;\n relationTarget?: string;\n blackbox: boolean;\n children: DepTreeNode[];\n}\n\n/** Build dependency tree for a node (spec format) */\nexport function buildDependencyTree(\n graph: Graph,\n nodePath: string,\n options: { depth?: number; relationType?: 'structural' | 'event' | 'all' } = {},\n): DepTreeNode[] {\n const node = graph.nodes.get(nodePath);\n if (!node) {\n throw new Error(`Node not found: ${nodePath}`);\n }\n\n const maxDepth = options.depth ?? Infinity;\n const typeFilter = options.relationType ?? 'all';\n\n function buildChildren(\n fromPath: string,\n currentDepth: number,\n branch: Set<string>,\n ): DepTreeNode[] {\n if (currentDepth >= maxDepth) return [];\n const fromNode = graph.nodes.get(fromPath)!;\n const children: DepTreeNode[] = [];\n for (const rel of fromNode.meta.relations ?? []) {\n if (!filterRelationType(rel.type, typeFilter)) continue;\n if (!graph.nodes.has(rel.target)) continue;\n if (branch.has(rel.target)) continue;\n const targetNode = graph.nodes.get(rel.target)!;\n const nextBranch = new Set(branch);\n nextBranch.add(rel.target);\n children.push({\n nodePath: rel.target,\n relationType: rel.type,\n relationTarget: fromPath,\n blackbox: targetNode.meta.blackbox ?? false,\n children: buildChildren(rel.target, currentDepth + 1, nextBranch),\n });\n }\n return children;\n }\n\n return buildChildren(nodePath, 0, new Set([nodePath]));\n}\n\n/** Format tree as text (spec format) */\nexport function formatDependencyTree(\n graph: Graph,\n nodePath: string,\n options: { depth?: number; relationType?: 'structural' | 'event' | 'all' } = {},\n): string {\n const roots = buildDependencyTree(graph, nodePath, options);\n const lines: string[] = [nodePath];\n\n function formatNode(node: DepTreeNode, prefix: string, isLast: boolean): void {\n const connector = isLast ? '└── ' : '├── ';\n const blackbox = node.blackbox ? ' ■ blackbox' : '';\n lines.push(`${prefix}${connector}${node.relationType} ${node.nodePath}${blackbox}`);\n const childPrefix = prefix + (isLast ? ' ' : '│ ');\n const lastIdx = node.children.length - 1;\n node.children.forEach((c, i) => formatNode(c, childPrefix, i === lastIdx));\n }\n\n roots.forEach((r, i) => formatNode(r, '', i === roots.length - 1));\n return lines.join('\\n');\n}\n\nexport async function resolveDeps(graph: Graph, options: ResolveOptions): Promise<Stage[]> {\n let candidatePaths: string[];\n\n switch (options.mode) {\n case 'all':\n candidatePaths = [...graph.nodes.keys()];\n break;\n case 'changed':\n candidatePaths = findChangedNodes(graph, options.ref);\n break;\n case 'node':\n candidatePaths = collectTransitiveDeps(graph, options.nodePath!);\n break;\n }\n\n candidatePaths = candidatePaths.filter((p) => {\n const node = graph.nodes.get(p)!;\n return !node.meta.blackbox && node.meta.mapping;\n });\n\n if (candidatePaths.length === 0) return [];\n\n const candidateSet = new Set(candidatePaths);\n\n // Validate relations: broken relation = target not in graph\n for (const p of candidatePaths) {\n const node = graph.nodes.get(p)!;\n for (const rel of node.meta.relations ?? []) {\n if (!graph.nodes.has(rel.target)) {\n throw new Error(`Relation target not found: ${rel.target}`);\n }\n }\n }\n\n const inDegree = new Map<string, number>();\n const dependents = new Map<string, string[]>();\n\n for (const p of candidatePaths) {\n inDegree.set(p, 0);\n dependents.set(p, []);\n }\n\n for (const p of candidatePaths) {\n const node = graph.nodes.get(p)!;\n for (const rel of node.meta.relations ?? []) {\n if (!STRUCTURAL_RELATION_TYPES.has(rel.type)) continue;\n if (candidateSet.has(rel.target)) {\n inDegree.set(p, (inDegree.get(p) ?? 0) + 1);\n dependents.get(rel.target)!.push(p);\n }\n }\n }\n\n const stages: Stage[] = [];\n let queue = candidatePaths.filter((p) => inDegree.get(p) === 0);\n let stageNum = 1;\n const processed = new Set<string>();\n\n while (queue.length > 0) {\n stages.push({\n stage: stageNum,\n parallel: queue.length > 1,\n nodes: [...queue],\n });\n\n const nextQueue: string[] = [];\n for (const nodePath of queue) {\n processed.add(nodePath);\n for (const dep of dependents.get(nodePath) ?? []) {\n inDegree.set(dep, (inDegree.get(dep) ?? 0) - 1);\n if (inDegree.get(dep) === 0) {\n nextQueue.push(dep);\n }\n }\n }\n\n queue = nextQueue;\n stageNum++;\n }\n\n if (processed.size < candidatePaths.length) {\n const cycleNodes = candidatePaths.filter((p) => !processed.has(p));\n throw new Error(`Circular dependency detected involving: ${cycleNodes.join(', ')}`);\n }\n\n return stages;\n}\n","import { Command } from 'commander';\nimport { loadGraph } from '../core/graph-loader.js';\nimport { formatDependencyTree } from '../core/dependency-resolver.js';\n\nexport function registerDepsCommand(program: Command): void {\n program\n .command('deps')\n .description('Show direct and transitive node dependencies')\n .requiredOption('--node <path>', 'Node path relative to .yggdrasil/model/')\n .option('--depth <n>', 'Maximum depth for tree (when using --node)', (v) => parseInt(v, 10))\n .option('--type <type>', 'Relation type filter: structural, event, all (default: all)', 'all')\n .action(async (options: { node: string; depth?: number; type?: string }) => {\n try {\n const graph = await loadGraph(process.cwd());\n const typeFilter =\n options.type === 'structural' || options.type === 'event' || options.type === 'all'\n ? options.type\n : 'all';\n const nodePath = options.node.trim().replace(/^\\.\\//, '').replace(/\\/+$/, '');\n const text = formatDependencyTree(graph, nodePath, {\n depth: options.depth,\n relationType: typeFilter,\n });\n process.stdout.write(text + '\\n');\n } catch (error) {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n process.exit(1);\n }\n });\n}\n","import { mkdtemp, rm } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport path from 'node:path';\nimport { execSync } from 'node:child_process';\nimport { loadGraph } from './graph-loader.js';\nimport type { Graph } from '../model/types.js';\n\n/**\n * Load graph from a git ref (e.g. HEAD) by extracting .yggdrasil to temp dir.\n * Returns null if not a git repo, ref doesn't exist, or .yggdrasil not in ref.\n */\nexport async function loadGraphFromRef(\n projectRoot: string,\n ref: string = 'HEAD',\n): Promise<Graph | null> {\n const yggPath = '.yggdrasil';\n let tmpDir: string | null = null;\n\n try {\n execSync(`git rev-parse ${ref}`, { cwd: projectRoot, stdio: 'pipe' });\n } catch {\n return null;\n }\n\n try {\n tmpDir = await mkdtemp(path.join(tmpdir(), 'ygg-git-'));\n const archivePath = path.join(tmpDir, 'archive.tar');\n execSync(`git archive ${ref} ${yggPath} -o \"${archivePath}\"`, {\n cwd: projectRoot,\n stdio: 'pipe',\n });\n execSync(`tar -xf \"${archivePath}\" -C \"${tmpDir}\"`, { stdio: 'pipe' });\n const graph = await loadGraph(tmpDir);\n return graph;\n } catch {\n return null;\n } finally {\n if (tmpDir) {\n await rm(tmpDir, { recursive: true, force: true });\n }\n }\n}\n","import { Command } from 'commander';\nimport { loadGraph } from '../core/graph-loader.js';\nimport { loadGraphFromRef } from '../core/graph-from-git.js';\nimport {\n buildContext,\n collectAncestors,\n collectEffectiveAspectIds,\n} from '../core/context-builder.js';\nimport { detectDrift } from '../core/drift-detector.js';\nimport type { Graph } from '../model/types.js';\n\nconst STRUCTURAL_TYPES = new Set(['uses', 'calls', 'extends', 'implements']);\n\nexport function collectReverseDependents(\n graph: Graph,\n targetNode: string,\n): {\n direct: string[];\n allDependents: string[];\n reverse: Map<string, Set<string>>;\n relationFrom: Map<string, { type: string; consumes?: string[] }>;\n} {\n const reverse = new Map<string, Set<string>>();\n const relationFrom = new Map<string, { type: string; consumes?: string[] }>();\n for (const [nodePath, node] of graph.nodes) {\n for (const rel of node.meta.relations ?? []) {\n if (!STRUCTURAL_TYPES.has(rel.type)) continue;\n const deps = reverse.get(rel.target) ?? new Set<string>();\n deps.add(nodePath);\n reverse.set(rel.target, deps);\n relationFrom.set(`${nodePath}->${rel.target}`, {\n type: rel.type,\n consumes: rel.consumes,\n });\n }\n }\n\n const direct = [...(reverse.get(targetNode) ?? [])].sort();\n const seen = new Set<string>(direct);\n const queue = [...direct];\n while (queue.length > 0) {\n const current = queue.shift()!;\n for (const next of reverse.get(current) ?? []) {\n if (seen.has(next)) continue;\n seen.add(next);\n queue.push(next);\n }\n }\n\n return {\n direct,\n allDependents: [...seen].sort(),\n reverse,\n relationFrom,\n };\n}\n\nexport function buildTransitiveChains(\n targetNode: string,\n direct: string[],\n allDependents: string[],\n reverse: Map<string, Set<string>>,\n): string[] {\n const directSet = new Set(direct);\n const transitiveOnly = allDependents.filter((t) => !directSet.has(t));\n if (transitiveOnly.length === 0) return [];\n\n const parent = new Map<string, string>();\n const queue: string[] = [targetNode];\n const visited = new Set<string>([targetNode]);\n while (queue.length > 0) {\n const current = queue.shift()!;\n for (const next of reverse.get(current) ?? []) {\n if (visited.has(next)) continue;\n visited.add(next);\n parent.set(next, current);\n queue.push(next);\n }\n }\n\n const chains: string[] = [];\n for (const node of transitiveOnly) {\n const path: string[] = [];\n let current: string | undefined = node;\n while (current) {\n path.unshift(current);\n current = parent.get(current);\n }\n if (path.length >= 3) {\n chains.push(path.slice(1).map((p) => `<- ${p}`).join(' '));\n }\n }\n return chains.sort();\n}\n\nexport function collectDescendants(graph: Graph, nodePath: string): string[] {\n const node = graph.nodes.get(nodePath);\n if (!node) return [];\n const result: string[] = [];\n const stack = [...node.children];\n while (stack.length > 0) {\n const child = stack.pop()!;\n result.push(child.path);\n stack.push(...child.children);\n }\n return result.sort();\n}\n\nasync function runSimulation(\n graph: Graph,\n nodePaths: Iterable<string>,\n targetNodePath: string | null,\n): Promise<void> {\n const budget = graph.config.quality?.context_budget ?? { warning: 10000, error: 20000 };\n process.stdout.write('\\nChanges in context packages:\\n\\n');\n const baselineGraph = await loadGraphFromRef(process.cwd(), 'HEAD');\n const driftReport = await detectDrift(graph);\n const driftByNode = new Map(driftReport.entries.map((e) => [e.nodePath, e]));\n\n for (const dep of nodePaths) {\n try {\n const pkg = await buildContext(graph, dep);\n const status =\n pkg.tokenCount >= budget.error\n ? 'error'\n : pkg.tokenCount >= budget.warning\n ? 'warning'\n : 'ok';\n\n let baselineTokens: number | null = null;\n if (baselineGraph?.nodes.has(dep)) {\n try {\n const baselinePkg = await buildContext(baselineGraph, dep);\n baselineTokens = baselinePkg.tokenCount;\n } catch {\n /* ignore */\n }\n }\n\n const hasDepOnTarget =\n targetNodePath &&\n graph.nodes\n .get(dep)\n ?.meta.relations?.some(\n (r) => r.target === targetNodePath && STRUCTURAL_TYPES.has(r.type),\n );\n const changedLine = hasDepOnTarget\n ? ` + Changed dependency interface: ${targetNodePath}\\n`\n : '';\n\n const budgetLine =\n baselineTokens !== null\n ? ` Budget: ${baselineTokens} -> ${pkg.tokenCount} tokens (${status})\\n`\n : ` Budget: ${pkg.tokenCount} tokens (${status})\\n`;\n\n const driftEntry = driftByNode.get(dep);\n const driftLine =\n driftEntry && driftEntry.status !== 'ok'\n ? ` Mapped files (on-disk): ${driftEntry.status}${driftEntry.details ? ` (${driftEntry.details})` : ''}\\n`\n : driftEntry\n ? ` Mapped files (on-disk): ok\\n`\n : '';\n\n process.stdout.write(`${dep}:\\n${changedLine}${budgetLine}${driftLine}\\n`);\n } catch {\n process.stdout.write(`${dep}:\\n failed to build context\\n\\n`);\n }\n }\n}\n\nasync function handleAspectImpact(\n graph: Graph,\n aspectId: string,\n simulate?: boolean,\n): Promise<void> {\n const aspect = graph.aspects.find((a) => a.id === aspectId);\n if (!aspect) {\n process.stderr.write(`Aspect not found: ${aspectId}\\n`);\n process.exit(1);\n }\n\n const affected: Array<{ path: string; source: string }> = [];\n for (const [nodePath] of graph.nodes) {\n const effective = collectEffectiveAspectIds(graph, nodePath);\n if (effective.has(aspectId)) {\n const node = graph.nodes.get(nodePath)!;\n const ownAspectIds = new Set((node.meta.aspects ?? []).map(a => a.aspect));\n if (ownAspectIds.has(aspectId)) {\n affected.push({ path: nodePath, source: 'own' });\n } else {\n let fromHierarchy = false;\n let anc = node.parent;\n while (anc) {\n if ((anc.meta.aspects ?? []).some(a => a.aspect === aspectId)) {\n fromHierarchy = true;\n break;\n }\n anc = anc.parent;\n }\n if (fromHierarchy) {\n affected.push({ path: nodePath, source: `hierarchy from ${anc!.path}` });\n } else {\n const ancestorPaths = new Set([nodePath, ...collectAncestors(node).map((a) => a.path)]);\n const flow = graph.flows.find(\n (f) =>\n (f.aspects ?? []).includes(aspectId) &&\n f.nodes.some((n) => ancestorPaths.has(n)),\n );\n affected.push({ path: nodePath, source: flow ? `flow: ${flow.name}` : 'implied' });\n }\n }\n }\n }\n\n affected.sort((a, b) => a.path.localeCompare(b.path));\n\n const propagatingFlows = graph.flows\n .filter((f) => (f.aspects ?? []).includes(aspectId))\n .map((f) => f.name);\n\n const impliedBy = graph.aspects\n .filter((a) => (a.implies ?? []).includes(aspectId))\n .map((a) => a.id);\n const implies = aspect.implies ?? [];\n\n process.stdout.write(`Impact of changes in aspect ${aspectId}:\\n\\n`);\n process.stdout.write(`Affected nodes (${affected.length}):\\n`);\n if (affected.length === 0) {\n process.stdout.write(' (none)\\n');\n } else {\n for (const { path: p, source } of affected) {\n process.stdout.write(` ${p} (${source})\\n`);\n }\n }\n process.stdout.write(\n `\\nFlows propagating this aspect: ${propagatingFlows.length > 0 ? propagatingFlows.join(', ') : '(none)'}\\n`,\n );\n process.stdout.write(`Implied by: ${impliedBy.length > 0 ? impliedBy.join(', ') : '(none)'}\\n`);\n process.stdout.write(`Implies: ${implies.length > 0 ? implies.join(', ') : '(none)'}\\n`);\n process.stdout.write(`\\nTotal scope: ${affected.length} nodes, ${propagatingFlows.length} flows\\n`);\n\n if (simulate && affected.length > 0) {\n await runSimulation(\n graph,\n affected.map((a) => a.path),\n null,\n );\n }\n}\n\nasync function handleFlowImpact(\n graph: Graph,\n flowName: string,\n simulate?: boolean,\n): Promise<void> {\n const flow = graph.flows.find((f) => f.name === flowName || f.path === flowName);\n if (!flow) {\n process.stderr.write(`Flow not found: ${flowName}\\n`);\n process.exit(1);\n }\n\n const participants = new Set<string>();\n for (const nodePath of flow.nodes) {\n if (graph.nodes.has(nodePath)) {\n participants.add(nodePath);\n for (const desc of collectDescendants(graph, nodePath)) {\n participants.add(desc);\n }\n }\n }\n\n const sorted = [...participants].sort();\n const flowAspects = flow.aspects ?? [];\n\n process.stdout.write(`Impact of changes in flow ${flow.name}:\\n\\n`);\n process.stdout.write('Participants:\\n');\n if (sorted.length === 0) {\n process.stdout.write(' (none)\\n');\n } else {\n for (const p of sorted) {\n const isDeclared = flow.nodes.includes(p);\n const suffix = isDeclared ? '' : ' (descendant)';\n process.stdout.write(` ${p}${suffix}\\n`);\n }\n }\n process.stdout.write(\n `\\nFlow aspects: ${flowAspects.length > 0 ? flowAspects.join(', ') : '(none)'}\\n`,\n );\n process.stdout.write(`\\nTotal scope: ${sorted.length} nodes\\n`);\n\n if (simulate && sorted.length > 0) {\n await runSimulation(graph, sorted, null);\n }\n}\n\nexport function registerImpactCommand(program: Command): void {\n program\n .command('impact')\n .description('Show reverse dependency impact for a node, aspect, or flow')\n .option('--node <path>', 'Node path relative to .yggdrasil/model/')\n .option('--aspect <id>', 'Aspect id (directory path under aspects/)')\n .option('--flow <name>', 'Flow name (directory name under flows/)')\n .option('--method <name>', 'Filter impact to dependents consuming a specific method (requires --node)')\n .option('--simulate', 'Simulate context package impact (compare HEAD vs current)')\n .action(\n async (options: { node?: string; aspect?: string; flow?: string; method?: string; simulate?: boolean }) => {\n try {\n const modeCount = [options.node, options.aspect, options.flow].filter(Boolean).length;\n if (modeCount === 0) {\n process.stderr.write(\n 'Error: one of --node, --aspect, or --flow is required\\n',\n );\n process.exit(1);\n }\n if (modeCount > 1) {\n process.stderr.write(\n 'Error: --node, --aspect, and --flow are mutually exclusive\\n',\n );\n process.exit(1);\n }\n\n const graph = await loadGraph(process.cwd());\n\n if (options.aspect) {\n await handleAspectImpact(graph, options.aspect.trim(), options.simulate);\n return;\n }\n if (options.flow) {\n await handleFlowImpact(graph, options.flow.trim(), options.simulate);\n return;\n }\n\n const nodePath = options.node!.trim().replace(/^\\.\\//, '').replace(/\\/+$/, '');\n\n if (!graph.nodes.has(nodePath)) {\n process.stderr.write(`Node not found: ${nodePath}\\n`);\n process.exit(1);\n }\n\n if (options.method && !options.node) {\n process.stderr.write('Error: --method requires --node\\n');\n process.exit(1);\n }\n\n const { direct, allDependents, reverse, relationFrom } = collectReverseDependents(\n graph,\n nodePath,\n );\n\n // When --method is specified, filter to only dependents consuming that method\n const methodFilter = options.method?.trim();\n let filteredDirect = direct;\n let filteredAllDependents = allDependents;\n if (methodFilter) {\n filteredDirect = direct.filter((dep) => {\n const rel = relationFrom.get(`${dep}->${nodePath}`);\n return rel?.consumes?.includes(methodFilter) || !rel?.consumes?.length;\n });\n // Rebuild transitive from filtered direct\n const filteredSet = new Set(filteredDirect);\n filteredAllDependents = allDependents.filter((dep) => filteredSet.has(dep));\n }\n\n const chains = buildTransitiveChains(nodePath, filteredDirect, filteredAllDependents, reverse);\n\n // Collect event-based dependents (emits/listens)\n const eventDependents: Array<{ path: string; type: string; eventName: string }> = [];\n for (const [np, n] of graph.nodes) {\n for (const rel of n.meta.relations ?? []) {\n if (rel.target === nodePath && (rel.type === 'emits' || rel.type === 'listens')) {\n eventDependents.push({\n path: np,\n type: rel.type,\n eventName: rel.event_name ?? n.meta.name,\n });\n }\n }\n }\n // Also check if the target node emits events and find listeners\n const targetNode = graph.nodes.get(nodePath)!;\n for (const rel of targetNode.meta.relations ?? []) {\n if (rel.type === 'emits') {\n const eventName = rel.event_name ?? rel.target;\n // Find listeners for this event target\n for (const [np, n] of graph.nodes) {\n if (np === nodePath) continue;\n for (const r of n.meta.relations ?? []) {\n if (r.type === 'listens' && r.target === rel.target) {\n eventDependents.push({\n path: np,\n type: 'listens',\n eventName: r.event_name ?? eventName,\n });\n }\n }\n }\n }\n }\n\n const flows: string[] = [];\n for (const flow of graph.flows) {\n if (flow.nodes.includes(nodePath)) {\n flows.push(flow.name);\n }\n }\n\n const targetEffective = collectEffectiveAspectIds(graph, nodePath);\n const aspectsInScope: string[] = [];\n for (const aspect of graph.aspects) {\n if (targetEffective.has(aspect.id)) {\n aspectsInScope.push(aspect.name);\n }\n }\n\n const methodLabel = methodFilter ? ` (method: ${methodFilter})` : '';\n process.stdout.write(`Impact of changes in ${nodePath}${methodLabel}:\\n\\n`);\n process.stdout.write('Directly dependent:\\n');\n if (filteredDirect.length === 0) {\n process.stdout.write(' (none)\\n');\n } else {\n for (const dep of filteredDirect) {\n const rel = relationFrom.get(`${dep}->${nodePath}`);\n const annot = rel?.consumes?.length\n ? ` (${rel.type}, consumes: ${rel.consumes.join(', ')})`\n : rel\n ? ` (${rel.type})`\n : '';\n process.stdout.write(` <- ${dep}${annot}\\n`);\n }\n }\n\n if (eventDependents.length > 0 && !methodFilter) {\n process.stdout.write('\\nEvent-connected:\\n');\n for (const { path: p, type, eventName } of eventDependents.sort((a, b) => a.path.localeCompare(b.path))) {\n process.stdout.write(` ${p} (${type}: ${eventName})\\n`);\n }\n }\n process.stdout.write('\\nTransitively dependent:\\n');\n if (chains.length === 0) {\n process.stdout.write(' (none)\\n');\n } else {\n for (const chain of chains) {\n process.stdout.write(` ${chain}\\n`);\n }\n }\n\n const descendants = collectDescendants(graph, nodePath);\n if (descendants.length > 0) {\n process.stdout.write('\\nDescendants (hierarchy impact):\\n');\n for (const desc of descendants) {\n process.stdout.write(` ${desc}\\n`);\n }\n }\n\n process.stdout.write(\n `\\nFlows: ${flows.length > 0 ? flows.join(', ') : '(none)'}\\n`,\n );\n process.stdout.write(\n `Aspects (scope covers node): ${aspectsInScope.length > 0 ? aspectsInScope.join(', ') : '(none)'}\\n`,\n );\n\n const coAspectNodes: Array<{ path: string; shared: string[] }> = [];\n if (targetEffective.size > 0) {\n for (const [p] of graph.nodes) {\n if (p === nodePath) continue;\n const nodeEffective = collectEffectiveAspectIds(graph, p);\n const shared = [...targetEffective].filter((id) => nodeEffective.has(id));\n if (shared.length > 0) {\n coAspectNodes.push({ path: p, shared });\n }\n }\n }\n if (coAspectNodes.length > 0) {\n process.stdout.write('Nodes sharing aspects:\\n');\n for (const { path: p, shared } of coAspectNodes.sort((a, b) =>\n a.path.localeCompare(b.path),\n )) {\n process.stdout.write(` ${p} (${shared.join(', ')})\\n`);\n }\n }\n\n const allAffected = new Set([...filteredAllDependents, ...descendants, ...eventDependents.map((e) => e.path)]);\n process.stdout.write(\n `\\nTotal scope: ${allAffected.size} nodes, ${flows.length} flows, ${aspectsInScope.length} aspects\\n`,\n );\n\n if (options.simulate && allAffected.size > 0) {\n await runSimulation(graph, allAffected, nodePath);\n }\n } catch (error) {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n process.exit(1);\n }\n },\n );\n}\n","import { Command } from 'commander';\nimport { stringify as yamlStringify } from 'yaml';\nimport { loadGraph } from '../core/graph-loader.js';\nimport { findYggRoot } from '../utils/paths.js';\n\nexport function registerAspectsCommand(program: Command): void {\n program\n .command('aspects')\n .description('List aspects with metadata (YAML output)')\n .action(async () => {\n try {\n const yggRoot = await findYggRoot(process.cwd());\n const graph = await loadGraph(yggRoot);\n const output = graph.aspects\n .sort((a, b) => a.id.localeCompare(b.id))\n .map((aspect) => {\n const entry: Record<string, unknown> = { id: aspect.id, name: aspect.name };\n if (aspect.description) entry.description = aspect.description;\n if (aspect.implies && aspect.implies.length > 0) entry.implies = aspect.implies;\n if (aspect.stability) entry.stability = aspect.stability;\n return entry;\n });\n process.stdout.write(yamlStringify(output));\n } catch (error) {\n const err = error as NodeJS.ErrnoException;\n if (err.code === 'ENOENT') {\n process.stderr.write(\n `Error: No .yggdrasil/ directory found. Run 'yg init' first.\\n`,\n );\n } else {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n }\n process.exit(1);\n }\n });\n}\n","import { Command } from 'commander';\nimport { stringify as yamlStringify } from 'yaml';\nimport { loadGraph } from '../core/graph-loader.js';\nimport { findYggRoot } from '../utils/paths.js';\n\nexport function registerFlowsCommand(program: Command): void {\n program\n .command('flows')\n .description('List flows with metadata (YAML output)')\n .action(async () => {\n try {\n const yggRoot = await findYggRoot(process.cwd());\n const graph = await loadGraph(yggRoot);\n const output = graph.flows\n .sort((a, b) => a.name.localeCompare(b.name))\n .map((flow) => {\n const entry: Record<string, unknown> = {\n name: flow.name,\n participants: flow.nodes.length,\n nodes: flow.nodes.sort(),\n };\n if (flow.aspects && flow.aspects.length > 0) entry.aspects = flow.aspects;\n return entry;\n });\n process.stdout.write(yamlStringify(output));\n } catch (error) {\n const err = error as NodeJS.ErrnoException;\n if (err.code === 'ENOENT') {\n process.stderr.write(\n `Error: No .yggdrasil/ directory found. Run 'yg init' first.\\n`,\n );\n } else {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n }\n process.exit(1);\n }\n });\n}\n","import { Command } from 'commander';\nimport { loadGraph } from '../core/graph-loader.js';\nimport { detectDrift } from '../core/drift-detector.js';\nimport { validate } from '../core/validator.js';\nimport { normalizeMappingPaths } from '../utils/paths.js';\n\nexport function registerPreflightCommand(program: Command): void {\n program\n .command('preflight')\n .description('Unified diagnostic report: drift, status, validation')\n .option('--quick', 'Skip drift detection for faster results')\n .action(async (options: { quick?: boolean }) => {\n try {\n const cwd = process.cwd();\n const graph = await loadGraph(cwd);\n\n // --- Drift ---\n const driftedEntries = options.quick\n ? []\n : (await detectDrift(graph)).entries.filter((e) => e.status !== 'ok');\n\n // --- Status counts ---\n const nodeCount = graph.nodes.size;\n const aspectCount = graph.aspects.length;\n const flowCount = graph.flows.length;\n let mappedPathCount = 0;\n for (const node of graph.nodes.values()) {\n mappedPathCount += normalizeMappingPaths(node.meta.mapping).length;\n }\n\n // --- Validation ---\n const validation = await validate(graph, 'all');\n const errors = validation.issues.filter((i) => i.severity === 'error');\n const warnings = validation.issues.filter((i) => i.severity === 'warning');\n\n // --- Build output ---\n const lines: string[] = [];\n lines.push('=== Preflight Report ===');\n lines.push('');\n\n // Drift section\n if (options.quick) {\n lines.push('Drift: skipped (--quick)');\n } else if (driftedEntries.length === 0) {\n lines.push('Drift: clean');\n } else {\n lines.push(`Drift: ${driftedEntries.length} nodes need attention`);\n for (const entry of driftedEntries) {\n lines.push(` - ${entry.nodePath}: ${entry.status}`);\n }\n }\n lines.push('');\n\n // Status section\n lines.push(\n `Status: ${nodeCount} nodes, ${aspectCount} aspects, ${flowCount} flows, ${mappedPathCount} mapped paths`,\n );\n if (nodeCount === 0) {\n lines.push('');\n lines.push(' ⚡ No nodes found. Enter BOOTSTRAP MODE:');\n lines.push(' Create nodes under .yggdrasil/model/ for your active work area.');\n lines.push(' See: yg help build-context');\n }\n lines.push('');\n\n // Validation section\n if (errors.length === 0 && warnings.length === 0) {\n lines.push('Validation: clean');\n } else {\n const parts: string[] = [];\n if (errors.length > 0) parts.push(`${errors.length} errors`);\n if (warnings.length > 0) parts.push(`${warnings.length} warnings`);\n lines.push(`Validation: ${parts.join(', ')}`);\n for (const issue of [...errors, ...warnings]) {\n const code = issue.code ? `[${issue.code}] ` : '';\n const loc = issue.nodePath ? `${issue.nodePath} -> ` : '';\n lines.push(` - ${code}${loc}${issue.message}`);\n }\n }\n lines.push('');\n\n process.stdout.write(lines.join('\\n'));\n\n // Exit code: 1 if drift or validation errors exist.\n // Warnings alone do not cause exit 1.\n const hasIssues = (!options.quick && driftedEntries.length > 0) || errors.length > 0;\n process.exit(hasIssues ? 1 : 0);\n } catch (error) {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n process.exit(1);\n }\n });\n}\n"],"mappings":";;;AACA,SAAS,eAAe;;;ACAxB,SAAS,SAAAA,QAAO,aAAAC,YAAW,WAAAC,UAAS,YAAAC,WAAU,QAAAC,aAAY;AAC1D,OAAOC,WAAU;AACjB,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAC7B,SAAS,MAAAC,KAAI,SAAAC,cAAa;;;ACLnB,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACA9B,SAAS,UAAU,WAAW,aAAa;AAC3C,OAAO,UAAU;;;ACUjB,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuItB,IAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2JnB,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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","names":["mkdir","writeFile","readdir","readFile","stat","path","gt","valid","readFile","path","readFile","writeFile","path","parseYaml","path","pkg","mkdir","readdir","readFile","writeFile","program","stat","valid","gt","rulesPath","readdir","readFile","path","readFile","parseYaml","readFile","parseYaml","readFile","parseYaml","readFile","readdir","path","readFile","parseYaml","readFile","path","parseYaml","readFile","parseYaml","path","readFile","path","parseYaml","path","fileURLToPath","stat","path","stat","path","path","path","readdir","readFile","readFile","path","path","readFile","readdir","readFile","stat","path","path","access","readdir","stat","readFile","pkg","pkg","program","pkg","program","chalk","readFile","writeFile","stat","readdir","mkdir","rm","path","state","readFile","readdir","stat","path","require","readFile","path","path","stat","readFile","readdir","path","STRUCTURAL_RELATION_TYPES","path","collectParticipatingFlows","access","path","program","chalk","chalk","program","chalk","program","program","path","path","access","program","path","access","path","STRUCTURAL_RELATION_TYPES","EVENT_RELATION_TYPES","STRUCTURAL_RELATION_TYPES","EVENT_RELATION_TYPES","program","rm","path","execSync","execSync","path","rm","path","pkg","program","program","yamlStringify","program","yamlStringify","program","readFileSync","fileURLToPath"]}
1
+ {"version":3,"sources":["../src/bin.ts","../src/cli/init.ts","../src/templates/default-config.ts","../src/templates/platform.ts","../src/templates/rules.ts","../src/core/migrator.ts","../src/migrations/to-2.0.0.ts","../src/migrations/index.ts","../src/core/graph-loader.ts","../src/io/config-parser.ts","../src/io/node-parser.ts","../src/io/aspect-parser.ts","../src/io/artifact-reader.ts","../src/io/flow-parser.ts","../src/io/schema-parser.ts","../src/utils/paths.ts","../src/core/context-builder.ts","../src/utils/tokens.ts","../src/core/validator.ts","../src/formatters/context-text.ts","../src/cli/build-context.ts","../src/cli/validate.ts","../src/cli/drift.ts","../src/io/drift-state-store.ts","../src/utils/hash.ts","../src/core/context-files.ts","../src/core/drift-detector.ts","../src/cli/drift-sync.ts","../src/cli/status.ts","../src/cli/tree.ts","../src/cli/owner.ts","../src/core/dependency-resolver.ts","../src/cli/deps.ts","../src/core/graph-from-git.ts","../src/cli/impact.ts","../src/cli/aspects.ts","../src/cli/flows.ts","../src/cli/preflight.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { registerInitCommand } from './cli/init.js';\nimport { registerBuildCommand } from './cli/build-context.js';\nimport { registerValidateCommand } from './cli/validate.js';\nimport { registerDriftCommand } from './cli/drift.js';\nimport { registerDriftSyncCommand } from './cli/drift-sync.js';\nimport { registerStatusCommand } from './cli/status.js';\nimport { registerTreeCommand } from './cli/tree.js';\nimport { registerOwnerCommand } from './cli/owner.js';\nimport { registerDepsCommand } from './cli/deps.js';\nimport { registerImpactCommand } from './cli/impact.js';\nimport { registerAspectsCommand } from './cli/aspects.js';\nimport { registerFlowsCommand } from './cli/flows.js';\nimport { registerPreflightCommand } from './cli/preflight.js';\nimport { readFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport { dirname, join } from 'node:path';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));\n\nconst program = new Command();\n\nprogram\n .name('yg')\n .description('Yggdrasil — architectural knowledge infrastructure for AI agents')\n .version(pkg.version);\n\nregisterInitCommand(program);\nregisterBuildCommand(program);\nregisterValidateCommand(program);\nregisterDriftCommand(program);\nregisterDriftSyncCommand(program);\nregisterStatusCommand(program);\nregisterTreeCommand(program);\nregisterOwnerCommand(program);\nregisterDepsCommand(program);\nregisterImpactCommand(program);\nregisterAspectsCommand(program);\nregisterFlowsCommand(program);\nregisterPreflightCommand(program);\n\nprogram.parse();\n","import { Command } from 'commander';\nimport { mkdir, writeFile, readdir, readFile, stat } from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { readFileSync } from 'node:fs';\nimport { gt, valid } from 'semver';\nimport { DEFAULT_CONFIG } from '../templates/default-config.js';\nimport { installRulesForPlatform, PLATFORMS, type Platform } from '../templates/platform.js';\nimport { detectVersion, runMigrations } from '../core/migrator.js';\nimport { MIGRATIONS } from '../migrations/index.js';\n\nfunction getGraphSchemasDir(): string {\n const currentDir = path.dirname(fileURLToPath(import.meta.url));\n const packageRoot = path.join(currentDir, '..');\n return path.join(packageRoot, 'graph-schemas');\n}\n\nfunction getCliVersion(): string {\n const currentDir = path.dirname(fileURLToPath(import.meta.url));\n const packageRoot = path.join(currentDir, '..');\n const pkg = JSON.parse(readFileSync(path.join(packageRoot, 'package.json'), 'utf-8')) as {\n version: string;\n };\n return pkg.version;\n}\n\nasync function refreshSchemas(yggRoot: string): Promise<void> {\n const schemasDir = path.join(yggRoot, 'schemas');\n await mkdir(schemasDir, { recursive: true });\n const graphSchemasDir = getGraphSchemasDir();\n try {\n const entries = await readdir(graphSchemasDir, { withFileTypes: true });\n const schemaFiles = entries.filter((e) => e.isFile()).map((e) => e.name);\n for (const file of schemaFiles) {\n const srcPath = path.join(graphSchemasDir, file);\n const content = await readFile(srcPath, 'utf-8');\n await writeFile(path.join(schemasDir, file), content, 'utf-8');\n }\n } catch {\n // Ignore schema copy errors\n }\n}\n\nconst GITIGNORE_CONTENT = ``;\n\nexport function registerInitCommand(program: Command): void {\n program\n .command('init')\n .description('Initialize Yggdrasil graph in current project')\n .option(\n '--platform <name>',\n 'Agent platform: cursor, claude-code, copilot, cline, roocode, codex, windsurf, aider, gemini, amp, generic',\n 'generic',\n )\n .option('--upgrade', 'Refresh rules only (when .yggdrasil/ already exists)')\n .action(async (options: { platform?: string; upgrade?: boolean }) => {\n const projectRoot = process.cwd();\n const yggRoot = path.join(projectRoot, '.yggdrasil');\n\n let upgradeMode = false;\n try {\n const statResult = await stat(yggRoot);\n if (!statResult.isDirectory()) {\n process.stderr.write('Error: .yggdrasil exists but is not a directory.\\n');\n process.exit(1);\n }\n if (options.upgrade) {\n upgradeMode = true;\n } else {\n process.stderr.write(\n 'Error: .yggdrasil/ already exists. Use --upgrade to refresh rules only.\\n',\n );\n process.exit(1);\n }\n } catch {\n // Directory does not exist — proceed with full init\n }\n\n const platform = (options.platform ?? 'generic') as Platform;\n if (!PLATFORMS.includes(platform)) {\n process.stderr.write(\n `Error: Unknown platform '${platform}'. Use: ${PLATFORMS.join(', ')}\\n`,\n );\n process.exit(1);\n }\n\n if (upgradeMode) {\n const projectVersion = await detectVersion(yggRoot);\n\n if (!projectVersion) {\n process.stderr.write('Error: No Yggdrasil project found. Run `yg init` first.\\n');\n process.exit(1);\n }\n\n const cliVersion = getCliVersion();\n\n // Warn if project is newer than CLI\n if (valid(projectVersion) && valid(cliVersion) && gt(projectVersion, cliVersion)) {\n process.stderr.write(\n `Warning: Project version (${projectVersion}) is newer than CLI (${cliVersion}). Upgrade your CLI.\\n`,\n );\n process.exit(1);\n }\n\n // Run migrations if project is older than CLI\n if (valid(projectVersion) && valid(cliVersion) && gt(cliVersion, projectVersion)) {\n process.stdout.write(`Migrating from ${projectVersion} to ${cliVersion}...\\n\\n`);\n const results = await runMigrations(projectVersion, MIGRATIONS, yggRoot);\n for (const result of results) {\n for (const action of result.actions) {\n process.stdout.write(` ✓ ${action}\\n`);\n }\n for (const warning of result.warnings) {\n process.stdout.write(` ⚠ ${warning}\\n`);\n }\n }\n if (results.length > 0) {\n process.stdout.write('\\n');\n }\n }\n\n // Refresh schemas (copy latest schema files)\n await refreshSchemas(yggRoot);\n\n // Refresh rules\n const rulesPath = await installRulesForPlatform(projectRoot, platform);\n process.stdout.write('✓ Rules refreshed.\\n');\n process.stdout.write(` ${path.relative(projectRoot, rulesPath)}\\n`);\n return;\n }\n\n await mkdir(path.join(yggRoot, 'model'), { recursive: true });\n await mkdir(path.join(yggRoot, 'aspects'), { recursive: true });\n await mkdir(path.join(yggRoot, 'flows'), { recursive: true });\n const schemasDir = path.join(yggRoot, 'schemas');\n await mkdir(schemasDir, { recursive: true });\n\n const graphSchemasDir = getGraphSchemasDir();\n try {\n const entries = await readdir(graphSchemasDir, { withFileTypes: true });\n const schemaFiles = entries.filter((e) => e.isFile()).map((e) => e.name);\n for (const file of schemaFiles) {\n const srcPath = path.join(graphSchemasDir, file);\n const content = await readFile(srcPath, 'utf-8');\n await writeFile(path.join(schemasDir, file), content, 'utf-8');\n }\n } catch (err) {\n process.stderr.write(\n `Warning: Could not copy graph schemas from ${graphSchemasDir}: ${(err as Error).message}\\n`,\n );\n }\n\n await writeFile(path.join(yggRoot, 'yg-config.yaml'), DEFAULT_CONFIG, 'utf-8');\n await writeFile(path.join(yggRoot, '.gitignore'), GITIGNORE_CONTENT, 'utf-8');\n\n const rulesPath = await installRulesForPlatform(projectRoot, platform);\n\n process.stdout.write('✓ Yggdrasil initialized.\\n\\n');\n process.stdout.write('Created:\\n');\n process.stdout.write(' .yggdrasil/yg-config.yaml\\n');\n process.stdout.write(' .yggdrasil/.gitignore\\n');\n process.stdout.write(' .yggdrasil/model/\\n');\n process.stdout.write(' .yggdrasil/aspects/\\n');\n process.stdout.write(' .yggdrasil/flows/\\n');\n process.stdout.write(' .yggdrasil/schemas/ (yg-config, yg-node, yg-aspect, yg-flow)\\n');\n process.stdout.write(` ${path.relative(projectRoot, rulesPath)} (rules)\\n\\n`);\n process.stdout.write('Next steps:\\n');\n process.stdout.write(' 1. Edit .yggdrasil/yg-config.yaml — set name and configure node types\\n');\n process.stdout.write(' 2. Create nodes under .yggdrasil/model/\\n');\n process.stdout.write(' 3. Run: yg validate\\n');\n });\n}\n","export const DEFAULT_CONFIG = `version: \"2.0.0\"\n\nname: \"\"\n\nnode_types:\n module:\n description: \"Business logic unit with clear domain responsibility\"\n service:\n description: \"Component providing functionality to other nodes\"\n library:\n description: \"Shared utility code with no domain knowledge\"\n infrastructure:\n description: \"Guards, middleware, interceptors — invisible in call graphs but affect blast radius\"\n\nartifacts:\n responsibility.md:\n required: always\n description: \"What this node is responsible for, and what it is not\"\n included_in_relations: true\n interface.md:\n required:\n when: has_incoming_relations\n description: \"Public API — methods, parameters, return types, contracts, failure modes, exposed data structures\"\n included_in_relations: true\n internals.md:\n required: never\n description: \"How the node works and why — algorithms, business rules, state machines, design decisions with rejected alternatives\"\n\nquality:\n min_artifact_length: 50\n max_direct_relations: 10\n context_budget:\n warning: 10000\n error: 20000\n`;\n","import { readFile, writeFile, mkdir } from 'node:fs/promises';\nimport path from 'node:path';\nimport { AGENT_RULES_CONTENT } from './rules.js';\n\nconst AGENT_RULES_IMPORT = '@.yggdrasil/agent-rules.md';\nconst YGGDRASIL_START = '<!-- yggdrasil:start -->';\nconst YGGDRASIL_END = '<!-- yggdrasil:end -->';\nconst YGGDRASIL_SECTION = `## Yggdrasil\\n\\n${AGENT_RULES_CONTENT}`;\nconst YGGDRASIL_BLOCK = `${YGGDRASIL_START}\\n${YGGDRASIL_SECTION}\\n${YGGDRASIL_END}`;\n\nexport type Platform =\n | 'cursor'\n | 'claude-code'\n | 'copilot'\n | 'cline'\n | 'roocode'\n | 'codex'\n | 'windsurf'\n | 'aider'\n | 'gemini'\n | 'amp'\n | 'generic';\n\nexport const PLATFORMS: Platform[] = [\n 'cursor',\n 'claude-code',\n 'copilot',\n 'cline',\n 'roocode',\n 'codex',\n 'windsurf',\n 'aider',\n 'gemini',\n 'amp',\n 'generic',\n];\n\nexport async function installRulesForPlatform(\n projectRoot: string,\n platform: Platform,\n): Promise<string> {\n const agentRulesPath = path.join(projectRoot, '.yggdrasil', 'agent-rules.md');\n\n switch (platform) {\n case 'cursor':\n return installForCursor(projectRoot);\n case 'claude-code':\n return installForClaudeCode(projectRoot, agentRulesPath);\n case 'copilot':\n return installForCopilot(projectRoot);\n case 'cline':\n return installForCline(projectRoot);\n case 'roocode':\n return installForRooCode(projectRoot);\n case 'codex':\n return installForCodex(projectRoot);\n case 'windsurf':\n return installForWindsurf(projectRoot);\n case 'aider':\n return installForAider(projectRoot, agentRulesPath);\n case 'gemini':\n return installForGemini(projectRoot, agentRulesPath);\n case 'amp':\n return installForAmp(projectRoot, agentRulesPath);\n case 'generic':\n default:\n return installForGeneric(projectRoot);\n }\n}\n\nasync function ensureAgentRules(agentRulesPath: string): Promise<void> {\n await mkdir(path.dirname(agentRulesPath), { recursive: true });\n await writeFile(agentRulesPath, AGENT_RULES_CONTENT, 'utf-8');\n}\n\nasync function installForCursor(projectRoot: string): Promise<string> {\n const dir = path.join(projectRoot, '.cursor', 'rules');\n await mkdir(dir, { recursive: true });\n const filePath = path.join(dir, 'yggdrasil.mdc');\n const content = `---\ndescription: Yggdrasil — semantic memory of the repository\nalwaysApply: true\n---\n\n${AGENT_RULES_CONTENT}`;\n await writeFile(filePath, content, 'utf-8');\n return filePath;\n}\n\nasync function installForClaudeCode(projectRoot: string, agentRulesPath: string): Promise<string> {\n await ensureAgentRules(agentRulesPath);\n const filePath = path.join(projectRoot, 'CLAUDE.md');\n let existing = '';\n try {\n existing = await readFile(filePath, 'utf-8');\n } catch {\n /* file doesn't exist */\n }\n const importLine = AGENT_RULES_IMPORT;\n if (existing.includes(importLine)) {\n return agentRulesPath;\n }\n const content = existing.trimEnd() ? `${existing.trimEnd()}\\n${importLine}\\n` : `${importLine}\\n`;\n await writeFile(filePath, content, 'utf-8');\n return agentRulesPath;\n}\n\nasync function installForCopilot(projectRoot: string): Promise<string> {\n const dir = path.join(projectRoot, '.github');\n await mkdir(dir, { recursive: true });\n const filePath = path.join(dir, 'copilot-instructions.md');\n let existing = '';\n try {\n existing = await readFile(filePath, 'utf-8');\n } catch {\n /* file doesn't exist */\n }\n let content: string;\n if (existing.includes(YGGDRASIL_START) && existing.includes(YGGDRASIL_END)) {\n content = existing.replace(\n new RegExp(`${escapeRegex(YGGDRASIL_START)}[\\\\s\\\\S]*?${escapeRegex(YGGDRASIL_END)}`, 'g'),\n YGGDRASIL_BLOCK,\n );\n } else {\n content = existing.trimEnd()\n ? `${existing.trimEnd()}\\n\\n${YGGDRASIL_BLOCK}\\n`\n : `${YGGDRASIL_BLOCK}\\n`;\n }\n await writeFile(filePath, content, 'utf-8');\n return filePath;\n}\n\nasync function installForCline(projectRoot: string): Promise<string> {\n const dir = path.join(projectRoot, '.clinerules');\n await mkdir(dir, { recursive: true });\n const filePath = path.join(dir, 'yggdrasil.md');\n await writeFile(filePath, AGENT_RULES_CONTENT, 'utf-8');\n return filePath;\n}\n\nasync function installForRooCode(projectRoot: string): Promise<string> {\n const dir = path.join(projectRoot, '.roo', 'rules');\n await mkdir(dir, { recursive: true });\n const filePath = path.join(dir, 'yggdrasil.md');\n await writeFile(filePath, AGENT_RULES_CONTENT, 'utf-8');\n return filePath;\n}\n\nasync function installForCodex(projectRoot: string): Promise<string> {\n const filePath = path.join(projectRoot, 'AGENTS.md');\n let existing = '';\n try {\n existing = await readFile(filePath, 'utf-8');\n } catch {\n /* file doesn't exist */\n }\n let content: string;\n if (existing.includes(YGGDRASIL_START) && existing.includes(YGGDRASIL_END)) {\n content = existing.replace(\n new RegExp(`${escapeRegex(YGGDRASIL_START)}[\\\\s\\\\S]*?${escapeRegex(YGGDRASIL_END)}`, 'g'),\n YGGDRASIL_BLOCK,\n );\n } else {\n content = existing.trimEnd()\n ? `${existing.trimEnd()}\\n\\n${YGGDRASIL_BLOCK}\\n`\n : `${YGGDRASIL_BLOCK}\\n`;\n }\n await writeFile(filePath, content, 'utf-8');\n return filePath;\n}\n\nasync function installForWindsurf(projectRoot: string): Promise<string> {\n const dir = path.join(projectRoot, '.windsurf', 'rules');\n await mkdir(dir, { recursive: true });\n const filePath = path.join(dir, 'yggdrasil.md');\n await writeFile(filePath, AGENT_RULES_CONTENT, 'utf-8');\n return filePath;\n}\n\nasync function installForAider(projectRoot: string, agentRulesPath: string): Promise<string> {\n await ensureAgentRules(agentRulesPath);\n const filePath = path.join(projectRoot, '.aider.conf.yml');\n const entry = '.yggdrasil/agent-rules.md';\n let existing = '';\n try {\n existing = await readFile(filePath, 'utf-8');\n } catch {\n /* file doesn't exist */\n }\n if (existing.includes(entry)) {\n return agentRulesPath;\n }\n const content = appendAiderReadEntry(existing, entry);\n await writeFile(filePath, content, 'utf-8');\n return agentRulesPath;\n}\n\nfunction appendAiderReadEntry(existing: string, entry: string): string {\n const newItem = ` - ${entry} # added by yg init\\n`;\n const readBlock = /^read:\\s*\\n((?:\\s+-\\s+[^\\n]+\\n)*)/m;\n const match = existing.match(readBlock);\n if (match) {\n return existing.replace(match[0], `read:\\n${match[1]}${newItem}`);\n }\n const readEmpty = /^read:\\s*$/m;\n if (readEmpty.test(existing)) {\n return existing.replace(readEmpty, `read:\\n${newItem}`);\n }\n const trimmed = existing.trimEnd();\n return trimmed ? `${trimmed}\\n\\nread:\\n${newItem}` : `read:\\n${newItem}`;\n}\n\nasync function installForGemini(projectRoot: string, agentRulesPath: string): Promise<string> {\n await ensureAgentRules(agentRulesPath);\n const filePath = path.join(projectRoot, 'GEMINI.md');\n let existing = '';\n try {\n existing = await readFile(filePath, 'utf-8');\n } catch {\n /* file doesn't exist */\n }\n const importLine = AGENT_RULES_IMPORT;\n if (existing.includes(importLine)) {\n return agentRulesPath;\n }\n const content = existing.trimEnd() ? `${existing.trimEnd()}\\n${importLine}\\n` : `${importLine}\\n`;\n await writeFile(filePath, content, 'utf-8');\n return agentRulesPath;\n}\n\nasync function installForAmp(projectRoot: string, agentRulesPath: string): Promise<string> {\n await ensureAgentRules(agentRulesPath);\n const filePath = path.join(projectRoot, 'AGENTS.md');\n let existing = '';\n try {\n existing = await readFile(filePath, 'utf-8');\n } catch {\n /* file doesn't exist */\n }\n const importLine = AGENT_RULES_IMPORT;\n if (existing.includes(importLine)) {\n return agentRulesPath;\n }\n const content = existing.trimEnd() ? `${existing.trimEnd()}\\n${importLine}\\n` : `${importLine}\\n`;\n await writeFile(filePath, content, 'utf-8');\n return agentRulesPath;\n}\n\nasync function installForGeneric(projectRoot: string): Promise<string> {\n const filePath = path.join(projectRoot, '.yggdrasil', 'agent-rules.md');\n await ensureAgentRules(filePath);\n return filePath;\n}\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","/**\n * Canonical agent rules content — hand-tuned, do not generate programmatically.\n *\n * Operating manual for agents working in a Yggdrasil-managed repository.\n * Split into three cognitive sections optimized for LLM attention patterns:\n * 1. CORE PROTOCOL — internalize before doing anything (primacy effect)\n * 2. OPERATIONS — execute while working (working memory)\n * 3. KNOWLEDGE BASE — look up when needed (recency effect)\n */\n\n// prettier-ignore\nconst CORE_PROTOCOL = `## CORE PROTOCOL\n\n<EXTREMELY-IMPORTANT>\nThis is your operating manual for working in a Yggdrasil-managed repository. Every rule below is mandatory — no skill, plan, workflow, or instruction overrides these requirements.\n\nBEFORE working with ANY source file, you MUST run \\`yg owner\\` to check if it is mapped. If mapped, you MUST use the graph before reading source. YOU DO NOT HAVE A CHOICE.\n\nThis is not negotiable. This is not optional. You cannot rationalize your way out of this.\n</EXTREMELY-IMPORTANT>\n\nYggdrasil is persistent semantic memory stored in \\`.yggdrasil/\\`. It maps the repository and provides deterministic implementation context for every node.\n\n### Quick Start Protocol\n\n\\`\\`\\`\nBEFORE reading, researching, planning, OR modifying ANY mapped file:\n 0. Don't know which file or node to start from? If a semantic search\n tool is available, search for your intent — the graph contains\n responsibility, flow, and aspect files with rich natural-language\n descriptions that match goal-oriented queries. Use the results\n to identify relevant nodes, then proceed to step 1.\n 1. yg owner --file <path>\n 2. Choose the right graph tool for your task:\n - Understanding how/why it works → yg build-context --node <owner>\n - Assessing what is affected by a change → yg impact --node <owner>\n - Planning modifications → both (build-context first, then impact)\n The context package is your primary source of ARCHITECTURAL understanding:\n intent, constraints, relations, rationale. For IMPLEMENTATION precision\n (exact behavior, error handling, await patterns, edge cases) — verify\n against source code. Aspects describe intended patterns; individual\n implementations may deviate.\n If the context package seems insufficient — enrich the graph.\n\nAFTER modifying:\n 3. Update graph artifacts to reflect changes\n 4. yg validate — fix all errors\n 5. yg drift-sync --node <owner>\n\nEVERY conversation start:\n yg preflight → act on findings (see Operations)\n\nNEVER: modify code without graph coverage.\nNEVER: read mapped source files to understand a component without\n running yg build-context first — the graph captures intent,\n constraints, and relations that source files cannot.\nNEVER: assess blast radius of a change without running yg impact first\n — the graph knows the dependency structure that grep cannot infer.\nNEVER: invent rationale, business rules, or decisions.\nNEVER: auto-resolve drift without asking the user.\nWHEN UNSURE: ask the user. Never guess. Never assume.\n\\`\\`\\`\n\n### Five Core Rules\n\n1. **Graph first.** Before reading, researching, planning, or modifying mapped files, run \\`yg owner\\` and the appropriate graph tool: \\`yg build-context\\` to understand a component, \\`yg impact\\` to assess blast radius. The graph is your primary source of architectural understanding. For implementation-level precision (exact behavior, error paths, edge cases) — verify against source code after loading the context package.\n2. **Code and graph are one.** Code changed → graph updated in the same response. Graph changed → source verified in the same response. No exceptions.\n3. **Never invent why.** The graph captures human intent. If you don't know why something was decided, ask. Never hallucinate rationale.\n4. **Always capture why — especially why NOT.** When the user explains a reason, record it in the graph immediately. When a design choice is made, also record rejected alternatives: \"Chose X over Y because Z.\" Rejected alternatives are the highest-value information — invisible in code and irrecoverable once forgotten. Conversation evaporates; graph persists.\n5. **Ask before resolving ambiguity.** When multiple valid interpretations exist, stop, list options, ask the user. Never silently choose.\n\n### Recognizing Graph-Required Actions\n\nWhat matters is the ACTION you are performing, not what instructed it. If the action involves reading, understanding, or modifying mapped code, the graph protocol applies — whether the instruction came from a skill, a plan, a user message, a brainstorming session, a debugging workflow, or your own initiative. This is not negotiable. You cannot rationalize your way out of this.\n\n**Actions that require \\`yg owner\\` + \\`yg build-context\\`:**\n\n- Reading or exploring source files to understand a component\n- Proposing approaches, designs, or plans for changing code\n- Reviewing or debugging code\n- Any form of reasoning about how mapped code works or should change\n\n**Actions that require \\`yg owner\\` + \\`yg impact\\`:**\n\n- Assessing blast radius before changing or removing a component\n- Finding all dependents of a component\n- Planning cross-cutting refactors or feature removals\n- Scoping work that spans multiple nodes\n\n**Actions that do NOT require yg:**\n\n- Git operations (log, diff, status, blame)\n- Reading documentation, READMEs, or config files outside \\`.yggdrasil/\\`\n- Running tests, builds, or linters\n- Working with files that \\`yg owner\\` reports as unmapped\n\n**Evasion patterns — if you think any of these, STOP:**\n\n| Thought | Reality |\n|---|---|\n| \"The skill/plan says to explore the codebase\" | Exploring mapped code = yg owner + graph tool first |\n| \"I'm just scoping/searching, not understanding\" | Scoping IS a graph action; use yg impact |\n| \"The plan step says to read this file\" | Reading a mapped file = yg owner first |\n| \"I'm brainstorming, not implementing\" | Brainstorming about mapped code needs graph context |\n| \"I'm only grepping for references\" | Grep finds text; yg impact finds structural dependencies. Use both. |\n| \"I'll use the graph later when I modify\" | Graph-first means BEFORE reading, not before modifying |\n| \"I'll grep the codebase to find where to start\" | If semantic search is available, search by intent first — graph files are designed to match natural-language goals. Then \\`yg owner\\` on results. |\n\n### Failure States\n\nYou have broken Yggdrasil if you do any of the following:\n\n- ❌ Worked on a mapped file without running \\`yg owner\\` + the appropriate graph tool (\\`build-context\\` or \\`impact\\`) first — regardless of what instructed the action (skill, plan, user request, workflow step).\n- ❌ Modified source code without updating graph artifacts in the same response, or vice versa.\n- ❌ Resolved a code-graph inconsistency or ambiguity without asking the user first.\n- ❌ Created or edited a graph element without reading its schema in \\`schemas/\\` first.\n- ❌ Ran \\`yg drift-sync\\` before both graph artifacts and source code are current.\n- ❌ Placed a cross-cutting requirement in a local artifact instead of an aspect, or used an aspect id with no \\`aspects/\\` directory.\n- ❌ Invented a rationale, business rule, or decision — or recorded a decision without documenting rejected alternatives and rationale (use \"rationale: unknown\" if unknown).\n- ❌ Used blackbox coverage for greenfield (new) code.\n\n### Escape Hatch\n\nIf the user explicitly requests a code-only change, comply but:\n\n- Warn: \"This creates drift. Run \\`yg drift\\` next session to reconcile.\"\n- Do NOT run \\`yg drift-sync\\` — leave the drift visible.\n\n### Environment Check\n\nBefore preflight:\n\n- Verify \\`yg\\` CLI is available. If not found, inform user and stop.\n- If \\`yg preflight\\` shows 0 nodes → enter BOOTSTRAP MODE (see Operations).\n- If drift report shows >10 drifted nodes → report scope to user, ask which area to prioritize. Do not resolve all at once.\n\n### Delegating to Subagents\n\nWhen you delegate work to a subagent (any subprocess, tool agent, or spawned assistant), the subagent does NOT inherit your Yggdrasil knowledge. Before any other instruction, the subagent MUST:\n\n1. Read \\`.yggdrasil/agent-rules.md\\` — this is the complete operating manual\n2. Follow the Quick Start Protocol from that file before touching any mapped code\n\nInclude this as the FIRST instruction in every subagent prompt:\n\n\\`\\`\\`\nBEFORE doing anything else: read .yggdrasil/agent-rules.md and follow its protocol.\n\\`\\`\\`\n\nA subagent that skips this step will read code without graph context, miss architectural constraints, and produce changes that break graph-code consistency.`;\n\n// prettier-ignore\nconst OPERATIONS = `## OPERATIONS\n\n### Conversation Lifecycle\n\n\\`\\`\\`\nPREFLIGHT (every conversation, before any work):\n - [ ] 1. yg preflight → read unified report\n - [ ] 2. If drift: resolve per Drift Resolution, then yg drift-sync per node\n - [ ] 3. If validation errors: fix, re-run yg validate\n Exception: read-only requests (explain, analyze) — skip preflight.\n\nUNDERSTANDING mapped code (questions, research, OR planning):\n - [ ] 1. yg owner --file <path>\n - [ ] 2. Owner found → yg build-context --node <path>. Use context package as primary source.\n - [ ] 3. Owner not found → use file analysis, state it is not graph-backed.\n Never use grep or raw file reads as primary understanding when graph coverage exists.\n Raw reads supplement the context package — they do not replace it.\n\nWRAP-UP (user signals \"done\", \"wrap up\", \"that's enough\"):\n - [ ] 1. yg drift --drifted-only → resolve\n - [ ] 2. yg validate → fix errors\n - [ ] 3. Report: which nodes and files were changed\n\nBEFORE ENDING ANY RESPONSE (self-audit):\n - [ ] Did I interact with mapped code (read, research, or modify)? If yes → did I use a graph tool BEFORE reading source?\n - [ ] Did I modify source code? If yes → did I update graph artifacts in this same response?\n - [ ] If you broke either rule, you have broken the protocol. Do not finish until both are fixed.\n\\`\\`\\`\n\n### Modify Source Code\n\nYou are not allowed to edit or create source code without establishing graph coverage first.\n\n**Step 1** — Check coverage: \\`yg owner --file <path>\\`\n\n**Step 2a** — Owner found: execute checklist:\n\n- [ ] 1. Read specification: \\`yg build-context --node <node_path>\\`\n- [ ] 2. Assess blast radius: \\`yg impact --node <node_path>\\` — review dependents, descendants, and co-aspect nodes before changing interfaces or shared behavior\n- [ ] 3. Modify source code\n- [ ] 4. Sync graph artifacts — edit artifact files to reflect the changes\n- [ ] 5. Run \\`yg validate\\` — fix all errors (if unfixable after 3 attempts → stop, report to user)\n- [ ] 6. Run \\`yg drift-sync --node <node_path>\\` — only after graph and code are both current\n\n**Step 2b** — Owner not found: establish coverage first. Present options to the user:\n\n*Partially mapped* (file unmapped but inside a mapped module): ask whether to add to existing node or create new one.\n\n*Existing code:*\n\n- Option A — Full node: create node(s), map files, write artifacts from code analysis\n- Option B — Blackbox: create a blackbox node at agreed granularity\n- Option C — Abort\n\n*Greenfield (new code):* Only Option A. Blackbox is forbidden for new code. Follow the graph-first workflow:\n\n1. Create aspects first (cross-cutting requirements the new code must satisfy)\n2. Create flows if the code participates in a business process\n3. Create nodes with full artifacts — responsibility, interface, internals\n4. Review the context package (\\`yg build-context\\`) — it is now the behavioral specification\n5. Implement code that satisfies the specification\n6. The graph specifies WHAT and WHY; the code implements HOW (framework APIs, library choices)\n\nAfter the user chooses, return to Step 1 and follow Step 2a.\n\n### Modify Graph\n\n- [ ] 1. Read the relevant schema from \\`schemas/\\` before touching any YAML\n- [ ] 2. Before changing an aspect or flow, check scope: \\`yg impact --aspect <id>\\` or \\`yg impact --flow <name>\\` — understand which nodes are affected before modifying shared rules or processes\n- [ ] 3. Make changes\n- [ ] 4. Run \\`yg validate\\` immediately — fix all errors\n- [ ] 5. Verify affected source files are consistent — update if needed\n- [ ] 6. Run \\`yg drift-sync\\` for affected nodes\n\n### Reverse Engineering\n\n**Order:** aspects (cross-cutting patterns) → flows (business processes) → model nodes. Never create nodes before aspects and flows are understood.\n\nPer area checklist:\n\n- [ ] 1. \\`yg owner --file <path>\\` — confirm no coverage\n- [ ] 2. Determine node granularity — propose to user if unclear\n- [ ] 3. Create node directory, read \\`schemas/yg-node.yaml\\`, create \\`yg-node.yaml\\`\n- [ ] 4. Analyze source — for each artifact type in \\`yg-config.yaml artifacts\\`: extract content, do not invent\n- [ ] 5. Identify relations — add to \\`yg-node.yaml\\`\n- [ ] 6. Identify cross-cutting requirements — add matching aspects, create if needed\n- [ ] 6b. For each aspect on the node: identify 2-5 code anchors (function names, constants) that evidence the pattern → add as \\`anchors\\` in the aspect entry in \\`yg-node.yaml\\`\n- [ ] 7. Identify business process participation — add to flow, ask user if process unclear\n- [ ] 8. \\`yg validate\\` — fix errors\n- [ ] 9. \\`yg drift-sync --node <path>\\`\n\n**When to ask:**\n\n- Business process unclear: \"This code appears to be part of a larger process. Can you describe what it means from a business perspective?\"\n- Constraint without rationale: \"I see [constraint X]. Do you know why this exists? I want to record the reason, not just the rule.\"\n- Unexplained architectural choice: \"I see [approach X]. What was the reason for this choice?\"\n- Decision without alternatives: \"You chose [X]. What alternatives did you consider, and why did you reject them?\" Record the answer in the Decisions section of \\`internals.md\\`.\n- Decision without known rationale: Record the decision in \\`internals.md\\` with \"rationale: unknown — inferred from code, not confirmed by developer.\" A recorded decision with unknown rationale is infinitely more valuable than no record at all, and safer than an invented rationale.\n\n### Bootstrap Mode\n\nTrigger: \\`yg preflight\\` shows 0 nodes, or no nodes cover the active work area.\n\n- [ ] 1. Identify the active work area (files the user wants to modify)\n- [ ] 2. Scan for cross-cutting patterns → create aspects\n- [ ] 3. Ask user about business processes → create flows if applicable\n- [ ] 4. Propose node structure for the area\n- [ ] 5. Create node(s) with initial artifacts, map files\n- [ ] 6. \\`yg validate\\`, \\`yg drift-sync\\`\n- [ ] 7. Proceed with user's original request\n\nConstraint: Do NOT map the entire repository. Focus on the active area. Expand incrementally.\n\n### Drift Resolution\n\nAlways ask the user before resolving drift. Never auto-resolve.\n\n- **Source drift** (source files changed) → update graph artifacts to match source, then \\`yg drift-sync\\`\n- **Graph drift** (graph artifacts changed) → review affected source, update if needed, then \\`yg drift-sync\\`\n- **Full drift** (both changed) → present both sides to user, ask which direction wins\n- **Missing** → ask: re-materialize or remove mapping?\n- **Unmaterialized** → ask user how to proceed\n\nThreshold: >10 drifted nodes → ask user which area to prioritize. Do not resolve all at once.\n\n**Drift triage:** Prioritize aspects and \\`internals.md\\` (highest decay rate), then \\`responsibility.md\\` and \\`interface.md\\` (most stable).\n\n### Graph Audit\n\nWhen reviewing graph quality (triggered by user or quality improvement):\n\n**Step 1 — Consistency** (catches WRONG information):\n\n- [ ] 1. \\`yg build-context --node <path>\\`\n- [ ] 2. Read mapped source files\n- [ ] 3. For each claim in graph: verify against source code\n- [ ] 4. For each aspect: verify the pattern holds in THIS node. If it deviates, add \\`exceptions\\` to the aspect entry in \\`yg-node.yaml\\`\n- [ ] 5. Report inconsistencies\n\n**Step 2 — Completeness** (catches MISSING information):\n\n- [ ] 1. For each public method: is it in \\`interface.md\\`?\n- [ ] 2. For each error path: is it in \\`interface.md\\` (Failure Modes section)?\n- [ ] 3. For each behavioral invariant: is it in the graph?\n- [ ] 4. Report omissions separately from inconsistencies\n\n### Error Recovery\n\n- **\\`yg\\` not found** → inform user: \"yg CLI is not installed or not in PATH.\" Stop.\n- **Unfixable validate errors** → if not resolved after 3 attempts, stop and report to user. Do not loop.\n- **Budget exceeded** → if \\`yg build-context\\` exits with error (context package exceeds budget), warn user: \"This node should be split.\" Do not proceed with implementation.\n- **Corrupted \\`.yggdrasil/\\` files** → report to user. Do not attempt repair.\n- **Incremental sync** → run \\`yg drift-sync\\` every 3-5 source files during multi-file tasks. Do not defer to end.`;\n\n// prettier-ignore\nconst KNOWLEDGE_BASE = `## KNOWLEDGE BASE\n\n### Graph Structure\n\n\\`\\`\\`\n.yggdrasil/\n yg-config.yaml ← version, vocabulary, node types, artifact rules, required aspects\n model/ ← what exists: nodes, hierarchy, relations, file mappings\n aspects/ ← what must: cross-cutting requirements with rationale and guidance\n flows/ ← why and in what process: business processes with node participation\n schemas/ ← YAML schemas — read before creating any graph element\n .drift-state/ ← generated by CLI; never edit manually\n\\`\\`\\`\n\nKey facts:\n\n- **Hierarchy:** nodes nest in \\`model/\\`. Children inherit parent context. Do not repeat parent content in children.\n- **Aspect id = directory path** under \\`aspects/\\`. Each aspect has \\`yg-aspect.yaml\\` + content \\`.md\\` files. No automatic parent-child — use \\`implies\\` explicitly.\n- **Flows = business processes.** A flow describes what happens in the world, not code sequences. Flow aspects propagate to all participants.\n\n**Node type guidance:** Each type in \\`yg-config.yaml node_types\\` has a \\`description\\` that tells you when to use it. Check the project's config for the full list and descriptions. Common types: \\`module\\` (business logic), \\`service\\` (providing functionality), \\`library\\` (shared utilities), \\`infrastructure\\` (guards, middleware, interceptors — invisible in call graphs but affect blast radius).\n\n### Artifact Structure\n\nThree artifacts capture node knowledge at three levels:\n\n- **responsibility.md** (always required) — WHAT: identity, boundaries, what the node is NOT responsible for.\n- **interface.md** (required when node has consumers) — HOW TO USE: public methods, parameters, return types, contracts, failure modes, exposed data structures. Everything another node needs to interact with this one.\n- **internals.md** (optional, highest value for cross-module nodes) — HOW IT WORKS + WHY: algorithms, control flow, business rules, invariants, state machines, lifecycle, and design decisions with rejected alternatives. Use sections within the file: ## Logic, ## Constraints, ## State, ## Decisions (with \"Chose X over Y because Z\" format).\n\n**Enrichment priority (when adding incrementally):** \\`interface.md\\` first (highest cross-module ROI — contracts enable other nodes to reason about interactions), then \\`responsibility.md\\` (identity and boundaries), then \\`internals.md\\` (depth for complex nodes). A node with only \\`interface.md\\` provides more cross-module value than one with only \\`internals.md\\`.\n\nProjects can define additional artifact types in \\`yg-config.yaml\\` under \\`artifacts\\`. Each custom artifact has a \\`description\\` (tells you what to write), a \\`required\\` condition (\\`always\\`, \\`never\\`, \\`when: has_incoming_relations\\`, \\`when: has_aspect:<id>\\`), and an \\`included_in_relations\\` flag (if true, included in dependency context packages for structural relations). The three standard artifacts are always present in config. Check \\`yg-config.yaml\\` to see all defined artifacts for the project.\n\n### Context Assembly\n\nRun \\`yg build-context --node <path>\\` to get the deterministic context package for a node. The package assembles global project identity, hierarchy, own artifacts, aspects, and relational context. It is your architectural map. For implementation-level claims (exact call patterns, error handling, await vs fire-and-forget) — verify against source code. If the package is insufficient, enrich the graph.\n\n### Information Routing\n\nWhen you encounter information, route it to the correct location:\n\n- **Specific to this node** → local node artifact (check \\`yg-config.yaml artifacts\\` for available types)\n- **Rule for many nodes** → aspect (\\`aspects/<id>/\\` with \\`yg-aspect.yaml\\` + content \\`.md\\` files). If applies to ALL nodes of a type → \\`node_types.<type>.required_aspects\\` in \\`yg-config.yaml\\`\n- **Business process** → flow (\\`flows/<name>/\\` with \\`yg-flow.yaml\\` + \\`description.md\\`). Ask user if process unclear.\n- **Shared across a domain** → parent node artifact. Children receive it through hierarchy.\n- **Technology stack or standard** → node artifact at the appropriate hierarchy level (e.g., root node's \\`responsibility.md\\` for single-stack repos, or deployment unit node for monorepos)\n- **Decision (why + why NOT):** one node → Decisions section of \\`internals.md\\` with format \"Chose X over Y because Z\"; category of nodes → aspect content files; tech choice → node artifact at the level where the technology applies. Always include rejected alternatives — they are the highest-value graph content. If the rationale is unknown: record the decision with \"rationale: unknown\" and note what CAN be observed from the code. Never invent a plausible-sounding rationale.\n\n### Creating Aspects\n\n- [ ] 1. Read \\`schemas/yg-aspect.yaml\\`\n- [ ] 2. Create \\`aspects/<id>/\\` directory\n- [ ] 3. Write \\`yg-aspect.yaml\\` — name, optional description, optional implies\n- [ ] 4. Write content \\`.md\\` files: WHAT must be satisfied + WHY (user's words, do not invent)\n- [ ] 5. \\`yg validate\\`\n\nTest: \"Does this requirement apply to more than one node?\" Yes → aspect. No → local artifact.\n\n**Aspect identification heuristic:** If the same pattern, constraint, or rule appears in 3+ places, it is a candidate aspect. Aspects fall into natural categories:\n\n- **Domain-specific:** Business rules that cross module boundaries (e.g., timezone handling, booking periods, currency rounding)\n- **Architectural:** Structural patterns with rationale (e.g., dual-rollback on provider failure, idempotency via key generation, fire-and-forget dispatch)\n- **Concurrency:** Shared concurrency strategies (e.g., pessimistic locking, retry-on-deadlock, optimistic versioning)\n\nWhen a node follows an aspect's pattern with exceptions, record them in the \\`exceptions\\` field of the aspect entry in \\`yg-node.yaml\\`. Example: aspect says \"fire-and-forget\" but this node awaits the publish call — add \\`exceptions: [\"awaits publish call instead of fire-and-forget because...\"]\\`. Exceptions appear in the context package next to the aspect content, preventing abstractions from masking implementation details.\n\n**Aspect lifecycle warning.** Aspects decay CATASTROPHICALLY — a pattern either exists or it doesn't. When a pattern changes, ALL aspect claims become wrong at once. This differs from other artifacts: \\`interface.md\\` and \\`responsibility.md\\` are most stable (~9-year half-life); \\`internals.md\\` has moderate stability (~2.5-year half-life); aspects are least stable (~2.4-year half-life, binary decay). After any significant feature addition, review ALL aspects touching the affected area. Don't wait for drift — aspects can be 100% wrong without any mapped file changing.\n\n**Aspect stability tiers.** If an aspect has a \\`stability\\` field in \\`yg-aspect.yaml\\`, use it to calibrate review urgency:\n\n- \\`schema\\` — enforced by data model; review only when data model changes (most stable)\n- \\`protocol\\` — contractual pattern; review when contracts or interfaces change\n- \\`implementation\\` — specific mechanism; review after ANY significant code change (least stable)\n\nWhen code anchors (\\`anchors\\` in an aspect entry in \\`yg-node.yaml\\`) are present, they list code patterns (function names, constants, SQL fragments) evidencing the aspect's implementation in this node. \\`yg validate\\` checks that each anchor exists in the node's mapped source files — a missing anchor (W014) signals the aspect may be stale for this node.\n\n### Creating Flows\n\n- [ ] 1. Read \\`schemas/yg-flow.yaml\\`\n- [ ] 2. Create \\`flows/<name>/\\` directory\n- [ ] 3. Write \\`yg-flow.yaml\\` — declare participants and flow-level aspects\n- [ ] 4. Write \\`description.md\\` with required sections: Business context, Trigger, Goal, Participants, Paths (at least Happy path), Invariants across all paths\n- [ ] 5. \\`yg validate\\`\n\nTest: \"Does this describe what happens in the world, or only in the software?\" If only software — rewrite.\n\n**Warning:** Flow descriptions must describe business processes, not code sequences. \"The OrderService calls PaymentGateway.charge()\" is WRONG. \"The system charges the customer's payment method\" is CORRECT.\n\n### Operational Rules\n\n- **English only** for all files in \\`.yggdrasil/\\`. Conversation can be any language.\n- **Read schemas before creating** any \\`yg-node.yaml\\`, \\`yg-aspect.yaml\\`, or \\`yg-flow.yaml\\`.\n- **Tools read, you write.** The \\`yg\\` CLI only reads, validates, and manages metadata. You create and edit files manually.\n- **Incremental sync.** Run \\`yg drift-sync\\` after every 3-5 source file changes. Do not defer to end of task.\n- **Completeness test:** Two checks, both required:\n 1. **Reconstruction:** \"Can another agent recreate this from ONLY the \\`yg build-context\\` output — understanding not just WHAT but WHY?\" Test: rejected alternatives, correct algorithm, design arguments.\n 2. **Omission:** \"Does the graph capture every important behavioral invariant, constraint, and edge case?\" Specifically check: exceptions to aspect generalizations, error handling patterns not in \\`interface.md\\`, concurrency behaviors not in \\`internals.md\\`.\n- **Value calibration.** Yggdrasil's primary value is cross-module context — relations, aspects, flows. For a single simple module, \\`responsibility.md\\` and \\`interface.md\\` provide most value. Invest depth (\\`internals.md\\`) where cross-module interactions demand it.\n- **These rules are invariant.** No plan, guide, skill, or workflow may override them.\n\n### CLI Reference\n\n\\`\\`\\`\nyg preflight [--quick] Unified diagnostic: drift + status + validate.\nyg owner --file <path> Find the node that owns this file.\nyg build-context --node <path> Assemble context package for this node.\nyg tree [--root <path>] [--depth N] Print graph structure.\nyg aspects List aspects with metadata (YAML output).\nyg flows List flows with metadata (YAML output).\nyg deps --node <path> [--depth N] [--type structural|event|all]\n Show dependencies.\nyg impact --node <path> --simulate Simulate blast radius of a planned change.\nyg impact --node <path> --method <name> Filter impact to dependents consuming a specific method.\nyg impact --aspect <id> Show all nodes where aspect is effective.\nyg impact --flow <name> Show flow participants and descendants.\nyg status Graph health: nodes, coverage, drift summary.\nyg validate [--scope <path>|all] Check structural integrity and completeness.\nyg drift [--scope <path>|all] [--drifted-only] [--limit <n>]\n Detect source and graph drift (bidirectional).\nyg drift-sync --node <path> [--recursive] | --all\n Record file hashes as new baseline.\n\\`\\`\\`\n\n### Quick Routing Table\n\n| What you have | Where it goes |\n|---|---|\n| Information specific to this node | Local node artifact (check \\`yg-config.yaml artifacts\\` for types) |\n| Rule that applies to many nodes | Aspect (content \\`.md\\` files in \\`aspects/<id>/\\`) |\n| Architectural invariant for a node type | Required aspect in \\`yg-config.yaml node_types\\` |\n| Business process participation | Flow (\\`yg-flow.yaml participants\\`) |\n| Process-level requirement | Flow \\`aspects\\` + aspect directory |\n| Context shared across a domain | Parent node artifact |\n| Technology stack | Node artifact at appropriate hierarchy level |\n| Coding standards | Node artifact at appropriate hierarchy level |`;\n\nexport const AGENT_RULES_CONTENT = [CORE_PROTOCOL, OPERATIONS, KNOWLEDGE_BASE].join('\\n\\n---\\n\\n') + '\\n';\n","import { readFile, access } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport { gt, valid, compare } from 'semver';\n\nexport interface Migration {\n to: string;\n description: string;\n run(yggRoot: string): Promise<MigrationResult>;\n}\n\nexport interface MigrationResult {\n actions: string[];\n warnings: string[];\n}\n\n/**\n * Detect the Yggdrasil version of a project.\n * Returns semver string, '1.4.3' for pre-version projects, or null if no config found.\n * Version field validation is intentionally deferred to the migration runner, not the config parser,\n * since migrating old configs is exactly the purpose of this module.\n */\nexport async function detectVersion(yggRoot: string): Promise<string | null> {\n // Try yg-config.yaml first\n const newConfigPath = path.join(yggRoot, 'yg-config.yaml');\n try {\n const content = await readFile(newConfigPath, 'utf-8');\n const raw = parseYaml(content) as Record<string, unknown>;\n if (raw && typeof raw === 'object' && typeof raw.version === 'string') {\n return raw.version.trim();\n }\n return '1.4.3'; // yg-config.yaml exists but no version field → pre-2.0.0\n } catch {\n // yg-config.yaml not found\n }\n\n // Try old config.yaml (1.x format)\n const oldConfigPath = path.join(yggRoot, 'config.yaml');\n try {\n await access(oldConfigPath);\n return '1.4.3';\n } catch {\n return null;\n }\n}\n\n/**\n * Run all applicable migrations sequentially.\n * A migration is applicable when its target version is strictly greater than currentVersion.\n * Migrations are sorted by target version ascending before running.\n */\nexport async function runMigrations(\n currentVersion: string,\n migrations: Migration[],\n yggRoot: string,\n): Promise<MigrationResult[]> {\n const cVer = valid(currentVersion);\n if (!cVer) return [];\n\n const applicable = migrations\n .filter((m) => {\n const mVer = valid(m.to);\n if (!mVer) return false;\n return gt(mVer, cVer);\n })\n .sort((a, b) => compare(valid(a.to)!, valid(b.to)!));\n\n const results: MigrationResult[] = [];\n for (const migration of applicable) {\n const result = await migration.run(yggRoot);\n results.push(result);\n }\n return results;\n}\n","import { readFile, writeFile, rename, readdir, rm, stat } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse as parseYaml, stringify as stringifyYaml } from 'yaml';\nimport type { MigrationResult } from '../core/migrator.js';\n\nconst KNOWN_TYPE_DESCRIPTIONS: Record<string, string> = {\n module: 'Business logic unit with clear domain responsibility',\n service: 'Component providing functionality to other nodes',\n library: 'Shared utility code with no domain knowledge',\n infrastructure: 'Guards, middleware, interceptors — invisible in call graphs but affect blast radius',\n};\n\nconst STANDARD_ARTIFACTS = {\n 'responsibility.md': {\n required: 'always' as const,\n description: 'What this node is responsible for, and what it is not',\n included_in_relations: true,\n },\n 'interface.md': {\n required: { when: 'has_incoming_relations' },\n description: 'Public API — methods, parameters, return types, contracts, failure modes, exposed data structures',\n included_in_relations: true,\n },\n 'internals.md': {\n required: 'never' as const,\n description: 'How the node works and why — algorithms, business rules, state machines, design decisions with rejected alternatives',\n },\n};\n\nexport async function migrateTo2(yggRoot: string): Promise<MigrationResult> {\n const actions: string[] = [];\n const warnings: string[] = [];\n\n // Step 1: Read and rename config (idempotent: fallback to yg-config.yaml if already renamed)\n const oldConfigPath = path.join(yggRoot, 'config.yaml');\n const newConfigPath = path.join(yggRoot, 'yg-config.yaml');\n let configContent: string;\n\n const oldConfigExists = await fileExists(oldConfigPath);\n if (oldConfigExists) {\n configContent = await readFile(oldConfigPath, 'utf-8');\n await rename(oldConfigPath, newConfigPath);\n actions.push('Renamed config.yaml → yg-config.yaml');\n } else {\n // Already renamed (idempotent)\n configContent = await readFile(newConfigPath, 'utf-8');\n }\n\n const raw = parseYaml(configContent) as Record<string, unknown>;\n\n // Step 2: Transform node_types\n const nodeTypesRaw = raw.node_types;\n const nodeTypes: Record<string, { description: string; required_aspects?: string[] }> = {};\n\n if (Array.isArray(nodeTypesRaw)) {\n for (const typeName of nodeTypesRaw) {\n if (typeof typeName === 'string') {\n const desc = KNOWN_TYPE_DESCRIPTIONS[typeName];\n if (desc) {\n nodeTypes[typeName] = { description: desc };\n } else {\n nodeTypes[typeName] = { description: 'TODO: add description' };\n warnings.push(`Unknown node type '${typeName}' — needs a description`);\n }\n }\n }\n actions.push('Converted node_types from array to object format');\n } else if (nodeTypesRaw && typeof nodeTypesRaw === 'object') {\n for (const [name, val] of Object.entries(nodeTypesRaw as Record<string, unknown>)) {\n const entry = val as Record<string, unknown>;\n const desc = KNOWN_TYPE_DESCRIPTIONS[name] ?? (typeof entry?.description === 'string' ? entry.description : 'TODO: add description');\n nodeTypes[name] = { description: desc };\n if (entry?.required_aspects) {\n nodeTypes[name].required_aspects = entry.required_aspects as string[];\n }\n if (!KNOWN_TYPE_DESCRIPTIONS[name] && (!entry?.description || entry.description === 'TODO: add description')) {\n warnings.push(`Unknown node type '${name}' — needs a description`);\n }\n }\n }\n\n // Add infrastructure if missing\n if (!nodeTypes.infrastructure) {\n nodeTypes.infrastructure = { description: KNOWN_TYPE_DESCRIPTIONS.infrastructure };\n actions.push('Added infrastructure node type');\n }\n\n // Step 3: Migrate stack/standards to root node internals.md (idempotent: checks for existing section)\n const stackRaw = raw.stack as Record<string, string> | undefined;\n const standardsRaw = raw.standards as string | undefined;\n\n if (stackRaw || standardsRaw) {\n await migrateStackStandards(yggRoot, stackRaw, standardsRaw, actions);\n }\n\n // Step 4: Write new config (always overwrite — idempotent since output is deterministic)\n const newConfig: Record<string, unknown> = {\n version: '2.0.0',\n name: raw.name,\n node_types: nodeTypes,\n artifacts: STANDARD_ARTIFACTS,\n };\n if (raw.quality) {\n newConfig.quality = raw.quality;\n }\n await writeFile(newConfigPath, stringifyYaml(newConfig, { lineWidth: 120 }), 'utf-8');\n actions.push('Updated config: version, artifacts, removed stack/standards');\n\n // Step 5: Rename and transform model files\n const modelDir = path.join(yggRoot, 'model');\n if (await fileExists(modelDir)) {\n // Rename must happen before transform — transformNodeFiles only processes yg-node.yaml\n await renameFilesRecursively(modelDir, 'node.yaml', 'yg-node.yaml', actions);\n await transformNodeFiles(modelDir, actions, warnings);\n }\n\n // Step 6: Rename aspect files\n const aspectsDir = path.join(yggRoot, 'aspects');\n if (await fileExists(aspectsDir)) {\n await renameFilesRecursively(aspectsDir, 'aspect.yaml', 'yg-aspect.yaml', actions);\n }\n\n // Step 7: Rename flow files\n const flowsDir = path.join(yggRoot, 'flows');\n if (await fileExists(flowsDir)) {\n await renameFilesRecursively(flowsDir, 'flow.yaml', 'yg-flow.yaml', actions);\n }\n\n // Step 8: Rename schema files (idempotent: skip if source missing or destination exists)\n const schemasDir = path.join(yggRoot, 'schemas');\n if (await fileExists(schemasDir)) {\n for (const name of ['config.yaml', 'node.yaml', 'aspect.yaml', 'flow.yaml']) {\n const oldPath = path.join(schemasDir, name);\n const newPath = path.join(schemasDir, `yg-${name}`);\n if ((await fileExists(oldPath)) && !(await fileExists(newPath))) {\n await rename(oldPath, newPath);\n actions.push(`Renamed schemas/${name} → yg-${name}`);\n }\n }\n }\n\n // Step 9: Delete drift state (idempotent: silently skip if already gone)\n const driftStatePath = path.join(yggRoot, '.drift-state');\n if (await fileExists(driftStatePath)) {\n await rm(driftStatePath);\n actions.push('Deleted .drift-state (requires fresh yg drift-sync --all)');\n }\n\n return { actions, warnings };\n}\n\nasync function fileExists(p: string): Promise<boolean> {\n try { await stat(p); return true; } catch { return false; }\n}\n\nasync function migrateStackStandards(\n yggRoot: string,\n stack: Record<string, string> | undefined,\n standards: string | undefined,\n actions: string[],\n): Promise<void> {\n const modelDir = path.join(yggRoot, 'model');\n if (!(await fileExists(modelDir))) return;\n\n const lines: string[] = [];\n if (stack && Object.keys(stack).length > 0) {\n lines.push('## Technology Stack');\n lines.push('');\n for (const [key, value] of Object.entries(stack)) {\n lines.push(`- **${key}:** ${value}`);\n }\n lines.push('');\n }\n if (standards) {\n lines.push('## Standards');\n lines.push('');\n lines.push(standards);\n lines.push('');\n }\n\n if (lines.length === 0) return;\n\n // Check if root node exists; create if not\n const rootNodeYgPath = path.join(modelDir, 'yg-node.yaml');\n const rootNodeOldPath = path.join(modelDir, 'node.yaml');\n const hasRootNode = (await fileExists(rootNodeYgPath)) || (await fileExists(rootNodeOldPath));\n\n if (!hasRootNode) {\n await writeFile(rootNodeYgPath, stringifyYaml({ name: 'Root', type: 'module' }), 'utf-8');\n await writeFile(path.join(modelDir, 'responsibility.md'), 'TBD\\n', 'utf-8');\n actions.push('Created root node in model/ for stack/standards migration');\n }\n\n // Write internals.md — idempotent: skip if marker already present\n const internalsPath = path.join(modelDir, 'internals.md');\n const existingInternals = (await fileExists(internalsPath)) ? await readFile(internalsPath, 'utf-8') : '';\n\n // Unique HTML comment marker — invisible in rendered Markdown, never false-triggers\n const MIGRATION_MARKER = '<!-- migrated-stack-standards-v2 -->';\n if (existingInternals.includes(MIGRATION_MARKER)) {\n return;\n }\n const markerLine = MIGRATION_MARKER + '\\n';\n const newContent = existingInternals\n ? existingInternals.trimEnd() + '\\n\\n' + markerLine + lines.join('\\n')\n : markerLine + lines.join('\\n');\n await writeFile(internalsPath, newContent, 'utf-8');\n actions.push('Migrated stack/standards to model/internals.md');\n}\n\nasync function renameFilesRecursively(\n dir: string,\n oldName: string,\n newName: string,\n actions: string[],\n): Promise<void> {\n let entries;\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n await renameFilesRecursively(fullPath, oldName, newName, actions);\n } else if (entry.name === oldName) {\n const destPath = path.join(dir, newName);\n // Idempotent: skip if destination already exists (previous run)\n if (!(await fileExists(destPath))) {\n await rename(fullPath, destPath);\n actions.push(`Renamed ${oldName} → ${newName} in ${dir}`);\n }\n }\n }\n}\n\nasync function transformNodeFiles(dir: string, actions: string[], warnings: string[]): Promise<void> {\n let entries;\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n await transformNodeFiles(fullPath, actions, warnings);\n } else if (entry.name === 'yg-node.yaml') {\n await transformSingleNode(fullPath, actions, warnings);\n }\n }\n}\n\nasync function transformSingleNode(filePath: string, actions: string[], warnings: string[]): Promise<void> {\n const content = await readFile(filePath, 'utf-8');\n const raw = parseYaml(content) as Record<string, unknown>;\n if (!raw || typeof raw !== 'object') {\n warnings.push(`Skipped ${filePath}: not a valid YAML object`);\n return;\n }\n\n let changed = false;\n\n // Convert aspects from string array to object array (idempotent: check first element type)\n if (Array.isArray(raw.aspects) && raw.aspects.length > 0 && typeof raw.aspects[0] === 'string') {\n const aspectExceptions = (raw.aspect_exceptions ?? {}) as Record<string, string[]>;\n const anchors = (raw.anchors ?? {}) as Record<string, string[]>;\n\n raw.aspects = (raw.aspects as string[]).map((id) => {\n const entry: Record<string, unknown> = { aspect: id };\n if (aspectExceptions[id]) entry.exceptions = aspectExceptions[id];\n if (anchors[id]) entry.anchors = anchors[id];\n return entry;\n });\n\n delete raw.aspect_exceptions;\n delete raw.anchors;\n changed = true;\n }\n\n // Remove tags (idempotent: only if present)\n if (raw.tags !== undefined) {\n delete raw.tags;\n changed = true;\n }\n\n if (changed) {\n await writeFile(filePath, stringifyYaml(raw, { lineWidth: 120 }), 'utf-8');\n actions.push(`Transformed ${path.basename(path.dirname(filePath))}/yg-node.yaml`);\n }\n}\n","import type { Migration } from '../core/migrator.js';\nimport { migrateTo2 } from './to-2.0.0.js';\n\nexport const MIGRATIONS: Migration[] = [\n {\n to: '2.0.0',\n description: 'Rename YAML files to yg-* prefix, restructure config, convert aspects format',\n run: migrateTo2,\n },\n];\n","import { readdir, readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type {\n Graph,\n GraphNode,\n AspectDef,\n FlowDef,\n SchemaDef,\n YggConfig,\n} from '../model/types.js';\nimport { parseConfig } from '../io/config-parser.js';\nimport { parseNodeYaml } from '../io/node-parser.js';\nimport { parseAspect } from '../io/aspect-parser.js';\nimport { parseFlow } from '../io/flow-parser.js';\nimport { parseSchema } from '../io/schema-parser.js';\nimport { readArtifacts } from '../io/artifact-reader.js';\nimport { findYggRoot } from '../utils/paths.js';\n\nfunction toModelPath(absolutePath: string, modelDir: string): string {\n return path.relative(modelDir, absolutePath).split(path.sep).join('/');\n}\n\nconst FALLBACK_CONFIG: YggConfig = {\n name: '',\n node_types: {},\n artifacts: {},\n};\n\nexport async function loadGraph(\n projectRoot: string,\n options: { tolerateInvalidConfig?: boolean } = {},\n): Promise<Graph> {\n const yggRoot = await findYggRoot(projectRoot);\n let configError: string | undefined;\n let config = FALLBACK_CONFIG;\n try {\n config = await parseConfig(path.join(yggRoot, 'yg-config.yaml'));\n } catch (error) {\n if (!options.tolerateInvalidConfig) {\n throw error;\n }\n configError = (error as Error).message;\n }\n\n const modelDir = path.join(yggRoot, 'model');\n const nodes = new Map<string, GraphNode>();\n const nodeParseErrors: Array<{ nodePath: string; message: string }> = [];\n const artifactFilenames = Object.keys(config.artifacts ?? {});\n try {\n await scanModelDirectory(modelDir, modelDir, null, nodes, nodeParseErrors, artifactFilenames);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new Error(`Directory .yggdrasil/model/ does not exist. Run 'yg init' first.`, {\n cause: err,\n });\n }\n throw err;\n }\n\n const aspects = await loadAspects(path.join(yggRoot, 'aspects'));\n const flows = await loadFlows(path.join(yggRoot, 'flows'));\n const schemas = await loadSchemas(path.join(yggRoot, 'schemas'));\n\n return {\n config,\n configError,\n nodeParseErrors: nodeParseErrors.length > 0 ? nodeParseErrors : undefined,\n nodes,\n aspects,\n flows,\n schemas,\n rootPath: yggRoot,\n };\n}\n\nasync function scanModelDirectory(\n dirPath: string,\n modelDir: string,\n parent: GraphNode | null,\n nodes: Map<string, GraphNode>,\n nodeParseErrors: Array<{ nodePath: string; message: string }>,\n artifactFilenames: string[],\n): Promise<void> {\n const entries = await readdir(dirPath, { withFileTypes: true });\n const hasNodeYaml = entries.some((e) => e.isFile() && e.name === 'yg-node.yaml');\n\n if (!hasNodeYaml && dirPath !== modelDir) {\n return;\n }\n\n if (hasNodeYaml) {\n const graphPath = toModelPath(dirPath, modelDir);\n const nodeYamlPath = path.join(dirPath, 'yg-node.yaml');\n let meta;\n let nodeYamlRaw: string | undefined;\n try {\n nodeYamlRaw = await readFile(nodeYamlPath, 'utf-8');\n meta = await parseNodeYaml(nodeYamlPath);\n } catch (err) {\n nodeParseErrors.push({\n nodePath: graphPath,\n message: (err as Error).message,\n });\n return;\n }\n const artifacts = await readArtifacts(dirPath, ['yg-node.yaml'], artifactFilenames);\n\n const node: GraphNode = {\n path: graphPath,\n meta,\n nodeYamlRaw,\n artifacts,\n children: [],\n parent,\n };\n\n nodes.set(graphPath, node);\n if (parent) {\n parent.children.push(node);\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n if (entry.name.startsWith('.')) continue;\n\n await scanModelDirectory(\n path.join(dirPath, entry.name),\n modelDir,\n node,\n nodes,\n nodeParseErrors,\n artifactFilenames,\n );\n }\n } else {\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n if (entry.name.startsWith('.')) continue;\n\n await scanModelDirectory(\n path.join(dirPath, entry.name),\n modelDir,\n null,\n nodes,\n nodeParseErrors,\n artifactFilenames,\n );\n }\n }\n}\n\nasync function loadAspects(aspectsDir: string): Promise<AspectDef[]> {\n try {\n const aspects: AspectDef[] = [];\n await scanAspectsDirectory(aspectsDir, aspectsDir, aspects);\n return aspects;\n } catch {\n return [];\n }\n}\n\nasync function scanAspectsDirectory(\n dirPath: string,\n aspectsRoot: string,\n aspects: AspectDef[],\n): Promise<void> {\n const entries = await readdir(dirPath, { withFileTypes: true });\n const hasAspectYaml = entries.some((e) => e.isFile() && e.name === 'yg-aspect.yaml');\n\n if (hasAspectYaml) {\n const id = path.relative(aspectsRoot, dirPath).split(path.sep).join('/');\n const aspectYamlPath = path.join(dirPath, 'yg-aspect.yaml');\n const aspect = await parseAspect(dirPath, aspectYamlPath, id);\n aspects.push(aspect);\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n if (entry.name.startsWith('.')) continue;\n await scanAspectsDirectory(path.join(dirPath, entry.name), aspectsRoot, aspects);\n }\n}\n\nasync function loadFlows(flowsDir: string): Promise<FlowDef[]> {\n try {\n const entries = await readdir(flowsDir, { withFileTypes: true });\n const flows: FlowDef[] = [];\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const flowYamlPath = path.join(flowsDir, entry.name, 'yg-flow.yaml');\n const flow = await parseFlow(path.join(flowsDir, entry.name), flowYamlPath);\n flows.push(flow);\n }\n return flows;\n } catch {\n return [];\n }\n}\n\nasync function loadSchemas(schemasDir: string): Promise<SchemaDef[]> {\n try {\n const entries = await readdir(schemasDir, { withFileTypes: true });\n const schemas: SchemaDef[] = [];\n for (const entry of entries) {\n if (!entry.isFile()) continue;\n if (!entry.name.endsWith('.yaml') && !entry.name.endsWith('.yml')) continue;\n const s = await parseSchema(path.join(schemasDir, entry.name));\n schemas.push(s);\n }\n return schemas;\n } catch {\n return [];\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { parse as parseYaml } from 'yaml';\nimport type {\n YggConfig,\n ArtifactConfig,\n QualityConfig,\n NodeTypeConfig,\n} from '../model/types.js';\n\nconst DEFAULT_QUALITY: QualityConfig = {\n min_artifact_length: 50,\n max_direct_relations: 10,\n context_budget: { warning: 10000, error: 20000 },\n};\n\nexport async function parseConfig(filePath: string): Promise<YggConfig> {\n const content = await readFile(filePath, 'utf-8');\n const raw = parseYaml(content) as Record<string, unknown>;\n\n if (!raw || typeof raw !== 'object') {\n throw new Error(`yg-config.yaml: file is empty or not a valid YAML mapping`);\n }\n\n const version = typeof raw.version === 'string' ? raw.version.trim() : undefined;\n\n if (!raw.name || typeof raw.name !== 'string' || raw.name.trim() === '') {\n throw new Error(`yg-config.yaml: missing or invalid 'name' field`);\n }\n\n const nodeTypesRaw = raw.node_types;\n if (\n !nodeTypesRaw ||\n typeof nodeTypesRaw !== 'object' ||\n Array.isArray(nodeTypesRaw) ||\n Object.keys(nodeTypesRaw).length === 0\n ) {\n throw new Error(`yg-config.yaml: 'node_types' must be a non-empty object`);\n }\n\n const nodeTypes: Record<string, NodeTypeConfig> = {};\n for (const [typeName, val] of Object.entries(nodeTypesRaw)) {\n const entry = val as Record<string, unknown>;\n if (!entry || typeof entry !== 'object' || typeof entry.description !== 'string' || entry.description.trim() === '') {\n throw new Error(\n `yg-config.yaml: node_types.${typeName} must have a non-empty 'description' string`,\n );\n }\n const requiredAspects = Array.isArray(entry.required_aspects)\n ? (entry.required_aspects as unknown[]).filter((t): t is string => typeof t === 'string')\n : undefined;\n nodeTypes[typeName] = {\n description: entry.description as string,\n required_aspects: requiredAspects && requiredAspects.length > 0 ? requiredAspects : undefined,\n };\n }\n\n const artifacts = raw.artifacts;\n if (\n !artifacts ||\n typeof artifacts !== 'object' ||\n Array.isArray(artifacts) ||\n Object.keys(artifacts).length === 0\n ) {\n throw new Error(`yg-config.yaml: 'artifacts' must be a non-empty object`);\n }\n\n const artifactsMap: Record<string, ArtifactConfig> = {};\n for (const [key, val] of Object.entries(artifacts)) {\n if (key === 'yg-node.yaml') {\n throw new Error(`yg-config.yaml: artifact name 'yg-node.yaml' is reserved`);\n }\n const a = val as Record<string, unknown>;\n const required = a.required;\n if (\n required !== 'always' &&\n required !== 'never' &&\n (typeof required !== 'object' || !required || !('when' in required))\n ) {\n throw new Error(`yg-config.yaml: artifact '${key}' has invalid 'required' field`);\n }\n if (typeof required === 'object' && required && 'when' in required) {\n const when = (required as { when: string }).when;\n const validWhen =\n when === 'has_incoming_relations' ||\n when === 'has_outgoing_relations' ||\n (typeof when === 'string' &&\n (when.startsWith('has_aspect:') || when.startsWith('has_tag:')));\n if (!validWhen) {\n throw new Error(\n `yg-config.yaml: artifact '${key}' has invalid 'required.when': must be has_incoming_relations, has_outgoing_relations, or has_aspect:<name>`,\n );\n }\n }\n artifactsMap[key] = {\n required: required as ArtifactConfig['required'],\n description: (a.description as string) ?? '',\n included_in_relations: (a.included_in_relations as boolean) ?? false,\n };\n }\n\n const qualityRaw = raw.quality as Record<string, unknown> | undefined;\n const quality: QualityConfig = qualityRaw\n ? {\n min_artifact_length:\n (qualityRaw.min_artifact_length as number) ?? DEFAULT_QUALITY.min_artifact_length,\n max_direct_relations:\n (qualityRaw.max_direct_relations as number) ?? DEFAULT_QUALITY.max_direct_relations,\n context_budget: {\n warning:\n (qualityRaw.context_budget as Record<string, number>)?.warning ??\n DEFAULT_QUALITY.context_budget.warning,\n error:\n (qualityRaw.context_budget as Record<string, number>)?.error ??\n DEFAULT_QUALITY.context_budget.error,\n },\n }\n : DEFAULT_QUALITY;\n\n if (quality.context_budget.error < quality.context_budget.warning) {\n throw new Error(\n `yg-config.yaml: quality.context_budget.error (${quality.context_budget.error}) must be >= warning (${quality.context_budget.warning})`,\n );\n }\n\n return {\n version,\n name: (raw.name as string).trim(),\n node_types: nodeTypes,\n artifacts: artifactsMap,\n quality,\n };\n}\n","import { readFile } from 'node:fs/promises';\nimport { parse as parseYaml } from 'yaml';\nimport type { NodeAspectEntry, NodeMeta, NodeMapping, Relation, RelationType } from '../model/types.js';\n\nconst RELATION_TYPES: RelationType[] = [\n 'uses',\n 'calls',\n 'extends',\n 'implements',\n 'emits',\n 'listens',\n];\n\nfunction isValidRelationType(t: unknown): t is RelationType {\n return typeof t === 'string' && RELATION_TYPES.includes(t as RelationType);\n}\n\nexport async function parseNodeYaml(filePath: string): Promise<NodeMeta> {\n const content = await readFile(filePath, 'utf-8');\n const raw = parseYaml(content) as Record<string, unknown>;\n\n if (!raw || typeof raw !== 'object') {\n throw new Error(`yg-node.yaml at ${filePath}: file is empty or not a valid YAML mapping`);\n }\n\n if (!raw.name || typeof raw.name !== 'string' || raw.name.trim() === '') {\n throw new Error(`yg-node.yaml at ${filePath}: missing or empty 'name'`);\n }\n if (!raw.type || typeof raw.type !== 'string' || raw.type.trim() === '') {\n throw new Error(`yg-node.yaml at ${filePath}: missing or empty 'type'`);\n }\n\n const relations = parseRelations(raw.relations, filePath);\n const mapping = parseMapping(raw.mapping, filePath);\n const aspects = parseAspects(raw.aspects, filePath);\n\n return {\n name: (raw.name as string).trim(),\n type: (raw.type as string).trim(),\n aspects,\n blackbox: (raw.blackbox as boolean) ?? false,\n relations: relations.length > 0 ? relations : undefined,\n mapping,\n };\n}\n\nfunction parseAspects(raw: unknown, filePath: string): NodeAspectEntry[] | undefined {\n if (raw === undefined || raw === null) return undefined;\n if (!Array.isArray(raw)) {\n throw new Error(`yg-node.yaml at ${filePath}: 'aspects' must be an array`);\n }\n if (raw.length === 0) return undefined;\n\n const result: NodeAspectEntry[] = [];\n const seenAspects = new Set<string>();\n\n for (let i = 0; i < raw.length; i++) {\n const item = raw[i];\n if (typeof item !== 'object' || item === null) {\n throw new Error(`yg-node.yaml at ${filePath}: aspects[${i}] must be an object with 'aspect' key`);\n }\n const obj = item as Record<string, unknown>;\n\n if (typeof obj.aspect !== 'string' || obj.aspect.trim() === '') {\n throw new Error(\n `yg-node.yaml at ${filePath}: aspects[${i}].aspect must be a non-empty string`,\n );\n }\n\n const aspectId = obj.aspect.trim();\n if (seenAspects.has(aspectId)) {\n throw new Error(\n `yg-node.yaml at ${filePath}: duplicate aspect '${aspectId}' in aspects list`,\n );\n }\n seenAspects.add(aspectId);\n\n const entry: NodeAspectEntry = { aspect: aspectId };\n\n // Parse exceptions (optional string[])\n if (obj.exceptions !== undefined && obj.exceptions !== null) {\n if (!Array.isArray(obj.exceptions)) {\n throw new Error(\n `yg-node.yaml at ${filePath}: aspects[${i}].exceptions must be an array of strings`,\n );\n }\n const exceptions = obj.exceptions.filter((e): e is string => typeof e === 'string' && e.trim() !== '');\n if (exceptions.length > 0) {\n entry.exceptions = exceptions;\n }\n }\n\n // Parse anchors (optional string[])\n if (obj.anchors !== undefined && obj.anchors !== null) {\n if (!Array.isArray(obj.anchors)) {\n throw new Error(\n `yg-node.yaml at ${filePath}: aspects[${i}].anchors must be an array of strings`,\n );\n }\n const anchors = obj.anchors.filter((a): a is string => typeof a === 'string' && a.trim() !== '');\n if (anchors.length > 0) {\n entry.anchors = anchors;\n }\n }\n\n result.push(entry);\n }\n\n return result.length > 0 ? result : undefined;\n}\n\nfunction parseRelations(raw: unknown, filePath: string): Relation[] {\n if (raw === undefined) return [];\n if (!Array.isArray(raw)) {\n throw new Error(`yg-node.yaml at ${filePath}: 'relations' must be an array`);\n }\n\n const result: Relation[] = [];\n for (let index = 0; index < raw.length; index++) {\n const r = raw[index];\n if (typeof r !== 'object' || r === null) {\n throw new Error(`yg-node.yaml at ${filePath}: relations[${index}] must be an object`);\n }\n const obj = r as Record<string, unknown>;\n const target = obj.target;\n const type = obj.type;\n\n if (typeof target !== 'string' || target.trim() === '') {\n throw new Error(\n `yg-node.yaml at ${filePath}: relations[${index}].target must be a non-empty string`,\n );\n }\n if (!isValidRelationType(type)) {\n throw new Error(`yg-node.yaml at ${filePath}: relations[${index}].type is invalid`);\n }\n\n const rel: Relation = {\n target: target.trim(),\n type: type as RelationType,\n };\n if (Array.isArray(obj.consumes)) {\n rel.consumes = (obj.consumes as unknown[]).filter((c): c is string => typeof c === 'string');\n }\n if (typeof obj.failure === 'string') {\n rel.failure = obj.failure;\n }\n if (typeof obj.event_name === 'string' && obj.event_name.trim()) {\n rel.event_name = obj.event_name.trim();\n }\n result.push(rel);\n }\n return result;\n}\n\nfunction validateRelativePath(pathValue: string, filePath: string, fieldName: string): string {\n const normalized = pathValue.trim();\n if (normalized === '') {\n throw new Error(`yg-node.yaml at ${filePath}: '${fieldName}' must be non-empty`);\n }\n if (normalized.startsWith('/')) {\n throw new Error(`yg-node.yaml at ${filePath}: '${fieldName}' must be relative to repository root`);\n }\n return normalized;\n}\n\nfunction parseMapping(rawMapping: unknown, filePath: string): NodeMapping | undefined {\n if (!rawMapping || typeof rawMapping !== 'object') return undefined;\n\n const obj = rawMapping as Record<string, unknown>;\n\n // Unified format: mapping.paths — list of files and/or directories (type auto-detected at runtime)\n if (Array.isArray(obj.paths) && obj.paths.length > 0) {\n const paths = (obj.paths as unknown[])\n .filter((p): p is string => typeof p === 'string')\n .map((p) => validateRelativePath(p, filePath, 'mapping.paths[]'));\n if (paths.length === 0) {\n throw new Error(`yg-node.yaml at ${filePath}: mapping.paths must be a non-empty array`);\n }\n return { paths };\n }\n\n if (obj.paths !== undefined || obj.type !== undefined || obj.path !== undefined) {\n throw new Error(\n `yg-node.yaml at ${filePath}: mapping must have paths (array of file/directory paths)`,\n );\n }\n\n return undefined;\n}\n","import { readFile } from 'node:fs/promises';\nimport { parse as parseYaml } from 'yaml';\nimport type { AspectDef, AspectStability } from '../model/types.js';\nimport { readArtifacts } from './artifact-reader.js';\n\nconst VALID_STABILITY_VALUES: AspectStability[] = ['schema', 'protocol', 'implementation'];\n\nexport async function parseAspect(\n aspectDir: string,\n aspectYamlPath: string,\n id: string,\n): Promise<AspectDef> {\n const idTrimmed = id?.trim() ?? '';\n if (!idTrimmed) {\n throw new Error(`Aspect id must be non-empty (relative path in aspects/)`);\n }\n const content = await readFile(aspectYamlPath, 'utf-8');\n const raw = parseYaml(content) as Record<string, unknown>;\n\n if (!raw || typeof raw !== 'object') {\n throw new Error(`Aspect file ${aspectYamlPath}: file is empty or not a valid YAML mapping`);\n }\n\n if (!raw.name || typeof raw.name !== 'string' || raw.name.trim() === '') {\n throw new Error(`Aspect file ${aspectYamlPath}: missing or empty 'name'`);\n }\n\n const description = typeof raw.description === 'string' ? raw.description.trim() : undefined;\n\n const artifacts = await readArtifacts(aspectDir, ['yg-aspect.yaml']);\n\n let implies: string[] | undefined;\n if (raw.implies !== undefined) {\n if (!Array.isArray(raw.implies)) {\n throw new Error(`Aspect file ${aspectYamlPath}: 'implies' must be an array of strings`);\n }\n implies = (raw.implies as unknown[]).filter((t): t is string => typeof t === 'string');\n }\n\n let stability: AspectStability | undefined;\n if (raw.stability !== undefined) {\n if (typeof raw.stability !== 'string' || !VALID_STABILITY_VALUES.includes(raw.stability as AspectStability)) {\n throw new Error(\n `Aspect file ${aspectYamlPath}: 'stability' must be one of: ${VALID_STABILITY_VALUES.join(', ')}`,\n );\n }\n stability = raw.stability as AspectStability;\n }\n\n return {\n name: (raw.name as string).trim(),\n id: idTrimmed,\n description,\n implies,\n stability,\n artifacts,\n };\n}\n","import { readFile, readdir } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Artifact } from '../model/types.js';\n\nexport async function readArtifacts(\n dirPath: string,\n excludeFiles: string[] = ['yg-node.yaml'],\n includeFiles?: string[],\n): Promise<Artifact[]> {\n const entries = await readdir(dirPath, { withFileTypes: true });\n const artifacts: Artifact[] = [];\n const includeSet = includeFiles && includeFiles.length > 0 ? new Set(includeFiles) : null;\n\n for (const entry of entries) {\n if (!entry.isFile()) continue;\n if (excludeFiles.includes(entry.name)) continue;\n if (includeSet && !includeSet.has(entry.name)) continue;\n\n const filePath = path.join(dirPath, entry.name);\n const content = await readFile(filePath, 'utf-8');\n artifacts.push({ filename: entry.name, content });\n }\n\n // Sort by filename for deterministic output\n artifacts.sort((a, b) => a.filename.localeCompare(b.filename));\n return artifacts;\n}\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport type { FlowDef } from '../model/types.js';\nimport { readArtifacts } from './artifact-reader.js';\n\nexport async function parseFlow(flowDir: string, flowYamlPath: string): Promise<FlowDef> {\n const content = await readFile(flowYamlPath, 'utf-8');\n const raw = parseYaml(content) as Record<string, unknown>;\n\n if (!raw || typeof raw !== 'object') {\n throw new Error(`yg-flow.yaml at ${flowYamlPath}: file is empty or not a valid YAML mapping`);\n }\n\n if (!raw.name || typeof raw.name !== 'string' || raw.name.trim() === '') {\n throw new Error(`yg-flow.yaml at ${flowYamlPath}: missing or empty 'name'`);\n }\n\n const nodes = raw.nodes;\n if (!Array.isArray(nodes) || nodes.length === 0) {\n throw new Error(`yg-flow.yaml at ${flowYamlPath}: 'nodes' must be a non-empty array`);\n }\n\n const nodePaths = (nodes as unknown[]).filter((n): n is string => typeof n === 'string');\n if (nodePaths.length === 0) {\n throw new Error(`yg-flow.yaml at ${flowYamlPath}: 'nodes' must contain string node paths`);\n }\n\n let aspects: string[] | undefined;\n if (raw.aspects !== undefined) {\n if (!Array.isArray(raw.aspects)) {\n throw new Error(`yg-flow.yaml at ${flowYamlPath}: 'aspects' must be an array of strings`);\n }\n const aspectTags = (raw.aspects as unknown[]).filter((a): a is string => typeof a === 'string');\n aspects = aspectTags.length > 0 ? aspectTags : [];\n }\n\n const artifacts = await readArtifacts(flowDir, ['yg-flow.yaml']);\n\n return {\n path: path.basename(flowDir),\n name: (raw.name as string).trim(),\n nodes: nodePaths,\n ...(aspects !== undefined && { aspects }),\n artifacts,\n };\n}\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport type { SchemaDef } from '../model/types.js';\n\nexport async function parseSchema(filePath: string): Promise<SchemaDef> {\n const content = await readFile(filePath, 'utf-8');\n parseYaml(content); // validate YAML is parseable\n const rawName = path.basename(filePath, path.extname(filePath));\n const schemaType = rawName.startsWith('yg-') ? rawName.slice(3) : rawName;\n return { schemaType };\n}\n","import path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { stat } from 'node:fs/promises';\n\n/**\n * Directory containing the CLI package (dist/ when bundled).\n * Uses import.meta.url so it works when installed globally.\n */\nexport function getPackageRoot(): string {\n return path.dirname(fileURLToPath(import.meta.url));\n}\n\n/**\n * Find the .yggdrasil/ directory starting from projectRoot.\n * Searches upward through parent directories until found or filesystem root.\n * Returns the absolute path to the .yggdrasil/ directory.\n */\nexport async function findYggRoot(projectRoot: string): Promise<string> {\n let current = path.resolve(projectRoot);\n const root = path.parse(current).root;\n\n while (true) {\n const yggPath = path.join(current, '.yggdrasil');\n try {\n const st = await stat(yggPath);\n if (!st.isDirectory()) {\n throw new Error(\n `.yggdrasil exists but is not a directory (${yggPath}). Run 'yg init' in a clean location.`,\n );\n }\n return yggPath;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n if (current === root) {\n throw new Error(`No .yggdrasil/ directory found. Run 'yg init' first.`, { cause: err });\n }\n current = path.dirname(current);\n continue;\n }\n throw err;\n }\n }\n}\n\nimport type { NodeMapping } from '../model/types.js';\n\n/**\n * Normalize a mapping to always return an array of paths (relative to project root).\n * Each path can be a file or directory — type is detected at runtime by hash/owner.\n */\nexport function normalizeMappingPaths(mapping: NodeMapping | undefined): string[] {\n if (!mapping?.paths?.length) return [];\n return mapping.paths.map((p) => p.trim()).filter(Boolean);\n}\n\n/**\n * Convert a node's directory path to its graph path.\n * E.g., \"/abs/path/.yggdrasil/orders/order-service\" → \"orders/order-service\"\n */\nexport function toGraphPath(absolutePath: string, yggRoot: string): string {\n return path.relative(yggRoot, absolutePath).split(path.sep).join('/');\n}\n\n/**\n * Normalize a user-provided path to project-relative POSIX form.\n * Throws when the target path points outside the project root.\n */\nexport function normalizeProjectRelativePath(projectRoot: string, rawPath: string): string {\n const normalizedInput = rawPath.trim().replace(/\\\\/g, '/');\n if (normalizedInput.length === 0) {\n throw new Error('Path cannot be empty');\n }\n\n const absolute = path.resolve(projectRoot, normalizedInput);\n const relative = path.relative(projectRoot, absolute);\n const isOutside = relative.startsWith('..') || path.isAbsolute(relative);\n if (isOutside) {\n throw new Error(`Path is outside project root: ${rawPath}`);\n }\n\n return relative.split(path.sep).join('/');\n}\n\n/**\n * Normalize a --node path argument: strip leading ./ and trailing /.\n */\nexport function normalizeNodePath(rawPath: string): string {\n return rawPath.trim().replace(/^\\.\\//, '').replace(/\\/+$/, '');\n}\n\n/**\n * Derive the actual project root (repo root) from the graph's .yggdrasil/ path.\n */\nexport function projectRootFromGraph(yggRootPath: string): string {\n return path.dirname(yggRootPath);\n}\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type {\n Graph,\n GraphNode,\n ContextPackage,\n ContextLayer,\n ContextSection,\n YggConfig,\n AspectDef,\n FlowDef,\n Relation,\n} from '../model/types.js';\nimport { normalizeMappingPaths } from '../utils/paths.js';\nimport { estimateTokens } from '../utils/tokens.js';\n\nconst STRUCTURAL_RELATION_TYPES = new Set(['uses', 'calls', 'extends', 'implements']);\nconst EVENT_RELATION_TYPES = new Set(['emits', 'listens']);\n\nexport async function buildContext(graph: Graph, nodePath: string): Promise<ContextPackage> {\n const node = graph.nodes.get(nodePath);\n if (!node) {\n throw new Error(`Node not found: ${nodePath}`);\n }\n\n const layers: ContextLayer[] = [];\n\n // 1. Global\n layers.push(buildGlobalLayer(graph.config));\n\n // 2. Hierarchy (only configured artifacts that exist in ancestor's directory)\n const ancestors = collectAncestors(node);\n for (const ancestor of ancestors) {\n layers.push(buildHierarchyLayer(ancestor, graph.config, graph));\n }\n\n // 3. Own (yg-node.yaml + configured artifacts)\n layers.push(await buildOwnLayer(node, graph.config, graph.rootPath, graph));\n\n // 4. Relational (structural + event, with consumes/failure)\n // Skip relations targeting ancestors — their context is already in hierarchy layers.\n const ancestorPaths = new Set(ancestors.map((a) => a.path));\n for (const relation of node.meta.relations ?? []) {\n const target = graph.nodes.get(relation.target);\n if (!target) {\n throw new Error(`Broken relation: ${nodePath} -> ${relation.target} (target not found)`);\n }\n if (ancestorPaths.has(relation.target)) continue;\n if (STRUCTURAL_RELATION_TYPES.has(relation.type)) {\n layers.push(buildStructuralRelationLayer(target, relation, graph.config));\n } else if (EVENT_RELATION_TYPES.has(relation.type)) {\n layers.push(buildEventRelationLayer(target, relation));\n }\n }\n\n // 5. Flows (node + all ancestors) — built before aspects so we can collect flow aspect ids\n for (const flow of collectParticipatingFlows(graph, node)) {\n layers.push(buildFlowLayer(flow, graph));\n }\n\n // 6. Aspects: union of aspect ids from hierarchy + own + flow layers\n const allAspectIds = new Set<string>();\n for (const l of layers) {\n const aspects = l.attrs?.aspects;\n if (aspects) {\n for (const id of aspects.split(',').map((t) => t.trim()).filter(Boolean)) {\n allAspectIds.add(id);\n }\n }\n }\n const aspectsToInclude = resolveAspects(allAspectIds, graph.aspects);\n for (const aspect of aspectsToInclude) {\n const entry = node.meta.aspects?.find(a => a.aspect === aspect.id);\n const exceptionNote = entry?.exceptions?.join('; ');\n layers.push(buildAspectLayer(aspect, exceptionNote));\n }\n\n const fullText = layers.map((l) => l.content).join('\\n\\n');\n const tokenCount = estimateTokens(fullText);\n const mapping = normalizeMappingPaths(node.meta.mapping);\n const sections = buildSections(layers, mapping.length > 0 ? mapping : null);\n\n return {\n nodePath,\n nodeName: node.meta.name,\n layers,\n sections,\n mapping: mapping.length > 0 ? mapping : null,\n tokenCount,\n };\n}\n\nfunction collectParticipatingFlows(graph: Graph, node: GraphNode): FlowDef[] {\n const paths = new Set<string>([node.path, ...collectAncestors(node).map((a) => a.path)]);\n return graph.flows.filter((f) => f.nodes.some((n) => paths.has(n)));\n}\n\n/** Expand aspect ids to include implied ids recursively. Returns unique list. */\nexport function expandAspects(aspectIds: string[], aspects: AspectDef[]): string[] {\n const idToAspect = new Map<string, AspectDef>();\n for (const a of aspects) {\n idToAspect.set(a.id, a);\n }\n const result: string[] = [];\n const visited = new Set<string>();\n const stack = new Set<string>();\n\n function collect(id: string): void {\n if (stack.has(id)) {\n throw new Error(`Aspect implies cycle detected involving aspect '${id}'`);\n }\n if (visited.has(id)) return;\n stack.add(id);\n visited.add(id);\n result.push(id);\n const aspect = idToAspect.get(id);\n if (aspect) {\n for (const implied of aspect.implies ?? []) {\n collect(implied);\n }\n }\n stack.delete(id);\n }\n\n for (const id of aspectIds) {\n collect(id);\n }\n return result;\n}\n\n/** Expand aspect ids to AspectDefs including implied (recursive, with cycle detection). */\nexport function resolveAspects(\n aspectIds: Iterable<string>,\n aspects: AspectDef[],\n): AspectDef[] {\n const idToAspect = new Map<string, AspectDef>();\n for (const a of aspects) {\n idToAspect.set(a.id, a);\n }\n const expandedIds = expandAspects([...aspectIds], aspects);\n return expandedIds\n .map((id) => idToAspect.get(id))\n .filter((a): a is AspectDef => a !== undefined);\n}\n\n// --- backward-compat aliases (used by tests / external callers) ---\nexport const expandTags = expandAspects;\nexport const expandAspectsForTags = resolveAspects;\n\n// --- Layer builders (exported for testing) ---\n\nexport function buildGlobalLayer(config: YggConfig): ContextLayer {\n const content = `**Project:** ${config.name}\\n`;\n return { type: 'global', label: 'Global Context', content };\n}\n\nfunction filterArtifactsByConfig(\n artifacts: Array<{ filename: string; content: string }>,\n config: YggConfig,\n): Array<{ filename: string; content: string }> {\n const allowed = new Set(Object.keys(config.artifacts ?? {}));\n return artifacts.filter((a) => allowed.has(a.filename));\n}\n\nexport function buildHierarchyLayer(\n ancestor: GraphNode,\n config: YggConfig,\n graph: Graph,\n): ContextLayer {\n const filtered = filterArtifactsByConfig(ancestor.artifacts, config);\n const content = filtered.map((a) => `### ${a.filename}\\n${a.content}`).join('\\n\\n');\n const nodeAspects = (ancestor.meta.aspects ?? []).map(a => a.aspect);\n const expanded = expandAspects(nodeAspects, graph.aspects);\n const attrs: Record<string, string> | undefined =\n expanded.length > 0 ? { aspects: expanded.join(',') } : undefined;\n return {\n type: 'hierarchy',\n label: `Module Context (${ancestor.path}/)`,\n content,\n attrs,\n };\n}\n\nexport async function buildOwnLayer(\n node: GraphNode,\n config: YggConfig,\n graphRootPath: string,\n graph: Graph,\n): Promise<ContextLayer> {\n const parts: string[] = [];\n\n if (node.nodeYamlRaw) {\n parts.push(`### yg-node.yaml\\n${node.nodeYamlRaw.trim()}`);\n } else {\n const nodeYamlPath = path.join(graphRootPath, 'model', node.path, 'yg-node.yaml');\n try {\n const nodeYamlContent = await readFile(nodeYamlPath, 'utf-8');\n parts.push(`### yg-node.yaml\\n${nodeYamlContent.trim()}`);\n } catch {\n parts.push(`### yg-node.yaml\\n(not found)`);\n }\n }\n\n const filtered = filterArtifactsByConfig(node.artifacts, config);\n for (const a of filtered) {\n parts.push(`### ${a.filename}\\n${a.content}`);\n }\n\n const content = parts.join('\\n\\n');\n const nodeAspects = (node.meta.aspects ?? []).map(a => a.aspect);\n const expanded = expandAspects(nodeAspects, graph.aspects);\n const attrs: Record<string, string> | undefined =\n expanded.length > 0 ? { aspects: expanded.join(',') } : undefined;\n return {\n type: 'own',\n label: `Node: ${node.meta.name}`,\n content,\n attrs,\n };\n}\n\nexport function buildStructuralRelationLayer(\n target: GraphNode,\n relation: Relation,\n config: YggConfig,\n): ContextLayer {\n let content = '';\n if (relation.consumes?.length) {\n content += `Consumes: ${relation.consumes.join(', ')}\\n\\n`;\n }\n if (relation.failure) {\n content += `On failure: ${relation.failure}\\n\\n`;\n }\n\n const structuralArtifactFilenames = Object.entries(config.artifacts ?? {})\n .filter(([, c]) => c.included_in_relations)\n .map(([filename]) => filename);\n\n const structuralArts = structuralArtifactFilenames\n .map((filename) => {\n const art = target.artifacts.find((a) => a.filename === filename);\n return art ? { filename: art.filename, content: art.content } : null;\n })\n .filter((a): a is { filename: string; content: string } => a !== null);\n\n if (structuralArts.length > 0) {\n content += structuralArts.map((a) => `### ${a.filename}\\n${a.content}`).join('\\n\\n');\n } else {\n const filtered = filterArtifactsByConfig(target.artifacts, config);\n content += filtered.map((a) => `### ${a.filename}\\n${a.content}`).join('\\n\\n');\n }\n\n const attrs: Record<string, string> = {\n target: target.path,\n type: relation.type,\n };\n if (relation.consumes?.length) attrs.consumes = relation.consumes.join(', ');\n if (relation.failure) attrs.failure = relation.failure;\n\n return {\n type: 'relational',\n label: `Dependency: ${target.meta.name} (${relation.type}) — ${target.path}`,\n content: content.trim(),\n attrs,\n };\n}\n\nexport function buildEventRelationLayer(target: GraphNode, relation: Relation): ContextLayer {\n const eventName = relation.event_name ?? target.meta.name;\n const isEmit = relation.type === 'emits';\n let content = isEmit\n ? `Target: ${target.path}\\nYou publish ${eventName}.`\n : `Source: ${target.path}\\nYou listen for ${eventName}.`;\n if (relation.consumes?.length) {\n content += `\\nConsumes: ${relation.consumes.join(', ')}`;\n }\n const attrs: Record<string, string> = {\n target: target.path,\n type: relation.type,\n 'event-name': eventName,\n };\n if (relation.consumes?.length) attrs.consumes = relation.consumes.join(', ');\n\n return {\n type: 'relational',\n label: `Event: ${eventName} [${relation.type}]`,\n content,\n attrs,\n };\n}\n\nexport function buildAspectLayer(aspect: AspectDef, exceptionNote?: string): ContextLayer {\n let content = aspect.artifacts.map((a) => `### ${a.filename}\\n${a.content}`).join('\\n\\n');\n if (aspect.stability) {\n content += `\\n**Stability tier:** ${aspect.stability}`;\n }\n if (exceptionNote) {\n content += `\\n\\n⚠ **Exception for this node:** ${exceptionNote}`;\n }\n return {\n type: 'aspects',\n label: `${aspect.name} (aspect: ${aspect.id})`,\n content,\n };\n}\n\nfunction buildFlowLayer(flow: FlowDef, graph: Graph): ContextLayer {\n const content = flow.artifacts.map((a) => `### ${a.filename}\\n${a.content}`).join('\\n\\n');\n const flowAspects = flow.aspects ?? [];\n const expanded = expandAspects(flowAspects, graph.aspects);\n const attrs: Record<string, string> | undefined =\n expanded.length > 0 ? { aspects: expanded.join(',') } : undefined;\n return {\n type: 'flows',\n label: `Flow: ${flow.name}`,\n content: content || '(no artifacts)',\n attrs,\n };\n}\n\nfunction buildSections(layers: ContextLayer[], mapping: string[] | null): ContextSection[] {\n const ownLayers = layers.filter((layer) => layer.type === 'own');\n if (mapping && mapping.length > 0) {\n ownLayers.push({\n type: 'own',\n label: 'Materialization Target',\n content: mapping.join(', '),\n });\n }\n\n return [\n { key: 'Global', layers: layers.filter((l) => l.type === 'global') },\n { key: 'Hierarchy', layers: layers.filter((l) => l.type === 'hierarchy') },\n { key: 'OwnArtifacts', layers: ownLayers },\n { key: 'Aspects', layers: layers.filter((l) => l.type === 'aspects') },\n {\n key: 'Relational',\n layers: [\n ...layers.filter((l) => l.type === 'relational'),\n ...layers.filter((l) => l.type === 'flows'),\n ],\n },\n ];\n}\n\n// --- Helpers (exported for testing) ---\n\nexport function collectAncestors(node: GraphNode): GraphNode[] {\n const ancestors: GraphNode[] = [];\n let current = node.parent;\n while (current) {\n ancestors.unshift(current);\n current = current.parent;\n }\n return ancestors;\n}\n\n/** Compute effective aspect ids for a node: own + hierarchy + flow + implies expanded. */\nexport function collectEffectiveAspectIds(graph: Graph, nodePath: string): Set<string> {\n const node = graph.nodes.get(nodePath);\n if (!node) return new Set();\n\n const raw = new Set<string>((node.meta.aspects ?? []).map(a => a.aspect));\n\n // Hierarchy aspects\n let ancestor = node.parent;\n while (ancestor) {\n for (const entry of ancestor.meta.aspects ?? []) raw.add(entry.aspect);\n ancestor = ancestor.parent;\n }\n\n // Flow aspects (flows where node or ancestor participates)\n const ancestorPaths = new Set([nodePath, ...collectAncestors(node).map((a) => a.path)]);\n for (const flow of graph.flows) {\n if (flow.nodes.some((n) => ancestorPaths.has(n))) {\n for (const id of flow.aspects ?? []) raw.add(id);\n }\n }\n\n // Expand implies\n return new Set(expandAspects([...raw], graph.aspects));\n}\n","/**\n * Estimate token count for a string.\n * Heuristic: ~4 characters per token (no tokenizer dependency).\n */\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n","import { readdir, readFile, stat } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Graph, ValidationResult, ValidationIssue, ArtifactConfig, NodeAspectEntry } from '../model/types.js';\nimport { buildContext, resolveAspects } from './context-builder.js';\nimport { normalizeMappingPaths } from '../utils/paths.js';\n\n/** Extract flat aspect id list from unified aspect entries */\nfunction getAspectIds(aspects: NodeAspectEntry[] | undefined): string[] {\n return (aspects ?? []).map(a => a.aspect);\n}\n\n/** Reserved directories that are NOT nodes (within model/) */\nconst RESERVED_DIRS = new Set<string>();\n\nexport async function validate(graph: Graph, scope: string = 'all'): Promise<ValidationResult> {\n const issues: ValidationIssue[] = [];\n\n if (graph.configError) {\n issues.push({\n severity: 'error',\n code: 'E012',\n rule: 'invalid-config',\n message: graph.configError,\n });\n }\n\n for (const { nodePath, message } of graph.nodeParseErrors ?? []) {\n issues.push({\n severity: 'error',\n code: 'E001',\n rule: 'invalid-node-yaml',\n message,\n nodePath,\n });\n }\n\n if (!graph.configError) {\n issues.push(...checkNodeTypes(graph));\n issues.push(...checkAspectsDefined(graph));\n issues.push(...checkAspectIds(graph));\n issues.push(...checkAspectIdUniqueness(graph));\n issues.push(...checkImpliedAspectsExist(graph));\n issues.push(...checkImpliesNoCycles(graph));\n issues.push(...checkRequiredAspectsCoverage(graph));\n issues.push(...(await checkAnchorPresence(graph)));\n issues.push(...checkRequiredArtifacts(graph));\n issues.push(...checkInvalidArtifactConditions(graph));\n issues.push(...(await checkContextBudget(graph)));\n issues.push(...checkHighFanOut(graph));\n }\n\n issues.push(...checkSchemas(graph));\n issues.push(...checkRelationTargets(graph));\n issues.push(...checkNoCycles(graph));\n issues.push(...checkMappingOverlap(graph));\n issues.push(...(await checkMappingPathsExist(graph)));\n issues.push(...checkBrokenFlowRefs(graph));\n issues.push(...checkFlowAspectIds(graph));\n issues.push(...(await checkDirectoriesHaveNodeYaml(graph)));\n issues.push(...(await checkShallowArtifacts(graph)));\n issues.push(...checkUnpairedEvents(graph));\n\n let filtered = issues;\n let nodesScanned = graph.nodes.size;\n if (scope !== 'all' && scope.trim()) {\n if (!graph.nodes.has(scope)) {\n // Check if the node exists but has a parse error\n const parseError = (graph.nodeParseErrors ?? []).find(\n (e) => e.nodePath === scope || scope.startsWith(e.nodePath + '/'),\n );\n if (parseError) {\n return {\n issues: [{\n severity: 'error',\n code: 'E001',\n rule: 'invalid-node-yaml',\n message: parseError.message,\n nodePath: parseError.nodePath,\n }],\n nodesScanned: 0,\n };\n }\n return {\n issues: [{ severity: 'error', rule: 'invalid-scope', message: `Node not found: ${scope}` }],\n nodesScanned: 0,\n };\n }\n const scopePrefix = scope + '/';\n filtered = issues.filter((i) => !i.nodePath || i.nodePath === scope || i.nodePath.startsWith(scopePrefix));\n nodesScanned = [...graph.nodes.keys()].filter((p) => p === scope || p.startsWith(scopePrefix)).length;\n }\n\n return { issues: filtered, nodesScanned };\n}\n\n// --- Rule 0: Node types from config ---\n\nfunction checkNodeTypes(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const allowedTypes = new Set(Object.keys(graph.config.node_types ?? {}));\n for (const [nodePath, node] of graph.nodes) {\n if (!allowedTypes.has(node.meta.type)) {\n issues.push({\n severity: 'error',\n code: 'E002',\n rule: 'unknown-node-type',\n message: `Node type '${node.meta.type}' not in config.node_types (${[...allowedTypes].join(', ')})`,\n nodePath,\n });\n }\n }\n return issues;\n}\n\n// --- Rule 1: Relation targets exist ---\n\nfunction findSimilar(target: string, candidates: string[]): string | null {\n if (candidates.length === 0) return null;\n\n let best: string | null = null;\n let bestScore = -1;\n\n for (const c of candidates) {\n if (c === target) return c;\n // Simple similarity: shared path segments\n const targetParts = target.split('/');\n const candParts = c.split('/');\n let score = 0;\n for (let i = 0; i < Math.min(targetParts.length, candParts.length); i++) {\n if (targetParts[i] === candParts[i]) score++;\n else break;\n }\n if (score > bestScore && score > 0) {\n bestScore = score;\n best = c;\n }\n }\n return best;\n}\n\nfunction checkRelationTargets(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const nodePaths = [...graph.nodes.keys()];\n for (const [nodePath, node] of graph.nodes) {\n for (const rel of node.meta.relations ?? []) {\n if (!graph.nodes.has(rel.target)) {\n const suggestion = findSimilar(rel.target, nodePaths);\n const parts = rel.target.split('/');\n const parentPrefix = parts.length > 1 ? parts.slice(0, -1).join('/') + '/' : '';\n const existingInParent = nodePaths\n .filter((p) => p.startsWith(parentPrefix) && p !== rel.target)\n .map((p) => {\n const rest = p.slice(parentPrefix.length);\n return rest.split('/')[0];\n })\n .filter((v, i, a) => a.indexOf(v) === i)\n .sort();\n const existingLine =\n existingInParent.length > 0\n ? `\\n Existing nodes in ${parentPrefix || 'model/'}: ${existingInParent.join(', ')}`\n : '';\n const hint = suggestion ? `\\n Did you mean '${suggestion}'?` : '';\n issues.push({\n severity: 'error',\n code: 'E004',\n rule: 'broken-relation',\n message: `Relation target '${rel.target}' does not exist${existingLine}${hint}`,\n nodePath,\n });\n }\n }\n }\n return issues;\n}\n\n// --- Rule 2: Node aspects must reference a defined aspect ---\n\nfunction checkAspectsDefined(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const validAspectIds = new Set(graph.aspects.map((a) => a.id));\n for (const [nodePath, node] of graph.nodes) {\n for (const aspectId of getAspectIds(node.meta.aspects)) {\n if (!validAspectIds.has(aspectId)) {\n issues.push({\n severity: 'error',\n code: 'E003',\n rule: 'unknown-aspect',\n message: `Aspect '${aspectId}' has no corresponding directory in aspects/`,\n nodePath,\n });\n }\n }\n }\n return issues;\n}\n\n// --- Rule 3: Aspect ids (derived from directory path) — always valid when aspect exists ---\n\nfunction checkAspectIds(_graph: Graph): ValidationIssue[] {\n // validAspectIds = graph.aspects.map(a => a.id), so every aspect's id is valid by definition\n return [];\n}\n\nfunction checkAspectIdUniqueness(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const byId = new Map<string, string[]>();\n for (const aspect of graph.aspects) {\n const names = byId.get(aspect.id) ?? [];\n names.push(aspect.name);\n byId.set(aspect.id, names);\n }\n for (const [id, names] of byId) {\n if (names.length <= 1) continue;\n issues.push({\n severity: 'error',\n code: 'E014',\n rule: 'duplicate-aspect-binding',\n message: `Aspect '${id}' is bound to multiple aspects (${names.join(', ')})`,\n });\n }\n return issues;\n}\n\n// --- Rule: Implied aspects exist ---\n\nfunction checkImpliedAspectsExist(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const idToAspect = new Map<string, { name: string }>();\n for (const a of graph.aspects) {\n idToAspect.set(a.id, { name: a.name });\n }\n for (const aspect of graph.aspects) {\n for (const impliedId of aspect.implies ?? []) {\n if (!idToAspect.has(impliedId)) {\n issues.push({\n severity: 'error',\n code: 'E016',\n rule: 'implied-aspect-missing',\n message: `Aspect '${aspect.name}' implies '${impliedId}' but no aspect with that id exists in aspects/`,\n });\n }\n }\n }\n return issues;\n}\n\n// --- Rule: No cycles in aspect implies graph ---\n\nfunction checkImpliesNoCycles(graph: Graph): ValidationIssue[] {\n const idToAspect = new Map<string, { implies?: string[] }>();\n for (const a of graph.aspects) {\n idToAspect.set(a.id, { implies: a.implies });\n }\n const WHITE = 0;\n const GRAY = 1;\n const BLACK = 2;\n const color = new Map<string, number>();\n for (const id of idToAspect.keys()) color.set(id, WHITE);\n\n const issues: ValidationIssue[] = [];\n\n function dfs(id: string, pathArr: string[]): boolean {\n color.set(id, GRAY);\n pathArr.push(id);\n const aspect = idToAspect.get(id);\n for (const implied of aspect?.implies ?? []) {\n if (color.get(implied) === GRAY) {\n const cycle = pathArr.slice(pathArr.indexOf(implied)).concat(implied);\n issues.push({\n severity: 'error',\n code: 'E017',\n rule: 'aspect-implies-cycle',\n message: `Aspect implies cycle: ${cycle.join(' → ')}`,\n });\n pathArr.pop();\n color.set(id, BLACK);\n return true;\n }\n if (color.get(implied) === WHITE && dfs(implied, pathArr)) {\n pathArr.pop();\n color.set(id, BLACK);\n return true;\n }\n }\n pathArr.pop();\n color.set(id, BLACK);\n return false;\n }\n\n for (const id of idToAspect.keys()) {\n if (color.get(id) === WHITE) {\n dfs(id, []);\n }\n }\n return issues;\n}\n\n// --- Rule: Required aspects coverage per node type ---\n\nfunction checkRequiredAspectsCoverage(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const typeConfig = new Map(\n Object.entries(graph.config.node_types ?? {}).map(([name, cfg]) => [name, cfg.required_aspects ?? []]),\n );\n for (const [nodePath, node] of graph.nodes) {\n if (node.meta.blackbox) continue;\n const requiredAspects = typeConfig.get(node.meta.type);\n if (!requiredAspects || requiredAspects.length === 0) continue;\n\n const nodeAspectIds = getAspectIds(node.meta.aspects);\n let effectiveAspects;\n try {\n effectiveAspects = resolveAspects(nodeAspectIds, graph.aspects);\n } catch {\n continue;\n }\n const effectiveAspectIds = new Set(effectiveAspects.map((a) => a.id));\n\n for (const required of requiredAspects) {\n if (!effectiveAspectIds.has(required)) {\n issues.push({\n severity: 'warning',\n code: 'W011',\n rule: 'missing-required-aspect-coverage',\n message: `Node '${nodePath}' (type: ${node.meta.type}) missing required aspect coverage for '${required}'`,\n nodePath,\n });\n }\n }\n }\n return issues;\n}\n\n// --- Rule 4: No circular dependencies (cycles involving blackbox are tolerated) ---\n\nfunction checkNoCycles(graph: Graph): ValidationIssue[] {\n const WHITE = 0;\n const GRAY = 1;\n const BLACK = 2;\n const color = new Map<string, number>();\n for (const p of graph.nodes.keys()) color.set(p, WHITE);\n\n const issues: ValidationIssue[] = [];\n\n function dfs(nodePath: string, pathSegments: string[]): boolean {\n color.set(nodePath, GRAY);\n const node = graph.nodes.get(nodePath)!;\n const structuralTypes = new Set(['uses', 'calls', 'extends', 'implements']);\n for (const rel of node.meta.relations ?? []) {\n const targetNode = graph.nodes.get(rel.target);\n if (!targetNode) continue;\n if (!structuralTypes.has(rel.type)) continue;\n if (color.get(rel.target) === GRAY) {\n const cyclePath = [...pathSegments, nodePath, rel.target];\n const cycleNodes = pathSegments.slice(pathSegments.indexOf(rel.target)).concat(nodePath);\n const hasBlackboxInCycle = cycleNodes.some(\n (p) => graph.nodes.get(p)?.meta.blackbox === true,\n );\n if (!hasBlackboxInCycle) {\n issues.push({\n severity: 'error',\n code: 'E010',\n rule: 'structural-cycle',\n message: `Circular dependency: ${cyclePath.join(' -> ')}`,\n });\n }\n return true;\n }\n if (color.get(rel.target) === WHITE) {\n if (dfs(rel.target, [...pathSegments, nodePath])) return true;\n }\n }\n color.set(nodePath, BLACK);\n return false;\n }\n\n for (const nodePath of graph.nodes.keys()) {\n if (color.get(nodePath) === WHITE) {\n dfs(nodePath, []);\n }\n }\n\n return issues;\n}\n\n// --- Rule 5: Mapping ownership overlap ---\n\nfunction normalizePathForCompare(mappingPath: string): string {\n return mappingPath.replace(/\\\\/g, '/').replace(/\\/+$/, '');\n}\n\nfunction arePathsOverlapping(pathA: string, pathB: string): boolean {\n if (pathA === pathB) return true;\n return pathA.startsWith(pathB + '/') || pathB.startsWith(pathA + '/');\n}\n\nfunction isAncestorNode(possibleAncestor: string, possibleDescendant: string): boolean {\n return possibleDescendant.startsWith(possibleAncestor + '/');\n}\n\nfunction checkMappingOverlap(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const ownership: Array<{ nodePath: string; mappingPath: string }> = [];\n\n for (const [nodePath, node] of graph.nodes) {\n const mappingPaths = normalizeMappingPaths(node.meta.mapping)\n .map(normalizePathForCompare)\n .filter((mappingPath) => mappingPath.length > 0);\n for (const mappingPath of mappingPaths) {\n ownership.push({ nodePath, mappingPath });\n }\n }\n\n for (let index = 0; index < ownership.length; index++) {\n const current = ownership[index];\n for (let nestedIndex = index + 1; nestedIndex < ownership.length; nestedIndex++) {\n const candidate = ownership[nestedIndex];\n if (current.nodePath === candidate.nodePath) continue;\n if (!arePathsOverlapping(current.mappingPath, candidate.mappingPath)) continue;\n\n // Allow containment overlaps between ancestor-descendant nodes (\"child wins\" model).\n // Exact duplicates (same path) are always errors regardless of hierarchy.\n const isContainment = current.mappingPath !== candidate.mappingPath;\n const isHierarchical =\n isAncestorNode(current.nodePath, candidate.nodePath) ||\n isAncestorNode(candidate.nodePath, current.nodePath);\n\n if (isContainment && isHierarchical) continue;\n\n issues.push({\n severity: 'error',\n code: 'E009',\n rule: 'overlapping-mapping',\n message:\n `Mapping paths '${current.mappingPath}' (${current.nodePath}) and ` +\n `'${candidate.mappingPath}' (${candidate.nodePath}) overlap. ` +\n `Keep one owner mapping and model other concerns via relations.`,\n nodePath: candidate.nodePath,\n });\n }\n }\n\n return issues;\n}\n\n// --- Rule: Mapping paths should exist on disk (W012) ---\n\nasync function checkMappingPathsExist(graph: Graph): Promise<ValidationIssue[]> {\n const issues: ValidationIssue[] = [];\n const projectRoot = path.dirname(graph.rootPath);\n const { access } = await import('node:fs/promises');\n\n for (const [nodePath, node] of graph.nodes) {\n const mappingPaths = normalizeMappingPaths(node.meta.mapping);\n for (const mp of mappingPaths) {\n const absPath = path.join(projectRoot, mp);\n try {\n await access(absPath);\n } catch {\n issues.push({\n severity: 'warning',\n code: 'W012',\n rule: 'mapping-path-missing',\n message: `Mapping path '${mp}' does not exist on disk`,\n nodePath,\n });\n }\n }\n }\n return issues;\n}\n\n// --- Rule 6: Required artifacts per config.artifacts (W001) ---\n\nfunction getIncomingRelationSources(graph: Graph, nodePath: string): string[] {\n const sources: string[] = [];\n for (const [srcPath, node] of graph.nodes) {\n for (const rel of node.meta.relations ?? []) {\n if (rel.target === nodePath) sources.push(srcPath);\n }\n }\n return sources;\n}\n\nfunction artifactRequiredReason(\n graph: Graph,\n nodePath: string,\n node: {\n meta: { relations?: Array<{ target: string }>; aspects?: NodeAspectEntry[]; blackbox?: boolean };\n artifacts: Array<{ filename: string }>;\n },\n required: ArtifactConfig['required'],\n): string | null {\n if (required === 'never') return null;\n if (required === 'always') {\n return node.meta.blackbox ? null : 'required: always';\n }\n const when = (required as { when: string }).when;\n if (when === 'has_incoming_relations') {\n const sources = getIncomingRelationSources(graph, nodePath);\n return sources.length > 0\n ? `${sources.length} incoming relation(s): ${sources.join(', ')}`\n : null;\n }\n if (when === 'has_outgoing_relations') {\n const count = node.meta.relations?.length ?? 0;\n return count > 0 ? `${count} outgoing relation(s)` : null;\n }\n if (when.startsWith('has_aspect:') || when.startsWith('has_tag:')) {\n const prefix = when.startsWith('has_aspect:') ? 'has_aspect:' : 'has_tag:';\n const aspectId = when.slice(prefix.length);\n return (node.meta.aspects ?? []).some(a => a.aspect === aspectId) ? `node has aspect '${aspectId}'` : null;\n }\n return null;\n}\n\nfunction getIncomingRelations(graph: Graph, nodePath: string): string[] {\n const incoming: string[] = [];\n for (const [fromPath, node] of graph.nodes) {\n for (const rel of node.meta.relations ?? []) {\n if (rel.target === nodePath) {\n incoming.push(fromPath);\n break;\n }\n }\n }\n return incoming.sort();\n}\n\nfunction checkRequiredArtifacts(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const artifacts = graph.config.artifacts ?? {};\n\n for (const [nodePath, node] of graph.nodes) {\n for (const [filename, config] of Object.entries(artifacts)) {\n const hasArtifact = node.artifacts.some((a) => a.filename === filename);\n const reason = artifactRequiredReason(graph, nodePath, node, config.required);\n\n if (reason && !hasArtifact) {\n const action = config.description ?? '';\n const incoming = getIncomingRelations(graph, nodePath);\n const incomingStr =\n incoming.length > 0\n ? ` Node has ${incoming.length} incoming relation(s): ${incoming.slice(0, 5).join(', ')}${incoming.length > 5 ? '...' : ''}.`\n : '';\n const msg = action\n ? `Missing required artifact '${filename}' (${reason}).${incomingStr} ${action}`\n : `Missing required artifact '${filename}' (${reason}).${incomingStr}`;\n issues.push({\n severity: 'warning',\n code: 'W001',\n rule: 'missing-artifact',\n message: msg.trim(),\n nodePath,\n });\n }\n }\n }\n\n return issues;\n}\n\n// --- E006: Broken flow refs (flow.nodes) ---\n\nfunction checkBrokenFlowRefs(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const nodePaths = new Set(graph.nodes.keys());\n for (const flow of graph.flows) {\n for (const n of flow.nodes) {\n if (!nodePaths.has(n)) {\n issues.push({\n severity: 'error',\n code: 'E006',\n rule: 'broken-flow-ref',\n message: `Flow '${flow.name}' references non-existent node '${n}'`,\n });\n }\n }\n }\n return issues;\n}\n\n// --- E007: Flow aspect ids must have corresponding aspect ---\n\nfunction checkFlowAspectIds(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const validAspectIds = new Set(graph.aspects.map((a) => a.id));\n\n for (const flow of graph.flows) {\n for (const aspectId of flow.aspects ?? []) {\n if (!validAspectIds.has(aspectId)) {\n issues.push({\n severity: 'error',\n code: 'E007',\n rule: 'broken-aspect-ref',\n message: `Flow '${flow.name}' references aspect '${aspectId}' but no aspect with that id exists in aspects/`,\n });\n }\n }\n }\n return issues;\n}\n\n// --- E013: Invalid artifact condition (has_aspect:X where X has no aspect) ---\n\nfunction checkInvalidArtifactConditions(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const validAspectIds = new Set(graph.aspects.map((a) => a.id));\n const artifacts = graph.config.artifacts ?? {};\n for (const [artifactName, config] of Object.entries(artifacts)) {\n const required = config.required;\n if (typeof required === 'object' && required && 'when' in required) {\n const when = (required as { when: string }).when;\n if (when.startsWith('has_aspect:') || when.startsWith('has_tag:')) {\n const prefix = when.startsWith('has_aspect:') ? 'has_aspect:' : 'has_tag:';\n const aspectId = when.slice(prefix.length);\n if (!validAspectIds.has(aspectId)) {\n issues.push({\n severity: 'error',\n code: 'E013',\n rule: 'invalid-artifact-condition',\n message: `Artifact '${artifactName}' condition has_aspect:${aspectId} has no corresponding aspect in aspects/`,\n });\n }\n }\n }\n }\n return issues;\n}\n\n// --- W002: Shallow artifacts (below min_artifact_length) ---\n\nasync function checkShallowArtifacts(graph: Graph): Promise<ValidationIssue[]> {\n const issues: ValidationIssue[] = [];\n const minLen = graph.config.quality?.min_artifact_length ?? 50;\n for (const [nodePath, node] of graph.nodes) {\n for (const art of node.artifacts) {\n if (art.content.trim().length < minLen) {\n issues.push({\n severity: 'warning',\n code: 'W002',\n rule: 'shallow-artifact',\n message: `Artifact '${art.filename}' is below minimum length (${art.content.trim().length} < ${minLen})`,\n nodePath,\n });\n }\n }\n }\n return issues;\n}\n\n// --- W007: High fan-out (exceeds max_direct_relations) ---\n\nfunction checkHighFanOut(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const maxRel = graph.config.quality?.max_direct_relations ?? 10;\n for (const [nodePath, node] of graph.nodes) {\n const count = node.meta.relations?.length ?? 0;\n if (count > maxRel) {\n issues.push({\n severity: 'warning',\n code: 'W007',\n rule: 'high-fan-out',\n message: `Node has ${count} direct relations (max: ${maxRel})`,\n nodePath,\n });\n }\n }\n return issues;\n}\n\n// --- W009: Unpaired event relations (emits without listens or vice versa) ---\n\nfunction checkUnpairedEvents(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const emitsTo = new Map<string, Set<string>>();\n const listensFrom = new Map<string, Set<string>>();\n for (const [nodePath, node] of graph.nodes) {\n for (const rel of node.meta.relations ?? []) {\n if (rel.type === 'emits') {\n const set = emitsTo.get(nodePath) ?? new Set();\n set.add(rel.target);\n emitsTo.set(nodePath, set);\n }\n if (rel.type === 'listens') {\n const set = listensFrom.get(nodePath) ?? new Set();\n set.add(rel.target);\n listensFrom.set(nodePath, set);\n }\n }\n }\n for (const [emitter, targets] of emitsTo) {\n for (const target of targets) {\n const listenerSet = listensFrom.get(target);\n if (!listenerSet?.has(emitter)) {\n issues.push({\n severity: 'warning',\n code: 'W009',\n rule: 'unpaired-event',\n message: `Node '${emitter}' emits to '${target}' but '${target}' has no listens from '${emitter}'`,\n nodePath: emitter,\n });\n }\n }\n }\n for (const [listener, sources] of listensFrom) {\n for (const source of sources) {\n const emitterSet = emitsTo.get(source);\n if (!emitterSet?.has(listener)) {\n issues.push({\n severity: 'warning',\n code: 'W009',\n rule: 'unpaired-event',\n message: `Node '${listener}' listens from '${source}' but '${source}' has no emits to '${listener}'`,\n nodePath: listener,\n });\n }\n }\n }\n return issues;\n}\n\n// --- Schema validation (required graph-layer schemas present in schemas/) ---\n\nconst REQUIRED_SCHEMAS = ['node', 'aspect', 'flow'] as const;\n\nfunction checkSchemas(graph: Graph): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const present = new Set(graph.schemas.map((s) => s.schemaType));\n\n for (const required of REQUIRED_SCHEMAS) {\n if (!present.has(required)) {\n issues.push({\n severity: 'warning',\n code: 'W010',\n rule: 'missing-schema',\n message: `Schema 'yg-${required}.yaml' missing from .yggdrasil/schemas/`,\n });\n }\n }\n\n return issues;\n}\n\n// --- Directories have yg-node.yaml ---\n\nasync function checkDirectoriesHaveNodeYaml(graph: Graph): Promise<ValidationIssue[]> {\n const issues: ValidationIssue[] = [];\n const modelDir = path.join(graph.rootPath, 'model');\n\n async function scanDir(dirPath: string, segments: string[]): Promise<void> {\n const entries = await readdir(dirPath, { withFileTypes: true });\n const hasNodeYaml = entries.some((e) => e.isFile() && e.name === 'yg-node.yaml');\n const dirName = path.basename(dirPath);\n\n if (RESERVED_DIRS.has(dirName)) return;\n\n const hasFiles = entries.some((e) => e.isFile());\n const hasSubdirs = entries.some((e) => e.isDirectory() && !RESERVED_DIRS.has(e.name) && !e.name.startsWith('.'));\n const graphPath = segments.join('/');\n\n if (!hasNodeYaml && graphPath !== '') {\n if (hasFiles) {\n issues.push({\n severity: 'error',\n code: 'E015',\n rule: 'missing-node-yaml',\n message: `Directory '${graphPath}' has files but no yg-node.yaml`,\n nodePath: graphPath,\n });\n } else if (hasSubdirs) {\n issues.push({\n severity: 'warning',\n code: 'W013',\n rule: 'directory-without-node',\n message: `Directory '${graphPath}' has subdirectories but no yg-node.yaml — consider creating a node`,\n nodePath: graphPath,\n });\n }\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n if (RESERVED_DIRS.has(entry.name)) continue;\n if (entry.name.startsWith('.')) continue;\n await scanDir(path.join(dirPath, entry.name), [...segments, entry.name]);\n }\n }\n\n try {\n const rootEntries = await readdir(modelDir, { withFileTypes: true });\n for (const entry of rootEntries) {\n if (!entry.isDirectory()) continue;\n if (entry.name.startsWith('.')) continue;\n await scanDir(path.join(modelDir, entry.name), [entry.name]);\n }\n } catch {\n // model/ may not exist\n }\n\n return issues;\n}\n\n// --- Anchor validation (E019, W014) ---\n\nasync function expandMappingToFiles(projectRoot: string, mappingPaths: string[]): Promise<string[]> {\n const files: string[] = [];\n\n async function collectFiles(absPath: string): Promise<void> {\n try {\n const s = await stat(absPath);\n if (s.isFile()) {\n files.push(absPath);\n } else if (s.isDirectory()) {\n const entries = await readdir(absPath, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.name.startsWith('.') || entry.name === 'node_modules') continue;\n const entryPath = path.join(absPath, entry.name);\n if (entry.isFile()) {\n files.push(entryPath);\n } else if (entry.isDirectory()) {\n await collectFiles(entryPath);\n }\n }\n }\n } catch {\n // Skip inaccessible paths\n }\n }\n\n for (const mp of mappingPaths) {\n await collectFiles(path.join(projectRoot, mp));\n }\n return files;\n}\n\nasync function checkAnchorPresence(graph: Graph): Promise<ValidationIssue[]> {\n const issues: ValidationIssue[] = [];\n const projectRoot = path.dirname(graph.rootPath);\n\n for (const [nodePath, node] of graph.nodes) {\n const aspectsWithAnchors = (node.meta.aspects ?? []).filter(a => a.anchors && a.anchors.length > 0);\n if (aspectsWithAnchors.length === 0) continue;\n\n // W014: check anchor strings exist in source files\n const mappingPaths = normalizeMappingPaths(node.meta.mapping);\n if (mappingPaths.length === 0) continue;\n\n const sourceFiles = await expandMappingToFiles(projectRoot, mappingPaths);\n if (sourceFiles.length === 0) continue;\n\n const fileContents: string[] = [];\n for (const filePath of sourceFiles) {\n try {\n const content = await readFile(filePath, 'utf-8');\n fileContents.push(content);\n } catch {\n // Skip unreadable files\n }\n }\n\n for (const entry of aspectsWithAnchors) {\n for (const anchor of entry.anchors!) {\n const found = fileContents.some((content) => content.includes(anchor));\n if (!found) {\n issues.push({\n severity: 'warning',\n code: 'W014',\n rule: 'anchor-not-found',\n message: `Anchor '${anchor}' for aspect '${entry.aspect}' not found in mapped source files`,\n nodePath,\n });\n }\n }\n }\n }\n\n return issues;\n}\n\n// --- Context budget (W005 warning, W006 error) ---\n\nasync function checkContextBudget(graph: Graph): Promise<ValidationIssue[]> {\n const issues: ValidationIssue[] = [];\n const warningThreshold = graph.config.quality?.context_budget.warning ?? 10000;\n const errorThreshold = graph.config.quality?.context_budget.error ?? 20000;\n\n for (const [nodePath, node] of graph.nodes) {\n if (node.meta.blackbox) continue;\n try {\n const pkg = await buildContext(graph, nodePath);\n if (pkg.tokenCount >= errorThreshold) {\n issues.push({\n severity: 'warning',\n code: 'W006',\n rule: 'budget-error',\n message: `Context is ${pkg.tokenCount.toLocaleString()} tokens (error threshold: ${errorThreshold.toLocaleString()}) — blocks materialization, node must be split`,\n nodePath,\n });\n } else if (pkg.tokenCount >= warningThreshold) {\n issues.push({\n severity: 'warning',\n code: 'W005',\n rule: 'budget-warning',\n message: `Context is ${pkg.tokenCount.toLocaleString()} tokens (warning threshold: ${warningThreshold.toLocaleString()}). Consider splitting the node or reducing dependencies.`,\n nodePath,\n });\n }\n } catch {\n // If context building fails, other rules will catch it\n }\n }\n return issues;\n}\n","import type { ContextPackage, ContextLayer } from '../model/types.js';\n\nfunction escapeAttr(val: string): string {\n return val.replace(/\"/g, '&quot;');\n}\n\nfunction formatLayer(layer: ContextLayer): string {\n switch (layer.type) {\n case 'global':\n return `<global>\\n${layer.content}\\n</global>`;\n case 'hierarchy': {\n const pathMatch = layer.label.match(/\\((.+)\\/\\)/);\n const pathAttr = pathMatch ? ` path=\"${escapeAttr(pathMatch[1])}\"` : '';\n const aspectsAttr = layer.attrs?.aspects ? ` aspects=\"${escapeAttr(layer.attrs.aspects)}\"` : '';\n return `<hierarchy${pathAttr}${aspectsAttr}>\\n${layer.content}\\n</hierarchy>`;\n }\n case 'own': {\n if (layer.label === 'Materialization Target') {\n return `<materialization-target paths=\"${escapeAttr(layer.content)}\" />`;\n }\n const ownAspectsAttr = layer.attrs?.aspects ? ` aspects=\"${escapeAttr(layer.attrs.aspects)}\"` : '';\n return `<own-artifacts${ownAspectsAttr}>\\n${layer.content}\\n</own-artifacts>`;\n }\n case 'aspects': {\n const nameMatch = layer.label.match(/^(.+?) \\(aspect: (.+)\\)$/);\n const name = nameMatch ? escapeAttr(nameMatch[1]) : '';\n const id = nameMatch ? escapeAttr(nameMatch[2]) : '';\n return `<aspect name=\"${name}\" id=\"${id}\">\\n${layer.content}\\n</aspect>`;\n }\n case 'relational': {\n const attrs = layer.attrs ?? {};\n const attrStr = Object.entries(attrs)\n .map(([k, v]) => ` ${k}=\"${escapeAttr(v)}\"`)\n .join('');\n const tagName = attrs.type && ['emits', 'listens'].includes(attrs.type) ? 'event' : 'dependency';\n return `<${tagName}${attrStr}>\\n${layer.content}\\n</${tagName}>`;\n }\n case 'flows': {\n const flowName = layer.label.replace(/^Flow: /, '').trim();\n const flowAspectsAttr = layer.attrs?.aspects ? ` aspects=\"${escapeAttr(layer.attrs.aspects)}\"` : '';\n return `<flow name=\"${escapeAttr(flowName)}\"${flowAspectsAttr}>\\n${layer.content}\\n</flow>`;\n }\n default:\n return layer.content;\n }\n}\n\nexport function formatContextText(pkg: ContextPackage): string {\n const attrs = [\n `node-path=\"${escapeAttr(pkg.nodePath)}\"`,\n `node-name=\"${escapeAttr(pkg.nodeName)}\"`,\n `token-count=\"${pkg.tokenCount}\"`,\n ].join(' ');\n\n let out = `<context-package ${attrs}>\\n\\n`;\n\n for (const section of pkg.sections) {\n for (const layer of section.layers) {\n out += formatLayer(layer) + '\\n\\n';\n }\n }\n\n out += '</context-package>';\n return out;\n}\n","import { Command } from 'commander';\nimport { loadGraph } from '../core/graph-loader.js';\nimport { buildContext, collectAncestors } from '../core/context-builder.js';\nimport { validate } from '../core/validator.js';\nimport { formatContextText } from '../formatters/context-text.js';\nimport type { Graph } from '../model/types.js';\n\n/**\n * Collect the set of node paths that participate in context assembly for a given node:\n * the node itself, its ancestors, and its direct relation targets.\n */\nfunction collectRelevantNodePaths(graph: Graph, nodePath: string): Set<string> {\n const relevant = new Set<string>();\n const node = graph.nodes.get(nodePath);\n if (!node) return relevant;\n\n relevant.add(nodePath);\n\n // Ancestors (hierarchy)\n for (const ancestor of collectAncestors(node)) {\n relevant.add(ancestor.path);\n }\n\n // Direct relation targets\n for (const rel of node.meta.relations ?? []) {\n relevant.add(rel.target);\n }\n\n return relevant;\n}\n\nexport function registerBuildCommand(program: Command): void {\n program\n .command('build-context')\n .description('Assemble a context package for one node')\n .requiredOption('--node <node-path>', 'Node path relative to .yggdrasil/model/')\n .action(async (options: { node: string }) => {\n try {\n const graph = await loadGraph(process.cwd());\n const nodePath = options.node.trim().replace(/^\\.\\//, '').replace(/\\/$/, '');\n\n // Collect nodes relevant to this context assembly\n const relevantNodes = collectRelevantNodePaths(graph, nodePath);\n\n // Validate but only block on errors relevant to this node's context\n const validationResult = await validate(graph, 'all');\n const relevantErrors = validationResult.issues.filter(\n (issue) =>\n issue.severity === 'error' &&\n // Global errors (no nodePath) always block — e.g., E012 invalid config\n (!issue.nodePath || relevantNodes.has(issue.nodePath)),\n );\n if (relevantErrors.length > 0) {\n const totalErrors = validationResult.issues.filter((i) => i.severity === 'error').length;\n const skippedErrors = totalErrors - relevantErrors.length;\n let msg = `Error: build-context blocked by ${relevantErrors.length} error(s) affecting this node's context.\\n`;\n if (skippedErrors > 0) {\n msg += `(${skippedErrors} unrelated error(s) in other nodes ignored.)\\n`;\n }\n for (const err of relevantErrors) {\n const loc = err.nodePath ? `${err.nodePath}: ` : '';\n msg += ` ${err.code ?? ''} ${loc}${err.message}\\n`;\n }\n process.stderr.write(msg);\n process.exit(1);\n }\n\n const pkg = await buildContext(graph, nodePath);\n const warningThreshold = graph.config.quality?.context_budget.warning ?? 10000;\n const errorThreshold = graph.config.quality?.context_budget.error ?? 20000;\n const budgetStatus =\n pkg.tokenCount >= errorThreshold\n ? 'error'\n : pkg.tokenCount >= warningThreshold\n ? 'warning'\n : 'ok';\n\n let output = formatContextText(pkg);\n output += `Budget status: ${budgetStatus}\\n`;\n process.stdout.write(output);\n\n if (budgetStatus === 'error') {\n process.stderr.write(\n `Warning: context package exceeds error budget (${pkg.tokenCount} >= ${errorThreshold}). Consider splitting the node.\\n`,\n );\n }\n } catch (error) {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n process.exit(1);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { loadGraph } from '../core/graph-loader.js';\nimport { validate } from '../core/validator.js';\n\nexport function registerValidateCommand(program: Command): void {\n program\n .command('validate')\n .description('Validate graph structural integrity and completeness signals')\n .option('--scope <scope>', 'Scope: all or node-path (default: all)', 'all')\n .action(async (options: { scope: string }) => {\n try {\n const graph = await loadGraph(process.cwd(), { tolerateInvalidConfig: true });\n const rawScope = (options.scope ?? 'all').trim() || 'all';\n const scope = rawScope === 'all' ? 'all' : rawScope.replace(/^\\.\\//, '').replace(/\\/+$/, '');\n const result = await validate(graph, scope);\n process.stdout.write(`${result.nodesScanned} nodes scanned\\n\\n`);\n const errors = result.issues.filter((i) => i.severity === 'error');\n const warnings = result.issues.filter((i) => i.severity === 'warning');\n for (const issue of errors) {\n const code = issue.code ?? '';\n const loc = issue.nodePath ?? '';\n const prefix = loc ? `${code} ${loc} -> ` : `${code} `;\n process.stdout.write(chalk.red(`✗ ${prefix}${issue.message}\\n`));\n }\n for (const issue of warnings) {\n const code = issue.code ?? '';\n const loc = issue.nodePath ?? '';\n const prefix = loc ? `${code} ${loc} -> ` : `${code} `;\n process.stdout.write(chalk.yellow(`⚠ ${prefix}${issue.message}\\n`));\n }\n if (errors.length === 0 && warnings.length === 0) {\n process.stdout.write(chalk.green('✓ No issues found.\\n'));\n } else {\n process.stdout.write(`\\n${errors.length} errors, ${warnings.length} warnings.\\n`);\n }\n\n const hasErrors = result.issues.some((i) => i.severity === 'error');\n process.exit(hasErrors ? 1 : 0);\n } catch (error) {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n process.exit(1);\n }\n });\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { loadGraph } from '../core/graph-loader.js';\nimport { detectDrift } from '../core/drift-detector.js';\nimport type { DriftEntry, DriftReport } from '../model/types.js';\n\nexport function registerDriftCommand(program: Command): void {\n program\n .command('drift')\n .description('Detect divergences between graph and mapped files')\n .option('--scope <scope>', 'Scope: \"all\" or node path', 'all')\n .option('--drifted-only', 'Show only nodes with drift (hide ok entries)')\n .option('--limit <n>', 'Maximum number of entries to show per section', parseInt)\n .action(async (opts: { scope: string; driftedOnly?: boolean; limit?: number }) => {\n try {\n const graph = await loadGraph(process.cwd());\n const rawScope = (opts.scope ?? 'all').trim() || 'all';\n const scope = rawScope === 'all' ? 'all' : rawScope.replace(/^\\.\\//, '').replace(/\\/+$/, '');\n\n if (scope !== 'all') {\n const node = graph.nodes.get(scope);\n if (!node) {\n process.stderr.write(`Error: Node not found: ${scope}\\n`);\n process.exit(1);\n }\n // Check if scope or any descendant has a mapping\n const hasAnyMapping = node.meta.mapping ||\n [...graph.nodes.entries()].some(([p, n]) => p.startsWith(scope + '/') && n.meta.mapping);\n if (!hasAnyMapping) {\n process.stderr.write(`Error: Node has no mapping: ${scope}\\n`);\n process.exit(1);\n }\n }\n\n const scopeNode = scope === 'all' ? undefined : scope;\n const report = await detectDrift(graph, scopeNode);\n printReport(report, opts.driftedOnly ?? false, opts.limit);\n\n const hasIssues =\n report.sourceDriftCount > 0 ||\n report.graphDriftCount > 0 ||\n report.fullDriftCount > 0 ||\n report.missingCount > 0 ||\n report.unmaterializedCount > 0;\n process.exit(hasIssues ? 1 : 0);\n } catch (error) {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n process.exit(1);\n }\n });\n}\n\nfunction printReport(report: DriftReport, driftedOnly: boolean, limit?: number): void {\n const sourceEntries = classifyForSection(report.entries, 'source', driftedOnly);\n const graphEntries = classifyForSection(report.entries, 'graph', driftedOnly);\n\n const sourceShown = limit !== undefined ? sourceEntries.slice(0, limit) : sourceEntries;\n const graphShown = limit !== undefined ? graphEntries.slice(0, limit) : graphEntries;\n\n process.stdout.write('Source drift:\\n');\n printSectionEntries(sourceShown, 'source');\n if (limit !== undefined && sourceEntries.length > limit) {\n process.stdout.write(chalk.dim(` ... ${sourceEntries.length - limit} more (${sourceEntries.length} total)\\n`));\n }\n\n process.stdout.write('\\nGraph drift:\\n');\n printSectionEntries(graphShown, 'graph');\n if (limit !== undefined && graphEntries.length > limit) {\n process.stdout.write(chalk.dim(` ... ${graphEntries.length - limit} more (${graphEntries.length} total)\\n`));\n }\n\n // Summary line\n const parts: string[] = [\n `${report.sourceDriftCount} source-drift`,\n `${report.graphDriftCount} graph-drift`,\n `${report.fullDriftCount} full-drift`,\n `${report.missingCount} missing`,\n `${report.unmaterializedCount} unmaterialized`,\n ];\n\n let summary = `\\nSummary: ${parts.join(', ')}`;\n if (driftedOnly && report.okCount > 0) {\n summary += ` (${report.okCount} ok hidden)`;\n } else {\n summary += `, ${report.okCount} ok`;\n }\n process.stdout.write(summary + '\\n');\n}\n\n/**\n * Classify entries for a given section (source or graph).\n * Source section shows: source-drift, full-drift, missing, unmaterialized, ok\n * Graph section shows: graph-drift, full-drift, ok\n */\nfunction classifyForSection(\n entries: DriftEntry[],\n section: 'source' | 'graph',\n driftedOnly: boolean,\n): DriftEntry[] {\n return entries.filter((entry) => {\n if (section === 'source') {\n // Source section: source-drift, full-drift, missing, unmaterialized, ok\n if (entry.status === 'graph-drift') return false;\n if (entry.status === 'ok' && driftedOnly) return false;\n return true;\n } else {\n // Graph section: graph-drift, full-drift, ok\n if (\n entry.status === 'source-drift' ||\n entry.status === 'missing' ||\n entry.status === 'unmaterialized'\n )\n return false;\n if (entry.status === 'ok' && driftedOnly) return false;\n return true;\n }\n });\n}\n\nfunction printSectionEntries(entries: DriftEntry[], section: 'source' | 'graph'): void {\n if (entries.length === 0) {\n process.stdout.write(chalk.dim(' (none)\\n'));\n return;\n }\n\n for (const entry of entries) {\n printEntryLine(entry);\n printChangedFiles(entry, section);\n }\n}\n\nfunction printEntryLine(entry: DriftEntry): void {\n const pad = 13; // width for status label column\n switch (entry.status) {\n case 'ok':\n process.stdout.write(chalk.green(` ${'[ok]'.padEnd(pad)}${entry.nodePath}\\n`));\n break;\n case 'source-drift':\n process.stdout.write(chalk.red(` ${'[drift]'.padEnd(pad)}${entry.nodePath}\\n`));\n break;\n case 'graph-drift':\n process.stdout.write(chalk.magenta(` ${'[drift]'.padEnd(pad)}${entry.nodePath}\\n`));\n break;\n case 'full-drift':\n process.stdout.write(chalk.red(` ${'[drift]'.padEnd(pad)}${entry.nodePath}\\n`));\n break;\n case 'missing':\n process.stdout.write(chalk.yellow(` ${'[missing]'.padEnd(pad)}${entry.nodePath}\\n`));\n break;\n case 'unmaterialized':\n process.stdout.write(chalk.dim(` ${'[unmat.]'.padEnd(pad)}${entry.nodePath}\\n`));\n break;\n }\n}\n\nfunction printChangedFiles(entry: DriftEntry, section: 'source' | 'graph'): void {\n if (!entry.changedFiles || entry.changedFiles.length === 0) return;\n\n const indent = ' '.repeat(15); // align under node path\n const relevantFiles = entry.changedFiles.filter((f) => {\n if (section === 'source') return f.category === 'source';\n return f.category === 'graph';\n });\n\n for (const file of relevantFiles) {\n process.stdout.write(chalk.dim(`${indent}${file.filePath} (changed)\\n`));\n }\n}\n","import { readFile, writeFile, stat, readdir, mkdir, rm } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse as yamlParse } from 'yaml';\nimport type { DriftState, DriftNodeState } from '../model/types.js';\n\nconst DRIFT_STATE_DIR = '.drift-state';\n\n/** Convert node path to per-node state file path under .drift-state/ */\nfunction nodeStatePath(yggRoot: string, nodePath: string): string {\n return path.join(yggRoot, DRIFT_STATE_DIR, `${nodePath}.json`);\n}\n\n/**\n * Recursively scan a directory for .json files.\n * Returns array of paths relative to baseDir (without .json extension).\n */\nasync function scanJsonFiles(dir: string, baseDir: string): Promise<string[]> {\n const results: string[] = [];\n let entries;\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n return results;\n }\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n const nested = await scanJsonFiles(fullPath, baseDir);\n results.push(...nested);\n } else if (entry.isFile() && entry.name.endsWith('.json')) {\n const relPath = path.relative(baseDir, fullPath);\n // Remove .json extension and normalize to posix\n const nodePath = relPath.replace(/\\\\/g, '/').replace(/\\.json$/, '');\n results.push(nodePath);\n }\n }\n return results;\n}\n\n/**\n * Remove empty directories walking up from filePath to (but not including) stopDir.\n */\nasync function removeEmptyParents(filePath: string, stopDir: string): Promise<void> {\n let dir = path.dirname(filePath);\n while (dir !== stopDir && dir.startsWith(stopDir)) {\n try {\n const entries = await readdir(dir);\n if (entries.length === 0) {\n await rm(dir, { recursive: true });\n dir = path.dirname(dir);\n } else {\n break;\n }\n } catch {\n break;\n }\n }\n}\n\n/** Read a single node's drift state from .drift-state/<nodePath>.json */\nexport async function readNodeDriftState(\n yggRoot: string,\n nodePath: string,\n): Promise<DriftNodeState | undefined> {\n try {\n const filePath = nodeStatePath(yggRoot, nodePath);\n const content = await readFile(filePath, 'utf-8');\n const parsed = JSON.parse(content) as DriftNodeState;\n return parsed;\n } catch {\n return undefined;\n }\n}\n\n/** Write a single node's drift state to .drift-state/<nodePath>.json */\nexport async function writeNodeDriftState(\n yggRoot: string,\n nodePath: string,\n nodeState: DriftNodeState,\n): Promise<void> {\n const filePath = nodeStatePath(yggRoot, nodePath);\n await mkdir(path.dirname(filePath), { recursive: true });\n const content = JSON.stringify(nodeState, null, 2) + '\\n';\n await writeFile(filePath, content, 'utf-8');\n}\n\n/**\n * Garbage-collect drift state: remove .json files for node paths NOT in validNodePaths.\n * Cleans up empty parent directories after removal.\n * Returns sorted list of removed node paths.\n */\nexport async function garbageCollectDriftState(\n yggRoot: string,\n validNodePaths: Set<string>,\n): Promise<string[]> {\n const driftDir = path.join(yggRoot, DRIFT_STATE_DIR);\n const allNodePaths = await scanJsonFiles(driftDir, driftDir);\n const removed: string[] = [];\n\n for (const nodePath of allNodePaths) {\n if (!validNodePaths.has(nodePath)) {\n const filePath = nodeStatePath(yggRoot, nodePath);\n await rm(filePath);\n await removeEmptyParents(filePath, driftDir);\n removed.push(nodePath);\n }\n }\n\n return removed.sort();\n}\n\n/**\n * Read full drift state.\n * - If .drift-state is a directory: scan for per-node .json files.\n * - If .drift-state is a file (legacy): parse it, migrate to per-node files, delete old file.\n * - If .drift-state doesn't exist: return {}.\n */\nexport async function readDriftState(yggRoot: string): Promise<DriftState> {\n const driftPath = path.join(yggRoot, DRIFT_STATE_DIR);\n\n let driftStat;\n try {\n driftStat = await stat(driftPath);\n } catch {\n return {};\n }\n\n // Legacy single-file format: migrate to per-node files\n if (driftStat.isFile()) {\n const content = await readFile(driftPath, 'utf-8');\n let raw: unknown;\n try {\n raw = JSON.parse(content);\n } catch {\n raw = yamlParse(content);\n }\n\n if (!raw || typeof raw !== 'object') return {};\n\n const state: DriftState = {};\n for (const [key, value] of Object.entries(raw)) {\n if (typeof value === 'object' && value !== null && 'hash' in value) {\n state[key] = value as DriftNodeState;\n }\n // Skip legacy string entries silently\n }\n\n // Migrate: delete old file, write per-node files\n await rm(driftPath);\n for (const [nodePath, nodeState] of Object.entries(state)) {\n await writeNodeDriftState(yggRoot, nodePath, nodeState);\n }\n\n return state;\n }\n\n // Directory format: scan for per-node .json files\n const nodePaths = await scanJsonFiles(driftPath, driftPath);\n const state: DriftState = {};\n for (const nodePath of nodePaths) {\n const nodeState = await readNodeDriftState(yggRoot, nodePath);\n if (nodeState) {\n state[nodePath] = nodeState;\n }\n }\n return state;\n}\n\n/**\n * Write full drift state as per-node files.\n * Each entry is written as a separate .json file under .drift-state/.\n */\nexport async function writeDriftState(yggRoot: string, state: DriftState): Promise<void> {\n for (const [nodePath, nodeState] of Object.entries(state)) {\n await writeNodeDriftState(yggRoot, nodePath, nodeState);\n }\n}\n","import { readFile, readdir, stat } from 'node:fs/promises';\nimport path from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { createRequire } from 'node:module';\nimport { type Ignore, type Options as IgnoreOptions } from 'ignore';\nimport type { TrackedFile } from '../core/context-files.js';\n\nconst require = createRequire(import.meta.url);\nconst ignoreFactory = require('ignore') as (options?: IgnoreOptions) => Ignore;\n\ntype HashPathOptions = {\n projectRoot?: string;\n};\n\ntype GitignoreEntry = { basePath: string; matcher: Ignore };\n\nexport async function hashFile(filePath: string): Promise<string> {\n const content = await readFile(filePath);\n return createHash('sha256').update(content).digest('hex');\n}\n\nexport async function hashPath(targetPath: string, options: HashPathOptions = {}): Promise<string> {\n const projectRoot = options.projectRoot ? path.resolve(options.projectRoot) : undefined;\n const gitignoreStack = await loadRootGitignoreStack(projectRoot);\n const targetStat = await stat(targetPath);\n\n if (targetStat.isFile()) {\n // Mapped files are always hashed — gitignore only applies to directory scans.\n return hashFile(targetPath);\n }\n\n if (targetStat.isDirectory()) {\n const fileHashes = await collectDirectoryFileHashes(targetPath, targetPath, {\n projectRoot,\n gitignoreStack,\n });\n const digestInput = fileHashes\n .sort((a, b) => a.path.localeCompare(b.path))\n .map((entry) => `${entry.path}:${entry.hash}`)\n .join('\\n');\n return hashString(digestInput);\n }\n\n throw new Error(`Unsupported mapping path type: ${targetPath}`);\n}\n\nasync function collectDirectoryFileHashes(\n directoryPath: string,\n rootDirectoryPath: string,\n options: { projectRoot?: string; gitignoreStack?: GitignoreEntry[] },\n): Promise<Array<{ path: string; hash: string }>> {\n const filePaths = await collectDirectoryFilePaths(directoryPath, rootDirectoryPath, options);\n const result: Array<{ path: string; hash: string }> = [];\n for (const entry of filePaths) {\n result.push({ path: entry.relPath, hash: await hashFile(entry.absPath) });\n }\n return result;\n}\n\nasync function loadRootGitignoreStack(projectRoot?: string): Promise<GitignoreEntry[]> {\n if (!projectRoot) return [];\n try {\n const content = await readFile(path.join(projectRoot, '.gitignore'), 'utf-8');\n const matcher = ignoreFactory();\n matcher.add(content);\n return [{ basePath: projectRoot, matcher }];\n } catch {\n return [];\n }\n}\n\nfunction isIgnoredByStack(candidatePath: string, stack: GitignoreEntry[]): boolean {\n for (const { basePath, matcher } of stack) {\n const relativePath = path.relative(basePath, candidatePath);\n if (relativePath === '' || relativePath.startsWith('..')) continue;\n if (matcher.ignores(relativePath) || matcher.ignores(relativePath + '/')) return true;\n }\n return false;\n}\n\nexport function hashString(content: string): string {\n return createHash('sha256').update(content).digest('hex');\n}\n\n/** Compute per-file hashes for a mapping. Used for diagnostics (which files changed). */\nexport async function perFileHashes(\n projectRoot: string,\n mapping: { paths?: string[] },\n): Promise<Array<{ path: string; hash: string }>> {\n const root = path.resolve(projectRoot);\n const paths = mapping.paths ?? [];\n if (paths.length === 0) return [];\n\n const result: Array<{ path: string; hash: string }> = [];\n const gitignoreStack = await loadRootGitignoreStack(root);\n\n for (const p of paths) {\n const absPath = path.join(root, p);\n const st = await stat(absPath);\n if (st.isFile()) {\n result.push({ path: p, hash: await hashFile(absPath) });\n } else if (st.isDirectory()) {\n const hashes = await collectDirectoryFileHashes(absPath, absPath, {\n projectRoot: root,\n gitignoreStack,\n });\n for (const h of hashes) {\n result.push({\n path: path.join(p, h.path).split(path.sep).join('/'),\n hash: h.hash,\n });\n }\n }\n }\n\n return result;\n}\n\n/** Compute drift hash for a node mapping. Returns hex. */\nexport async function hashForMapping(\n projectRoot: string,\n mapping: { paths?: string[] },\n): Promise<string> {\n const root = path.resolve(projectRoot);\n const paths = mapping.paths ?? [];\n if (paths.length === 0) throw new Error('Invalid mapping for hash: no paths');\n\n const pairs: Array<{ path: string; hash: string }> = [];\n\n for (const p of paths) {\n const absPath = path.join(root, p);\n const st = await stat(absPath);\n if (st.isFile()) {\n pairs.push({ path: p, hash: await hashFile(absPath) });\n } else if (st.isDirectory()) {\n const dirHash = await hashPath(absPath, { projectRoot: root });\n pairs.push({ path: p, hash: dirHash });\n }\n }\n\n const digestInput = pairs\n .sort((a, b) => a.path.localeCompare(b.path))\n .map((e) => `${e.path}:${e.hash}`)\n .join('\\n');\n return createHash('sha256').update(digestInput).digest('hex');\n}\n\n/** Stored file data for mtime-based drift optimization. */\nexport interface StoredFileData {\n hashes: Record<string, string>;\n mtimes: Record<string, number>;\n}\n\n/**\n * Hash all tracked files (source + graph) for bidirectional drift detection.\n * Directories in the tracked list are expanded to their contained files.\n * Returns a canonical hash (sorted path:hash digest), per-file hashes, and mtimes.\n *\n * When `storedFileData` is provided, files whose mtime has not changed since\n * the last sync will reuse the stored hash instead of re-reading and hashing.\n * This makes the common case (no changes) nearly instant even for large mappings.\n */\nexport async function hashTrackedFiles(\n projectRoot: string,\n trackedFiles: TrackedFile[],\n storedFileData?: StoredFileData,\n excludePrefixes?: string[],\n): Promise<{ canonicalHash: string; fileHashes: Record<string, string>; fileMtimes: Record<string, number> }> {\n const fileHashes: Record<string, string> = {};\n const fileMtimes: Record<string, number> = {};\n const gitignoreStack = await loadRootGitignoreStack(projectRoot);\n\n // Collect all file entries (expanding directories) with their metadata\n type FileEntry = { relPath: string; absPath: string; mtimeMs: number };\n const allFiles: FileEntry[] = [];\n\n for (const tf of trackedFiles) {\n const absPath = path.join(projectRoot, tf.path);\n try {\n const st = await stat(absPath);\n if (st.isDirectory()) {\n const dirEntries = await collectDirectoryFilePaths(absPath, absPath, {\n projectRoot,\n gitignoreStack,\n });\n for (const entry of dirEntries) {\n allFiles.push({\n relPath: path.join(tf.path, entry.relPath).replace(/\\\\/g, '/'),\n absPath: entry.absPath,\n mtimeMs: entry.mtimeMs,\n });\n }\n } else {\n allFiles.push({ relPath: tf.path, absPath, mtimeMs: st.mtimeMs });\n }\n } catch {\n continue;\n }\n }\n\n // Exclude files owned by descendant nodes (child-wins model)\n const filtered = excludePrefixes?.length\n ? allFiles.filter((entry) =>\n !excludePrefixes.some((prefix) =>\n entry.relPath === prefix || entry.relPath.startsWith(prefix + '/')))\n : allFiles;\n\n // Separate files into cached (mtime match) and dirty (need hashing)\n const dirty: FileEntry[] = [];\n for (const entry of filtered) {\n const storedMtime = storedFileData?.mtimes[entry.relPath];\n const storedHash = storedFileData?.hashes[entry.relPath];\n if (storedMtime !== undefined && storedHash !== undefined && entry.mtimeMs === storedMtime) {\n fileHashes[entry.relPath] = storedHash;\n } else {\n dirty.push(entry);\n }\n fileMtimes[entry.relPath] = entry.mtimeMs;\n }\n\n // Hash dirty files in parallel batches to avoid overwhelming file descriptors\n const BATCH_SIZE = 256;\n for (let i = 0; i < dirty.length; i += BATCH_SIZE) {\n const batch = dirty.slice(i, i + BATCH_SIZE);\n const hashes = await Promise.all(batch.map((e) => hashFile(e.absPath)));\n for (let j = 0; j < batch.length; j++) {\n fileHashes[batch[j].relPath] = hashes[j];\n }\n }\n\n // Canonical hash: sorted path:hash pairs\n const sorted = Object.entries(fileHashes).sort(([a], [b]) => a.localeCompare(b));\n const digest = sorted.map(([p, h]) => `${p}:${h}`).join('\\n');\n const canonicalHash = hashString(digest);\n\n return { canonicalHash, fileHashes, fileMtimes };\n}\n\n/**\n * Collect file paths and mtimes from a directory without hashing.\n * Used by hashTrackedFiles to separate discovery from hashing,\n * enabling mtime-based optimization.\n *\n * Directory recursion and file stat() calls are parallelized for performance.\n */\nasync function collectDirectoryFilePaths(\n directoryPath: string,\n rootDirectoryPath: string,\n options: { projectRoot?: string; gitignoreStack?: GitignoreEntry[] },\n): Promise<Array<{ relPath: string; absPath: string; mtimeMs: number }>> {\n let stack = options.gitignoreStack ?? [];\n try {\n const localContent = await readFile(path.join(directoryPath, '.gitignore'), 'utf-8');\n const localMatcher = ignoreFactory();\n localMatcher.add(localContent);\n stack = [...stack, { basePath: directoryPath, matcher: localMatcher }];\n } catch {\n // No local .gitignore\n }\n\n const entries = await readdir(directoryPath, { withFileTypes: true });\n const dirs: string[] = [];\n const files: string[] = [];\n\n for (const entry of entries) {\n const absoluteChildPath = path.join(directoryPath, entry.name);\n if (isIgnoredByStack(absoluteChildPath, stack)) continue;\n if (entry.isDirectory()) dirs.push(absoluteChildPath);\n else if (entry.isFile()) files.push(absoluteChildPath);\n }\n\n // Parallel: recurse into directories AND stat files concurrently\n const [dirResults, fileStats] = await Promise.all([\n Promise.all(dirs.map((d) => collectDirectoryFilePaths(d, rootDirectoryPath, {\n projectRoot: options.projectRoot,\n gitignoreStack: stack,\n }))),\n Promise.all(files.map(async (f) => {\n const fileStat = await stat(f);\n return {\n relPath: path.relative(rootDirectoryPath, f),\n absPath: f,\n mtimeMs: fileStat.mtimeMs,\n };\n })),\n ]);\n\n const result: Array<{ relPath: string; absPath: string; mtimeMs: number }> = [];\n for (const nested of dirResults) result.push(...nested);\n result.push(...fileStats);\n return result;\n}\n","import path from 'node:path';\nimport type { Graph, GraphNode, DriftCategory, FlowDef } from '../model/types.js';\nimport { normalizeMappingPaths } from '../utils/paths.js';\nimport { collectAncestors, resolveAspects } from './context-builder.js';\n\nexport interface TrackedFile {\n path: string; // relative to project root\n category: DriftCategory; // 'source' or 'graph'\n}\n\nconst STRUCTURAL_RELATION_TYPES = new Set(['uses', 'calls', 'extends', 'implements']);\n\n/**\n * Collect all files tracked by a node's context package.\n * Mirrors the traversal of build-context but returns file paths\n * instead of rendered content. This is the core function for\n * bidirectional drift detection.\n *\n * Synchronous — no I/O needed; all data comes from the loaded Graph.\n */\nexport function collectTrackedFiles(node: GraphNode, graph: Graph): TrackedFile[] {\n const seen = new Set<string>();\n const result: TrackedFile[] = [];\n\n // Compute the .yggdrasil prefix relative to project root.\n // graph.rootPath is absolute path to .yggdrasil/; project root is its parent.\n const projectRoot = path.dirname(graph.rootPath);\n const yggPrefix = path.relative(projectRoot, graph.rootPath);\n // Normalize to forward slashes for consistency\n const yggPrefixNormalized = yggPrefix.split(path.sep).join('/');\n\n const configArtifactKeys = new Set(Object.keys(graph.config.artifacts ?? {}));\n\n function addFile(filePath: string, category: DriftCategory): void {\n if (seen.has(filePath)) return;\n seen.add(filePath);\n result.push({ path: filePath, category });\n }\n\n function graphPath(...segments: string[]): string {\n return [yggPrefixNormalized, ...segments].join('/');\n }\n\n function addNodeFiles(n: GraphNode): void {\n // yg-node.yaml\n addFile(graphPath('model', n.path, 'yg-node.yaml'), 'graph');\n // artifacts filtered by config\n for (const art of n.artifacts) {\n if (configArtifactKeys.has(art.filename)) {\n addFile(graphPath('model', n.path, art.filename), 'graph');\n }\n }\n }\n\n // 1. OWN — yg-node.yaml + config-filtered artifacts\n addNodeFiles(node);\n\n // 2. HIERARCHICAL — ancestors from root to parent\n const ancestors = collectAncestors(node);\n for (const ancestor of ancestors) {\n addNodeFiles(ancestor);\n }\n\n // 3. ASPECTS — resolve all aspects from own + ancestors + flows (with recursive implies)\n // First, collect all aspect ids from own node and ancestors\n const allAspectIds = new Set<string>();\n\n for (const entry of node.meta.aspects ?? []) {\n allAspectIds.add(entry.aspect);\n }\n for (const ancestor of ancestors) {\n for (const entry of ancestor.meta.aspects ?? []) {\n allAspectIds.add(entry.aspect);\n }\n }\n\n // Collect participating flows (same logic as build-context)\n const participatingFlows = collectParticipatingFlows(graph, node, ancestors);\n\n // Add flow-propagated aspects\n for (const flow of participatingFlows) {\n for (const id of flow.aspects ?? []) {\n allAspectIds.add(id);\n }\n }\n\n // Resolve with recursive implies\n const resolvedAspects = resolveAspects(allAspectIds, graph.aspects);\n for (const aspect of resolvedAspects) {\n addFile(graphPath('aspects', aspect.id, 'yg-aspect.yaml'), 'graph');\n for (const art of aspect.artifacts) {\n addFile(graphPath('aspects', aspect.id, art.filename), 'graph');\n }\n }\n\n // 4. RELATIONAL-DEPS — structural relations (uses/calls/extends/implements)\n for (const relation of node.meta.relations ?? []) {\n if (!STRUCTURAL_RELATION_TYPES.has(relation.type)) continue;\n const target = graph.nodes.get(relation.target);\n if (!target) continue;\n\n // Determine which artifacts to include from the target\n const structuralFilenames = Object.entries(graph.config.artifacts ?? {})\n .filter(([, c]) => c.included_in_relations)\n .map(([filename]) => filename);\n\n // Check if the target actually has any of the included_in_relations artifacts\n const structuralArts = structuralFilenames.filter((filename) =>\n target.artifacts.some((a) => a.filename === filename),\n );\n\n if (structuralArts.length > 0) {\n // Use only included_in_relations artifacts that exist on target\n for (const filename of structuralArts) {\n addFile(graphPath('model', target.path, filename), 'graph');\n }\n } else {\n // Fallback: all config-allowed artifacts\n for (const art of target.artifacts) {\n if (configArtifactKeys.has(art.filename)) {\n addFile(graphPath('model', target.path, art.filename), 'graph');\n }\n }\n }\n }\n\n // 5. RELATIONAL-FLOWS — yg-flow.yaml + flow artifacts for participating flows\n for (const flow of participatingFlows) {\n addFile(graphPath('flows', flow.path, 'yg-flow.yaml'), 'graph');\n for (const art of flow.artifacts) {\n addFile(graphPath('flows', flow.path, art.filename), 'graph');\n }\n }\n\n // 6. SOURCE — files from mapping.paths\n const mappingPaths = normalizeMappingPaths(node.meta.mapping);\n for (const p of mappingPaths) {\n addFile(p, 'source');\n }\n\n return result;\n}\n\n/**\n * Find all flows where the node or any of its ancestors is a participant.\n * Same logic as collectParticipatingFlows in context-builder.ts.\n */\nfunction collectParticipatingFlows(\n graph: Graph,\n node: GraphNode,\n ancestors: GraphNode[],\n): FlowDef[] {\n const paths = new Set<string>([node.path, ...ancestors.map((a) => a.path)]);\n return graph.flows.filter((f) => f.nodes.some((n) => paths.has(n)));\n}\n","import type {\n Graph,\n DriftReport,\n DriftEntry,\n DriftStatus,\n DriftFileChange,\n DriftCategory,\n} from '../model/types.js';\nimport {\n readDriftState,\n readNodeDriftState,\n writeNodeDriftState,\n} from '../io/drift-state-store.js';\nimport { hashTrackedFiles } from '../utils/hash.js';\nimport { collectTrackedFiles } from './context-files.js';\nimport { normalizeMappingPaths } from '../utils/paths.js';\nimport { access } from 'node:fs/promises';\nimport path from 'node:path';\n\n/**\n * Compute mapping paths owned by descendant nodes that overlap with a node's own\n * mapping paths. Used to exclude child-owned files from parent drift hashing\n * (\"child wins\" model).\n */\nfunction getChildMappingExclusions(graph: Graph, nodePath: string): string[] {\n const node = graph.nodes.get(nodePath);\n if (!node) return [];\n const parentMappings = normalizeMappingPaths(node.meta.mapping);\n if (parentMappings.length === 0) return [];\n\n const exclusions: string[] = [];\n for (const [childPath, childNode] of graph.nodes) {\n if (childPath === nodePath) continue;\n if (!childPath.startsWith(nodePath + '/')) continue; // not a descendant\n const childMappings = normalizeMappingPaths(childNode.meta.mapping);\n for (const cm of childMappings) {\n for (const pm of parentMappings) {\n if (cm === pm || cm.startsWith(pm + '/')) {\n exclusions.push(cm);\n }\n }\n }\n }\n return exclusions;\n}\n\nexport async function detectDrift(graph: Graph, filterNodePath?: string): Promise<DriftReport> {\n const projectRoot = path.dirname(graph.rootPath);\n const driftState = await readDriftState(graph.rootPath);\n const entries: DriftEntry[] = [];\n\n for (const [nodePath, node] of graph.nodes) {\n if (filterNodePath && nodePath !== filterNodePath && !nodePath.startsWith(filterNodePath + '/')) continue;\n const mapping = node.meta.mapping;\n if (!mapping) continue;\n\n const mappingPaths = normalizeMappingPaths(mapping);\n if (mappingPaths.length === 0) continue;\n\n const storedEntry = driftState[nodePath];\n\n if (!storedEntry) {\n const allMissing = await allPathsMissing(projectRoot, mappingPaths);\n entries.push({\n nodePath,\n status: allMissing ? 'unmaterialized' : 'source-drift',\n details: allMissing\n ? 'No drift state recorded, files do not exist'\n : 'No drift state recorded, files exist (run drift-sync after materialization)',\n });\n continue;\n }\n\n // Check if source files are entirely missing (all mapping paths gone)\n // This must happen BEFORE hash comparison — a node whose source files\n // are all gone is 'missing' regardless of whether graph-only hashes match.\n const sourceFilesMissing = await allPathsMissing(projectRoot, mappingPaths);\n if (sourceFilesMissing) {\n entries.push({\n nodePath,\n status: 'missing',\n details: 'All source mapping paths are missing',\n });\n continue;\n }\n\n // Collect all tracked files (source + graph) for this node\n const trackedFiles = collectTrackedFiles(node, graph);\n // Exclude files owned by descendant nodes (child-wins model)\n const excludePrefixes = getChildMappingExclusions(graph, nodePath);\n // Pass stored file data for mtime-based optimization: skip hashing files whose\n // modification time has not changed since the last drift-sync.\n const storedFileData = storedEntry.files\n ? { hashes: storedEntry.files, mtimes: storedEntry.mtimes ?? {} }\n : undefined;\n const { canonicalHash, fileHashes } = await hashTrackedFiles(projectRoot, trackedFiles, storedFileData, excludePrefixes);\n\n if (canonicalHash === storedEntry.hash) {\n entries.push({ nodePath, status: 'ok' });\n continue;\n }\n\n // Something changed — determine what\n const changedFiles: DriftFileChange[] = [];\n const storedFiles = storedEntry.files;\n\n // Check current files against stored\n for (const [filePath, hash] of Object.entries(fileHashes)) {\n const storedHash = storedFiles[filePath];\n if (!storedHash || storedHash !== hash) {\n changedFiles.push({\n filePath,\n category: categorizeFile(filePath, graph.rootPath, projectRoot),\n });\n }\n }\n\n // Check for deleted files (in stored but not in current)\n for (const storedPath of Object.keys(storedFiles)) {\n if (!(storedPath in fileHashes)) {\n changedFiles.push({\n filePath: `${storedPath} (deleted)`,\n category: categorizeFile(storedPath, graph.rootPath, projectRoot),\n });\n }\n }\n\n // Determine drift status from changed file categories\n const hasSourceChanges = changedFiles.some((f) => f.category === 'source');\n const hasGraphChanges = changedFiles.some((f) => f.category === 'graph');\n\n let status: DriftStatus;\n if (hasSourceChanges && hasGraphChanges) {\n status = 'full-drift';\n } else if (hasGraphChanges) {\n status = 'graph-drift';\n } else if (hasSourceChanges) {\n status = 'source-drift';\n } else {\n // Hash changed but no individual file identified — fallback\n status = 'source-drift';\n }\n\n const details =\n changedFiles.length > 0\n ? `Changed files: ${changedFiles.map((f) => f.filePath).join(', ')}`\n : 'File(s) modified since last sync';\n\n entries.push({ nodePath, status, details, changedFiles });\n }\n\n return {\n entries,\n totalChecked: entries.length,\n okCount: entries.filter((e) => e.status === 'ok').length,\n sourceDriftCount: entries.filter((e) => e.status === 'source-drift').length,\n graphDriftCount: entries.filter((e) => e.status === 'graph-drift').length,\n fullDriftCount: entries.filter((e) => e.status === 'full-drift').length,\n missingCount: entries.filter((e) => e.status === 'missing').length,\n unmaterializedCount: entries.filter((e) => e.status === 'unmaterialized').length,\n };\n}\n\n/**\n * Categorize a file path as 'source' or 'graph' based on whether it lives\n * under the .yggdrasil/ directory.\n */\nfunction categorizeFile(filePath: string, _rootPath: string, projectRoot: string): DriftCategory {\n const yggPrefix = path.relative(projectRoot, _rootPath);\n const normalizedPrefix = yggPrefix.split(path.sep).join('/');\n const normalizedFilePath = filePath.replace(/\\\\/g, '/');\n return normalizedFilePath.startsWith(normalizedPrefix) ? 'graph' : 'source';\n}\n\nasync function allPathsMissing(projectRoot: string, mappingPaths: string[]): Promise<boolean> {\n for (const mp of mappingPaths) {\n const absPath = path.join(projectRoot, mp);\n try {\n await access(absPath);\n return false;\n } catch {\n // path missing\n }\n }\n return true;\n}\n\nexport async function syncDriftState(\n graph: Graph,\n nodePath: string,\n): Promise<{ previousHash?: string; currentHash: string }> {\n const projectRoot = path.dirname(graph.rootPath);\n const node = graph.nodes.get(nodePath);\n if (!node) throw new Error(`Node not found: ${nodePath}`);\n if (!node.meta.mapping) throw new Error(`Node has no mapping: ${nodePath}`);\n\n const trackedFiles = collectTrackedFiles(node, graph);\n const excludePrefixes = getChildMappingExclusions(graph, nodePath);\n // For sync, pass stored data so unchanged files can reuse cached hashes.\n const existingEntry = await readNodeDriftState(graph.rootPath, nodePath);\n const storedFileData = existingEntry?.files\n ? { hashes: existingEntry.files, mtimes: existingEntry.mtimes ?? {} }\n : undefined;\n const { canonicalHash, fileHashes, fileMtimes } = await hashTrackedFiles(projectRoot, trackedFiles, storedFileData, excludePrefixes);\n\n const previousHash = existingEntry?.hash;\n\n await writeNodeDriftState(graph.rootPath, nodePath, {\n hash: canonicalHash,\n files: fileHashes,\n mtimes: fileMtimes,\n });\n\n return { previousHash, currentHash: canonicalHash };\n}\n","import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { loadGraph } from '../core/graph-loader.js';\nimport { syncDriftState } from '../core/drift-detector.js';\nimport { garbageCollectDriftState } from '../io/drift-state-store.js';\nimport { normalizeMappingPaths } from '../utils/paths.js';\n\nexport function registerDriftSyncCommand(program: Command): void {\n program\n .command('drift-sync')\n .description('Record current file hash after resolving drift')\n .option('--node <path>', 'Node path to sync')\n .option('--recursive', 'Also sync all descendant nodes')\n .option('--all', 'Sync all nodes with mappings')\n .action(async (options: { node?: string; recursive?: boolean; all?: boolean }) => {\n try {\n if (!options.node && !options.all) {\n process.stderr.write(\"Error: either '--node <path>' or '--all' is required\\n\");\n process.exit(1);\n }\n\n const graph = await loadGraph(process.cwd());\n\n let nodesToSync: string[];\n\n if (options.all) {\n nodesToSync = [...graph.nodes.entries()]\n .filter(([, n]) => normalizeMappingPaths(n.meta.mapping).length > 0)\n .map(([p]) => p)\n .sort();\n } else {\n const nodePath = options.node!.trim().replace(/^\\.\\//, '').replace(/\\/+$/, '');\n\n if (!graph.nodes.has(nodePath)) {\n await syncDriftState(graph, nodePath); // will throw with proper error\n return;\n }\n\n nodesToSync = [nodePath];\n if (options.recursive) {\n const prefix = nodePath + '/';\n for (const [p] of graph.nodes) {\n if (p.startsWith(prefix)) {\n nodesToSync.push(p);\n }\n }\n nodesToSync.sort();\n }\n }\n\n for (const np of nodesToSync) {\n const node = graph.nodes.get(np)!;\n if (normalizeMappingPaths(node.meta.mapping).length === 0) {\n if (!options.all && !options.recursive && np === options.node) {\n await syncDriftState(graph, np); // will throw with proper error\n }\n continue;\n }\n const { previousHash, currentHash } = await syncDriftState(graph, np);\n process.stdout.write(chalk.green(`Synchronized: ${np}\\n`));\n process.stdout.write(\n ` Hash: ${previousHash ? previousHash.slice(0, 8) : 'none'} -> ${currentHash.slice(0, 8)}\\n`,\n );\n }\n\n // Garbage collect orphaned drift state files after --all sync\n if (options.all) {\n const validPaths = new Set(nodesToSync);\n const removed = await garbageCollectDriftState(graph.rootPath, validPaths);\n for (const r of removed) {\n process.stdout.write(chalk.dim(`Removed orphaned drift state: ${r}\\n`));\n }\n }\n } catch (error) {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n process.exit(1);\n }\n });\n}\n","import { Command } from 'commander';\nimport { loadGraph } from '../core/graph-loader.js';\nimport { detectDrift } from '../core/drift-detector.js';\nimport { validate } from '../core/validator.js';\nimport { collectEffectiveAspectIds } from '../core/context-builder.js';\nimport { normalizeMappingPaths } from '../utils/paths.js';\n\nexport function registerStatusCommand(program: Command): void {\n program\n .command('status')\n .description('Show graph summary')\n .action(async () => {\n try {\n const graph = await loadGraph(process.cwd());\n\n // Count nodes by type\n const typeCounts = new Map<string, number>();\n let blackboxCount = 0;\n\n for (const node of graph.nodes.values()) {\n typeCounts.set(node.meta.type, (typeCounts.get(node.meta.type) ?? 0) + 1);\n if (node.meta.blackbox) blackboxCount++;\n }\n\n // Count relations\n let structuralRelations = 0;\n let eventRelations = 0;\n const structuralTypes = new Set(['uses', 'calls', 'extends', 'implements']);\n let maxRelCount = 0;\n let maxRelNode = '';\n for (const node of graph.nodes.values()) {\n const relCount = (node.meta.relations ?? []).length;\n if (relCount > maxRelCount) {\n maxRelCount = relCount;\n maxRelNode = node.path;\n }\n for (const rel of node.meta.relations ?? []) {\n if (structuralTypes.has(rel.type)) structuralRelations += 1;\n else eventRelations += 1;\n }\n }\n\n const flowCount = graph.flows.length;\n\n const drift = await detectDrift(graph);\n const validation = await validate(graph, 'all');\n const errorCount = validation.issues.filter((issue) => issue.severity === 'error').length;\n const warningCount = validation.issues.filter(\n (issue) => issue.severity === 'warning',\n ).length;\n\n // Quality metrics\n const configuredArtifactTypes = Object.keys(graph.config.artifacts ?? {});\n const totalSlots = graph.nodes.size * configuredArtifactTypes.length;\n let filledSlots = 0;\n let mappedNodeCount = 0;\n\n for (const node of graph.nodes.values()) {\n const allowed = new Set(configuredArtifactTypes);\n filledSlots += node.artifacts.filter((a) => allowed.has(a.filename)).length;\n if (normalizeMappingPaths(node.meta.mapping).length > 0) mappedNodeCount++;\n }\n\n let aspectCoveredNodes = 0;\n for (const node of graph.nodes.values()) {\n const effective = collectEffectiveAspectIds(graph, node.path);\n if (effective.size > 0) aspectCoveredNodes++;\n }\n\n process.stdout.write(`Graph: ${graph.config.name}\\n`);\n const pluralize = (word: string, count: number) =>\n count === 1 ? word : word.endsWith('y') ? word.slice(0, -1) + 'ies' : word + 's';\n const typeStr = [...typeCounts.entries()]\n .map(([t, c]) => `${c} ${pluralize(t, c)}`)\n .join(', ');\n process.stdout.write(\n `Nodes: ${graph.nodes.size} (${typeStr}) + ${blackboxCount} blackbox\\n`,\n );\n process.stdout.write(\n `Relations: ${structuralRelations} structural, ${eventRelations} event\\n`,\n );\n process.stdout.write(\n `Aspects: ${graph.aspects.length} Flows: ${flowCount}\\n`,\n );\n process.stdout.write(\n `Drift: ${drift.sourceDriftCount} source-drift, ${drift.graphDriftCount} graph-drift, ${drift.fullDriftCount} full-drift, ${drift.missingCount} missing, ${drift.unmaterializedCount} unmaterialized, ${drift.okCount} ok\\n`,\n );\n process.stdout.write(`Validation: ${errorCount} errors, ${warningCount} warnings\\n`);\n\n // Quality section\n const fillPct = totalSlots > 0 ? Math.round((filledSlots / totalSlots) * 100) : 0;\n const totalRelations = structuralRelations + eventRelations;\n const avgRel = graph.nodes.size > 0 ? (totalRelations / graph.nodes.size).toFixed(1) : '0';\n process.stdout.write(`\\nQuality:\\n`);\n process.stdout.write(\n ` Artifacts: ${filledSlots}/${totalSlots} slots filled (${fillPct}%) — ${configuredArtifactTypes.length} types × ${graph.nodes.size} nodes\\n`,\n );\n process.stdout.write(\n ` Relations: avg ${avgRel}/node, max ${maxRelCount}${maxRelNode ? ` (${maxRelNode})` : ''}\\n`,\n );\n process.stdout.write(\n ` Mapping: ${mappedNodeCount}/${graph.nodes.size} nodes mapped to source\\n`,\n );\n process.stdout.write(\n ` Aspects: ${aspectCoveredNodes}/${graph.nodes.size} nodes have aspect coverage\\n`,\n );\n } catch (error) {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n process.exit(1);\n }\n });\n}\n","import { Command } from 'commander';\nimport { loadGraph } from '../core/graph-loader.js';\nimport type { GraphNode } from '../model/types.js';\n\nexport function registerTreeCommand(program: Command): void {\n program\n .command('tree')\n .description('Display graph structure as a tree')\n .option('--root <path>', 'Show only subtree rooted at this path')\n .option('--depth <n>', 'Maximum depth', (v) => parseInt(v, 10))\n .action(async (options: { root?: string; depth?: number }) => {\n try {\n const graph = await loadGraph(process.cwd());\n\n let roots: GraphNode[];\n let showProjectName: boolean;\n\n if (options.root?.trim()) {\n const path = options.root.trim().replace(/\\/$/, '');\n const node = graph.nodes.get(path);\n if (!node) {\n process.stderr.write(`Error: path '${path}' not found\\n`);\n process.exit(1);\n }\n roots = [node];\n showProjectName = false;\n } else {\n roots = [...graph.nodes.values()]\n .filter((n) => n.parent === null)\n .sort((a, b) => a.path.localeCompare(b.path));\n showProjectName = true;\n }\n\n if (showProjectName) {\n process.stdout.write('model/\\n');\n }\n\n for (let i = 0; i < roots.length; i++) {\n const isLast = i === roots.length - 1;\n printNode(roots[i], '', isLast, 1, options.depth);\n }\n } catch (error) {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n process.exit(1);\n }\n });\n}\n\nfunction printNode(\n node: GraphNode,\n prefix: string,\n isLast: boolean,\n depth: number,\n maxDepth: number | undefined,\n): void {\n const connector = isLast ? '└── ' : '├── ';\n const name = node.path.split('/').pop() ?? node.path;\n const type = `[${node.meta.type}]`;\n const tags = node.meta.aspects?.length ? ` aspects:${node.meta.aspects.join(',')}` : '';\n const blackbox = node.meta.blackbox ? ' ■ blackbox' : '';\n const relationCount = node.meta.relations?.length ?? 0;\n\n process.stdout.write(\n `${prefix}${connector}${name}/ ${type}${tags}${blackbox} -> ${relationCount} relations\\n`,\n );\n\n const childPrefix = prefix + (isLast ? ' ' : '│ ');\n\n // Recurse into children\n if (maxDepth !== undefined && depth >= maxDepth) return;\n\n const children = [...node.children].sort((a, b) => a.path.localeCompare(b.path));\n for (let i = 0; i < children.length; i++) {\n printNode(children[i], childPrefix, i === children.length - 1, depth + 1, maxDepth);\n }\n}\n","import path from 'node:path';\nimport { access } from 'node:fs/promises';\nimport { Command } from 'commander';\nimport { loadGraph } from '../core/graph-loader.js';\nimport type { Graph, OwnerResult } from '../model/types.js';\nimport { normalizeMappingPaths, normalizeProjectRelativePath, projectRootFromGraph } from '../utils/paths.js';\n\nfunction normalizeForMatch(inputPath: string): string {\n return inputPath.replace(/\\\\/g, '/').replace(/\\/+$/, '');\n}\n\nexport function findOwner(graph: Graph, projectRoot: string, rawPath: string): OwnerResult {\n const file = normalizeForMatch(normalizeProjectRelativePath(projectRoot, rawPath));\n let best: { nodePath: string; mappingPath: string; exact: boolean } | null = null;\n\n for (const [nodePath, node] of graph.nodes) {\n const mappingPaths = normalizeMappingPaths(node.meta.mapping)\n .map(normalizeForMatch)\n .filter((mappingPath) => mappingPath.length > 0);\n\n for (const mappingPath of mappingPaths) {\n if (file === mappingPath) {\n return { file, nodePath, mappingPath, direct: true };\n }\n if (file.startsWith(mappingPath + '/')) {\n if (!best || (best && mappingPath.length > best.mappingPath.length)) {\n best = { nodePath, mappingPath, exact: false };\n }\n }\n }\n }\n\n return best\n ? { file, nodePath: best.nodePath, mappingPath: best.mappingPath, direct: false }\n : { file, nodePath: null };\n}\n\nexport function registerOwnerCommand(program: Command): void {\n program\n .command('owner')\n .description('Find which graph node owns a source file')\n .requiredOption('--file <path>', 'File path (relative to repository root)')\n .action(async (options: { file: string }) => {\n try {\n const cwd = process.cwd();\n const graph = await loadGraph(cwd);\n // Resolve the file path relative to CWD (so subdirectory-relative paths work),\n // then make it relative to the actual repo root (where .yggdrasil/ lives).\n const repoRoot = projectRootFromGraph(graph.rootPath);\n const rawPath = options.file.trim();\n const absolute = path.resolve(cwd, rawPath);\n const repoRelative = path.relative(repoRoot, absolute).split(path.sep).join('/');\n const result = findOwner(graph, repoRoot, repoRelative);\n\n if (!result.nodePath) {\n // Distinguish \"file doesn't exist\" from \"file exists but not mapped\"\n const absPath = path.resolve(repoRoot, result.file);\n let exists = true;\n try { await access(absPath); } catch { exists = false; }\n if (exists) {\n process.stdout.write(`${result.file} -> no graph coverage\\n`);\n } else {\n process.stdout.write(`${result.file} -> no graph coverage (file not found)\\n`);\n }\n } else {\n process.stdout.write(`${result.file} -> ${result.nodePath}\\n`);\n if (result.direct === false && result.mappingPath) {\n process.stdout.write(\n ` Plik nie ma własnego mapowania; kontekst pochodzi z nadrzędnego katalogu ${result.mappingPath}. Użyj: yg build-context --node ${result.nodePath}\\n`,\n );\n }\n }\n } catch (error) {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n process.exit(1);\n }\n });\n}\n","import type { Graph, Stage } from '../model/types.js';\nimport { execSync } from 'node:child_process';\nimport path from 'node:path';\n\nexport interface ResolveOptions {\n mode: 'all' | 'changed' | 'node';\n nodePath?: string; // required when mode === 'node'\n ref?: string; // git ref for --changed mode (default: HEAD)\n depth?: number; // max depth for tree (when mode === 'node')\n relationType?: 'structural' | 'event' | 'all'; // filter for tree\n}\n\nconst STRUCTURAL_RELATION_TYPES = new Set(['uses', 'calls', 'extends', 'implements']);\nconst EVENT_RELATION_TYPES = new Set(['emits', 'listens']);\n\n/** Expand changed set with direct dependents only (one level, no cascade) */\nfunction expandWithDependents(graph: Graph, changed: string[]): string[] {\n const dependents = new Map<string, string[]>();\n for (const [nodePath, node] of graph.nodes) {\n for (const rel of node.meta.relations ?? []) {\n if (!STRUCTURAL_RELATION_TYPES.has(rel.type)) continue;\n const deps = dependents.get(rel.target) ?? [];\n deps.push(nodePath);\n dependents.set(rel.target, deps);\n }\n }\n\n const result = new Set<string>(changed);\n for (const node of changed) {\n for (const dep of dependents.get(node) ?? []) {\n result.add(dep);\n }\n }\n\n return [...result];\n}\n\n/** Find nodes whose graph files have changed according to git */\nexport function findChangedNodes(graph: Graph, ref?: string): string[] {\n const gitRef = ref ?? 'HEAD';\n const yggDirName = path.basename(graph.rootPath);\n const projectRoot = path.dirname(graph.rootPath);\n\n let changedFiles: string[];\n try {\n const output = execSync(`git diff --name-only ${gitRef} -- ${yggDirName}/`, {\n cwd: projectRoot,\n encoding: 'utf-8',\n }).trim();\n changedFiles = output ? output.split('\\n') : [];\n } catch {\n // If git diff fails (no commits, not a repo, etc.), fall back to empty\n changedFiles = [];\n }\n\n // Map changed file paths back to node paths\n const changedNodePaths = new Set<string>();\n for (const filePath of changedFiles) {\n // filePath is like \".yggdrasil/auth/login-service/yg-node.yaml\"\n // Strip the yggdrasil dir prefix to get \"auth/login-service/yg-node.yaml\"\n const relative = filePath.startsWith(yggDirName + '/')\n ? filePath.slice(yggDirName.length + 1)\n : filePath;\n\n // Walk up directories to find matching node paths (nodes are under model/)\n const parts = relative.split('/');\n const modelIdx = parts.indexOf('model');\n const startIdx = modelIdx >= 0 ? modelIdx + 1 : 0;\n for (let i = parts.length - 1; i >= startIdx + 1; i--) {\n const candidate = parts.slice(startIdx, i).join('/');\n if (graph.nodes.has(candidate)) {\n changedNodePaths.add(candidate);\n break;\n }\n }\n }\n\n return expandWithDependents(graph, [...changedNodePaths]);\n}\n\n/** Collect node and its transitive dependencies (for --node mode) */\nexport function collectTransitiveDeps(graph: Graph, nodePath: string): string[] {\n return collectTransitiveDepsFiltered(graph, nodePath, undefined, 'structural');\n}\n\n/** Filter relation types for inclusion */\nfunction filterRelationType(relType: string, filter: 'structural' | 'event' | 'all'): boolean {\n if (filter === 'all') return true;\n if (filter === 'structural') return STRUCTURAL_RELATION_TYPES.has(relType);\n if (filter === 'event') return EVENT_RELATION_TYPES.has(relType);\n return false;\n}\n\n/** Collect transitive deps with depth and type filter */\nfunction collectTransitiveDepsFiltered(\n graph: Graph,\n nodePath: string,\n maxDepth: number | undefined,\n relationType: 'structural' | 'event' | 'all',\n): string[] {\n const node = graph.nodes.get(nodePath);\n if (!node) {\n throw new Error(`Node not found: ${nodePath}`);\n }\n\n const result = new Set<string>();\n const queue: Array<{ path: string; depth: number }> = [{ path: nodePath, depth: 0 }];\n\n while (queue.length > 0) {\n const { path: p, depth } = queue.shift()!;\n if (result.has(p)) continue;\n result.add(p);\n if (maxDepth !== undefined && depth >= maxDepth) continue;\n\n const n = graph.nodes.get(p)!;\n for (const rel of n.meta.relations ?? []) {\n if (!filterRelationType(rel.type, relationType)) continue;\n if (!graph.nodes.has(rel.target)) {\n throw new Error(`Relation target not found: ${rel.target}`);\n }\n if (!result.has(rel.target)) {\n queue.push({ path: rel.target, depth: depth + 1 });\n }\n }\n }\n\n return [...result];\n}\n\n/** Tree node for dependency tree output */\nexport interface DepTreeNode {\n nodePath: string;\n relationType: string;\n relationTarget?: string;\n blackbox: boolean;\n children: DepTreeNode[];\n}\n\n/** Build dependency tree for a node (spec format) */\nexport function buildDependencyTree(\n graph: Graph,\n nodePath: string,\n options: { depth?: number; relationType?: 'structural' | 'event' | 'all' } = {},\n): DepTreeNode[] {\n const node = graph.nodes.get(nodePath);\n if (!node) {\n throw new Error(`Node not found: ${nodePath}`);\n }\n\n const maxDepth = options.depth ?? Infinity;\n const typeFilter = options.relationType ?? 'all';\n\n function buildChildren(\n fromPath: string,\n currentDepth: number,\n branch: Set<string>,\n ): DepTreeNode[] {\n if (currentDepth >= maxDepth) return [];\n const fromNode = graph.nodes.get(fromPath)!;\n const children: DepTreeNode[] = [];\n for (const rel of fromNode.meta.relations ?? []) {\n if (!filterRelationType(rel.type, typeFilter)) continue;\n if (!graph.nodes.has(rel.target)) continue;\n if (branch.has(rel.target)) continue;\n const targetNode = graph.nodes.get(rel.target)!;\n const nextBranch = new Set(branch);\n nextBranch.add(rel.target);\n children.push({\n nodePath: rel.target,\n relationType: rel.type,\n relationTarget: fromPath,\n blackbox: targetNode.meta.blackbox ?? false,\n children: buildChildren(rel.target, currentDepth + 1, nextBranch),\n });\n }\n return children;\n }\n\n return buildChildren(nodePath, 0, new Set([nodePath]));\n}\n\n/** Format tree as text (spec format) */\nexport function formatDependencyTree(\n graph: Graph,\n nodePath: string,\n options: { depth?: number; relationType?: 'structural' | 'event' | 'all' } = {},\n): string {\n const roots = buildDependencyTree(graph, nodePath, options);\n const lines: string[] = [nodePath];\n\n function formatNode(node: DepTreeNode, prefix: string, isLast: boolean): void {\n const connector = isLast ? '└── ' : '├── ';\n const blackbox = node.blackbox ? ' ■ blackbox' : '';\n lines.push(`${prefix}${connector}${node.relationType} ${node.nodePath}${blackbox}`);\n const childPrefix = prefix + (isLast ? ' ' : '│ ');\n const lastIdx = node.children.length - 1;\n node.children.forEach((c, i) => formatNode(c, childPrefix, i === lastIdx));\n }\n\n roots.forEach((r, i) => formatNode(r, '', i === roots.length - 1));\n return lines.join('\\n');\n}\n\nexport async function resolveDeps(graph: Graph, options: ResolveOptions): Promise<Stage[]> {\n let candidatePaths: string[];\n\n switch (options.mode) {\n case 'all':\n candidatePaths = [...graph.nodes.keys()];\n break;\n case 'changed':\n candidatePaths = findChangedNodes(graph, options.ref);\n break;\n case 'node':\n candidatePaths = collectTransitiveDeps(graph, options.nodePath!);\n break;\n }\n\n candidatePaths = candidatePaths.filter((p) => {\n const node = graph.nodes.get(p)!;\n return !node.meta.blackbox && node.meta.mapping;\n });\n\n if (candidatePaths.length === 0) return [];\n\n const candidateSet = new Set(candidatePaths);\n\n // Validate relations: broken relation = target not in graph\n for (const p of candidatePaths) {\n const node = graph.nodes.get(p)!;\n for (const rel of node.meta.relations ?? []) {\n if (!graph.nodes.has(rel.target)) {\n throw new Error(`Relation target not found: ${rel.target}`);\n }\n }\n }\n\n const inDegree = new Map<string, number>();\n const dependents = new Map<string, string[]>();\n\n for (const p of candidatePaths) {\n inDegree.set(p, 0);\n dependents.set(p, []);\n }\n\n for (const p of candidatePaths) {\n const node = graph.nodes.get(p)!;\n for (const rel of node.meta.relations ?? []) {\n if (!STRUCTURAL_RELATION_TYPES.has(rel.type)) continue;\n if (candidateSet.has(rel.target)) {\n inDegree.set(p, (inDegree.get(p) ?? 0) + 1);\n dependents.get(rel.target)!.push(p);\n }\n }\n }\n\n const stages: Stage[] = [];\n let queue = candidatePaths.filter((p) => inDegree.get(p) === 0);\n let stageNum = 1;\n const processed = new Set<string>();\n\n while (queue.length > 0) {\n stages.push({\n stage: stageNum,\n parallel: queue.length > 1,\n nodes: [...queue],\n });\n\n const nextQueue: string[] = [];\n for (const nodePath of queue) {\n processed.add(nodePath);\n for (const dep of dependents.get(nodePath) ?? []) {\n inDegree.set(dep, (inDegree.get(dep) ?? 0) - 1);\n if (inDegree.get(dep) === 0) {\n nextQueue.push(dep);\n }\n }\n }\n\n queue = nextQueue;\n stageNum++;\n }\n\n if (processed.size < candidatePaths.length) {\n const cycleNodes = candidatePaths.filter((p) => !processed.has(p));\n throw new Error(`Circular dependency detected involving: ${cycleNodes.join(', ')}`);\n }\n\n return stages;\n}\n","import { Command } from 'commander';\nimport { loadGraph } from '../core/graph-loader.js';\nimport { formatDependencyTree } from '../core/dependency-resolver.js';\n\nexport function registerDepsCommand(program: Command): void {\n program\n .command('deps')\n .description('Show direct and transitive node dependencies')\n .requiredOption('--node <path>', 'Node path relative to .yggdrasil/model/')\n .option('--depth <n>', 'Maximum depth for tree (when using --node)', (v) => parseInt(v, 10))\n .option('--type <type>', 'Relation type filter: structural, event, all (default: all)', 'all')\n .action(async (options: { node: string; depth?: number; type?: string }) => {\n try {\n const graph = await loadGraph(process.cwd());\n const typeFilter =\n options.type === 'structural' || options.type === 'event' || options.type === 'all'\n ? options.type\n : 'all';\n const nodePath = options.node.trim().replace(/^\\.\\//, '').replace(/\\/+$/, '');\n const text = formatDependencyTree(graph, nodePath, {\n depth: options.depth,\n relationType: typeFilter,\n });\n process.stdout.write(text + '\\n');\n } catch (error) {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n process.exit(1);\n }\n });\n}\n","import { mkdtemp, rm } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport path from 'node:path';\nimport { execSync } from 'node:child_process';\nimport { loadGraph } from './graph-loader.js';\nimport type { Graph } from '../model/types.js';\n\n/**\n * Load graph from a git ref (e.g. HEAD) by extracting .yggdrasil to temp dir.\n * Returns null if not a git repo, ref doesn't exist, or .yggdrasil not in ref.\n */\nexport async function loadGraphFromRef(\n projectRoot: string,\n ref: string = 'HEAD',\n): Promise<Graph | null> {\n const yggPath = '.yggdrasil';\n let tmpDir: string | null = null;\n\n try {\n execSync(`git rev-parse ${ref}`, { cwd: projectRoot, stdio: 'pipe' });\n } catch {\n return null;\n }\n\n try {\n tmpDir = await mkdtemp(path.join(tmpdir(), 'ygg-git-'));\n const archivePath = path.join(tmpDir, 'archive.tar');\n execSync(`git archive ${ref} ${yggPath} -o \"${archivePath}\"`, {\n cwd: projectRoot,\n stdio: 'pipe',\n });\n execSync(`tar -xf \"${archivePath}\" -C \"${tmpDir}\"`, { stdio: 'pipe' });\n const graph = await loadGraph(tmpDir);\n return graph;\n } catch {\n return null;\n } finally {\n if (tmpDir) {\n await rm(tmpDir, { recursive: true, force: true });\n }\n }\n}\n","import { Command } from 'commander';\nimport { loadGraph } from '../core/graph-loader.js';\nimport { loadGraphFromRef } from '../core/graph-from-git.js';\nimport {\n buildContext,\n collectAncestors,\n collectEffectiveAspectIds,\n} from '../core/context-builder.js';\nimport { detectDrift } from '../core/drift-detector.js';\nimport type { Graph } from '../model/types.js';\n\nconst STRUCTURAL_TYPES = new Set(['uses', 'calls', 'extends', 'implements']);\n\nexport function collectReverseDependents(\n graph: Graph,\n targetNode: string,\n): {\n direct: string[];\n allDependents: string[];\n reverse: Map<string, Set<string>>;\n relationFrom: Map<string, { type: string; consumes?: string[] }>;\n} {\n const reverse = new Map<string, Set<string>>();\n const relationFrom = new Map<string, { type: string; consumes?: string[] }>();\n for (const [nodePath, node] of graph.nodes) {\n for (const rel of node.meta.relations ?? []) {\n if (!STRUCTURAL_TYPES.has(rel.type)) continue;\n const deps = reverse.get(rel.target) ?? new Set<string>();\n deps.add(nodePath);\n reverse.set(rel.target, deps);\n relationFrom.set(`${nodePath}->${rel.target}`, {\n type: rel.type,\n consumes: rel.consumes,\n });\n }\n }\n\n const direct = [...(reverse.get(targetNode) ?? [])].sort();\n const seen = new Set<string>(direct);\n const queue = [...direct];\n while (queue.length > 0) {\n const current = queue.shift()!;\n for (const next of reverse.get(current) ?? []) {\n if (seen.has(next)) continue;\n seen.add(next);\n queue.push(next);\n }\n }\n\n return {\n direct,\n allDependents: [...seen].sort(),\n reverse,\n relationFrom,\n };\n}\n\nexport function buildTransitiveChains(\n targetNode: string,\n direct: string[],\n allDependents: string[],\n reverse: Map<string, Set<string>>,\n): string[] {\n const directSet = new Set(direct);\n const transitiveOnly = allDependents.filter((t) => !directSet.has(t));\n if (transitiveOnly.length === 0) return [];\n\n const parent = new Map<string, string>();\n const queue: string[] = [targetNode];\n const visited = new Set<string>([targetNode]);\n while (queue.length > 0) {\n const current = queue.shift()!;\n for (const next of reverse.get(current) ?? []) {\n if (visited.has(next)) continue;\n visited.add(next);\n parent.set(next, current);\n queue.push(next);\n }\n }\n\n const chains: string[] = [];\n for (const node of transitiveOnly) {\n const path: string[] = [];\n let current: string | undefined = node;\n while (current) {\n path.unshift(current);\n current = parent.get(current);\n }\n if (path.length >= 3) {\n chains.push(path.slice(1).map((p) => `<- ${p}`).join(' '));\n }\n }\n return chains.sort();\n}\n\nexport function collectDescendants(graph: Graph, nodePath: string): string[] {\n const node = graph.nodes.get(nodePath);\n if (!node) return [];\n const result: string[] = [];\n const stack = [...node.children];\n while (stack.length > 0) {\n const child = stack.pop()!;\n result.push(child.path);\n stack.push(...child.children);\n }\n return result.sort();\n}\n\nasync function runSimulation(\n graph: Graph,\n nodePaths: Iterable<string>,\n targetNodePath: string | null,\n): Promise<void> {\n const budget = graph.config.quality?.context_budget ?? { warning: 10000, error: 20000 };\n process.stdout.write('\\nChanges in context packages:\\n\\n');\n const baselineGraph = await loadGraphFromRef(process.cwd(), 'HEAD');\n const driftReport = await detectDrift(graph);\n const driftByNode = new Map(driftReport.entries.map((e) => [e.nodePath, e]));\n\n for (const dep of nodePaths) {\n try {\n const pkg = await buildContext(graph, dep);\n const status =\n pkg.tokenCount >= budget.error\n ? 'error'\n : pkg.tokenCount >= budget.warning\n ? 'warning'\n : 'ok';\n\n let baselineTokens: number | null = null;\n if (baselineGraph?.nodes.has(dep)) {\n try {\n const baselinePkg = await buildContext(baselineGraph, dep);\n baselineTokens = baselinePkg.tokenCount;\n } catch {\n /* ignore */\n }\n }\n\n const hasDepOnTarget =\n targetNodePath &&\n graph.nodes\n .get(dep)\n ?.meta.relations?.some(\n (r) => r.target === targetNodePath && STRUCTURAL_TYPES.has(r.type),\n );\n const changedLine = hasDepOnTarget\n ? ` + Changed dependency interface: ${targetNodePath}\\n`\n : '';\n\n const budgetLine =\n baselineTokens !== null\n ? ` Budget: ${baselineTokens} -> ${pkg.tokenCount} tokens (${status})\\n`\n : ` Budget: ${pkg.tokenCount} tokens (${status})\\n`;\n\n const driftEntry = driftByNode.get(dep);\n const driftLine =\n driftEntry && driftEntry.status !== 'ok'\n ? ` Mapped files (on-disk): ${driftEntry.status}${driftEntry.details ? ` (${driftEntry.details})` : ''}\\n`\n : driftEntry\n ? ` Mapped files (on-disk): ok\\n`\n : '';\n\n process.stdout.write(`${dep}:\\n${changedLine}${budgetLine}${driftLine}\\n`);\n } catch {\n process.stdout.write(`${dep}:\\n failed to build context\\n\\n`);\n }\n }\n}\n\nasync function handleAspectImpact(\n graph: Graph,\n aspectId: string,\n simulate?: boolean,\n): Promise<void> {\n const aspect = graph.aspects.find((a) => a.id === aspectId);\n if (!aspect) {\n process.stderr.write(`Aspect not found: ${aspectId}\\n`);\n process.exit(1);\n }\n\n const affected: Array<{ path: string; source: string }> = [];\n for (const [nodePath] of graph.nodes) {\n const effective = collectEffectiveAspectIds(graph, nodePath);\n if (effective.has(aspectId)) {\n const node = graph.nodes.get(nodePath)!;\n const ownAspectIds = new Set((node.meta.aspects ?? []).map(a => a.aspect));\n if (ownAspectIds.has(aspectId)) {\n affected.push({ path: nodePath, source: 'own' });\n } else {\n let fromHierarchy = false;\n let anc = node.parent;\n while (anc) {\n if ((anc.meta.aspects ?? []).some(a => a.aspect === aspectId)) {\n fromHierarchy = true;\n break;\n }\n anc = anc.parent;\n }\n if (fromHierarchy) {\n affected.push({ path: nodePath, source: `hierarchy from ${anc!.path}` });\n } else {\n const ancestorPaths = new Set([nodePath, ...collectAncestors(node).map((a) => a.path)]);\n const flow = graph.flows.find(\n (f) =>\n (f.aspects ?? []).includes(aspectId) &&\n f.nodes.some((n) => ancestorPaths.has(n)),\n );\n affected.push({ path: nodePath, source: flow ? `flow: ${flow.name}` : 'implied' });\n }\n }\n }\n }\n\n affected.sort((a, b) => a.path.localeCompare(b.path));\n\n const propagatingFlows = graph.flows\n .filter((f) => (f.aspects ?? []).includes(aspectId))\n .map((f) => f.name);\n\n const impliedBy = graph.aspects\n .filter((a) => (a.implies ?? []).includes(aspectId))\n .map((a) => a.id);\n const implies = aspect.implies ?? [];\n\n process.stdout.write(`Impact of changes in aspect ${aspectId}:\\n\\n`);\n process.stdout.write(`Affected nodes (${affected.length}):\\n`);\n if (affected.length === 0) {\n process.stdout.write(' (none)\\n');\n } else {\n for (const { path: p, source } of affected) {\n process.stdout.write(` ${p} (${source})\\n`);\n }\n }\n process.stdout.write(\n `\\nFlows propagating this aspect: ${propagatingFlows.length > 0 ? propagatingFlows.join(', ') : '(none)'}\\n`,\n );\n process.stdout.write(`Implied by: ${impliedBy.length > 0 ? impliedBy.join(', ') : '(none)'}\\n`);\n process.stdout.write(`Implies: ${implies.length > 0 ? implies.join(', ') : '(none)'}\\n`);\n process.stdout.write(`\\nTotal scope: ${affected.length} nodes, ${propagatingFlows.length} flows\\n`);\n\n if (simulate && affected.length > 0) {\n await runSimulation(\n graph,\n affected.map((a) => a.path),\n null,\n );\n }\n}\n\nasync function handleFlowImpact(\n graph: Graph,\n flowName: string,\n simulate?: boolean,\n): Promise<void> {\n const flow = graph.flows.find((f) => f.name === flowName || f.path === flowName);\n if (!flow) {\n process.stderr.write(`Flow not found: ${flowName}\\n`);\n process.exit(1);\n }\n\n const participants = new Set<string>();\n for (const nodePath of flow.nodes) {\n if (graph.nodes.has(nodePath)) {\n participants.add(nodePath);\n for (const desc of collectDescendants(graph, nodePath)) {\n participants.add(desc);\n }\n }\n }\n\n const sorted = [...participants].sort();\n const flowAspects = flow.aspects ?? [];\n\n process.stdout.write(`Impact of changes in flow ${flow.name}:\\n\\n`);\n process.stdout.write('Participants:\\n');\n if (sorted.length === 0) {\n process.stdout.write(' (none)\\n');\n } else {\n for (const p of sorted) {\n const isDeclared = flow.nodes.includes(p);\n const suffix = isDeclared ? '' : ' (descendant)';\n process.stdout.write(` ${p}${suffix}\\n`);\n }\n }\n process.stdout.write(\n `\\nFlow aspects: ${flowAspects.length > 0 ? flowAspects.join(', ') : '(none)'}\\n`,\n );\n process.stdout.write(`\\nTotal scope: ${sorted.length} nodes\\n`);\n\n if (simulate && sorted.length > 0) {\n await runSimulation(graph, sorted, null);\n }\n}\n\nexport function registerImpactCommand(program: Command): void {\n program\n .command('impact')\n .description('Show reverse dependency impact for a node, aspect, or flow')\n .option('--node <path>', 'Node path relative to .yggdrasil/model/')\n .option('--aspect <id>', 'Aspect id (directory path under aspects/)')\n .option('--flow <name>', 'Flow name (directory name under flows/)')\n .option('--method <name>', 'Filter impact to dependents consuming a specific method (requires --node)')\n .option('--simulate', 'Simulate context package impact (compare HEAD vs current)')\n .action(\n async (options: { node?: string; aspect?: string; flow?: string; method?: string; simulate?: boolean }) => {\n try {\n const modeCount = [options.node, options.aspect, options.flow].filter(Boolean).length;\n if (modeCount === 0) {\n process.stderr.write(\n 'Error: one of --node, --aspect, or --flow is required\\n',\n );\n process.exit(1);\n }\n if (modeCount > 1) {\n process.stderr.write(\n 'Error: --node, --aspect, and --flow are mutually exclusive\\n',\n );\n process.exit(1);\n }\n\n const graph = await loadGraph(process.cwd());\n\n if (options.aspect) {\n await handleAspectImpact(graph, options.aspect.trim(), options.simulate);\n return;\n }\n if (options.flow) {\n await handleFlowImpact(graph, options.flow.trim(), options.simulate);\n return;\n }\n\n const nodePath = options.node!.trim().replace(/^\\.\\//, '').replace(/\\/+$/, '');\n\n if (!graph.nodes.has(nodePath)) {\n process.stderr.write(`Node not found: ${nodePath}\\n`);\n process.exit(1);\n }\n\n if (options.method && !options.node) {\n process.stderr.write('Error: --method requires --node\\n');\n process.exit(1);\n }\n\n const { direct, allDependents, reverse, relationFrom } = collectReverseDependents(\n graph,\n nodePath,\n );\n\n // When --method is specified, filter to only dependents consuming that method\n const methodFilter = options.method?.trim();\n let filteredDirect = direct;\n let filteredAllDependents = allDependents;\n if (methodFilter) {\n filteredDirect = direct.filter((dep) => {\n const rel = relationFrom.get(`${dep}->${nodePath}`);\n return rel?.consumes?.includes(methodFilter) || !rel?.consumes?.length;\n });\n // Rebuild transitive from filtered direct\n const filteredSet = new Set(filteredDirect);\n filteredAllDependents = allDependents.filter((dep) => filteredSet.has(dep));\n }\n\n const chains = buildTransitiveChains(nodePath, filteredDirect, filteredAllDependents, reverse);\n\n // Collect event-based dependents (emits/listens)\n const eventDependents: Array<{ path: string; type: string; eventName: string }> = [];\n for (const [np, n] of graph.nodes) {\n for (const rel of n.meta.relations ?? []) {\n if (rel.target === nodePath && (rel.type === 'emits' || rel.type === 'listens')) {\n eventDependents.push({\n path: np,\n type: rel.type,\n eventName: rel.event_name ?? n.meta.name,\n });\n }\n }\n }\n // Also check if the target node emits events and find listeners\n const targetNode = graph.nodes.get(nodePath)!;\n for (const rel of targetNode.meta.relations ?? []) {\n if (rel.type === 'emits') {\n const eventName = rel.event_name ?? rel.target;\n // Find listeners for this event target\n for (const [np, n] of graph.nodes) {\n if (np === nodePath) continue;\n for (const r of n.meta.relations ?? []) {\n if (r.type === 'listens' && r.target === rel.target) {\n eventDependents.push({\n path: np,\n type: 'listens',\n eventName: r.event_name ?? eventName,\n });\n }\n }\n }\n }\n }\n\n const flows: string[] = [];\n for (const flow of graph.flows) {\n if (flow.nodes.includes(nodePath)) {\n flows.push(flow.name);\n }\n }\n\n const targetEffective = collectEffectiveAspectIds(graph, nodePath);\n const aspectsInScope: string[] = [];\n for (const aspect of graph.aspects) {\n if (targetEffective.has(aspect.id)) {\n aspectsInScope.push(aspect.name);\n }\n }\n\n const methodLabel = methodFilter ? ` (method: ${methodFilter})` : '';\n process.stdout.write(`Impact of changes in ${nodePath}${methodLabel}:\\n\\n`);\n process.stdout.write('Directly dependent:\\n');\n if (filteredDirect.length === 0) {\n process.stdout.write(' (none)\\n');\n } else {\n for (const dep of filteredDirect) {\n const rel = relationFrom.get(`${dep}->${nodePath}`);\n const annot = rel?.consumes?.length\n ? ` (${rel.type}, consumes: ${rel.consumes.join(', ')})`\n : rel\n ? ` (${rel.type})`\n : '';\n process.stdout.write(` <- ${dep}${annot}\\n`);\n }\n }\n\n if (eventDependents.length > 0 && !methodFilter) {\n process.stdout.write('\\nEvent-connected:\\n');\n for (const { path: p, type, eventName } of eventDependents.sort((a, b) => a.path.localeCompare(b.path))) {\n process.stdout.write(` ${p} (${type}: ${eventName})\\n`);\n }\n }\n process.stdout.write('\\nTransitively dependent:\\n');\n if (chains.length === 0) {\n process.stdout.write(' (none)\\n');\n } else {\n for (const chain of chains) {\n process.stdout.write(` ${chain}\\n`);\n }\n }\n\n const descendants = collectDescendants(graph, nodePath);\n if (descendants.length > 0) {\n process.stdout.write('\\nDescendants (hierarchy impact):\\n');\n for (const desc of descendants) {\n process.stdout.write(` ${desc}\\n`);\n }\n }\n\n process.stdout.write(\n `\\nFlows: ${flows.length > 0 ? flows.join(', ') : '(none)'}\\n`,\n );\n process.stdout.write(\n `Aspects (scope covers node): ${aspectsInScope.length > 0 ? aspectsInScope.join(', ') : '(none)'}\\n`,\n );\n\n const coAspectNodes: Array<{ path: string; shared: string[] }> = [];\n if (targetEffective.size > 0) {\n for (const [p] of graph.nodes) {\n if (p === nodePath) continue;\n const nodeEffective = collectEffectiveAspectIds(graph, p);\n const shared = [...targetEffective].filter((id) => nodeEffective.has(id));\n if (shared.length > 0) {\n coAspectNodes.push({ path: p, shared });\n }\n }\n }\n if (coAspectNodes.length > 0) {\n process.stdout.write('Nodes sharing aspects:\\n');\n for (const { path: p, shared } of coAspectNodes.sort((a, b) =>\n a.path.localeCompare(b.path),\n )) {\n process.stdout.write(` ${p} (${shared.join(', ')})\\n`);\n }\n }\n\n const allAffected = new Set([...filteredAllDependents, ...descendants, ...eventDependents.map((e) => e.path)]);\n process.stdout.write(\n `\\nTotal scope: ${allAffected.size} nodes, ${flows.length} flows, ${aspectsInScope.length} aspects\\n`,\n );\n\n if (options.simulate && allAffected.size > 0) {\n await runSimulation(graph, allAffected, nodePath);\n }\n } catch (error) {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n process.exit(1);\n }\n },\n );\n}\n","import { Command } from 'commander';\nimport { stringify as yamlStringify } from 'yaml';\nimport { loadGraph } from '../core/graph-loader.js';\nimport { findYggRoot } from '../utils/paths.js';\n\nexport function registerAspectsCommand(program: Command): void {\n program\n .command('aspects')\n .description('List aspects with metadata (YAML output)')\n .action(async () => {\n try {\n const yggRoot = await findYggRoot(process.cwd());\n const graph = await loadGraph(yggRoot);\n const output = graph.aspects\n .sort((a, b) => a.id.localeCompare(b.id))\n .map((aspect) => {\n const entry: Record<string, unknown> = { id: aspect.id, name: aspect.name };\n if (aspect.description) entry.description = aspect.description;\n if (aspect.implies && aspect.implies.length > 0) entry.implies = aspect.implies;\n if (aspect.stability) entry.stability = aspect.stability;\n return entry;\n });\n process.stdout.write(yamlStringify(output));\n } catch (error) {\n const err = error as NodeJS.ErrnoException;\n if (err.code === 'ENOENT') {\n process.stderr.write(\n `Error: No .yggdrasil/ directory found. Run 'yg init' first.\\n`,\n );\n } else {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n }\n process.exit(1);\n }\n });\n}\n","import { Command } from 'commander';\nimport { stringify as yamlStringify } from 'yaml';\nimport { loadGraph } from '../core/graph-loader.js';\nimport { findYggRoot } from '../utils/paths.js';\n\nexport function registerFlowsCommand(program: Command): void {\n program\n .command('flows')\n .description('List flows with metadata (YAML output)')\n .action(async () => {\n try {\n const yggRoot = await findYggRoot(process.cwd());\n const graph = await loadGraph(yggRoot);\n const output = graph.flows\n .sort((a, b) => a.name.localeCompare(b.name))\n .map((flow) => {\n const entry: Record<string, unknown> = {\n name: flow.name,\n participants: flow.nodes.length,\n nodes: flow.nodes.sort(),\n };\n if (flow.aspects && flow.aspects.length > 0) entry.aspects = flow.aspects;\n return entry;\n });\n process.stdout.write(yamlStringify(output));\n } catch (error) {\n const err = error as NodeJS.ErrnoException;\n if (err.code === 'ENOENT') {\n process.stderr.write(\n `Error: No .yggdrasil/ directory found. Run 'yg init' first.\\n`,\n );\n } else {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n }\n process.exit(1);\n }\n });\n}\n","import { Command } from 'commander';\nimport { loadGraph } from '../core/graph-loader.js';\nimport { detectDrift } from '../core/drift-detector.js';\nimport { validate } from '../core/validator.js';\nimport { normalizeMappingPaths } from '../utils/paths.js';\n\nexport function registerPreflightCommand(program: Command): void {\n program\n .command('preflight')\n .description('Unified diagnostic report: drift, status, validation')\n .option('--quick', 'Skip drift detection for faster results')\n .action(async (options: { quick?: boolean }) => {\n try {\n const cwd = process.cwd();\n const graph = await loadGraph(cwd);\n\n // --- Drift ---\n const driftedEntries = options.quick\n ? []\n : (await detectDrift(graph)).entries.filter((e) => e.status !== 'ok');\n\n // --- Status counts ---\n const nodeCount = graph.nodes.size;\n const aspectCount = graph.aspects.length;\n const flowCount = graph.flows.length;\n let mappedPathCount = 0;\n for (const node of graph.nodes.values()) {\n mappedPathCount += normalizeMappingPaths(node.meta.mapping).length;\n }\n\n // --- Validation ---\n const validation = await validate(graph, 'all');\n const errors = validation.issues.filter((i) => i.severity === 'error');\n const warnings = validation.issues.filter((i) => i.severity === 'warning');\n\n // --- Build output ---\n const lines: string[] = [];\n lines.push('=== Preflight Report ===');\n lines.push('');\n\n // Drift section\n if (options.quick) {\n lines.push('Drift: skipped (--quick)');\n } else if (driftedEntries.length === 0) {\n lines.push('Drift: clean');\n } else {\n lines.push(`Drift: ${driftedEntries.length} nodes need attention`);\n for (const entry of driftedEntries) {\n lines.push(` - ${entry.nodePath}: ${entry.status}`);\n }\n }\n lines.push('');\n\n // Status section\n lines.push(\n `Status: ${nodeCount} nodes, ${aspectCount} aspects, ${flowCount} flows, ${mappedPathCount} mapped paths`,\n );\n if (nodeCount === 0) {\n lines.push('');\n lines.push(' ⚡ No nodes found. Enter BOOTSTRAP MODE:');\n lines.push(' Create nodes under .yggdrasil/model/ for your active work area.');\n lines.push(' See: yg help build-context');\n }\n lines.push('');\n\n // Validation section\n if (errors.length === 0 && warnings.length === 0) {\n lines.push('Validation: clean');\n } else {\n const parts: string[] = [];\n if (errors.length > 0) parts.push(`${errors.length} errors`);\n if (warnings.length > 0) parts.push(`${warnings.length} warnings`);\n lines.push(`Validation: ${parts.join(', ')}`);\n for (const issue of [...errors, ...warnings]) {\n const code = issue.code ? `[${issue.code}] ` : '';\n const loc = issue.nodePath ? `${issue.nodePath} -> ` : '';\n lines.push(` - ${code}${loc}${issue.message}`);\n }\n }\n lines.push('');\n\n process.stdout.write(lines.join('\\n'));\n\n // Exit code: 1 if drift or validation errors exist.\n // Warnings alone do not cause exit 1.\n const hasIssues = (!options.quick && driftedEntries.length > 0) || errors.length > 0;\n process.exit(hasIssues ? 1 : 0);\n } catch (error) {\n process.stderr.write(`Error: ${(error as Error).message}\\n`);\n process.exit(1);\n }\n });\n}\n"],"mappings":";;;AACA,SAAS,eAAe;;;ACAxB,SAAS,SAAAA,QAAO,aAAAC,YAAW,WAAAC,UAAS,YAAAC,WAAU,QAAAC,aAAY;AAC1D,OAAOC,WAAU;AACjB,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAC7B,SAAS,MAAAC,KAAI,SAAAC,cAAa;;;ACLnB,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACA9B,SAAS,UAAU,WAAW,aAAa;AAC3C,OAAO,UAAU;;;ACUjB,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA6ItB,IAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2JnB,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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","names":["mkdir","writeFile","readdir","readFile","stat","path","gt","valid","readFile","path","readFile","writeFile","path","parseYaml","path","pkg","mkdir","readdir","readFile","writeFile","program","stat","valid","gt","rulesPath","readdir","readFile","path","readFile","parseYaml","readFile","parseYaml","readFile","parseYaml","readFile","readdir","path","readFile","parseYaml","readFile","path","parseYaml","readFile","parseYaml","path","readFile","path","parseYaml","path","fileURLToPath","stat","path","stat","path","path","path","readdir","readFile","readFile","path","path","readFile","readdir","readFile","stat","path","path","access","readdir","stat","readFile","pkg","pkg","program","pkg","program","chalk","readFile","writeFile","stat","readdir","mkdir","rm","path","state","readFile","readdir","stat","path","require","readFile","path","path","stat","readFile","readdir","path","STRUCTURAL_RELATION_TYPES","path","collectParticipatingFlows","access","path","program","chalk","chalk","program","chalk","program","program","path","path","access","program","path","access","path","STRUCTURAL_RELATION_TYPES","EVENT_RELATION_TYPES","STRUCTURAL_RELATION_TYPES","EVENT_RELATION_TYPES","program","rm","path","execSync","execSync","path","rm","path","pkg","program","program","yamlStringify","program","yamlStringify","program","readFileSync","fileURLToPath"]}