feat: implement knowledge management system (spec complete, all 53 tasks done)

This commit is contained in:
2026-07-01 14:14:16 +02:00
parent e4256d3222
commit 8ac664d33d
89 changed files with 19759 additions and 72 deletions
@@ -0,0 +1 @@
{"specId": "5c8d60f3-e66e-42d4-adb6-818992d7e37a", "workflowType": "requirements-first", "specType": "feature"}
@@ -0,0 +1,114 @@
# Knowledge Management System Briefing for New Spec Chat
## What We Want
A unified personal knowledge management system integrated into the monorepo structure. It replaces the old NoteGraph app and builds on top of the existing monorepo knowledge store infrastructure.
**Core idea:** Organize, document, and work with notes (markdown, pictures, emails, chats) and additional context (links, Confluence, Jira, Git repos) across all three work contexts (bahn, dhive, privat).
## Current State
### What Exists
1. **Monorepo structure** (`bahn/`, `dhive/`, `privat/`, `shared/`)
2. **Knowledge store tooling** in `shared/tools/monorepo-cli/src/monorepo/knowledge/`:
- `store.py` KnowledgeStore with ETL pipeline, YAML index, search
- `artifact.py` Artifact model with YAML frontmatter
- `etl.py` ETL pipeline with incremental processing (content-hash based)
- `index.py` YAML index with progressive disclosure
- `sources/markdown.py` Markdown source strategy
- `migration.py` NoteGraphMigrator (stub)
3. **NoteGraph ingestion pipeline** in `privat/NoteGraph/ingestion/` (partially built):
- CLI import + watcher
- OCR extraction (images, PDFs)
- LLM-powered enrichment (entity detection, wiki-links)
- Folder routing (meetings, projects, inbox, decisions)
- OrgMyLife task creation from action items
4. **NoteGraph notes structure** in `privat/NoteGraph/notes/`:
- `decisions/`, `inbox/`, `meetings/`, `people/`, `projects/`, `templates/`
5. **Context bridge** (`shared/tools/monorepo-cli/src/monorepo/bridge.py`) for cross-context sharing
6. **Wissensdatenbank** in `bahn/wissensdatenbank/` the ETL pipeline for DB InfraGO knowledge (Confluence, web, PDFs → processed markdown)
### What Doesn't Work
- The NoteGraph app (SilverBullet-based) is not working as a daily driver
- No unified way to capture and organize notes across all 3 contexts
- No integration between the ingestion pipeline and the monorepo knowledge store
- No way to consume Jira, Confluence, email, chat as knowledge sources per context
## Inputs to Consider
### From NoteGraph Spec (reusable)
- Folder structure: decisions, inbox, meetings, people, projects
- Ingestion pipeline: OCR, LLM enrichment, entity detection, wiki-links
- Model-agnostic LLM provider layer (LiteLLM)
- Auto-reference generation (people, projects → wiki-links)
- TODO extraction → OrgMyLife task creation
- Drop-folder watcher for continuous import
- Git auto-commit for imported notes
- Frontmatter format: title, date, tags, people, projects, source
### From Monorepo Knowledge Store (already built)
- YAML-Frontmatter + YAML-Index (progressive disclosure)
- Scope-based folder structure (privat, dhive, bahn, shared)
- Content-hash based incremental processing
- Scope-filtered search (only see what you're authorized for)
- Graph-Verknüpfungen (bidirectional links in YAML frontmatter)
- Context bridge for cross-context sharing with sensitive content filtering
### From Wissensdatenbank (pattern to follow for bahn context)
- ETL strategies: confluence_page, confluence_tree, confluence_faq, crawler, sitemap, gitlab_md, file, pdf
- Scope classification (intern, extern, allgemein)
- Incremental processing with source versioning
- Auto-filter and review pipeline
- Chunking for large documents
### New Requirements (not yet specced)
- **Per-context knowledge folders**: `bahn/knowledge/`, `dhive/knowledge/`, `privat/knowledge/`
- **Multi-source ingestion per context**:
- bahn: Confluence, Jira, DB GitLab wikis, meeting notes, emails
- dhive: dhive GitLab, Confluence, project docs, chat exports
- privat: handwritten notes (reMarkable), personal docs, bookmarks, ideas
- **Jira integration**: Import issues/comments as knowledge artifacts
- **Email/chat import**: Extract actionable info from email threads and chat messages
- **Picture/scan support**: OCR for reMarkable exports, whiteboard photos
- **Link management**: Save and tag web links as reference material per context
- **Agent context injection**: When the AI-Orchestrator works on a task, inject relevant knowledge from the context's knowledge folder into the prompt
## Architecture Constraints
- Must live within the monorepo context structure
- Must respect security boundaries (no cross-context leakage)
- Must integrate with existing `ctx-guard` CLI tooling
- Must work with the AI-Orchestrator's knowledge injection (Req 7.4)
- Must support federation (bahn knowledge syncs to bahn team repo)
- Markdown + YAML frontmatter as canonical format (like Wissensdatenbank)
- Progressive disclosure: index → summary → full document
## User's Working Style
- Operates across many parallel projects, domains, meetings
- Takes handwritten notes on reMarkable tablet
- Attends many meetings (bahn + dhive)
- Uses Jira (bahn) and GitLab (both) daily
- Wants quick capture and later organization
- Trusts AI-assisted enrichment but wants control over results
- Uses OrgMyLife for task management
## Key Questions for the New Chat
1. Should each context have its own `knowledge/` folder, or should it all live in `shared/knowledge-store/` with scope tags?
2. How to handle the ingestion pipeline: one shared pipeline with context routing, or per-context pipelines?
3. Priority of sources: What to implement first? (Markdown files → Confluence → Jira → email?)
4. How does this relate to the Wissensdatenbank? Is bahn/knowledge just a filtered view of it, or separate?
5. What's the daily workflow? Quick capture → inbox → process → organize?
## Files to Reference in New Chat
- `#[[.kiro/specs/monorepo-consolidation/design.md]]` (knowledge store architecture)
- `#[[.kiro/specs/monorepo-consolidation/requirements.md]]` (Req 3: Wissensspeicher, Req 5: Kontextbrücke)
- `#[[.kiro/specs/notegraph-ingestion/requirements.md]]` (ingestion pipeline reqs)
- `#[[.kiro/specs/notegraph-ingestion/design.md]]` (ingestion architecture)
- `#[[privat/NoteGraph/notes/index.md]]` (existing folder structure)
- `#[[shared/tools/monorepo-cli/src/monorepo/knowledge/store.py]]` (implemented knowledge store)
- `#[[bahn/wissensdatenbank/README.md]]` (ETL pipeline pattern)
+862
View File
@@ -0,0 +1,862 @@
# Design Document: Knowledge Management System
## Overview
Das Knowledge Management System erweitert den bestehenden Monorepo-CLI um ein vollständiges persönliches Wissensmanagement. Es baut auf dem existierenden Knowledge Store (ETL-Pipeline, YAML-Index, Scope-basierte Suche) und der Wissensdatenbank (Confluence, Web, PDF-Ingestion) auf und vereint sie zu einer integrierten Lösung.
**Kernarchitektur:**
- Kontextlokale `knowledge/`-Ordner in bahn, dhive, privat (Google OKF-Struktur)
- Gemeinsame Ingestion-Pipeline in `shared/tools/monorepo-cli/src/monorepo/knowledge/ingestion/`
- Pluggable Source-Strategien (Markdown, PDF, OCR, Confluence, Jira, E-Mail, Chat, Links)
- LLM-basierter Enrichment Agent (Kiro als primärer Provider, LiteLLM als spätere Alternative)
- OrgMyLife-Integration für Action-Item-Extraktion
- CLI-Schnittstelle als `monorepo knowledge`-Subcommand
**Design-Entscheidungen:**
1. **Erweiterung statt Neubau:** Die bestehenden Module `knowledge/artifact.py`, `knowledge/etl.py`, `knowledge/index.py`, `knowledge/store.py` werden wiederverwendet und erweitert.
2. **Source-Strategie-Pattern:** Neue Quellen implementieren ein gemeinsames `SourceStrategy`-Interface (analog zu `MarkdownSource`).
3. **Separation of Concerns:** Ingestion (Extract/Transform/Load), Enrichment (LLM), Routing (Kontext-Zuordnung) und CLI sind separate Module.
4. **Wissensdatenbank als Read-Only-Upstream:** Die bestehende ETL-Pipeline in `bahn/wissensdatenbank/` wird referenziert, nicht modifiziert.
5. **Kiro-first für LLM und OCR:** Der AI-Orchestrator (Kiro) dient als primärer Provider für Enrichment und OCR keine externe Abhängigkeit (LiteLLM, Tesseract) nötig für den Start. Alternativen können später für CI/Batch-Szenarien ergänzt werden.
## Architecture
### High-Level System Architecture
```mermaid
graph TB
subgraph "CLI Layer"
CLI[monorepo knowledge CLI]
end
subgraph "Ingestion Pipeline (shared/tools/monorepo-cli/src/monorepo/knowledge/ingestion/)"
Router[Context Router]
Pipeline[Ingestion Pipeline]
Enrichment[Enrichment Agent<br/>Kiro / LiteLLM]
end
subgraph "Source Strategies"
MD[Markdown Source]
PDF[PDF Source]
OCR[OCR Engine]
CONF[Confluence Source]
JIRA[Jira Source]
EMAIL[Email Source]
CHAT[Chat Source]
LINK[Link Source]
WDB[Wissensdatenbank Source]
end
subgraph "Context Knowledge Folders"
BK[bahn/knowledge/]
DK[dhive/knowledge/]
PK[privat/knowledge/]
end
subgraph "Integrations"
OML[OrgMyLife API]
GIT[Git Auto-Commit]
FED[Federation Sync]
end
subgraph "Search & Retrieval"
IDX[YAML Index<br/>per Context]
SEARCH[Cross-Context Search]
INJECT[Agent Context Injection]
end
CLI --> Router
CLI --> SEARCH
Router --> Pipeline
Pipeline --> Enrichment
Pipeline --> MD & PDF & OCR & CONF & JIRA & EMAIL & CHAT & LINK & WDB
Pipeline --> BK & DK & PK
Pipeline --> IDX
Enrichment --> OML
Pipeline --> GIT
BK & DK & PK --> FED
IDX --> SEARCH
SEARCH --> INJECT
```
### Data Flow
```mermaid
sequenceDiagram
participant U as User/CLI
participant R as Context Router
participant P as Ingestion Pipeline
participant S as Source Strategy
participant E as Enrichment Agent
participant K as Knowledge Folder
participant I as YAML Index
participant G as Git
U->>R: knowledge ingest --context bahn
R->>P: load sources.yaml, start pipeline
P->>S: extract(source_config)
S-->>P: raw artifacts
P->>E: enrich(raw_artifact)
E-->>P: enriched artifact (tags, category, entities, action-items)
P->>K: write artifact to {context}/knowledge/{category}/
P->>I: update _index.yaml
P->>G: git commit "knowledge(bahn): ingest N artifacts from source"
```
### Module Layout
```
shared/tools/monorepo-cli/src/monorepo/knowledge/
├── __init__.py # Existing exports + new ones
├── artifact.py # Existing: ArtifactMetadata, parse/write
├── etl.py # Existing: ETLPipeline (enhanced)
├── index.py # Existing: YAMLIndex, IndexEntry
├── store.py # Existing: KnowledgeStore, search
├── migration.py # Existing: migration utilities
├── ingestion/ # NEW: Unified ingestion pipeline
│ ├── __init__.py
│ ├── pipeline.py # IngestionPipeline orchestrator
│ ├── router.py # ContextRouter
│ ├── enrichment.py # EnrichmentAgent (Kiro-first, LiteLLM als Fallback)
│ ├── capture.py # QuickCapture logic
│ ├── config.py # SourceConfig, sources.yaml parsing
│ └── git_integration.py # Auto-commit logic
├── sources/ # Source strategies
│ ├── __init__.py
│ ├── base.py # NEW: SourceStrategy ABC
│ ├── markdown.py # Existing (enhanced)
│ ├── pdf.py # NEW: PDF + OCR (Kiro-Vision als primärer OCR-Provider)
│ ├── confluence.py # NEW: Confluence REST API
│ ├── jira.py # NEW: Jira JQL
│ ├── email.py # NEW: .eml/.msg parsing
│ ├── chat.py # NEW: Chat export parsing
│ ├── link.py # NEW: Link registry
│ └── wissensdatenbank.py # NEW: bahn/wissensdatenbank/ adapter
├── integrations/ # External integrations
│ ├── __init__.py
│ ├── orgmylife.py # OrgMyLife task creation
│ ├── kiro_client.py # Kiro AI-Agent als LLM-Provider (primär)
│ └── litellm_client.py # LiteLLM wrapper (optional, spätere Alternative)
└── cli.py # NEW: knowledge subcommand group
```
## Components and Interfaces
### 1. SourceStrategy (Abstract Base Class)
```python
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any
from monorepo.knowledge.artifact import Artifact
@dataclass
class SourceConfig:
"""Configuration for a single source in sources.yaml."""
type: str # confluence, jira, email, file, link, wissensdatenbank
name: str # human-readable identifier
params: dict[str, Any] # type-specific connection/filter params
target_folder: str = "" # override target subfolder
sync_frequency: str = "manual" # on-push, hourly, daily, manual
enabled: bool = True
@dataclass
class ExtractionResult:
"""Result from a source strategy extraction."""
artifacts: list[Artifact] = field(default_factory=list)
errors: list[SourceError] = field(default_factory=list)
skipped: int = 0
class SourceStrategy(ABC):
"""Abstract base class for all source strategies."""
@abstractmethod
def extract(self, config: SourceConfig, context: str) -> ExtractionResult:
"""Extract raw artifacts from the configured source."""
...
@abstractmethod
def supports_incremental(self) -> bool:
"""Whether this strategy supports incremental processing."""
...
```
### 2. ContextRouter
```python
@dataclass
class RoutingDecision:
"""Result of context routing."""
context: str # bahn, dhive, privat
target_folder: str # knowledge subfolder (meetings, decisions, etc.)
artifact_path: Path # full path for the artifact
class ContextRouter:
"""Routes incoming data to the correct context knowledge folder."""
def __init__(self, monorepo_root: Path) -> None: ...
def determine_context(self, source_config: SourceConfig | None = None,
cwd: Path | None = None) -> str:
"""Determine target context from source config or working directory."""
...
def resolve_target_path(self, context: str, category: str,
filename: str) -> Path:
"""Compute full path: {root}/{context}/knowledge/{category}/{filename}"""
...
```
### 3. IngestionPipeline
```python
@dataclass
class IngestionResult:
"""Result of a full ingestion run."""
context: str
processed: int = 0
updated: int = 0
skipped: int = 0
errors: list[IngestError] = field(default_factory=list)
tasks_created: int = 0
commit_sha: str = ""
class IngestionPipeline:
"""Orchestrates the full ingestion workflow."""
def __init__(self, monorepo_root: Path, context: str,
dry_run: bool = False, no_commit: bool = False) -> None: ...
def run(self) -> IngestionResult:
"""Execute full pipeline: load config → extract → enrich → store → index → commit."""
...
def process_inbox(self) -> IngestionResult:
"""Process all items in {context}/knowledge/inbox/."""
...
```
### 4. EnrichmentAgent
```python
@dataclass
class EnrichmentResult:
"""Output from LLM-based enrichment."""
title: str
category: str # meeting, decision, project, reference, link, inbox
tags: list[str]
people: list[str] # detected person names
projects: list[str] # detected project references
action_items: list[ActionItem]
confidence: float # overall confidence score
@dataclass
class ActionItem:
"""An extracted action item from content."""
description: str
assignee: str | None = None
deadline: str | None = None # ISO date string
hash: str = "" # for dedup: sha256 of description
class EnrichmentAgent:
"""LLM-powered content analysis and enrichment.
Provider-Strategie (Priorität):
1. Kiro AI-Agent (primär) nutzt den laufenden Orchestrator-Agenten direkt,
keine externe Abhängigkeit, kein API-Key nötig
2. LiteLLM (optional, spätere Alternative) für Batch-Verarbeitung oder
wenn Kiro nicht verfügbar ist (z.B. CI-Pipeline)
OCR-Strategie (Priorität):
1. Kiro Vision Bilder werden direkt an den Agenten gesendet,
der den Text extrahiert (keine Tesseract-Installation nötig)
2. Tesseract (optional, spätere Alternative) für Offline-/CI-Betrieb
"""
def __init__(self, provider: str = "kiro", model: str = "") -> None:
"""Initialize with LLM config. Defaults to 'kiro' provider.
Providers: 'kiro' (default), 'litellm' (future alternative)
Falls provider='litellm': config from env vars LLM_PROVIDER, LLM_MODEL.
"""
...
def enrich(self, content: str, source_type: str = "") -> EnrichmentResult:
"""Analyze content and generate metadata."""
...
def classify_relevance(self, content: str) -> float:
"""Score content relevance (0.0 = irrelevant, 1.0 = highly relevant)."""
...
```
### 5. QuickCapture
```python
class QuickCapture:
"""Fast knowledge capture to inbox."""
def __init__(self, monorepo_root: Path) -> None: ...
def capture(self, input_text: str, context: str | None = None,
tags: list[str] | None = None) -> Path:
"""Capture text/URL/filepath to inbox. Returns path of created artifact."""
...
def _detect_input_type(self, input_text: str) -> str:
"""Detect if input is URL, file path, or plain text."""
...
def _generate_filename(self, title: str) -> str:
"""Generate YYYY-MM-DD-HH-MM-title-slug.md filename."""
...
```
### 6. LinkRegistry
```python
class LinkRegistry:
"""Manages web links as knowledge artifacts."""
def __init__(self, context_path: Path) -> None: ...
def save_link(self, url: str, title: str | None = None,
tags: list[str] | None = None) -> Path:
"""Save or update a link artifact. Deduplicates by URL."""
...
def search_links(self, query: str) -> list[Artifact]:
"""Search links by URL, title, or tags."""
...
def _fetch_metadata(self, url: str) -> tuple[str, str]:
"""Fetch page title and description from URL."""
...
def _find_existing(self, url: str) -> Path | None:
"""Check for duplicate URL in context."""
...
```
### 7. OrgMyLife Integration
```python
@dataclass
class TaskMapping:
"""Maps artifact action items to OrgMyLife task IDs."""
artifact_id: str
action_item_hash: str
task_id: int
created: str # ISO date
class OrgMyLifeIntegration:
"""Creates tasks in OrgMyLife from detected action items."""
def __init__(self, context_path: Path, enabled: bool = True) -> None: ...
def create_tasks(self, artifact_id: str,
action_items: list[ActionItem],
source_path: str) -> list[TaskMapping]:
"""Create OrgMyLife tasks for new action items (dedup via mapping file)."""
...
def _load_mapping(self) -> dict[str, TaskMapping]: ...
def _save_mapping(self, mappings: dict[str, TaskMapping]) -> None: ...
```
### 8. CLI Interface
```python
# Registered as subcommand group under ctx-guard / monorepo CLI
# Commands:
# knowledge capture <text|url|path> [--context CTX] [--tags TAG,TAG]
# knowledge ingest [--context CTX] [--dry-run] [--verbose] [--no-commit]
# knowledge search <query> [--context CTX] [--limit N]
# knowledge status [--context CTX]
# knowledge link <url> [--title TITLE] [--tags TAG,TAG] [--context CTX]
```
## Data Models
### Extended ArtifactMetadata (backward-compatible extension)
The existing `ArtifactMetadata` dataclass is extended with optional fields:
```python
@dataclass
class ArtifactMetadata:
"""Extended metadata supporting knowledge management features."""
# Existing fields (unchanged)
type: str
title: str
tags: list[str] = field(default_factory=list)
source_context: str = ""
created: date | None = None
updated: date | None = None
shareable: bool = False
links: list[ArtifactLink] = field(default_factory=list)
content_hash: str = ""
# NEW: Knowledge Management extensions
source: dict[str, str] = field(default_factory=dict)
# e.g. {"type": "confluence", "url": "...", "space": "...", "file": "..."}
category: str = "" # meeting, decision, project, reference, link, inbox
people: list[str] = field(default_factory=list) # [[people/name]] refs
projects: list[str] = field(default_factory=list) # [[projects/slug]] refs
enrichment_pending: bool = False
ocr_failed: bool = False
fetch_failed: bool = False
```
### sources.yaml Schema
```yaml
# {context}/knowledge/sources.yaml
version: "1.0"
sources:
- name: "Team Confluence"
type: confluence
enabled: true
sync_frequency: daily
params:
base_url: "https://confluence.bahn.de"
api_key: "${CONFLUENCE_API_TOKEN}"
spaces: ["ACV2", "EINFACHBAHN"]
tree_roots: ["12345678"]
target_folder: references
- name: "Sprint Issues"
type: jira
enabled: true
sync_frequency: daily
params:
base_url: "https://jira.bahn.de"
api_key: "${JIRA_API_TOKEN}"
jql: "project = ACV2 AND updatedDate > -7d"
target_folder: projects
- name: "Wissensdatenbank"
type: wissensdatenbank
enabled: true
sync_frequency: manual
params:
output_path: "../../wissensdatenbank/output/"
target_folder: references
settings:
create_tasks: true
enrichment:
provider: "kiro" # Primär: Kiro AI-Agent (kein API-Key nötig)
# provider: "${LLM_PROVIDER}" # Alternative: LiteLLM (für CI/Batch)
# model: "${LLM_MODEL}"
confidence_threshold: 0.7
ocr:
provider: "kiro" # Primär: Kiro Vision (kein Tesseract nötig)
# provider: "tesseract" # Alternative: lokales Tesseract
# languages: "deu+eng"
git:
auto_commit: true
```
### Knowledge Folder Structure (Google OKF)
```
{context}/knowledge/
├── _index.yaml # YAML Index (Progressive Disclosure Layer 1)
├── sources.yaml # Source configuration
├── .task-mapping.yaml # OrgMyLife action-item → task ID mapping
├── inbox/ # Unprocessed captures and imports
│ └── index.md # Auto-generated directory listing
├── meetings/
│ └── index.md
├── decisions/
│ └── index.md
├── projects/
│ └── index.md
├── people/
│ └── index.md
├── references/
│ └── index.md
└── links/
└── index.md
```
### Artifact Frontmatter Example (Google OKF)
```yaml
---
type: meeting
title: "Sprint Planning ACV2 W24"
tags: [acv2, sprint, planning]
source_context: bahn
created: 2025-07-01
updated: 2025-07-01
shareable: true
category: meeting
source:
type: confluence
url: "https://confluence.bahn.de/pages/viewpage.action?pageId=123456"
space: ACV2
people:
- "[[people/max-mustermann]]"
- "[[people/anna-schmidt]]"
projects:
- "[[projects/acv2-migration]]"
links:
- target: "decisions/api-redesign"
relation: "discussed_in"
- target: "../references/inb-2026-kapitel-3"
relation: "references"
content_hash: "sha256:abc123..."
---
# Sprint Planning ACV2 W24
## Agenda
...
## Action Items
- [ ] @max-mustermann: API-Konzept bis Freitag finalisieren (Deadline: 2025-07-04)
- [ ] @anna-schmidt: Testdaten bereitstellen
```
### _index.yaml Entry Structure
```yaml
version: "1.0"
last_updated: "2025-07-01T14:30:00Z"
artifacts:
- id: "bahn/meeting/sprint-planning-acv2-w24"
title: "Sprint Planning ACV2 W24"
type: meeting
tags: [acv2, sprint, planning]
scope: bahn
summary: "Sprint Planning für ACV2 Migration, Woche 24. API-Redesign besprochen."
path: "bahn/knowledge/meetings/sprint-planning-acv2-w24.md"
content_hash: "sha256:abc123..."
links: ["bahn/decision/api-redesign"]
source: wissensdatenbank # or: personal, confluence, jira
```
### Git Commit Message Format
```
knowledge({context}): {action} {count} artifacts from {source}
knowledge(bahn): ingest 3 artifacts from confluence
knowledge(privat): capture "Quick idea about X"
knowledge(dhive): ingest 1 artifacts from jira
```
## Correctness Properties
*A property is a characteristic or behavior that should hold true across all valid executions of a system — essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
### Property 1: Artifact Serialization Round-Trip
*For any* valid `ArtifactMetadata` object with content, writing it to a Markdown file with YAML frontmatter and then reading it back SHALL produce an identical `ArtifactMetadata` object (fields, types, and values match).
**Validates: Requirements 16.6, 1.5**
### Property 2: Context Derivation from Path
*For any* file path within the monorepo that resides under a context folder (`bahn/`, `dhive/`, `privat/`), the context derivation function SHALL return the correct context string matching the top-level folder name. This applies both to artifact paths and working directory resolution.
**Validates: Requirements 1.4, 3.2**
### Property 3: Idempotent Ingestion via Content Hash
*For any* artifact that has already been ingested and whose content has not changed, running the ingestion pipeline again SHALL skip re-processing (updated count = 0) and the YAML index entry SHALL remain unchanged.
**Validates: Requirements 2.4**
### Property 4: Error Resilience — Partial Source Failure
*For any* set of N configured sources where 1 ≤ K < N sources fail during extraction, the ingestion pipeline SHALL still successfully process all non-failing sources and produce artifacts for them. The IngestResult.errors list SHALL contain exactly the K failed sources.
**Validates: Requirements 2.5**
### Property 5: Index Completeness After Ingestion
*For any* set of artifacts successfully processed by the ingestion pipeline, the YAML index SHALL contain an entry for each processed artifact, with matching id, title, type, and content_hash.
**Validates: Requirements 2.6**
### Property 6: Context Routing Determinism
*For any* valid `SourceConfig` with an assigned context, the `ContextRouter` SHALL always route to that context. For any working directory within a context folder, the router SHALL derive the same context as the path-based derivation.
**Validates: Requirements 2.3**
### Property 7: Filename Pattern from Title
*For any* non-empty title string, the Quick Capture filename generator SHALL produce a filename matching the pattern `\d{4}-\d{2}-\d{2}-\d{2}-\d{2}-[a-z0-9-]+\.md` (date-time prefix + slugified title + .md extension).
**Validates: Requirements 3.3**
### Property 8: Category to Folder Mapping
*For any* valid category string from the set {meeting, decision, project, reference, link, inbox}, the folder mapping function SHALL return the corresponding plural folder name (meetings/, decisions/, projects/, references/, links/, inbox/). For any unknown category, it SHALL default to inbox/.
**Validates: Requirements 3.5, 9.6**
### Property 9: File Extension Format Detection
*For any* file path with a supported extension (`.md`, `.txt`, `.pdf`, `.png`, `.jpg`, `.jpeg`, `.docx`), the format detection function SHALL return the correct format type. For unsupported extensions, it SHALL raise an appropriate error or return a fallback type.
**Validates: Requirements 4.7**
### Property 10: Image Source File Reference Preservation
*For any* artifact created from an image source (PNG, JPG, JPEG), the resulting artifact's frontmatter SHALL contain a `source.file` field referencing the original image file path.
**Validates: Requirements 4.5**
### Property 11: URL Detection in Quick Capture
*For any* string that is a valid HTTP or HTTPS URL, the Quick Capture input type detector SHALL classify it as type "link". For any string that is not a valid HTTP(S) URL, it SHALL NOT classify it as "link".
**Validates: Requirements 8.3**
### Property 12: Link Artifact Structure
*For any* URL saved via the Link Registry, the resulting artifact SHALL have `type: link`, be stored in the `links/` subfolder, and its frontmatter SHALL contain the fields: url, title (non-empty), tags (list), and created (valid date).
**Validates: Requirements 8.1, 8.2**
### Property 13: Link Deduplication with Tag Merging
*For any* URL that is saved twice to the same context Link Registry (possibly with different tags), only one artifact file SHALL exist for that URL, and its tags SHALL be the union of all tags provided across both save operations.
**Validates: Requirements 8.7**
### Property 14: Link Search Completeness
*For any* stored link artifact and any substring query that matches its URL, title, or any of its tags, the Link Registry search SHALL return that artifact in its results.
**Validates: Requirements 8.6**
### Property 15: Wiki-Link Format for Entities
*For any* person name detected by the Enrichment Agent, the generated wiki-link SHALL match the format `[[people/{slugified-name}]]`. For any project name, it SHALL match `[[projects/{slugified-name}]]`. Slugification SHALL produce lowercase, hyphen-separated strings.
**Validates: Requirements 9.2**
### Property 16: Confidence Threshold Filtering
*For any* set of detected entities with varying confidence scores, only entities with confidence ≥ 0.7 SHALL appear in the final enrichment output. Entities below 0.7 SHALL be excluded.
**Validates: Requirements 9.5**
### Property 17: Action Items Section Generation
*For any* non-empty list of `ActionItem` objects, the generated markdown SHALL contain a `## Action Items` section header followed by a markdown list item for each action item's description.
**Validates: Requirements 9.4**
### Property 18: Task Deduplication via Mapping
*For any* action item whose hash already exists in the `.task-mapping.yaml` file, the OrgMyLife integration SHALL NOT create a new task. Only action items with hashes not present in the mapping SHALL trigger task creation.
**Validates: Requirements 10.5, 10.6**
### Property 19: Scope-Filtered Search Isolation
*For any* search query and set of allowed scopes, the search results SHALL contain ONLY artifacts whose scope is in the allowed set. No artifact from an unauthorized scope SHALL appear in results, and its existence SHALL NOT be revealed.
**Validates: Requirements 11.5**
### Property 20: Context Injection Result Limit
*For any* search query that would return more than 10 results, the context injection function SHALL return at most 10 artifact paths, sorted by relevance score in descending order.
**Validates: Requirements 11.6**
### Property 21: Environment Variable Resolution in Config
*For any* string containing `${VAR_NAME}` patterns where the environment variable exists, the resolution function SHALL substitute the pattern with the variable's value. For any `${VAR_NAME}` where the variable is NOT set, the validation SHALL report an error.
**Validates: Requirements 12.4, 12.6**
### Property 22: Federation Sync Exclusion
*For any* set of artifacts where some have `shareable: false` in their frontmatter, the federation sync file list SHALL exclude ALL artifacts with `shareable: false`. Only artifacts with `shareable: true` (or shareable not explicitly set to false) SHALL be included.
**Validates: Requirements 14.4**
### Property 23: Git Commit Message Format
*For any* valid combination of context (bahn|dhive|privat), action (ingest|capture), count (positive integer), and source name, the generated commit message SHALL match the pattern `knowledge({context}): {action} {count} artifacts from {source}`.
**Validates: Requirements 16.2**
### Property 24: Ingestion Produces Valid Artifacts
*For any* raw text content processed by the ingestion pipeline, the resulting artifact SHALL have a non-empty title, a valid category from the allowed set, a non-empty content_hash in sha256 format, and a valid source_context.
**Validates: Requirements 2.2**
## Error Handling
### Strategy: Fail-Forward with Logging
The system uses a "fail-forward" approach: individual failures are logged and skipped, while the overall pipeline continues processing. This matches the existing ETL pipeline's error resilience pattern.
### Error Categories
| Category | Handling | Recovery |
|----------|----------|----------|
| Source unavailable (API timeout, auth failure) | Log error with source identifier, skip source, continue with remaining | Retry on next scheduled run |
| OCR failure (unreadable image) | Create artifact with empty content, set `ocr_failed: true` | Manual review via `knowledge status` |
| LLM/Kiro provider unavailable | Store artifact with minimal metadata, set `enrichment_pending: true` | Re-enrich on next run with `--re-enrich` flag |
| OrgMyLife API failure | Log warning, continue without task creation | Tasks created on next successful run (dedup handles this) |
| Git commit failure | Log warning, keep created files, skip commit | User commits manually or runs `--no-commit` |
| Invalid source config (missing fields, bad env vars) | Reject entire config with validation errors BEFORE starting pipeline | User fixes sources.yaml |
| File write failure (permissions, disk full) | Log error, skip artifact, continue | User resolves filesystem issue |
| Duplicate URL (Link Registry) | Not an error — merge tags with existing artifact | N/A (expected behavior) |
### Error Propagation
```python
@dataclass
class PipelineError:
"""Structured error for pipeline operations."""
source: str # which source/component failed
error_type: str # "connection", "auth", "parse", "write", "llm"
message: str # human-readable description
timestamp: str # ISO 8601
retry: bool # whether retry is sensible
artifact_path: str = "" # affected artifact, if applicable
```
### Graceful Degradation Levels
1. **Full operation:** All sources accessible, Kiro/LLM available → enriched artifacts with tasks
2. **No Kiro/LLM:** Sources accessible, Kiro session not active and no LiteLLM configured → artifacts with minimal metadata (`enrichment_pending: true`)
3. **Partial sources:** Some sources down → process available sources, log failures
4. **No Git:** Git unavailable → files created but not committed (warning)
5. **Read-only fallback:** No write access → search and read still work via existing index
### Logging
- Uses Python `logging` module (consistent with existing codebase)
- Log level from `--verbose` flag or `KNOWLEDGE_LOG_LEVEL` env var
- Pipeline run summary always printed to stdout (processed/updated/skipped/errors)
- Detailed errors to stderr
## Testing Strategy
### Dual Testing Approach
The testing strategy combines property-based tests (PBT) for universal correctness properties with example-based unit tests for specific scenarios and integration tests for external service interactions.
### Property-Based Tests (Hypothesis)
**Library:** [Hypothesis](https://hypothesis.readthedocs.io/) (already in dev dependencies)
**Configuration:**
- Minimum 100 iterations per property (`@settings(max_examples=100)`)
- Each property test is tagged with its design document property reference
**Tag format:** `Feature: knowledge-management, Property {number}: {property_text}`
**Properties to implement:**
| Property | Module Under Test | Generator Strategy |
|----------|-------------------|-------------------|
| 1: Round-Trip | `artifact.py` | Generate random `ArtifactMetadata` with all field combinations |
| 2: Context from Path | `router.py` | Generate paths like `{context}/knowledge/{subdir}/{filename}` |
| 3: Idempotent Ingestion | `pipeline.py` | Generate artifacts, ingest twice, verify skip |
| 4: Error Resilience | `pipeline.py` | Generate source lists with injected failures |
| 5: Index Completeness | `pipeline.py` + `index.py` | Generate artifact batches |
| 6: Context Routing | `router.py` | Generate SourceConfig objects |
| 7: Filename Pattern | `capture.py` | Generate random Unicode titles |
| 8: Category Mapping | `router.py` | Generate from category enum + random strings |
| 9: Extension Detection | `pipeline.py` | Generate file paths with various extensions |
| 10: Image Source Ref | `sources/pdf.py` | Generate image-sourced artifacts |
| 11: URL Detection | `capture.py` | Generate valid URLs + non-URL strings |
| 12: Link Structure | `sources/link.py` | Generate random URLs and metadata |
| 13: Link Dedup | `sources/link.py` | Generate duplicate URL scenarios |
| 14: Link Search | `sources/link.py` | Generate links + substring queries |
| 15: Wiki-Link Format | `enrichment.py` | Generate person/project name strings |
| 16: Confidence Filter | `enrichment.py` | Generate entity lists with random confidences |
| 17: Action Items Markdown | `enrichment.py` | Generate ActionItem lists |
| 18: Task Dedup | `integrations/orgmylife.py` | Generate action items + existing mappings |
| 19: Scope Isolation | `store.py` | Generate multi-scope data + restricted scope lists |
| 20: Result Limit | `store.py` | Generate large artifact sets + queries |
| 21: Env Var Resolution | `config.py` | Generate strings with `${VAR}` patterns + env dicts |
| 22: Sync Exclusion | `federation` integration | Generate artifacts with mixed shareable flags |
| 23: Commit Message | `git_integration.py` | Generate context/action/count/source combinations |
| 24: Valid Artifact Output | `pipeline.py` | Generate raw text content |
### Example-Based Unit Tests
- CLI argument parsing and dispatch
- Specific Confluence page parsing scenarios
- Specific Jira issue formatting
- Email header extraction
- OKF structure validation examples
- sources.yaml parsing with real-world examples
### Integration Tests
- Confluence API interaction (mocked `httpx` responses)
- Jira API interaction (mocked responses)
- OrgMyLife API task creation (mocked)
- OCR via Kiro Vision (mocked agent responses); optional: Tesseract with sample images
- PDF text extraction with sample documents
- Git commit operations (using tmp repos)
- Full pipeline end-to-end with fixture data
### Test Organization
```
shared/tools/monorepo-cli/tests/
├── knowledge/
│ ├── test_artifact_roundtrip.py # Property 1
│ ├── test_context_routing.py # Properties 2, 6, 8
│ ├── test_ingestion_pipeline.py # Properties 3, 4, 5, 24
│ ├── test_capture.py # Properties 7, 11
│ ├── test_format_detection.py # Property 9
│ ├── test_link_registry.py # Properties 12, 13, 14
│ ├── test_enrichment.py # Properties 15, 16, 17
│ ├── test_orgmylife_integration.py # Property 18
│ ├── test_search.py # Properties 19, 20
│ ├── test_config.py # Property 21
│ ├── test_federation_filter.py # Property 22
│ ├── test_git_integration.py # Property 23
│ ├── test_image_source.py # Property 10
│ └── integration/
│ ├── test_confluence_source.py
│ ├── test_jira_source.py
│ ├── test_email_source.py
│ ├── test_ocr_engine.py
│ └── test_full_pipeline.py
```
### Running Tests
```powershell
# Quick property tests (fast)
cd shared\tools\monorepo-cli
python -m pytest tests/knowledge/ -x --tb=short -q -k "not integration"
# Full test suite including integration
python -m pytest tests/knowledge/ --tb=short
# Specific property
python -m pytest tests/knowledge/test_artifact_roundtrip.py -v
```
@@ -0,0 +1,251 @@
# Requirements Document
## Introduction
Dieses Dokument beschreibt die Anforderungen für ein vereinheitlichtes persönliches Wissensmanagement-System, das in die bestehende Monorepo-Struktur integriert wird. Das System ersetzt die nicht funktionierende NoteGraph-App und baut auf dem bereits implementierten Knowledge Store (ETL-Pipeline, YAML-Index, Scope-basierte Suche) sowie der NoteGraph-Ingestion-Pipeline (OCR, LLM-Enrichment, Entity-Detection) auf.
**Kernziel:** Wissen aus allen drei Arbeitskontexten (bahn, dhive, privat) erfassen, organisieren und für den AI-Orchestrator nutzbar machen mit Quellen wie Markdown-Notizen, handschriftlichen Aufzeichnungen (reMarkable), Confluence, Jira, E-Mails, Chat-Exporten und Web-Links.
**Architekturentscheidungen:**
- Jeder Kontext erhält einen eigenen `knowledge/`-Ordner (kontextlokale Ablage)
- Eine gemeinsame Ingestion-Pipeline im shared-Bereich mit kontextbasiertem Routing
- Die bahn/wissensdatenbank bleibt als Upstream-Quelle bestehen; bahn/knowledge/ enthält zusätzlich persönliches Bahn-Wissen
- Workflow: Quick Capture → Inbox → Verarbeitung → Organisation
- **Google Open Knowledge Format (OKF)** als verbindliches Strukturprinzip für alle eigenen Wissensartefakte (privat, dhive, persönliches bahn-Wissen): ein Konzept pro Datei, Markdown mit YAML-Frontmatter, Cross-Links als Graph-Kanten, `index.md` pro Verzeichnis. Die Wissensdatenbank (Upstream DB-InfraGO) ist davon ausgenommen und behält ihr bestehendes Format.
## Glossary
- **Knowledge_Management_System**: Das Gesamtsystem zur Erfassung, Verarbeitung, Organisation und Abfrage von persönlichem Wissen über alle Arbeitskontexte hinweg
- **Kontext_Knowledge_Folder**: Der kontextspezifische Ordner (`bahn/knowledge/`, `dhive/knowledge/`, `privat/knowledge/`) zur lokalen Ablage verarbeiteter Wissensartefakte
- **Ingestion_Pipeline**: Die gemeinsame Verarbeitungspipeline im shared-Bereich, die Rohdaten aus verschiedenen Quellen in strukturierte Wissensartefakte transformiert
- **Inbox**: Der Eingangsordner pro Kontext (`{context}/knowledge/inbox/`), in dem unverarbeitete Rohdaten und Quick-Captures landen
- **Quellstrategie**: Ein austauschbarer Adapter, der eine bestimmte Quelle (Confluence, Jira, E-Mail, Markdown, etc.) anbindet und Rohdaten extrahiert
- **Wissensartefakt**: Eine strukturierte Markdown-Datei mit YAML-Frontmatter, die ein einzelnes Wissenselement repräsentiert (Notiz, Meeting-Protokoll, Entscheidung, Referenz, Link)
- **YAML_Index**: Der maschinenlesbare Index pro Kontext-Knowledge-Folder, der kompakte Metadaten aller Artefakte enthält (Progressive Disclosure Schicht 1)
- **Enrichment_Agent**: Die LLM-gestützte Komponente, die Rohdaten analysiert, Entitäten erkennt, Tags generiert und Artefakte kategorisiert
- **Quick_Capture**: Der vereinfachte Erfassungsmechanismus für schnelle Notizen, Links oder Ideen ohne manuelle Metadaten-Eingabe
- **Kontext_Router**: Die Komponente, die eingehende Daten anhand von Quelltyp und Konfiguration dem richtigen Arbeitskontext zuordnet
- **Link_Registry**: Die Verwaltung gespeicherter Web-Links als Referenzmaterial mit Tags und Kontext-Zuordnung
- **Federation_Sync**: Der Mechanismus, der kontextlokales Wissen mit dem jeweiligen Team-Repo synchronisiert
- **OCR_Engine**: Die Komponente zur Texterkennung aus Bildern und gescannten PDFs (reMarkable-Exporte, Whiteboard-Fotos)
- **Wissensdatenbank**: Die bestehende ETL-Pipeline in `bahn/wissensdatenbank/` für DB-InfraGO-Wissen (Confluence, Web, PDFs)
- **Google_OKF**: Das Google Open Knowledge Format ein Strukturprinzip für Wissensartefakte: ein Konzept pro Datei, Markdown mit YAML-Frontmatter, Cross-Links als Graph-Kanten, `index.md` pro Verzeichnis für Inhaltsübersichten. Verbindlich für alle eigenen Artefakte (privat, dhive, persönliches bahn-Wissen); nicht verbindlich für Upstream-Wissensdatenbank-Artefakte
## Requirements
### Requirement 1: Kontextlokale Wissensordner-Struktur
**User Story:** Als Wissensarbeiter möchte ich in jedem Arbeitskontext einen dedizierten Knowledge-Ordner haben, damit mein Wissen kontextnah organisiert ist und die Sicherheitsgrenzen des Monorepos automatisch greifen.
#### Acceptance Criteria
1. THE Knowledge_Management_System SHALL für jeden Arbeitskontext (bahn, dhive, privat) einen eigenen Kontext_Knowledge_Folder unter `{context}/knowledge/` bereitstellen
2. THE Kontext_Knowledge_Folder SHALL folgende Unterordner enthalten: `inbox/`, `meetings/`, `decisions/`, `projects/`, `people/`, `references/`, `links/`
3. THE Kontext_Knowledge_Folder SHALL einen eigenen YAML_Index (`_index.yaml`) bereitstellen, der alle lokalen Artefakte mit kompakten Metadaten (Titel, Tags, Typ, Erstelldatum, Content-Hash, Verknüpfungen) indexiert
4. WHEN ein Wissensartefakt in einem Kontext_Knowledge_Folder erstellt wird, THE Knowledge_Management_System SHALL den Quellkontext automatisch aus dem Dateipfad ableiten und im YAML-Frontmatter als `source_context` eintragen
5. THE Kontext_Knowledge_Folder SHALL die bestehende Artefakt-Struktur des Knowledge Store verwenden: Markdown-Dateien mit YAML-Frontmatter (mindestens type, title, tags, source_context, created, content_hash, links)
6. THE Kontext_Knowledge_Folder SHALL dem Google_OKF folgen: ein Konzept pro Datei, Cross-Links als Graph-Kanten im Frontmatter, und eine `index.md`-Datei pro Unterordner, die als Inhaltsverzeichnis dient und bei jedem Ingestion-Durchlauf aktualisiert wird
7. WHILE der bestehende Knowledge Store im shared-Bereich existiert, THE Knowledge_Management_System SHALL die Kontext_Knowledge_Folder als primäre Ablageorte verwenden und den shared Knowledge Store als übergreifenden Suchindex beibehalten
### Requirement 2: Gemeinsame Ingestion-Pipeline mit Kontext-Routing
**User Story:** Als Wissensarbeiter möchte ich eine einheitliche Verarbeitungspipeline für alle Quellen haben, die eingehende Daten automatisch dem richtigen Kontext zuordnet, damit ich nicht für jeden Kontext separate Tools betreiben muss.
#### Acceptance Criteria
1. THE Ingestion_Pipeline SHALL als gemeinsames Modul im shared-Bereich (`shared/tools/monorepo-cli/src/monorepo/knowledge/ingestion/`) implementiert werden
2. THE Ingestion_Pipeline SHALL Rohdaten aus einer konfigurierbaren Menge von Quellstrategien entgegennehmen und in strukturierte Wissensartefakte transformieren
3. WHEN Rohdaten verarbeitet werden, THE Kontext_Router SHALL den Zielkontext anhand der Quellkonfiguration bestimmen und das resultierende Artefakt im entsprechenden Kontext_Knowledge_Folder ablegen
4. THE Ingestion_Pipeline SHALL inkrementelle Verarbeitung über Content-Hashes unterstützen, wobei nur neue oder geänderte Inhalte verarbeitet werden
5. WHEN die Verarbeitung einer einzelnen Quelle fehlschlägt, THE Ingestion_Pipeline SHALL den Fehler mit Quellidentifikator und Zeitstempel protokollieren und mit den verbleibenden Quellen fortfahren
6. THE Ingestion_Pipeline SHALL nach jedem Verarbeitungsdurchlauf den YAML_Index des betroffenen Kontext_Knowledge_Folders aktualisieren, sodass neue Artefakte sofort auffindbar sind
7. THE Ingestion_Pipeline SHALL die bestehenden ETL-Quellstrategien der Wissensdatenbank wiederverwenden können (confluence_page, confluence_tree, crawler, sitemap, gitlab_md, file, pdf)
### Requirement 3: Quick Capture und Inbox-Workflow
**User Story:** Als Wissensarbeiter möchte ich schnell Notizen, Links und Ideen erfassen können, die später automatisch verarbeitet und eingeordnet werden, damit ich im Arbeitsfluss bleibe und nichts verloren geht.
#### Acceptance Criteria
1. THE Quick_Capture SHALL eine CLI-Schnittstelle bereitstellen (`knowledge capture`), die einen Freitext, eine URL oder einen Dateipfad entgegennimmt und als Rohartefakt in der Inbox des angegebenen Kontexts ablegt
2. WHEN kein Kontext explizit angegeben wird, THE Quick_Capture SHALL den Kontext aus dem aktuellen Arbeitsverzeichnis ableiten
3. THE Quick_Capture SHALL das erfasste Element mit minimalem Frontmatter (title, created, source, type: inbox) als Markdown-Datei im Format `YYYY-MM-DD-HH-MM-title-slug.md` in `{context}/knowledge/inbox/` ablegen
4. THE Inbox SHALL einen Drop-Folder-Mechanismus bereitstellen, der neue Dateien im Inbox-Ordner automatisch erkennt und zur Verarbeitung durch die Ingestion_Pipeline einreiht
5. WHEN ein Inbox-Element von der Ingestion_Pipeline verarbeitet wird, THE Enrichment_Agent SHALL das Element analysieren, kategorisieren und in den passenden Unterordner des Kontext_Knowledge_Folders verschieben (meetings, decisions, projects, references)
6. IF der Enrichment_Agent keine klare Kategorie bestimmen kann, THEN THE Ingestion_Pipeline SHALL das Artefakt im `inbox/`-Ordner belassen und mit dem Tag `unclassified` versehen
7. WHEN ein Quick_Capture ein erfolgreich abgelegt wird, THE Quick_Capture SHALL den Dateipfad des erstellten Artefakts auf der Konsole ausgeben
### Requirement 4: Multi-Source-Ingestion Markdown und Dateien
**User Story:** Als Wissensarbeiter möchte ich Markdown-Dateien, PDFs und Bilder (reMarkable-Exporte, Whiteboard-Fotos) als Wissensquellen importieren können, damit meine handschriftlichen Notizen und Dokumente durchsuchbar werden.
#### Acceptance Criteria
1. WHEN eine Markdown-Datei als Quelle bereitgestellt wird, THE Ingestion_Pipeline SHALL den Inhalt inklusive bestehendem Frontmatter einlesen und als Wissensartefakt verarbeiten
2. WHEN eine Bilddatei (PNG, JPG, JPEG) als Quelle bereitgestellt wird, THE OCR_Engine SHALL den Text mittels OCR extrahieren und der Ingestion_Pipeline als Rohtext übergeben
3. WHEN eine PDF-Datei als Quelle bereitgestellt wird, THE Ingestion_Pipeline SHALL eingebetteten Text direkt extrahieren und für gescannte Seiten die OCR_Engine einsetzen
4. THE OCR_Engine SHALL für die Sprachkombination Deutsch und Englisch (`deu+eng`) konfiguriert sein
5. WHEN der Enrichment_Agent ein Bild-basiertes Artefakt verarbeitet, THE Enrichment_Agent SHALL eine Referenz auf die Originaldatei im Frontmatter-Feld `source.file` beibehalten
6. IF die OCR_Engine keinen lesbaren Text aus einem Bild extrahieren kann, THEN THE Ingestion_Pipeline SHALL das Artefakt mit leerem Textinhalt erstellen und im Frontmatter das Feld `ocr_failed: true` setzen
7. THE Ingestion_Pipeline SHALL die Dateiformat-Erkennung anhand der Dateiendung vornehmen und folgende Formate unterstützen: `.md`, `.txt`, `.pdf`, `.png`, `.jpg`, `.jpeg`, `.docx`
### Requirement 5: Multi-Source-Ingestion Confluence
**User Story:** Als Wissensarbeiter möchte ich Confluence-Seiten und -Bäume als Wissensquellen einbinden, damit relevantes Team-Wissen aus Confluence automatisch in meinem persönlichen Wissensspeicher verfügbar ist.
#### Acceptance Criteria
1. THE Ingestion_Pipeline SHALL eine Quellstrategie für Confluence bereitstellen, die einzelne Seiten, Seitenbäume und FAQ-Spaces importieren kann
2. WHEN eine Confluence-Quelle konfiguriert wird, THE Quellstrategie SHALL die Confluence-REST-API verwenden und Seiteninhalte als Markdown extrahieren
3. THE Quellstrategie SHALL pro Kontext eine separate Confluence-Instanz-Konfiguration unterstützen (bahn: DB-Confluence, dhive: dhive-Confluence)
4. WHEN eine Confluence-Seite aktualisiert wurde (erkannt über Versions-Nummer oder Last-Modified), THE Ingestion_Pipeline SHALL das zugehörige Artefakt inkrementell aktualisieren
5. THE Quellstrategie SHALL das Confluence-Seiten-Frontmatter mit Quell-URL, Space-Key, Seitentitel und letztem Aktualisierungsdatum anreichern
6. WHEN eine Confluence-Seite Anhänge enthält, THE Quellstrategie SHALL Anhänge als Referenz-Links im Artefakt vermerken
7. IF die Confluence-API nicht erreichbar ist, THEN THE Ingestion_Pipeline SHALL den Fehler protokollieren und den Verarbeitungsdurchlauf für diese Quelle überspringen, ohne bestehende Artefakte zu löschen
### Requirement 6: Multi-Source-Ingestion Jira
**User Story:** Als Wissensarbeiter möchte ich Jira-Issues und deren Kommentare als Wissensartefakte importieren, damit Entscheidungen und Diskussionen aus Jira-Tickets in meinem Wissensspeicher auffindbar sind.
#### Acceptance Criteria
1. THE Ingestion_Pipeline SHALL eine Quellstrategie für Jira bereitstellen, die Issues anhand von JQL-Filtern importiert
2. WHEN ein Jira-Issue importiert wird, THE Quellstrategie SHALL Summary, Description, Kommentare und Status als strukturiertes Markdown-Artefakt zusammenstellen
3. THE Quellstrategie SHALL das Artefakt-Frontmatter mit Issue-Key, Projekt, Status, Assignee, Reporter und Jira-URL anreichern
4. WHEN ein Jira-Issue seit dem letzten Import aktualisiert wurde (erkannt über `updated`-Feld), THE Ingestion_Pipeline SHALL das zugehörige Artefakt inkrementell aktualisieren
5. THE Quellstrategie SHALL konfigurierbare JQL-Filter pro Kontext unterstützen (z.B. `project = ACV2 AND updatedDate > -7d` für bahn)
6. WHEN Jira-Kommentare Action-Items enthalten (erkannt über den Enrichment_Agent), THE Ingestion_Pipeline SHALL diese als TODO-Einträge im Artefakt markieren
7. IF die Jira-API nicht erreichbar ist oder die Authentifizierung fehlschlägt, THEN THE Ingestion_Pipeline SHALL den Fehler mit API-Endpunkt protokollieren und den Verarbeitungsdurchlauf für diese Quelle überspringen
### Requirement 7: Multi-Source-Ingestion E-Mail und Chat
**User Story:** Als Wissensarbeiter möchte ich relevante E-Mail-Threads und Chat-Nachrichten als Wissensartefakte importieren, damit wichtige Informationen aus der Kommunikation nicht verloren gehen.
#### Acceptance Criteria
1. THE Ingestion_Pipeline SHALL eine Quellstrategie für E-Mails bereitstellen, die exportierte E-Mail-Dateien (`.eml`, `.msg`) oder Ordner mit E-Mails verarbeitet
2. WHEN eine E-Mail verarbeitet wird, THE Quellstrategie SHALL Absender, Empfänger, Betreff, Datum und Body als strukturiertes Markdown-Artefakt zusammenstellen
3. THE Ingestion_Pipeline SHALL eine Quellstrategie für Chat-Exporte bereitstellen, die Textdateien oder JSON-Exporte aus Chat-Systemen verarbeitet
4. WHEN der Enrichment_Agent eine E-Mail oder Chat-Nachricht analysiert, THE Enrichment_Agent SHALL explizit nach Action-Items, Entscheidungen und Deadlines suchen
5. THE Quellstrategie SHALL das Artefakt-Frontmatter mit Absender, Empfänger-Liste, Datum und Thread-Referenz anreichern
6. WHEN eine E-Mail Anhänge enthält, THE Quellstrategie SHALL Anhänge als separate Artefakte verarbeiten und über Links im Eltern-Artefakt referenzieren
7. IF eine E-Mail oder Chat-Nachricht keine verwertbare Information enthält (vom Enrichment_Agent als irrelevant klassifiziert), THEN THE Ingestion_Pipeline SHALL das Element überspringen und im Verarbeitungsprotokoll als `skipped: low-relevance` vermerken
### Requirement 8: Link-Management
**User Story:** Als Wissensarbeiter möchte ich Web-Links als Referenzmaterial speichern und taggen können, damit ich wichtige Ressourcen pro Kontext organisiert wiederfinde.
#### Acceptance Criteria
1. THE Link_Registry SHALL Web-Links als Wissensartefakte vom Typ `link` im `links/`-Unterordner des jeweiligen Kontext_Knowledge_Folders speichern
2. WHEN ein Link gespeichert wird, THE Link_Registry SHALL die URL, einen optionalen Titel, Tags und den Speicherzeitpunkt im YAML-Frontmatter erfassen
3. THE Quick_Capture SHALL URLs automatisch erkennen und als Link-Artefakte behandeln, wenn der eingegebene Text eine gültige HTTP(S)-URL ist
4. WHEN ein Link-Artefakt erstellt wird, THE Ingestion_Pipeline SHALL versuchen den Seitentitel und eine Kurzbeschreibung von der Ziel-URL zu extrahieren (via HTTP-Request auf die Seite)
5. IF die Ziel-URL nicht erreichbar ist, THEN THE Link_Registry SHALL den Link dennoch speichern, mit dem vom Nutzer angegebenen Titel und dem Frontmatter-Feld `fetch_failed: true`
6. THE Link_Registry SHALL eine Suche über gespeicherte Links nach URL, Titel und Tags unterstützen
7. THE Link_Registry SHALL duplikate URLs innerhalb eines Kontexts erkennen und bei erneutem Speichern die Tags des bestehenden Artefakts ergänzen statt ein neues Artefakt zu erstellen
### Requirement 9: LLM-gestützte Anreicherung und Kategorisierung
**User Story:** Als Wissensarbeiter möchte ich, dass importierte Inhalte automatisch mit Tags, Kategorien und erkannten Entitäten angereichert werden, damit ich weniger manuelle Metadaten-Pflege betreiben muss.
#### Acceptance Criteria
1. WHEN ein Rohartefakt verarbeitet wird, THE Enrichment_Agent SHALL den Inhalt analysieren und folgende Metadaten generieren: Titel (sofern nicht vorhanden), Kategorie (meeting, decision, project, reference, inbox), Tags, erkannte Personen und Projekte
2. THE Enrichment_Agent SHALL erkannte Personen als Wiki-Links im Format `[[people/vorname-nachname]]` und Projekte als `[[projects/projekt-slug]]` in den Artefakt-Body einfügen
3. THE Enrichment_Agent SHALL die modell-agnostische LLM-Schicht (LiteLLM) verwenden und über Umgebungsvariablen (`LLM_PROVIDER`, `LLM_MODEL`) konfigurierbar sein
4. WHEN der Enrichment_Agent Action-Items im Text erkennt, THE Enrichment_Agent SHALL diese in einem `## Action Items`-Abschnitt am Ende des Artefakts zusammenfassen
5. THE Enrichment_Agent SHALL Entitäten nur mit einer Konfidenz von 0.7 oder höher in die Ausgabe übernehmen
6. WHEN der Enrichment_Agent ein Artefakt kategorisiert hat, THE Ingestion_Pipeline SHALL die Zielordner-Zuordnung aus der Kategorie ableiten (meeting → meetings/, decision → decisions/, project → projects/, link → links/, default → inbox/)
7. IF der LLM-Provider nicht erreichbar ist, THEN THE Ingestion_Pipeline SHALL das Artefakt mit minimalen Metadaten (Titel aus Dateiname, Kategorie `inbox`) im Inbox-Ordner ablegen und im Frontmatter `enrichment_pending: true` setzen
### Requirement 10: OrgMyLife-Integration und Action-Item-Extraktion
**User Story:** Als Wissensarbeiter möchte ich, dass erkannte Action-Items automatisch als Tasks in OrgMyLife erstellt werden, damit Aufgaben aus Meetings und E-Mails nicht verloren gehen.
#### Acceptance Criteria
1. WHEN der Enrichment_Agent Action-Items in einem Artefakt erkennt, THE Ingestion_Pipeline SHALL optional für jedes Action-Item einen Task in OrgMyLife erstellen (steuerbar über Konfigurationsflag `create_tasks`)
2. WHEN ein OrgMyLife-Task erstellt wird, THE Ingestion_Pipeline SHALL den Task-Titel auf die Action-Item-Beschreibung setzen und im Feld `source_url` einen Verweis auf das Quell-Artefakt hinterlegen
3. WHEN ein Action-Item eine erkannte Deadline enthält, THE Ingestion_Pipeline SHALL das Fälligkeitsdatum im OrgMyLife-Task setzen
4. IF die OrgMyLife-API nicht erreichbar ist, THEN THE Ingestion_Pipeline SHALL eine Warnung protokollieren und die Verarbeitung ohne Task-Erstellung fortsetzen
5. THE Ingestion_Pipeline SHALL bereits erstellte Tasks nicht duplizieren, indem sie eine Mapping-Datei (`{context}/knowledge/.task-mapping.yaml`) führt, die Artefakt-ID und Action-Item-Hash auf OrgMyLife-Task-IDs abbildet
6. WHEN ein Artefakt erneut verarbeitet wird und neue Action-Items enthält, THE Ingestion_Pipeline SHALL nur für bisher nicht erfasste Action-Items neue Tasks erstellen
### Requirement 11: Kontextübergreifende Suche und Agent-Context-Injection
**User Story:** Als Wissensarbeiter und als AI-Orchestrator möchte ich relevantes Wissen aus dem aktiven Kontext in Agenten-Prompts injizieren, damit der Agent fundierte Antworten auf Basis meines persönlichen Wissens geben kann.
#### Acceptance Criteria
1. THE Knowledge_Management_System SHALL eine einheitliche Suchschnittstelle bereitstellen, die über alle Kontext_Knowledge_Folder und den shared Knowledge Store sucht, gefiltert nach autorisierten Scopes
2. WHEN der AI-Orchestrator einen Task-Prompt zusammenstellt, THE Knowledge_Management_System SHALL die relevantesten Artefakte aus dem YAML_Index des aktiven Kontexts identifizieren und deren Pfade als Kontextinformation bereitstellen
3. THE Knowledge_Management_System SHALL die Suche über den Progressive-Disclosure-Ansatz realisieren: Schicht 1 (YAML_Index mit kompakten Metadaten) für schnelle Relevanzprüfung, Schicht 2 (vollständiges Dokument) nur bei Bedarf
4. WHEN eine Suchanfrage gestellt wird, THE Knowledge_Management_System SHALL Ergebnisse innerhalb von 5 Sekunden zurückgeben und bei Timeout-Überschreitung Teilergebnisse mit einer `partial_results`-Markierung liefern
5. THE Knowledge_Management_System SHALL die Sicherheitsgrenzen des ctx-guard-Systems respektieren und ausschließlich Artefakte aus autorisierten Kontexten in Suchergebnissen und Agent-Prompts berücksichtigen
6. WHEN der AI-Orchestrator Kontext injiziert, THE Knowledge_Management_System SHALL maximal 10 relevante Artefakt-Pfade pro Anfrage zurückliefern, sortiert nach Relevanz-Score
### Requirement 12: Quellkonfiguration pro Kontext
**User Story:** Als Wissensarbeiter möchte ich pro Kontext definieren, welche Quellen regelmäßig importiert werden sollen, damit der Wissensimport automatisiert und kontextspezifisch abläuft.
#### Acceptance Criteria
1. THE Knowledge_Management_System SHALL eine Konfigurationsdatei pro Kontext bereitstellen (`{context}/knowledge/sources.yaml`), die alle aktiven Quellstrategien mit ihren Parametern definiert
2. THE Konfigurationsdatei SHALL pro Quellstrategie folgende Felder unterstützen: Typ (confluence, jira, email, file, link), Verbindungsparameter, Filterkriterien, Sync-Frequenz und Zielordner
3. WHEN die Ingestion_Pipeline gestartet wird, THE Ingestion_Pipeline SHALL alle in der `sources.yaml` des angegebenen Kontexts konfigurierten Quellen sequentiell verarbeiten
4. THE Konfigurationsdatei SHALL Secrets über Umgebungsvariablen-Referenzen einbinden (z.B. `api_key: ${JIRA_API_TOKEN}`) statt Klartext-Credentials zu enthalten
5. WHEN eine neue Quellstrategie zur Konfiguration hinzugefügt wird, THE Ingestion_Pipeline SHALL beim nächsten Durchlauf einen vollständigen Initial-Import dieser Quelle durchführen
6. THE Knowledge_Management_System SHALL eine Validierung der `sources.yaml` bereitstellen, die fehlende Pflichtfelder und nicht-auflösbare Umgebungsvariablen vor dem Start der Verarbeitung erkennt
### Requirement 13: Wissensdatenbank-Integration (bahn-Kontext)
**User Story:** Als Wissensarbeiter im bahn-Kontext möchte ich, dass die bestehende Wissensdatenbank als Upstream-Quelle in mein Knowledge-System einfließt, damit ich DB-InfraGO-Wissen zusammen mit meinen persönlichen bahn-Notizen durchsuchen kann.
#### Acceptance Criteria
1. THE Knowledge_Management_System SHALL die Wissensdatenbank (`bahn/wissensdatenbank/output/`) als Quellstrategie vom Typ `wissensdatenbank` für den bahn-Kontext einbinden
2. WHEN die Wissensdatenbank aktualisiert wird (via Upstream-Sync), THE Ingestion_Pipeline SHALL geänderte Artefakte im bahn/knowledge/ YAML_Index aktualisieren, ohne die Originaldateien in `bahn/wissensdatenbank/` zu verändern
3. THE Quellstrategie SHALL Artefakte aus der Wissensdatenbank als Read-Only-Referenzen im bahn-Knowledge-Index führen, mit dem Frontmatter-Feld `source: wissensdatenbank` und einer Referenz auf den Originalpfad
4. THE Quellstrategie SHALL Wissensdatenbank-Artefakte in ihrem Originalformat belassen und NICHT dem Google_OKF-Strukturprinzip unterwerfen (kein Splitting in Ein-Konzept-pro-Datei, keine erzwungene index.md-Generierung für Wissensdatenbank-Inhalte)
5. THE Knowledge_Management_System SHALL persönliche bahn-Notizen (Meetings, Entscheidungen) separat von Wissensdatenbank-Artefakten im bahn/knowledge/ ablegen, wobei persönliche Artefakte dem Google_OKF folgen und beide über den YAML_Index durchsuchbar sind
6. WHEN ein Wissensdatenbank-Artefakt und ein persönliches bahn-Artefakt thematisch verknüpft sind, THE Knowledge_Management_System SHALL bidirektionale Links zwischen beiden im YAML_Index unterstützen
### Requirement 14: Federation und Team-Repo-Synchronisation
**User Story:** Als Wissensarbeiter möchte ich, dass mein kontextlokales Wissen über die bestehende Föderationsstruktur mit dem jeweiligen Team-Repo synchronisiert wird, damit relevantes Wissen auch im Team-Kontext verfügbar ist.
#### Acceptance Criteria
1. WHEN der Kontext_Knowledge_Folder eines Kontexts aktualisiert wird, THE Federation_Sync SHALL die Änderungen im Rahmen der regulären Team-Repo-Synchronisation (gemäß monorepo-consolidation Req 10) mit dem zugehörigen Team-Repo synchronisieren
2. THE Federation_Sync SHALL die bestehende `team-repos.yaml`-Konfiguration respektieren und den Knowledge-Ordner als Teil des Kontextordners behandeln (keine separate Sync-Konfiguration nötig)
3. WHILE Artefakte synchronisiert werden, THE Knowledge_Management_System SHALL sicherstellen, dass keine kontextübergreifenden Links oder Referenzen auf andere Kontexte in das Team-Repo gelangen
4. THE Knowledge_Management_System SHALL Artefakte mit dem Frontmatter-Feld `shareable: false` von der Federation-Synchronisation ausschließen
5. IF ein Artefakt sensible Inhalte enthält (erkannt über den bestehenden ctx-guard-Mechanismus), THEN THE Federation_Sync SHALL das Artefakt von der Synchronisation ausschließen und dies im Sync-Protokoll vermerken
### Requirement 15: CLI-Schnittstelle
**User Story:** Als Wissensarbeiter möchte ich alle Knowledge-Management-Operationen über eine konsistente CLI-Schnittstelle ausführen, damit ich Wissen effizient von der Kommandozeile aus verwalten kann.
#### Acceptance Criteria
1. THE Knowledge_Management_System SHALL eine CLI-Schnittstelle als Unterkommando des Monorepo-CLI bereitstellen (`monorepo knowledge` oder `knowledge`)
2. THE CLI SHALL folgende Unterkommandos unterstützen: `capture` (Quick-Capture), `ingest` (Pipeline-Durchlauf starten), `search` (Suche über Knowledge-Index), `status` (Übersicht über Inbox-Elemente und letzte Verarbeitung)
3. THE CLI SHALL den aktiven Kontext über das Flag `--context` oder automatisch aus dem aktuellen Arbeitsverzeichnis ableiten
4. WHEN das Unterkommando `ingest` ausgeführt wird, THE CLI SHALL die `sources.yaml` des aktiven Kontexts laden und alle konfigurierten Quellen verarbeiten
5. THE CLI SHALL die Flags `--dry-run` (Vorschau ohne Schreiboperationen), `--verbose` (detaillierte Ausgabe) und `--no-commit` (Git-Commit überspringen) unterstützen
6. WHEN das Unterkommando `search` mit einem Suchbegriff ausgeführt wird, THE CLI SHALL die Ergebnisse mit Titel, Typ, Tags und Dateipfad auf der Konsole ausgeben
7. WHEN das CLI ohne Argumente aufgerufen wird, THE CLI SHALL eine Hilfe-Nachricht mit verfügbaren Unterkommandos und Beispielen anzeigen
### Requirement 16: Git-Integration und Versionierung
**User Story:** Als Wissensarbeiter möchte ich, dass alle Wissensänderungen automatisch versioniert werden, damit ich die Historie meines Wissensspeichers nachvollziehen und bei Bedarf zurückspringen kann.
#### Acceptance Criteria
1. WHEN die Ingestion_Pipeline neue oder aktualisierte Artefakte erzeugt, THE Knowledge_Management_System SHALL diese automatisch mit einer beschreibenden Commit-Message in Git committen
2. THE Knowledge_Management_System SHALL die Commit-Message im Format `knowledge({context}): {action} {count} artifacts from {source}` generieren (z.B. `knowledge(bahn): ingest 3 artifacts from confluence`)
3. WHEN der Quick_Capture ein neues Artefakt erstellt, THE Knowledge_Management_System SHALL einen separaten Commit mit der Message `knowledge({context}): capture "{title}"` erzeugen
4. WHEN das Flag `--no-commit` gesetzt ist, THE Knowledge_Management_System SHALL keine Git-Commits erzeugen
5. IF ein Git-Commit fehlschlägt, THEN THE Knowledge_Management_System SHALL eine Warnung protokollieren, die erstellten Dateien beibehalten und die Verarbeitung fortsetzen
6. FOR ALL gültige Artefakt-Inhalte, das Schreiben in eine Markdown-Datei mit YAML-Frontmatter und anschließendes Einlesen SHALL ein identisches ArtifactMetadata-Objekt reproduzieren (Round-Trip-Eigenschaft)
+325
View File
@@ -0,0 +1,325 @@
# Implementation Plan: Knowledge Management System
## Overview
Implementierung des vereinheitlichten Knowledge Management Systems als Erweiterung des bestehenden Monorepo-CLI. Die Umsetzung erfolgt inkrementell: zuerst die Kerninfrastruktur (Datenmodelle, Routing, Konfiguration), dann die Ingestion-Pipeline, Source-Strategien, Enrichment, Integrationen und abschließend die CLI-Schnittstelle.
**Sprache:** Python (konsistent mit dem bestehenden Monorepo-CLI)
**Pfade:**
- Ingestion-Pipeline: `shared/tools/monorepo-cli/src/monorepo/knowledge/ingestion/`
- Source-Strategien: `shared/tools/monorepo-cli/src/monorepo/knowledge/sources/`
- Integrationen: `shared/tools/monorepo-cli/src/monorepo/knowledge/integrations/`
- CLI: `shared/tools/monorepo-cli/src/monorepo/knowledge/cli.py`
- Knowledge-Ordner: `bahn/knowledge/`, `dhive/knowledge/`, `privat/knowledge/`
## Tasks
- [x] 1. Projekt-Struktur und Knowledge-Ordner anlegen
- [x] 1.1 Erstelle die Knowledge-Ordner-Struktur für alle drei Kontexte
- Erstelle `bahn/knowledge/`, `dhive/knowledge/`, `privat/knowledge/` mit Unterordnern: `inbox/`, `meetings/`, `decisions/`, `projects/`, `people/`, `references/`, `links/`
- Erstelle eine `index.md` pro Unterordner als Platzhalter-Inhaltsverzeichnis
- Erstelle eine leere `_index.yaml` und `sources.yaml` pro Kontext-Knowledge-Folder
- _Requirements: 1.1, 1.2, 1.6, 12.1_
- [x] 1.2 Erstelle die Modul-Struktur für die Ingestion-Pipeline
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/ingestion/__init__.py`
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/sources/__init__.py`
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/integrations/__init__.py`
- Erstelle leere Module: `pipeline.py`, `router.py`, `enrichment.py`, `capture.py`, `config.py`, `git_integration.py` im ingestion-Ordner
- _Requirements: 2.1_
- [x] 2. Datenmodelle und Konfiguration
- [x] 2.1 Erweitere ArtifactMetadata um Knowledge-Management-Felder
- Erweitere die bestehende `ArtifactMetadata`-Klasse in `artifact.py` um: `source` (dict), `category` (str), `people` (list), `projects` (list), `enrichment_pending` (bool), `ocr_failed` (bool), `fetch_failed` (bool)
- Stelle Rückwärtskompatibilität sicher (alle neuen Felder sind optional mit Defaults)
- Passe `parse`/`write`-Funktionen an, damit Round-Trip für erweiterte Felder funktioniert
- _Requirements: 1.5, 16.6_
- [x] 2.2 Property-Test: Artifact Serialization Round-Trip
- **Property 1: Artifact Serialization Round-Trip**
- **Validates: Requirements 16.6, 1.5**
- [x] 2.3 Implementiere SourceConfig und sources.yaml-Parsing
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/ingestion/config.py`
- Implementiere `SourceConfig`-Dataclass mit Feldern: type, name, params, target_folder, sync_frequency, enabled
- Implementiere `load_sources_config(path: Path) -> list[SourceConfig]` zum Parsen der YAML-Datei
- Implementiere Umgebungsvariablen-Auflösung für `${VAR_NAME}`-Patterns in Werten
- Implementiere Validierung: fehlende Pflichtfelder, nicht auflösbare Env-Vars → Fehler
- _Requirements: 12.1, 12.2, 12.4, 12.6_
- [x] 2.4 Property-Test: Environment Variable Resolution
- **Property 21: Environment Variable Resolution in Config**
- **Validates: Requirements 12.4, 12.6**
- [x] 3. Context Router
- [x] 3.1 Implementiere ContextRouter
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/ingestion/router.py`
- Implementiere `determine_context(source_config, cwd)` leitet Kontext aus SourceConfig oder Arbeitsverzeichnis ab
- Implementiere `resolve_target_path(context, category, filename)` berechnet `{root}/{context}/knowledge/{category}/{filename}`
- Implementiere Kategorie-zu-Ordner-Mapping: meeting→meetings/, decision→decisions/, project→projects/, reference→references/, link→links/, inbox→inbox/, unbekannt→inbox/
- _Requirements: 1.4, 2.3, 3.2, 3.5, 9.6_
- [x] 3.2 Property-Tests: Context Routing und Category Mapping
- **Property 2: Context Derivation from Path**
- **Property 6: Context Routing Determinism**
- **Property 8: Category to Folder Mapping**
- **Validates: Requirements 1.4, 2.3, 3.2, 3.5, 9.6**
- [x] 4. Checkpoint Basis-Infrastruktur
- Ensure all tests pass, ask the user if questions arise.
- [x] 5. Quick Capture und Inbox
- [x] 5.1 Implementiere QuickCapture
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/ingestion/capture.py`
- Implementiere `capture(input_text, context, tags)` erzeugt Markdown-Datei in `{context}/knowledge/inbox/`
- Implementiere `_detect_input_type(input_text)` erkennt ob Input eine URL, ein Dateipfad oder Freitext ist
- Implementiere `_generate_filename(title)` erzeugt `YYYY-MM-DD-HH-MM-title-slug.md`
- Erzeuge minimales Frontmatter: title, created, source, type: inbox
- Gib den Dateipfad des erstellten Artefakts zurück
- _Requirements: 3.1, 3.2, 3.3, 3.7, 8.3_
- [x] 5.2 Property-Tests: Quick Capture
- **Property 7: Filename Pattern from Title**
- **Property 11: URL Detection in Quick Capture**
- **Validates: Requirements 3.3, 8.3**
- [x] 6. Source Strategies Base und Markdown
- [x] 6.1 Implementiere SourceStrategy ABC und MarkdownSource
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/sources/base.py` mit `SourceStrategy` ABC (extract, supports_incremental)
- Erstelle `ExtractionResult`-Dataclass und `SourceError`-Dataclass
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/sources/markdown.py`
- Implementiere MarkdownSource: liest .md/.txt-Dateien, extrahiert bestehendes Frontmatter
- Unterstütze inkrementelle Verarbeitung via Content-Hash
- _Requirements: 2.2, 2.4, 2.7, 4.1_
- [x] 6.2 Property-Test: File Extension Format Detection
- **Property 9: File Extension Format Detection**
- **Validates: Requirements 4.7**
- [x] 6.3 Implementiere PDF- und OCR-Source
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/sources/pdf.py`
- Implementiere PDF-Text-Extraktion (eingebetteter Text via PyPDF2 oder pdfplumber)
- Implementiere OCR-Fallback für gescannte Seiten (Kiro Vision als primärer Provider)
- Setze `ocr_failed: true` falls OCR fehlschlägt
- Behalte Referenz auf Originaldatei in `source.file`
- _Requirements: 4.2, 4.3, 4.4, 4.5, 4.6_
- [x] 6.4 Property-Test: Image Source File Reference
- **Property 10: Image Source File Reference Preservation**
- **Validates: Requirements 4.5**
- [x] 7. Source Strategies Externe Quellen
- [x] 7.1 Implementiere Confluence-Source
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/sources/confluence.py`
- Implementiere Confluence REST-API-Anbindung (Seiten, Bäume, FAQ-Spaces)
- Extrahiere Seiteninhalte als Markdown, reichere Frontmatter an (URL, Space, Titel, Last-Modified)
- Unterstütze inkrementelle Updates via Versions-Nummer
- Behandle API-Fehler graceful (skip source, log error)
- _Requirements: 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7_
- [x] 7.2 Implementiere Jira-Source
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/sources/jira.py`
- Implementiere JQL-basierte Issue-Extraktion
- Stelle Issue als Markdown zusammen (Summary, Description, Kommentare, Status)
- Reichere Frontmatter an (Issue-Key, Projekt, Status, Assignee, Reporter, URL)
- Unterstütze inkrementelle Updates via `updated`-Feld
- _Requirements: 6.1, 6.2, 6.3, 6.4, 6.5, 6.7_
- [x] 7.3 Implementiere Email- und Chat-Source
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/sources/email.py`
- Implementiere .eml/.msg-Parsing (Absender, Empfänger, Betreff, Datum, Body)
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/sources/chat.py`
- Implementiere Chat-Export-Parsing (Text/JSON)
- Verarbeite Anhänge als separate Artefakte mit Link im Eltern-Artefakt
- _Requirements: 7.1, 7.2, 7.3, 7.5, 7.6_
- [x] 7.4 Implementiere Link-Source und LinkRegistry
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/sources/link.py`
- Implementiere `LinkRegistry`: save_link, search_links, _fetch_metadata, _find_existing
- Speichere Links als Artefakte vom Typ `link` in `links/`
- Implementiere URL-Deduplication mit Tag-Merging
- Implementiere Suche über URL, Titel, Tags
- Setze `fetch_failed: true` falls URL nicht erreichbar
- _Requirements: 8.1, 8.2, 8.4, 8.5, 8.6, 8.7_
- [x] 7.5 Property-Tests: Link Registry
- **Property 12: Link Artifact Structure**
- **Property 13: Link Deduplication with Tag Merging**
- **Property 14: Link Search Completeness**
- **Validates: Requirements 8.1, 8.2, 8.6, 8.7**
- [x] 7.6 Implementiere Wissensdatenbank-Source
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/sources/wissensdatenbank.py`
- Implementiere Adapter für `bahn/wissensdatenbank/output/`
- Führe Artefakte als Read-Only-Referenzen im Index (`source: wissensdatenbank`)
- Lasse Originaldateien unverändert (kein Google-OKF-Reformat)
- _Requirements: 13.1, 13.2, 13.3, 13.4, 13.5_
- [x] 8. Checkpoint Source Strategies
- Ensure all tests pass, ask the user if questions arise.
- [x] 9. Enrichment Agent
- [x] 9.1 Implementiere EnrichmentAgent
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/ingestion/enrichment.py`
- Implementiere `enrich(content, source_type)` → EnrichmentResult (title, category, tags, people, projects, action_items, confidence)
- Implementiere `classify_relevance(content)` → float
- Implementiere Kiro-first Provider-Strategie (kein API-Key nötig im Normalfall)
- Implementiere Konfidenz-Schwelle: nur Entitäten ≥ 0.7 in Ausgabe
- Generiere Wiki-Links: `[[people/vorname-nachname]]`, `[[projects/projekt-slug]]`
- Generiere `## Action Items`-Abschnitt aus erkannten ActionItems
- Setze `enrichment_pending: true` falls Provider nicht erreichbar
- _Requirements: 9.1, 9.2, 9.3, 9.4, 9.5, 9.7_
- [x] 9.2 Property-Tests: Enrichment
- **Property 15: Wiki-Link Format for Entities**
- **Property 16: Confidence Threshold Filtering**
- **Property 17: Action Items Section Generation**
- **Validates: Requirements 9.2, 9.4, 9.5**
- [x] 10. Ingestion Pipeline Orchestrator
- [x] 10.1 Implementiere IngestionPipeline
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/ingestion/pipeline.py`
- Implementiere `run()`: load config → extract (via Strategies) → enrich → store → index → commit
- Implementiere `process_inbox()`: verarbeite alle Dateien in `{context}/knowledge/inbox/`
- Implementiere inkrementelle Verarbeitung via Content-Hash (skip unchanged)
- Implementiere Fail-Forward: einzelne Source-Fehler loggen, Rest weiterverarbeiten
- Aktualisiere `_index.yaml` nach jedem Durchlauf
- Aktualisiere `index.md` pro Unterordner (OKF-Konformität)
- Gib `IngestionResult` zurück (processed, updated, skipped, errors, tasks_created, commit_sha)
- _Requirements: 2.2, 2.3, 2.4, 2.5, 2.6, 3.4, 3.5, 3.6, 12.3_
- [x] 10.2 Property-Tests: Ingestion Pipeline
- **Property 3: Idempotent Ingestion via Content Hash**
- **Property 4: Error Resilience Partial Source Failure**
- **Property 5: Index Completeness After Ingestion**
- **Property 24: Ingestion Produces Valid Artifacts**
- **Validates: Requirements 2.2, 2.4, 2.5, 2.6**
- [x] 11. Integrationen
- [x] 11.1 Implementiere OrgMyLife-Integration
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/integrations/orgmylife.py`
- Implementiere `create_tasks(artifact_id, action_items, source_path)` → list[TaskMapping]
- Implementiere Deduplication via `.task-mapping.yaml` (Hash-basiert)
- Erstelle Tasks nur für neue Action-Items (nicht bereits gemappte)
- Setze Deadline falls im ActionItem erkannt
- Behandle API-Fehler graceful (Warnung loggen, weiter)
- _Requirements: 10.1, 10.2, 10.3, 10.4, 10.5, 10.6_
- [x] 11.2 Property-Test: Task Deduplication
- **Property 18: Task Deduplication via Mapping**
- **Validates: Requirements 10.5, 10.6**
- [x] 11.3 Implementiere Git-Auto-Commit-Integration
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/ingestion/git_integration.py`
- Implementiere Commit-Message-Generierung im Format `knowledge({context}): {action} {count} artifacts from {source}`
- Implementiere `auto_commit(context, action, count, source, paths)` staged + committed
- Respektiere `--no-commit`-Flag und `git.auto_commit`-Config
- Behandle Git-Fehler graceful (Warnung, Dateien bleiben)
- _Requirements: 16.1, 16.2, 16.3, 16.4, 16.5_
- [x] 11.4 Property-Test: Git Commit Message Format
- **Property 23: Git Commit Message Format**
- **Validates: Requirements 16.2**
- [x] 11.5 Implementiere Kiro-Client-Integration
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/integrations/kiro_client.py`
- Implementiere Wrapper für Kiro AI-Agent als LLM-Provider (Enrichment + OCR)
- Implementiere Fallback-Logik: Kiro nicht verfügbar → `enrichment_pending: true`
- _Requirements: 9.3, 9.7_
- [x] 12. Checkpoint Pipeline und Integrationen
- Ensure all tests pass, ask the user if questions arise.
- [x] 13. Suche und Federation
- [x] 13.1 Erweitere die Suche um Knowledge-Folder-Support
- Erweitere `store.py` um kontextübergreifende Suche über alle `_index.yaml`-Dateien
- Implementiere Scope-Filterung (nur autorisierte Kontexte in Ergebnissen)
- Implementiere Agent-Context-Injection: max. 10 relevante Artefakt-Pfade, sortiert nach Relevanz
- Implementiere Progressive-Disclosure: Schicht 1 (Index) für Relevanz, Schicht 2 (Datei) bei Bedarf
- _Requirements: 11.1, 11.2, 11.3, 11.5, 11.6_
- [x] 13.2 Property-Tests: Suche
- **Property 19: Scope-Filtered Search Isolation**
- **Property 20: Context Injection Result Limit**
- **Validates: Requirements 11.5, 11.6**
- [x] 13.3 Implementiere Federation-Sync-Filter
- Erweitere die bestehende Federation-Logik um Knowledge-Ordner-Behandlung
- Exkludiere Artefakte mit `shareable: false` aus der Sync-Liste
- Exkludiere ctx-guard-markierte sensible Artefakte
- Stelle sicher, dass keine kontextübergreifenden Links in Team-Repos gelangen
- _Requirements: 14.1, 14.2, 14.3, 14.4, 14.5_
- [x] 13.4 Property-Test: Federation Sync Exclusion
- **Property 22: Federation Sync Exclusion**
- **Validates: Requirements 14.4**
- [x] 14. CLI-Schnittstelle
- [x] 14.1 Implementiere das knowledge-Subcommand
- Erstelle `shared/tools/monorepo-cli/src/monorepo/knowledge/cli.py`
- Registriere als Subcommand-Gruppe unter dem Monorepo-CLI
- Implementiere `knowledge capture <text|url|path> [--context CTX] [--tags TAG,TAG]`
- Implementiere `knowledge ingest [--context CTX] [--dry-run] [--verbose] [--no-commit]`
- Implementiere `knowledge search <query> [--context CTX] [--limit N]`
- Implementiere `knowledge status [--context CTX]`
- Implementiere `knowledge link <url> [--title TITLE] [--tags TAG,TAG] [--context CTX]`
- Implementiere Hilfe-Ausgabe bei Aufruf ohne Argumente
- Leite Kontext aus `--context`-Flag oder CWD ab
- _Requirements: 15.1, 15.2, 15.3, 15.4, 15.5, 15.6, 15.7_
- [x] 14.2 Unit-Tests: CLI-Argument-Parsing
- Teste alle Subcommands mit verschiedenen Flag-Kombinationen
- Teste Kontext-Ableitung aus CWD
- Teste Hilfe-Ausgabe
- _Requirements: 15.2, 15.3, 15.7_
- [x] 15. End-to-End-Wiring und Integration
- [x] 15.1 Verdrahte alle Komponenten im Pipeline-Orchestrator
- Verbinde CLI → Router → Pipeline → Sources → Enrichment → Store → Index → Git
- Stelle sicher, dass `knowledge ingest` den vollständigen Workflow durchläuft
- Stelle sicher, dass `knowledge capture` → Inbox → nächster `ingest`-Durchlauf → Kategorisierung funktioniert
- Verbinde OrgMyLife-Integration (Task-Erstellung bei Action-Items)
- Aktualisiere `__init__.py` aller Module mit korrekten Exports
- _Requirements: 2.1, 2.2, 2.3, 3.4, 10.1_
- [x] 15.2 Integration-Tests: Full Pipeline E2E
- Teste vollständigen Pipeline-Durchlauf mit Fixture-Daten
- Teste Quick Capture → Inbox → Ingest → Kategorisierung
- Teste Confluence- und Jira-Source mit gemockten API-Responses
- _Requirements: 2.2, 2.3, 5.1, 6.1_
- [x] 16. Final Checkpoint Alle Tests bestehen
- Ensure all tests pass, ask the user if questions arise.
## Notes
- Tasks mit `*` markiert sind optional und können für ein schnelleres MVP übersprungen werden
- Jede Task referenziert spezifische Requirements für Nachvollziehbarkeit
- Checkpoints sichern inkrementelle Validierung
- Property-Tests validieren universelle Korrektheitseigenschaften aus dem Design-Dokument
- Unit-Tests validieren spezifische Beispiele und Edge Cases
- Die bestehenden Module in `shared/tools/monorepo-cli/src/monorepo/knowledge/` (artifact.py, etl.py, index.py, store.py) werden wiederverwendet und erweitert nicht neu geschrieben
- Kiro ist der primäre LLM/OCR-Provider; LiteLLM und Tesseract sind optionale Alternativen für CI/Batch
## Task Dependency Graph
```json
{
"waves": [
{ "id": 0, "tasks": ["1.1", "1.2"] },
{ "id": 1, "tasks": ["2.1", "2.3"] },
{ "id": 2, "tasks": ["2.2", "2.4", "3.1"] },
{ "id": 3, "tasks": ["3.2", "5.1"] },
{ "id": 4, "tasks": ["5.2", "6.1"] },
{ "id": 5, "tasks": ["6.2", "6.3", "7.4", "7.6"] },
{ "id": 6, "tasks": ["6.4", "7.1", "7.2", "7.3", "7.5"] },
{ "id": 7, "tasks": ["9.1"] },
{ "id": 8, "tasks": ["9.2", "10.1"] },
{ "id": 9, "tasks": ["10.2", "11.1", "11.3", "11.5"] },
{ "id": 10, "tasks": ["11.2", "11.4", "13.1", "13.3"] },
{ "id": 11, "tasks": ["13.2", "13.4", "14.1"] },
{ "id": 12, "tasks": ["14.2", "15.1"] },
{ "id": 13, "tasks": ["15.2"] }
]
}
```
+35
View File
@@ -0,0 +1,35 @@
---
inclusion: fileMatch
fileMatchPattern: "bahn/**"
---
# Bahn-Kontext
When working on any file under `bahn/`, always consider the **Wissensdatenbank** (`bahn/wissensdatenbank/`) as relevant context.
## Wissensdatenbank (ETL-Pipeline für LLM/RAG)
Location: `bahn/wissensdatenbank/`
Remote: `https://git.tech.rz.db.de/einfachbahn-lab/tools/wissensdatenbank_group/wissensdatenbank.git`
This is the central knowledge base ETL pipeline for DB InfraGO 1st-level support and chatbots. Key points:
- **Purpose:** Collects knowledge from Confluence, web pages, PDFs, GitLab repos → processes into Markdown → serves as Single Source of Truth for vector DBs/chatbots
- **Architecture:** ETL pipeline with strategies (confluence_page, confluence_tree, crawler, sitemap, gitlab_md, file, pdf)
- **Output:** `data/processed/<scope>/<domain>/` (intern, extern, allgemein)
- **Config:** `config/tools.yaml`, `config/general.yaml`, `config/filter_rules.json`
- **Key files:** `src/` (pipeline code), `config/` (tool/source definitions), `data/` (processed output)
## When to reference it
- Any bahn project that involves knowledge, documentation, or AI/chatbot integration
- When discussing scope classification (intern/extern/allgemein)
- When building MCP servers or tools that consume DB knowledge
- When working on O2C-Harness, aisupport, or Confluence_Bot (they feed into or consume from the Wissensdatenbank)
## Sync
```powershell
git subtree pull --prefix=bahn/wissensdatenbank wissensdatenbank main --squash
git subtree push --prefix=bahn/wissensdatenbank wissensdatenbank main
```