- 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.
164 lines
5.5 KiB
Markdown
164 lines
5.5 KiB
Markdown
# 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 `null` zurückgibt → `dangling_target` Finding
|
|
|
|
**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_heading` Finding
|
|
|
|
**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()` `null` zurü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:
|
|
|
|
1. **`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
|
|
|
|
2. **`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
|
|
|
|
3. **`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`
|
|
|
|
### ❌ 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
|
|
|
|
```typescript
|
|
// 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
|
|
|
|
```typescript
|
|
const resolvedFile = app.metadataCache.getFirstLinkpathDest(
|
|
normalizeLinkTarget(targetFile),
|
|
context.file
|
|
);
|
|
|
|
if (!resolvedFile) {
|
|
// → dangling_target (ERROR)
|
|
}
|
|
```
|
|
|
|
### Heading-Check
|
|
|
|
```typescript
|
|
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
|
|
|
|
1. **Trash Detection:** Dateien im `.trash` Ordner werden als "nicht existierend" erkannt (korrektes Verhalten)
|
|
|
|
2. **File Cache:** Wenn `getFileCache()` nicht verfügbar ist, wird Heading-Check übersprungen (akzeptabel, da Cache später aktualisiert wird)
|
|
|
|
3. **Case Sensitivity:** Heading-Matching ist case-sensitive (abhängig von Obsidian-Konfiguration)
|
|
|
|
4. **Note-scoped Edges:** Werden nicht auf `dangling_target` geprüft (nur section-scoped Edges)
|
|
|
|
5. **Candidate Edges:** Werden nicht auf `dangling_target` geprü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 | ❌ | - |
|