mindnet_obsidian/src/commands/inspectChainsCommand.ts

138 lines
4.5 KiB
TypeScript
Raw Normal View History

/**
* Command: Inspect Chains (Current Section)
*/
import type { App, Editor } from "obsidian";
import { resolveSectionContext } from "../analysis/sectionContext";
import { inspectChains } from "../analysis/chainInspector";
import type { ChainRolesConfig } from "../dictionary/types";
export interface InspectChainsOptions {
includeNoteLinks?: boolean;
includeCandidates?: boolean;
maxDepth?: number;
direction?: "forward" | "backward" | "both";
}
/**
* Format report as pretty-printed string.
*/
function formatReport(report: Awaited<ReturnType<typeof inspectChains>>): string {
const lines: string[] = [];
lines.push("=== Chain Inspector Report ===");
lines.push("");
lines.push(`Context: ${report.context.file}`);
if (report.context.heading) {
lines.push(`Section: ${report.context.heading}`);
}
lines.push(`Zone: ${report.context.zoneKind}`);
lines.push("");
lines.push("Settings:");
lines.push(` - Include Note Links: ${report.settings.includeNoteLinks}`);
lines.push(` - Include Candidates: ${report.settings.includeCandidates}`);
lines.push(` - Max Depth: ${report.settings.maxDepth}`);
lines.push(` - Direction: ${report.settings.direction}`);
lines.push("");
lines.push(`Neighbors:`);
lines.push(` Incoming: ${report.neighbors.incoming.length}`);
for (const edge of report.neighbors.incoming.slice(0, 5)) {
const targetStr = edge.target.heading
? `${edge.target.file}#${edge.target.heading}`
: edge.target.file;
lines.push(` - ${edge.rawEdgeType} -> ${targetStr} [${edge.scope}]`);
}
if (report.neighbors.incoming.length > 5) {
lines.push(` ... and ${report.neighbors.incoming.length - 5} more`);
}
lines.push(` Outgoing: ${report.neighbors.outgoing.length}`);
for (const edge of report.neighbors.outgoing.slice(0, 5)) {
const targetStr = edge.target.heading
? `${edge.target.file}#${edge.target.heading}`
: edge.target.file;
lines.push(` - ${edge.rawEdgeType} -> ${targetStr} [${edge.scope}]`);
}
if (report.neighbors.outgoing.length > 5) {
lines.push(` ... and ${report.neighbors.outgoing.length - 5} more`);
}
lines.push("");
lines.push(`Paths:`);
lines.push(` Forward: ${report.paths.forward.length}`);
for (const path of report.paths.forward.slice(0, 3)) {
const pathStr = path.nodes
.map((n) => (n.heading ? `${n.file}#${n.heading}` : n.file))
.join(" -> ");
lines.push(` - ${pathStr} (${path.edges.length} edges)`);
}
if (report.paths.forward.length > 3) {
lines.push(` ... and ${report.paths.forward.length - 3} more`);
}
lines.push(` Backward: ${report.paths.backward.length}`);
for (const path of report.paths.backward.slice(0, 3)) {
const pathStr = path.nodes
.map((n) => (n.heading ? `${n.file}#${n.heading}` : n.file))
.join(" -> ");
lines.push(` - ${pathStr} (${path.edges.length} edges)`);
}
if (report.paths.backward.length > 3) {
lines.push(` ... and ${report.paths.backward.length - 3} more`);
}
lines.push("");
lines.push(`Gap Heuristics (Findings): ${report.findings.length}`);
if (report.findings.length === 0) {
lines.push(` ✓ No issues detected`);
} else {
for (const finding of report.findings) {
const severityIcon =
finding.severity === "error"
? "❌"
: finding.severity === "warn"
? "⚠️"
: "ℹ️";
lines.push(
` ${severityIcon} [${finding.severity.toUpperCase()}] ${finding.code}: ${finding.message}`
);
}
}
return lines.join("\n");
}
/**
* Execute inspect chains command.
*/
export async function executeInspectChains(
app: App,
editor: Editor,
filePath: string,
chainRoles: ChainRolesConfig | null,
options: InspectChainsOptions = {}
): Promise<void> {
// Resolve section context
const context = resolveSectionContext(editor, filePath);
// Build options with defaults
const inspectorOptions = {
includeNoteLinks: options.includeNoteLinks ?? true,
includeCandidates: options.includeCandidates ?? false,
maxDepth: options.maxDepth ?? 3,
direction: options.direction ?? "both",
};
// Inspect chains
const report = await inspectChains(app, context, inspectorOptions, chainRoles);
// Log report as JSON
console.log("=== Chain Inspector Report (JSON) ===");
console.log(JSON.stringify(report, null, 2));
// Log pretty-printed summary
console.log("\n=== Chain Inspector Report (Summary) ===");
console.log(formatReport(report));
}