Migrate all repos into monorepo context folders

Bahn: aisupport, Analyse-O2C-C2S, awesome-bahn-mcp-servers, beam-mcp,
      Confluence_Bot, db-planet-mcp-server, O2C-Harness, project-audit,
      Projekt-KIQ-HP, teamlandkarte-mcp
Dhive: Jury-Voting
Privat: CV, NoteGraph (NOTE: NoteGraph needs complete redo after consolidation)
Shared: AI-Orchestrator, OrgMyLife, power_skills_and_more
Shared/references: symphony (read-only)

Bahn repos remain available as independent remotes - this monorepo
pulls them in via subtree, the originals are untouched.
This commit is contained in:
2026-06-30 20:39:52 +02:00
parent 2f2b295531
commit a5f8fb49ab
1717 changed files with 447332 additions and 0 deletions
+125
View File
@@ -0,0 +1,125 @@
/**
* Entity file management functions for the knowledge base.
*
* Maps entity types to directory paths, reads/writes/lists/deletes entity YAML files.
* Uses fs/promises for all file operations.
*/
import { readFile, writeFile, readdir, unlink, access, mkdir } from 'node:fs/promises';
import { join } from 'node:path';
import type { Entity, EntityType } from '../schemas/types';
import { serializeEntity, deserializeEntity } from './yaml-utils';
import { validateEntity } from '../schemas/validate';
/**
* Maps entity types to their kb/ subdirectory names.
*/
const ENTITY_TYPE_DIRS: Record<EntityType, string> = {
person: 'profiles',
experience: 'experiences',
skill: 'skills',
organization: 'organizations',
project: 'projects',
certification: 'certifications',
tandem: 'tandems',
};
/**
* Returns the directory path for a given entity type.
*/
export function getEntityDir(type: EntityType, basePath: string = process.cwd()): string {
const dir = ENTITY_TYPE_DIRS[type];
return join(basePath, 'kb', dir);
}
/**
* Constructs the full file path for an entity given its type and ID.
*/
export function getEntityPath(type: EntityType, id: string, basePath: string = process.cwd()): string {
return join(getEntityDir(type, basePath), `${id}.yaml`);
}
/**
* Reads an entity from its YAML file.
* Throws a descriptive error if the file is not found.
*/
export async function readEntity(type: EntityType, id: string, basePath: string = process.cwd()): Promise<Entity> {
const filePath = getEntityPath(type, id, basePath);
let content: string;
try {
content = await readFile(filePath, 'utf-8');
} catch (err: unknown) {
if (err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'ENOENT') {
throw new Error(`Entity not found: ${type} "${id}" (expected at ${filePath})`);
}
throw err;
}
return deserializeEntity(content);
}
/**
* Writes an entity to its YAML file.
* Validates the entity before writing; rejects invalid entities with validation errors.
*/
export async function writeEntity(entity: Entity, basePath: string = process.cwd()): Promise<void> {
const result = validateEntity(entity);
if (!result.valid) {
throw new Error(`Validation failed for entity "${entity.id}": ${result.errors.join('; ')}`);
}
const filePath = getEntityPath(entity.type, entity.id, basePath);
const dir = getEntityDir(entity.type, basePath);
await mkdir(dir, { recursive: true });
const yaml = serializeEntity(entity);
await writeFile(filePath, yaml, 'utf-8');
}
/**
* Lists all entity IDs in a given type directory.
* Returns an array of entity IDs (file names without .yaml extension).
*/
export async function listEntities(type: EntityType, basePath: string = process.cwd()): Promise<string[]> {
const dir = getEntityDir(type, basePath);
let files: string[];
try {
files = await readdir(dir);
} catch (err: unknown) {
if (err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'ENOENT') {
return [];
}
throw err;
}
return files
.filter((f) => f.endsWith('.yaml'))
.map((f) => f.replace(/\.yaml$/, ''));
}
/**
* Deletes an entity file.
* Throws a descriptive error if the file is not found.
*/
export async function deleteEntity(type: EntityType, id: string, basePath: string = process.cwd()): Promise<void> {
const filePath = getEntityPath(type, id, basePath);
try {
await unlink(filePath);
} catch (err: unknown) {
if (err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'ENOENT') {
throw new Error(`Entity not found: ${type} "${id}" (expected at ${filePath})`);
}
throw err;
}
}
/**
* Checks if an entity file exists.
*/
export async function entityExists(type: EntityType, id: string, basePath: string = process.cwd()): Promise<boolean> {
const filePath = getEntityPath(type, id, basePath);
try {
await access(filePath);
return true;
} catch {
return false;
}
}