- Added a new command to fix findings in the current section of a markdown file, enhancing user experience by automating issue resolution. - Introduced settings for configuring actions related to missing notes and headings, allowing for customizable behavior during the fixing process. - Enhanced the chain inspector to support template matching, providing users with insights into template utilization and potential gaps in their content. - Updated the analysis report to include detailed metadata about edges and role matches, improving the clarity and usefulness of inspection results. - Improved error handling and user notifications for fixing findings and template matching processes, ensuring better feedback during execution.
5.5 KiB
Dangling Target Cases - Übersicht
Welche Fälle werden erkannt?
Chain Inspector v0.2+ erkennt zwei Arten von dangling_target Findings:
1. dangling_target (Severity: ERROR)
Wann wird es erkannt?
- Ein outgoing Edge von der aktuellen Section verweist auf eine Datei, die nicht existiert
- Die Datei wird über
app.metadataCache.getFirstLinkpathDest()aufgelöst - Wenn die Auflösung
nullzurückgibt →dangling_targetFinding
Welche Edges werden geprüft?
- Alle section-scoped Edges aus der aktuellen Section (nicht Note-scoped, nicht Candidates)
- Edges aus expliziten Edge-Callouts:
> [!edge] <type>\n> [[TargetFile]] - Edges aus Semantic Mapping Blocks
Beispiele:
## Meine Section
> [!edge] causes
> [[MissingNote]] ← dangling_target (ERROR)
> [!abstract] 🕸️ Semantic Mapping
>> [!edge] influences
>> [[AnotherMissingNote]] ← dangling_target (ERROR)
Was wird NICHT geprüft?
- ❌ Note-scoped Edges (aus "## Note-Verbindungen" Zone)
- ❌ Candidate Edges (aus "## Kandidaten" Zone)
- ❌ Incoming Edges (nur outgoing Edges werden geprüft)
2. dangling_target_heading (Severity: WARN)
Wann wird es erkannt?
- Ein outgoing Edge verweist auf eine existierende Datei, aber mit einem Heading, das nicht existiert
- Die Datei existiert (wird erfolgreich aufgelöst)
- Das Heading wird in
metadataCache.getFileCache()geprüft - Wenn das Heading nicht in der Liste der Headings gefunden wird →
dangling_target_headingFinding
Beispiele:
## Meine Section
> [!edge] references
> [[ExistingNote#MissingHeading]] ← dangling_target_heading (WARN)
> [!edge] part_of
> [[AnotherNote#NonExistentSection]] ← dangling_target_heading (WARN)
Was passiert wenn File Cache nicht verfügbar ist?
- Wenn
getFileCache()nullzurückgibt (z.B. Datei noch nicht indexiert) - → Kein Finding (wird übersprungen, da Cache später aktualisiert wird)
Welche Fälle sind behebbar?
✅ Behebbar via Fix Actions:
-
dangling_target(ERROR)- ✅ Action 1: Create Missing Note
- Erstellt neue Note (skeleton oder mit Profile/Wizard)
- Verwendet Settings:
fixActions.createMissingNote.*
- ✅ Action 2: Retarget Link
- Zeigt Entity Picker Modal
- Ersetzt Link im Editor zu existierender Note
- Behält Heading bei wenn vorhanden
- ✅ Action 1: Create Missing Note
-
dangling_target_heading(WARN)- ✅ Action 1: Create Missing Heading
- Erstellt Heading am Ende der Target-Datei
- Verwendet Settings:
fixActions.createMissingHeading.level
- ✅ Action 2: Retarget to Existing Heading
- Zeigt Heading-Picker (aus File Cache)
- Ersetzt Link im Editor zu existierendem Heading
- ✅ Action 1: Create Missing Heading
-
only_candidates(INFO)- ✅ Action: Promote Candidate Edge
- Befördert Candidate-Edge zu explizitem Edge
- Fügt Edge zu aktueller Section hinzu
- Verwendet Settings:
fixActions.promoteCandidate.keepOriginal
- ✅ Action: Promote Candidate Edge
❌ NICHT behebbar (keine Fix Actions):
missing_edges- Section hat keine Edges (nur Info)one_sided_connectivity- Nur incoming ODER nur outgoing Edges (nur Info)no_causal_roles- Keine causal-ish Rollen (nur Info)
Technische Details
Edge-Filterung für dangling_target Check
// sectionEdges = alle Edges aus aktueller Section
const sectionEdges = currentEdges.filter((edge) => {
// Nur section-scoped Edges (nicht note-scoped, nicht candidates)
if (edge.scope === "candidate") return false;
if (edge.scope === "note") return false;
// Nur Edges aus aktueller Section
return "sectionHeading" in edge.source
? edge.source.sectionHeading === context.heading &&
edge.source.file === context.file
: false;
});
Datei-Auflösung
const resolvedFile = app.metadataCache.getFirstLinkpathDest(
normalizeLinkTarget(targetFile),
context.file
);
if (!resolvedFile) {
// → dangling_target (ERROR)
}
Heading-Check
if (targetHeading !== null) {
const targetContent = app.metadataCache.getFileCache(resolvedFile);
if (targetContent) {
const headings = targetContent.headings || [];
const headingExists = headings.some(
(h) => h.heading === targetHeading
);
if (!headingExists) {
// → dangling_target_heading (WARN)
}
}
}
Bekannte Einschränkungen
-
Trash Detection: Dateien im
.trashOrdner werden als "nicht existierend" erkannt (korrektes Verhalten) -
File Cache: Wenn
getFileCache()nicht verfügbar ist, wird Heading-Check übersprungen (akzeptabel, da Cache später aktualisiert wird) -
Case Sensitivity: Heading-Matching ist case-sensitive (abhängig von Obsidian-Konfiguration)
-
Note-scoped Edges: Werden nicht auf
dangling_targetgeprüft (nur section-scoped Edges) -
Candidate Edges: Werden nicht auf
dangling_targetgeprüft (nur explizite Edges)
Zusammenfassung
| Finding | Severity | Geprüft für | Behebbar | Actions |
|---|---|---|---|---|
dangling_target |
ERROR | Outgoing section-scoped Edges | ✅ | Create Note, Retarget Link |
dangling_target_heading |
WARN | Outgoing section-scoped Edges mit Heading | ✅ | Create Heading, Retarget to Heading |
only_candidates |
INFO | Sections mit nur Candidate-Edges | ✅ | Promote Candidate |
missing_edges |
INFO | Sections ohne Edges | ❌ | - |
one_sided_connectivity |
INFO | Sections mit nur incoming/outgoing | ❌ | - |
no_causal_roles |
INFO | Sections ohne causal roles | ❌ | - |