mindnet_obsidian/docs/10_Workbench_Findings_Integration.md
Lars a9b3e2f0e2
Some checks are pending
Node.js build / build (20.x) (push) Waiting to run
Node.js build / build (22.x) (push) Waiting to run
Implement Chain Workbench and Vault Triage features in Mindnet plugin
- Introduced new workflows for Chain Workbench and Vault Triage, enhancing user capabilities for managing template matches and identifying chain gaps.
- Added commands for opening the Chain Workbench and scanning the vault for chain gaps, improving the overall functionality of the plugin.
- Updated documentation to include detailed instructions for the new workflows, ensuring users can effectively utilize the features.
- Enhanced the UI for both the Chain Workbench and Vault Triage Scan, providing a more intuitive user experience.
- Implemented tests for the new functionalities to ensure reliability and accuracy in various scenarios.
2026-01-26 10:51:12 +01:00

343 lines
10 KiB
Markdown

# Chain Workbench - Findings Integration (Vorschlag)
> **Status:** Vorschlag für zukünftige Implementierung
> **Stand:** 2025-01-XX
> **Zielgruppe:** Entwickler
---
## Problemstellung
Die Chain Workbench (0.5.x) verwendet aktuell **nur** Template Matches aus Chain Inspector (0.4.x), nicht aber die **Findings** und **Gap-Heuristiken**, die aufwendig getestet wurden.
**Verlorene Informationen:**
- `dangling_target` - Target-Datei existiert nicht
- `dangling_target_heading` - Target-Heading existiert nicht
- `only_candidates` - Nur Candidate-Edges, keine expliziten
- `missing_edges` - Section hat Content aber keine Edges
- `no_causal_roles` - Section hat Edges aber keine kausalen Rollen
- `one_sided_connectivity` - Nur incoming oder nur outgoing edges
---
## Lösungsvorschlag
### 1. Findings zu Todos konvertieren
Erweitere `todoGenerator.ts` um eine Funktion `generateFindingsTodos()`:
```typescript
/**
* Generate todos from Chain Inspector findings.
*/
export function generateFindingsTodos(
findings: Finding[],
allEdges: IndexedEdge[],
context: { file: string; heading: string | null }
): WorkbenchTodoUnion[] {
const todos: WorkbenchTodoUnion[] = [];
for (const finding of findings) {
switch (finding.code) {
case "dangling_target":
// Find edge with dangling target
const danglingEdge = allEdges.find(
(e) => e.target.file === finding.evidence?.file
);
if (danglingEdge) {
todos.push({
type: "dangling_target",
id: `dangling_target_${finding.evidence?.file}`,
description: finding.message,
priority: finding.severity === "error" ? "high" : "medium",
targetFile: danglingEdge.target.file,
targetHeading: danglingEdge.target.heading,
sourceEdge: {
file: "sectionHeading" in danglingEdge.source
? danglingEdge.source.file
: danglingEdge.source.file,
heading: "sectionHeading" in danglingEdge.source
? danglingEdge.source.sectionHeading
: null,
},
actions: ["create_missing_note", "retarget_link"],
});
}
break;
case "dangling_target_heading":
// Similar to dangling_target, but for headings
todos.push({
type: "dangling_target_heading",
id: `dangling_target_heading_${finding.evidence?.file}_${finding.evidence?.sectionHeading}`,
description: finding.message,
priority: finding.severity === "warn" ? "medium" : "low",
targetFile: finding.evidence?.file || "",
targetHeading: finding.evidence?.sectionHeading || null,
actions: ["create_missing_heading", "retarget_to_existing_heading"],
});
break;
case "only_candidates":
// Find all candidate edges in section
const candidateEdges = allEdges.filter(
(e) => e.scope === "candidate" &&
("sectionHeading" in e.source
? e.source.sectionHeading === context.heading
: false)
);
if (candidateEdges.length > 0) {
todos.push({
type: "only_candidates",
id: `only_candidates_${context.file}_${context.heading}`,
description: finding.message,
priority: "medium",
candidateEdges: candidateEdges.map((e) => ({
rawEdgeType: e.rawEdgeType,
from: "sectionHeading" in e.source
? { file: e.source.file, heading: e.source.sectionHeading }
: { file: e.source.file, heading: null },
to: e.target,
})),
actions: ["promote_all_candidates", "create_explicit_edges"],
});
}
break;
case "missing_edges":
todos.push({
type: "missing_edges",
id: `missing_edges_${context.file}_${context.heading}`,
description: finding.message,
priority: "medium",
section: {
file: context.file,
heading: context.heading,
},
actions: ["add_edges_to_section"],
});
break;
case "no_causal_roles":
// Find edges without causal roles
const nonCausalEdges = allEdges.filter(
(e) => e.scope === "section" &&
("sectionHeading" in e.source
? e.source.sectionHeading === context.heading
: false)
);
todos.push({
type: "no_causal_roles",
id: `no_causal_roles_${context.file}_${context.heading}`,
description: finding.message,
priority: "medium",
edges: nonCausalEdges.map((e) => ({
rawEdgeType: e.rawEdgeType,
from: "sectionHeading" in e.source
? { file: e.source.file, heading: e.source.sectionHeading }
: { file: e.source.file, heading: null },
to: e.target,
currentRole: null, // Would need to resolve via chain_roles
suggestedRoles: ["causal", "influences", "enables_constraints"],
})),
actions: ["change_edge_type"],
});
break;
case "one_sided_connectivity":
// Informational only
todos.push({
type: "one_sided_connectivity",
id: `one_sided_connectivity_${context.file}_${context.heading}`,
description: finding.message,
priority: "low",
section: {
file: context.file,
heading: context.heading,
},
actions: [], // No actions, informational only
});
break;
}
}
return todos;
}
```
### 2. Erweitere Todo-Types
Füge neue Todo-Types zu `types.ts` hinzu:
```typescript
export type TodoType =
| "missing_slot"
| "missing_link"
| "weak_roles"
| "candidate_cleanup"
| "create_candidates_zone"
| "create_note_links_zone"
| "dangling_target" // NEU
| "dangling_target_heading" // NEU
| "only_candidates" // NEU
| "missing_edges" // NEU
| "no_causal_roles" // NEU
| "one_sided_connectivity"; // NEU
export interface DanglingTargetTodo extends WorkbenchTodo {
type: "dangling_target";
targetFile: string;
targetHeading: string | null;
sourceEdge: {
file: string;
heading: string | null;
};
actions: Array<"create_missing_note" | "retarget_link">;
}
export interface DanglingTargetHeadingTodo extends WorkbenchTodo {
type: "dangling_target_heading";
targetFile: string;
targetHeading: string | null;
actions: Array<"create_missing_heading" | "retarget_to_existing_heading">;
}
export interface OnlyCandidatesTodo extends WorkbenchTodo {
type: "only_candidates";
candidateEdges: Array<{
rawEdgeType: string;
from: { file: string; heading: string | null };
to: { file: string; heading: string | null };
}>;
actions: Array<"promote_all_candidates" | "create_explicit_edges">;
}
export interface MissingEdgesTodo extends WorkbenchTodo {
type: "missing_edges";
section: {
file: string;
heading: string | null;
};
actions: Array<"add_edges_to_section">;
}
export interface NoCausalRolesTodo extends WorkbenchTodo {
type: "no_causal_roles";
edges: Array<{
rawEdgeType: string;
from: { file: string; heading: string | null };
to: { file: string; heading: string | null };
currentRole: string | null;
suggestedRoles: string[];
}>;
actions: Array<"change_edge_type">;
}
export interface OneSidedConnectivityTodo extends WorkbenchTodo {
type: "one_sided_connectivity";
section: {
file: string;
heading: string | null;
};
actions: []; // Informational only
}
```
### 3. Integriere Findings in Workbench Builder
Erweitere `workbenchBuilder.ts`:
```typescript
export async function buildWorkbenchModel(
app: App,
report: ChainInspectorReport,
chainTemplates: ChainTemplatesConfig | null,
chainRoles: ChainRolesConfig | null,
edgeVocabulary: EdgeVocabulary | null,
allEdges: IndexedEdge[]
): Promise<WorkbenchModel> {
const matches: WorkbenchMatch[] = [];
const globalTodos: WorkbenchTodoUnion[] = []; // NEU: Global todos from findings
// ... existing template match processing ...
// NEU: Generate todos from findings
if (report.findings && report.findings.length > 0) {
const findingsTodos = generateFindingsTodos(
report.findings,
allEdges,
report.context
);
globalTodos.push(...findingsTodos);
}
return {
context: report.context,
matches,
globalTodos, // NEU: Add global todos
timestamp: Date.now(),
};
}
```
### 4. Erweitere WorkbenchModel Interface
```typescript
export interface WorkbenchModel {
context: {
file: string;
heading: string | null;
zoneKind: string;
};
matches: WorkbenchMatch[];
globalTodos?: WorkbenchTodoUnion[]; // NEU: Todos from findings (not template-based)
timestamp: number;
}
```
### 5. UI-Integration
Erweitere `ChainWorkbenchModal.ts`:
```typescript
// Show global todos (from findings) separately
if (model.globalTodos && model.globalTodos.length > 0) {
// Render "Section-Level Issues" section
// Show findings-based todos before template matches
}
```
---
## Vorteile
1. **Nutzt getestete Heuristiken** - Findings aus 0.4.x werden verwendet
2. **Vollständigere Analyse** - Nicht nur Template-basiert, sondern auch Section-Level
3. **Konsistenz** - Chain Inspector und Workbench zeigen dieselben Probleme
4. **Bessere UX** - User sieht alle Probleme auf einen Blick
---
## Implementierungsreihenfolge
1. **Phase 1:** Todo-Types erweitern (`types.ts`)
2. **Phase 2:** `generateFindingsTodos()` implementieren (`todoGenerator.ts`)
3. **Phase 3:** `buildWorkbenchModel()` erweitern (`workbenchBuilder.ts`)
4. **Phase 4:** UI erweitern (`ChainWorkbenchModal.ts`)
5. **Phase 5:** Actions implementieren (z.B. `create_missing_note`, `retarget_link`)
---
## Offene Fragen
1. **Priorität:** Sollen Findings-Todos höhere Priorität haben als Template-Todos?
2. **Duplikate:** Wie vermeiden wir Duplikate zwischen Findings-Todos und Template-Todos?
- Beispiel: `dangling_target` könnte auch als `missing_link` Todo erscheinen
3. **Filterung:** Sollen Findings-Todos gefiltert werden können (z.B. nur Errors)?
4. **Actions:** Welche Actions sind für welche Findings sinnvoll?
---
**Letzte Aktualisierung:** 2025-01-XX
**Status:** Vorschlag für zukünftige Implementierung