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
+129
View File
@@ -0,0 +1,129 @@
import { describe, it, expect } from 'vitest';
import fc from 'fast-check';
import { generateIntroduction } from './intro-generator';
import type { EventContext, IntroductionInput } from './intro-generator';
import type { Person, Skill, Experience, SkillCategory, SkillLevel } from '../schemas/types';
// --- Arbitraries ---
const kebabCaseId = fc
.array(
fc.stringMatching(/^[a-z0-9]{1,8}$/),
{ minLength: 1, maxLength: 4 }
)
.map(parts => parts.join('-'));
const isoDate = fc
.record({
year: fc.integer({ min: 1990, max: 2030 }),
month: fc.integer({ min: 1, max: 12 }),
})
.map(({ year, month }) => `${year}-${String(month).padStart(2, '0')}`);
const skillCategory: fc.Arbitrary<SkillCategory> = fc.constantFrom(
'programming-language',
'framework',
'methodology',
'soft-skill',
'domain'
);
const skillLevel: fc.Arbitrary<SkillLevel> = fc.constantFrom(
'beginner',
'intermediate',
'advanced',
'expert'
);
const eventContext: fc.Arbitrary<EventContext> = fc.constantFrom(
'technical',
'business',
'academic'
);
const skillArb: fc.Arbitrary<Skill> = fc.record({
id: kebabCaseId,
type: fc.constant('skill' as const),
created: isoDate,
modified: isoDate,
name: fc.string({ minLength: 2, maxLength: 30 }).filter(s => s.trim().length > 0),
category: skillCategory,
level: skillLevel,
years: fc.option(fc.integer({ min: 1, max: 20 }), { nil: undefined }),
}).map(fields => fields as Skill);
const experienceArb: fc.Arbitrary<Experience> = fc.record({
id: kebabCaseId,
type: fc.constant('experience' as const),
created: isoDate,
modified: isoDate,
title: fc.string({ minLength: 3, maxLength: 40 }).filter(s => s.trim().length > 0),
organization: fc.string({ minLength: 2, maxLength: 30 }).filter(s => s.trim().length > 0),
start: isoDate,
end: fc.option(isoDate, { nil: null }),
description: fc.option(fc.string({ minLength: 10, maxLength: 100 }), { nil: undefined }),
achievements: fc.option(
fc.array(fc.string({ minLength: 5, maxLength: 60 }).filter(s => s.trim().length > 0), { minLength: 1, maxLength: 3 }),
{ nil: undefined }
),
}).map(fields => fields as Experience);
const personArb: fc.Arbitrary<Person> = fc.record({
id: kebabCaseId,
type: fc.constant('person' as const),
created: isoDate,
modified: isoDate,
name: fc.record({
first: fc.string({ minLength: 2, maxLength: 15 }).filter(s => s.trim().length > 0),
last: fc.string({ minLength: 2, maxLength: 15 }).filter(s => s.trim().length > 0),
display: fc.string({ minLength: 4, maxLength: 30 }).filter(s => s.trim().length > 0),
}),
education: fc.option(
fc.array(fc.record({
institution: fc.string({ minLength: 3, maxLength: 30 }).filter(s => s.trim().length > 0),
degree: fc.string({ minLength: 2, maxLength: 20 }).filter(s => s.trim().length > 0),
field: fc.string({ minLength: 2, maxLength: 20 }).filter(s => s.trim().length > 0),
start: isoDate,
end: isoDate,
}), { minLength: 1, maxLength: 2 }),
{ nil: undefined }
),
}).map(fields => fields as Person);
const topicArb = fc.string({ minLength: 3, maxLength: 50 }).filter(s => s.trim().length > 0);
/** Generates a complete IntroductionInput with at least 1 skill and 1 experience */
const introductionInputArb: fc.Arbitrary<IntroductionInput> = fc.record({
person: personArb,
topic: topicArb,
eventContext: eventContext,
relevantSkills: fc.array(skillArb, { minLength: 1, maxLength: 5 }),
relevantExperiences: fc.array(experienceArb, { minLength: 1, maxLength: 4 }),
});
// --- Property 12: Introduction length variants (short < medium < long) ---
describe('Property 12: Introduction length variants', () => {
it('produces exactly three variants where short.length < medium.length < long.length', () => {
fc.assert(
fc.property(introductionInputArb, (input) => {
const result = generateIntroduction(input);
// Verify exactly three variants exist
expect(result).toHaveProperty('short');
expect(result).toHaveProperty('medium');
expect(result).toHaveProperty('long');
// Verify character count ordering: short < medium < long
expect(result.short.length).toBeGreaterThan(0);
expect(result.medium.length).toBeGreaterThan(result.short.length);
expect(result.long.length).toBeGreaterThan(result.medium.length);
}),
{ numRuns: 100 }
);
});
/**
* Validates: Requirements 6.2
*/
});