- 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.
10 KiB
10 KiB
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 nichtdangling_target_heading- Target-Heading existiert nichtonly_candidates- Nur Candidate-Edges, keine explizitenmissing_edges- Section hat Content aber keine Edgesno_causal_roles- Section hat Edges aber keine kausalen Rollenone_sided_connectivity- Nur incoming oder nur outgoing edges
Lösungsvorschlag
1. Findings zu Todos konvertieren
Erweitere todoGenerator.ts um eine Funktion generateFindingsTodos():
/**
* 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:
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:
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
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:
// 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
- Nutzt getestete Heuristiken - Findings aus 0.4.x werden verwendet
- Vollständigere Analyse - Nicht nur Template-basiert, sondern auch Section-Level
- Konsistenz - Chain Inspector und Workbench zeigen dieselben Probleme
- Bessere UX - User sieht alle Probleme auf einen Blick
Implementierungsreihenfolge
- Phase 1: Todo-Types erweitern (
types.ts) - Phase 2:
generateFindingsTodos()implementieren (todoGenerator.ts) - Phase 3:
buildWorkbenchModel()erweitern (workbenchBuilder.ts) - Phase 4: UI erweitern (
ChainWorkbenchModal.ts) - Phase 5: Actions implementieren (z.B.
create_missing_note,retarget_link)
Offene Fragen
- Priorität: Sollen Findings-Todos höhere Priorität haben als Template-Todos?
- Duplikate: Wie vermeiden wir Duplikate zwischen Findings-Todos und Template-Todos?
- Beispiel:
dangling_targetkönnte auch alsmissing_linkTodo erscheinen
- Beispiel:
- Filterung: Sollen Findings-Todos gefiltert werden können (z.B. nur Errors)?
- Actions: Welche Actions sind für welche Findings sinnvoll?
Letzte Aktualisierung: 2025-01-XX
Status: Vorschlag für zukünftige Implementierung