From ff4f4eb3332ce0a190591a9b0274f5220c0f617d Mon Sep 17 00:00:00 2001 From: dgtalbug Date: Sun, 7 Jun 2026 12:53:28 +0530 Subject: [PATCH 01/15] refactor: comment hygiene + enforce no-vscode-in-core (stabilization group 1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Strip spec/process tracking metadata from non-test source comments across all three packages, keeping the genuine why-explanations. Removes Slice/FR/US/T0xx/ S8/M7/CodeRabbit/CodeQL/"this slice" tags; rewrites comments that named the four extractor classes deleted in the indexing rewrite to describe the generic engine. Also fixes three user-facing strings that leaked slice numbers into the UI (Mermaid sequence-diagram unavailable label, decorator-classification label, sequence-preview message) and adds an ESLint `no-restricted-imports` rule banning `vscode` in `packages/core/src` (RULE-ARCH-005), making the boundary self-policing. Comments only — no code logic changed. Global spec-tag grep is now 0 in non-test source. typecheck 5/5, tests unchanged (core 263 / exporters 161 / extension 638), lint green with the new ban active. The `@duckdb/node-api` ban is deferred to group 3, after storage access moves behind the repository adapter. --- eslint.config.js | 23 ++++++++ .../classification/classifySymbol.ts | 3 +- .../src/extractors/frameworks/detector.ts | 7 ++- .../frameworks/matchers/manifest.ts | 4 +- .../extractors/frameworks/matchers/toml.ts | 6 +- .../src/extractors/frameworks/registry.ts | 2 +- packages/core/src/extractors/registry.ts | 11 ++-- packages/core/src/extractors/types.ts | 11 ++-- packages/core/src/index.ts | 2 +- .../core/src/quality/recomputeGraphHealth.ts | 11 ++-- packages/core/src/query/sessionSummary.ts | 2 +- packages/core/src/query/subgraph.ts | 18 +++--- .../core/src/storage/migrations/runner.ts | 7 +-- packages/core/src/storage/repository.ts | 41 +++++++------- packages/core/src/storage/schema.ts | 2 +- .../core/src/storage/workspaceRegistry.ts | 6 +- packages/core/src/types.ts | 4 +- packages/exporters/src/mermaid/preview.ts | 14 ++--- .../exporters/src/mermaid/scopedSerializer.ts | 15 ++--- .../exporters/src/mermaid/sequenceDiagram.ts | 9 ++- packages/exporters/src/mermaid/serializer.ts | 8 +-- packages/exporters/src/mermaid/validator.ts | 2 +- .../extension/src/cache/workspaceRegistry.ts | 2 +- .../extension/src/commands/exportMermaid.ts | 24 ++++---- .../extension/src/commands/indexWorkspace.ts | 2 +- .../extension/src/commands/switchWorkspace.ts | 2 +- packages/extension/src/extension.ts | 4 +- .../extension/src/watcher/workspaceWatcher.ts | 2 +- packages/extension/src/webview/App.tsx | 24 ++++---- .../src/webview/components/EmptyState.tsx | 2 +- .../src/webview/components/GraphToolbar.tsx | 4 +- .../src/webview/components/GraphView.tsx | 56 +++++++++---------- .../src/webview/components/LoadingState.tsx | 2 +- .../components/MermaidPreviewPanel.tsx | 40 +++++++------ .../src/webview/components/SigmaController.ts | 4 +- .../src/webview/components/WorkspaceCard.tsx | 2 +- .../src/webview/components/WorkspacesPage.tsx | 4 +- .../webview/components/graphLayoutPresets.ts | 14 ++--- .../src/webview/components/graphTraversal.ts | 4 +- .../src/webview/components/graphViewTypes.ts | 40 ++++++------- .../src/webview/components/lensColor.ts | 2 +- .../src/webview/components/shellLayout.ts | 2 +- packages/extension/src/webview/html.ts | 20 +++---- packages/extension/src/webview/panel.ts | 46 +++++++-------- .../src/webview/preview/exportPreview.ts | 4 +- .../src/webview/preview/renderMermaid.ts | 2 +- .../src/webview/protocol/messages.ts | 32 +++++------ packages/extension/src/webview/validate.ts | 2 +- 48 files changed, 282 insertions(+), 268 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 3066b36..5ea1b70 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -81,5 +81,28 @@ export default [ }, }, }, + { + // core must run in Node, browser (WASM), and VS Code contexts — it can never + // depend on the `vscode` host API. Host-specific behaviour is injected via + // interfaces. Enforces the no-vscode-in-core architecture boundary. + // (The DuckDB-driver ban lands once storage access moves behind the + // repository adapter, so it can be scoped to everything but the adapters.) + files: ["packages/core/src/**/*.ts"], + ignores: ["**/*.test.ts", "**/__fixtures__/**"], + rules: { + "no-restricted-imports": [ + "error", + { + paths: [ + { + name: "vscode", + message: + "core must not import vscode — it runs in Node/WASM/browser. Inject host behaviour via an interface.", + }, + ], + }, + ], + }, + }, prettier, ]; diff --git a/packages/core/src/extractors/classification/classifySymbol.ts b/packages/core/src/extractors/classification/classifySymbol.ts index dc9f980..5d16272 100644 --- a/packages/core/src/extractors/classification/classifySymbol.ts +++ b/packages/core/src/extractors/classification/classifySymbol.ts @@ -24,8 +24,7 @@ const UNCLASSIFIED_ENTRY: EntryKind = "unclassified"; const UNKNOWN_LAYER: ArchitecturalLayer = "unknown"; // Each branch is wrapped so the trailing `$` on the file-extension branch -// cannot be misread as also anchoring the directory-segment branch -// (CodeQL js/regex/missing-regexp-anchor). +// cannot be misread as also anchoring the directory-segment branch. const TEST_PATH_RX = /(?:(?:^|\/)(?:__tests__|__test__|tests?)\/)|(?:\.(?:test|spec)\.[mc]?[jt]sx?$)/; diff --git a/packages/core/src/extractors/frameworks/detector.ts b/packages/core/src/extractors/frameworks/detector.ts index a7b4c35..6c3955d 100644 --- a/packages/core/src/extractors/frameworks/detector.ts +++ b/packages/core/src/extractors/frameworks/detector.ts @@ -10,8 +10,9 @@ import type { /** * Pure entrypoint for workspace-level framework detection. Walks the - * registry; per framework wraps both matchers in try/catch (FR-007). Returns - * results in registry order. Empty array — never null — when nothing matched. + * registry; per framework wraps both matchers in try/catch for isolation. + * Returns results in registry order. Empty array — never null — when nothing + * matched. */ export const detectFrameworks: DetectFrameworksFn = async ( params: DetectFrameworksParams, @@ -45,7 +46,7 @@ async function runMatchersFor( tryMatchStructural(def.structural, structuralIO), ]); - // FR-003: BOTH signals required. + // BOTH signals required. if (!manifestHit || !structuralHit) { return null; } diff --git a/packages/core/src/extractors/frameworks/matchers/manifest.ts b/packages/core/src/extractors/frameworks/matchers/manifest.ts index 1d11b59..67e3210 100644 --- a/packages/core/src/extractors/frameworks/matchers/manifest.ts +++ b/packages/core/src/extractors/frameworks/matchers/manifest.ts @@ -53,8 +53,8 @@ function extractValue(content: string, keyPath: ManifestKeyPath): string | undef } if (lower.endsWith(".toml") || lower === "go.mod") { // go.mod is technically not TOML, but its `require ( ... )` blocks are - // matched by a different path — for slice 018 we treat the whole file as - // text and rely on the regex policy. The TOML reader will return + // matched by a different path — we treat the whole file as text and rely on + // the regex policy. The TOML reader will return // undefined for go.mod, so we fall through to whole-file regex below. const tomlValue = readTomlKeypath(content, keyPath.keypath); if (tomlValue !== undefined) return tomlValue; diff --git a/packages/core/src/extractors/frameworks/matchers/toml.ts b/packages/core/src/extractors/frameworks/matchers/toml.ts index a4eb89c..e45a29c 100644 --- a/packages/core/src/extractors/frameworks/matchers/toml.ts +++ b/packages/core/src/extractors/frameworks/matchers/toml.ts @@ -2,8 +2,8 @@ * Minimal TOML keypath reader. Returns the string value at a dot-separated * keypath, or undefined if missing. Handles `[section]` and `[section.sub]` * headers, plus `key = "value"` and `key = value` lines. Comments (`#`) are - * ignored. Arrays-of-tables (`[[name]]`) are out of scope for slice 018; - * if a framework needs them, upgrade to a library and keep the contract. + * ignored. Arrays-of-tables (`[[name]]`) are out of scope for this minimal + * parser; if a framework needs them, upgrade to a library and keep the contract. * * Why inline: we only need keypath lookup. A full TOML parser is ~5 KB * of dependency surface we don't otherwise use. @@ -26,7 +26,7 @@ export function readTomlKeypath(content: string, keypath: string): string | unde } if (line.startsWith("[[")) { - // Array-of-tables not supported in this slice; skip the section. + // Array-of-tables not supported; skip the section. currentSection = "__unsupported__"; continue; } diff --git a/packages/core/src/extractors/frameworks/registry.ts b/packages/core/src/extractors/frameworks/registry.ts index b5e2a66..16623cd 100644 --- a/packages/core/src/extractors/frameworks/registry.ts +++ b/packages/core/src/extractors/frameworks/registry.ts @@ -15,7 +15,7 @@ * - manifest: one or more `ManifestKeyPath` rules. Detection requires at * least one manifest match. * - structural: one `StructuralSignal`. Detection requires this AND - * manifest to fire — both signals are needed (FR-003). + * manifest to fire — both signals are needed. * - fileRole: pure (filePath, fileContent) → role | null. Returns the * per-file role attribution for files in workspaces where * this framework was detected. diff --git a/packages/core/src/extractors/registry.ts b/packages/core/src/extractors/registry.ts index 5bd2d5a..2276abd 100644 --- a/packages/core/src/extractors/registry.ts +++ b/packages/core/src/extractors/registry.ts @@ -15,7 +15,7 @@ function toKnownSymbol(s: StoredSymbol): KnownSymbol { name: s.name, kind: s.kind, // StoredSymbol.range uses 0-based rows (tree-sitter convention from toRange()). - // NaiveCallExtractor also uses 0-based node.startPosition.row — no adjustment needed. + // Extractors also use 0-based node.startPosition.row — no adjustment needed. startLine: s.range.startLine, startCol: s.range.startCol, endLine: s.range.endLine, @@ -50,9 +50,9 @@ class InMemoryExtractorRegistry implements ExtractorRegistry { const modules: unknown[] = []; const tests: unknown[] = []; // Accumulate known symbols so each extractor sees the IDs the earlier - // extractors already minted. This lets NaiveCallExtractor look up the - // exact symbol IDs that BaselineTsJsExtractor wrote instead of minting - // its own (which would produce dangling foreign keys in the edge table). + // extractors already minted. This lets relational extractors look up the + // exact symbol IDs that definition extractors wrote instead of minting + // their own (which would produce dangling foreign keys in the edge table). const knownSymbols: KnownSymbol[] = [...(input.knownSymbols ?? [])]; for (const extractor of matching) { @@ -61,7 +61,8 @@ class InMemoryExtractorRegistry implements ExtractorRegistry { try { result = await extractor.extract(enrichedInput); } catch (err) { - // Per FR-007 / contract: failure isolation. Log and continue. + // Failure isolation: one extractor's error must not abort the rest. + // Log and continue. this.logger?.warn("Extractor failed", { extractor: extractor.name, file: input.absolutePath, diff --git a/packages/core/src/extractors/types.ts b/packages/core/src/extractors/types.ts index 954578a..3981107 100644 --- a/packages/core/src/extractors/types.ts +++ b/packages/core/src/extractors/types.ts @@ -4,8 +4,8 @@ import type { ExtractedFileRecord, ExtractedImportRef, StoredSymbol } from "../t /** * Minimal symbol descriptor forwarded from earlier extractors so that later - * extractors (e.g. NaiveCallExtractor) can resolve symbol IDs without minting - * their own. Populated by the registry after each extractor runs. + * relational extractors can resolve symbol IDs without minting their own. + * Populated by the registry after each extractor runs. */ export interface KnownSymbol { readonly id: string; @@ -60,8 +60,7 @@ export interface EdgeRow { } /** - * What each extractor returns. Matches `.dextree/design.md` §8.6 except for the - * additive `imports` field — slice 009 persists imports as `edge` rows, but the + * What each extractor returns. Imports are persisted as `edge` rows, but the * in-memory representation still travels through this typed array on the way to * `replaceFileGraph`. * @@ -82,8 +81,8 @@ export interface ExtractionResult { * Plugin-style extractor contract. `name` is unique across registrations. * `version` is informational and surfaces in `console.warn` failure logs. * `supports(language)` is the language filter; `extract(input)` produces rows. - * Future plugin-loaded extractors will implement the same interface — slice 010 - * keeps the surface internal, so no packaging / sandboxing yet. + * Future plugin-loaded extractors will implement the same interface; the surface + * is internal for now, so no packaging / sandboxing yet. */ export interface Extractor { readonly name: string; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 26aeb5d..4ba9eaf 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -250,7 +250,7 @@ class DuckTreeIndexer implements Indexer { // (which `replaceFileGraph` writes itself) flow through `extraEdges`. const extraEdges = [...result.edges]; - // Per-file framework attribution (slice 018) is needed before classification + // Per-file framework attribution is needed before classification // so the classifier can use it as one of its local structural inputs. const detected = this.frameworkCache.get(workspaceRoot) ?? []; const attribution = diff --git a/packages/core/src/quality/recomputeGraphHealth.ts b/packages/core/src/quality/recomputeGraphHealth.ts index 97a9425..7b7384f 100644 --- a/packages/core/src/quality/recomputeGraphHealth.ts +++ b/packages/core/src/quality/recomputeGraphHealth.ts @@ -12,9 +12,8 @@ import type { DuckDBConnection } from "@duckdb/node-api"; * Owned by `packages/core/src/quality/` per Constitution III: "quality logic * MUST remain under `packages/core/src/quality`". * - * STUB — implementation scheduled for slice S11.7 (PageRank symbol ranking + - * community overlay). See `.dextree/design.md` §7.5 (Blast Radius) and ROADMAP - * slice S11.7 for the planned algorithm: + * STUB — implementation pending (PageRank symbol ranking + community overlay). + * See `.dextree/design.md` §7.5 (Blast Radius) for the planned algorithm: * 1. Build a graphology MultiDirectedGraph from the persisted `edge` table. * 2. Compute per-symbol fan-in (incoming CALLS + REFERENCES). * 3. Run PageRank; mark top-5% as `is_core`. @@ -28,8 +27,8 @@ import type { DuckDBConnection } from "@duckdb/node-api"; */ export async function recomputeGraphHealth(_connection: DuckDBConnection): Promise { // Intentionally a no-op stub for the MVP foundation. - // Throwing here would break the workspace-indexing loop in slice S6 once any - // caller wires this in; instead the function is a no-op until S11.7 lands real - // logic. The `_connection` parameter is reserved for that implementation. + // Throwing here would break the workspace-indexing loop once any caller wires + // this in; instead the function is a no-op until real logic lands. The + // `_connection` parameter is reserved for that implementation. return; } diff --git a/packages/core/src/query/sessionSummary.ts b/packages/core/src/query/sessionSummary.ts index 5694b47..a28fc77 100644 --- a/packages/core/src/query/sessionSummary.ts +++ b/packages/core/src/query/sessionSummary.ts @@ -10,7 +10,7 @@ import { EmptyGraphError, type SessionSummary } from "../types.js"; * or data changes (CC-001). Returns only pass-1 structural data; pass-2 * enrichment fields are not required (CC-003). * - * @throws {EmptyGraphError} when no files have been indexed (FR-005). + * @throws {EmptyGraphError} when no files have been indexed. */ export async function querySessionSummary( connection: DuckDBConnection, diff --git a/packages/core/src/query/subgraph.ts b/packages/core/src/query/subgraph.ts index 2bb4597..efc2012 100644 --- a/packages/core/src/query/subgraph.ts +++ b/packages/core/src/query/subgraph.ts @@ -34,7 +34,7 @@ function normalizeRange(value: unknown): SymbolRange { /** * DuckDB returns `VARCHAR[]` columns as JS arrays. NULL maps to undefined so * downstream "is this defined?" checks behave correctly. An empty array stays - * as `[]` — meaningful distinct from undefined (slice 020 FR-010). + * as `[]` — meaningful distinct from undefined. */ function normalizeStringArray(value: unknown): readonly string[] | undefined { if (value === null || value === undefined) return undefined; @@ -145,9 +145,9 @@ export async function getWorkspaceSubgraph( ) ).getRowObjectsJS(); - // Slice 031 US3 — count annotations per parent symbol so the graph view's - // Decorator node-filter chip can become truthful (and not a placeholder). - // An empty result is the honest signal for an unsupported workspace. + // Count annotations per parent symbol so the graph view's Decorator + // node-filter chip can become truthful (and not a placeholder). An empty + // result is the honest signal for an unsupported workspace. const annotationCountRows = await ( await connection.run( ` @@ -210,7 +210,7 @@ export async function getWorkspaceSubgraph( ).getRowObjectsJS(); // Post-v3: CALLS edges live in the unified `edge` table too. Pass-1 may leave - // target_id NULL (unresolved); pass-2 LSP (S8) will fill it in. This query + // target_id NULL (unresolved); pass-2 LSP will fill it in. This query // shows only resolved calls. const callRows = await ( await connection.run( @@ -284,7 +284,7 @@ export async function getWorkspaceSubgraph( ).getRowObjectsJS(); // IMPLEMENTS: class → interface (resolved source + target, same shape as INHERITS). - // Slice 031 US2 — kept distinct from INHERITS by edge kind so the classDiagram + // Kept distinct from INHERITS by edge kind so the classDiagram // renderer can use a different relationship arrow (`<|..`) and the graph edge // filter exposes them separately. const implementsRows = await ( @@ -348,9 +348,9 @@ export async function getWorkspaceSubgraph( typeof rawEnclosing === "string" && rawEnclosing.length > 0 ? rawEnclosing : undefined; const symbolId = String(row.id); const annotationCount = annotationCountsBySymbolId.get(symbolId) ?? 0; - // Slice 031 US3 — project decorator-backed presence onto the node's - // flags so the Decorator node-filter chip in the webview can become a - // truthful filter instead of a disabled stub. + // Project decorator-backed presence onto the node's flags so the + // Decorator node-filter chip in the webview can become a truthful filter + // instead of a disabled stub. const flags = annotationCount > 0 ? (Object.freeze([...(baseFlags ?? []), "decorator-backed"]) as readonly string[]) diff --git a/packages/core/src/storage/migrations/runner.ts b/packages/core/src/storage/migrations/runner.ts index 4de53cd..5c4b8c0 100644 --- a/packages/core/src/storage/migrations/runner.ts +++ b/packages/core/src/storage/migrations/runner.ts @@ -335,10 +335,9 @@ const MIGRATION_006: Migration = { // enclosing_symbol_id briefly. The schema-version bump invalidates the workspace // cache (validateWorkspaceCache compares metadata.schemaVersion to // SCHEMA_VERSION), which forces a reindex on the next session. That reindex -// rewrites every symbol row with the parent class id populated by -// ClassRelationExtractor's tree-sitter parent walk (slice 028 T022). NULL is -// also the correct steady-state value for any top-level symbol that is not a -// member of a class-like parent. +// rewrites every symbol row with the parent class id populated by the +// extractor's tree-sitter parent walk. NULL is also the correct steady-state +// value for any top-level symbol that is not a member of a class-like parent. async function runMigration007(connection: DuckDBConnection): Promise { const hasEnclosingId = await columnExists(connection, "symbol", "enclosing_symbol_id"); diff --git a/packages/core/src/storage/repository.ts b/packages/core/src/storage/repository.ts index 8bb3dbf..1e83cd2 100644 --- a/packages/core/src/storage/repository.ts +++ b/packages/core/src/storage/repository.ts @@ -66,8 +66,8 @@ async function deleteExistingRows( "DELETE FROM edge WHERE target_id IN (SELECT id FROM symbol WHERE file_id = $file_id)", { file_id: existingFileId }, ); - // Slice 031 US3 — clear annotation rows whose parent symbol is about to be - // dropped so the table never carries dangling rows after a reindex. + // Clear annotation rows whose parent symbol is about to be dropped so the + // table never carries dangling rows after a reindex. await connection.run( "DELETE FROM annotation WHERE parent_symbol_id IN (SELECT id FROM symbol WHERE file_id = $file_id)", { file_id: existingFileId }, @@ -81,8 +81,8 @@ async function insertFile(connection: DuckDBConnection, input: ExtractedIndexDat // _schema_version, is_core, fan_in, tags, labels, metadata, last_modified, // last_author, change_count_30d are omitted from the column list — they take // their schema-defined default values. fan_in/is_core are populated later by - // `recomputeGraphHealth` (S11.7); the rest stay at their defaults until git - // (S10) or diagnostics (S9) fill them in. + // `recomputeGraphHealth`; the rest stay at their defaults until git or + // diagnostics fill them in. await connection.run( ` INSERT INTO file ( @@ -118,8 +118,8 @@ async function updateFile(connection: DuckDBConnection, input: ExtractedIndexDat // Update only the columns that change when a file is re-indexed (path metadata, // size, hash, last_indexed). is_core, fan_in, tags, labels, metadata, and the // git-derived columns are deliberately NOT reset: they're owned by other - // subsystems (S9 diagnostics, S10 git, S11.7 graph health) and a reindex - // should preserve their state. Closes audit finding M7. + // subsystems (diagnostics, git, graph health) and a reindex should preserve + // their state. await connection.run( ` UPDATE file @@ -153,7 +153,7 @@ async function insertSymbol( ): Promise { // _schema_version, fan_in, is_core are omitted — column defaults handle them. // The pass-2 enrichment columns (visibility, signature, return_type, etc.) are - // also omitted; they're nullable and stay NULL until LSP enrichment (S8) runs. + // also omitted; they're nullable and stay NULL until LSP enrichment runs. // // entry_kind and arch_layer are always written explicitly so migrated v5→v6 // databases (where the columns are bare-added without DEFAULT) get the same @@ -277,8 +277,8 @@ async function insertExtraEdges( connection: DuckDBConnection, edges: readonly EdgeRow[], ): Promise { - // Generic insert path for extractor-emitted edges (e.g. naive `CALLS` rows - // from `NaiveCallExtractor`). Metadata is serialized as JSON via `json` cast. + // Generic insert path for extractor-emitted edges (e.g. `CALLS` rows). + // Metadata is serialized as JSON via `json` cast. for (const edge of edges) { await connection.run( ` @@ -319,11 +319,11 @@ function remapExtraEdges( * relational edges (CALLS, INHERITS, INSTANTIATES) after the symbols and edges * for `fileId` have been inserted. * - * Why this is needed: NaiveCallExtractor and ClassRelationExtractor cannot know - * the symbol UUIDs minted by BaselineTsJsExtractor (both use random uuidv4). - * Instead they write a stable `source_fqn` (e.g. `"src/foo.ts:MyClass"`) and a - * target-name key (`callee_name` / `parent_name` / `class_name`) into edge - * metadata. This step resolves them against the just-written `symbol` rows. + * Why this is needed: relational extractors cannot know the symbol UUIDs minted + * for definitions (every symbol gets a random uuidv4). Instead they write a + * stable `source_fqn` (e.g. `"src/foo.ts:MyClass"`) and a target-name key + * (`callee_name` / `parent_name` / `class_name`) into edge metadata. This step + * resolves them against the just-written `symbol` rows. * * Step 1 — source_id: all three kinds have `source_fqn` in metadata. Edges * whose source_id still equals the file UUID placeholder are updated to the @@ -420,7 +420,7 @@ async function resolveCallEdgeSymbols(connection: DuckDBConnection, fileId: stri // Step 2d (IMPLEMENTS): target_id → same-file interface (or class for the // JS pattern where an interface is implemented via a class shape) by - // interface_name. Slice 031 US2. + // interface_name. await connection.run( ` UPDATE edge @@ -598,11 +598,10 @@ function isAnnotationLikeRow(row: unknown): row is AnnotationLikeRow { } /** - * Persist annotation rows from {@link DecoratorExtractor} into the existing - * `annotation` table. Rows missing a valid `parentSymbolId` (e.g. when the - * extractor could not resolve an enclosing symbol) are silently skipped — - * the table has a NOT NULL FK to `symbol`, and per slice 031 contract the - * extractor must not invent synthetic targets. Slice 031 US3. + * Persist extractor-emitted annotation rows into the existing `annotation` + * table. Rows missing a valid `parentSymbolId` (e.g. when the extractor could + * not resolve an enclosing symbol) are silently skipped — the table has a NOT + * NULL FK to `symbol`, and extractors must not invent synthetic targets. */ async function insertAnnotations( connection: DuckDBConnection, @@ -751,7 +750,7 @@ export async function resolveWorkspaceCrossFileEdges( ); // Resolve IMPLEMENTS: interface_name → any matching interface (or class - // used as an interface) in the workspace. Slice 031 US2. + // used as an interface) in the workspace. await connection.run( ` UPDATE edge diff --git a/packages/core/src/storage/schema.ts b/packages/core/src/storage/schema.ts index 7b49a82..3cd8cd1 100644 --- a/packages/core/src/storage/schema.ts +++ b/packages/core/src/storage/schema.ts @@ -77,7 +77,7 @@ export const SCHEMA_STATEMENTS = [ id VARCHAR PRIMARY KEY, source_id VARCHAR NOT NULL, -- target_id is nullable post-v3: pass-1 IMPORTS edges and pass-1 naive CALLS - -- edges may not have a resolved target yet; pass-2 (S8 LSP) fills them in. + -- edges may not have a resolved target yet; pass-2 LSP fills them in. target_id VARCHAR, kind VARCHAR NOT NULL, weight FLOAT, diff --git a/packages/core/src/storage/workspaceRegistry.ts b/packages/core/src/storage/workspaceRegistry.ts index 5d0a844..ddcfaa0 100644 --- a/packages/core/src/storage/workspaceRegistry.ts +++ b/packages/core/src/storage/workspaceRegistry.ts @@ -1,5 +1,5 @@ /** - * Per-workspace DuckDB read summary for the workspace switcher (slice 024). + * Per-workspace DuckDB read summary for the workspace switcher. * * Opens a foreign DuckDB file in read-only mode to extract the single * `workspace_cache` row and the framework list — without running migrations @@ -40,7 +40,7 @@ function toIsoOrNull(value: unknown): string | null { * Opens the DuckDB file at `dbPath` in read-only mode and returns a summary of * the indexed workspace. Returns null if the file is missing, the workspace_cache * row is absent, or any I/O error occurs. The framework list degrades to `[]` - * when the `workspace_framework` table is missing (slice 018 not applied). + * when the `workspace_framework` table is missing (an older index). * * Does NOT run migrations on the opened file — read-only access mode prevents * accidental schema mutation of foreign workspace DBs. @@ -120,7 +120,7 @@ export interface ForeignWorkspaceGraph { * payload `Indexer.getWorkspaceSubgraph` produces for the active workspace. * * Returns null on any I/O or schema error so the caller can show a graceful - * "could not open workspace" notification (slice 024 FR-008). + * "could not open workspace" notification. */ export async function readWorkspaceGraph( dbPath: string, diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 6bd7a3b..8f0aabc 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -1,5 +1,5 @@ // Schema version history: -// 1 — initial baseline (slice 008 era) +// 1 — initial baseline // 2 — adds annotation, module, test core entity tables (migration 002) // 3 — unifies call_site + import_ref into edge with kind/metadata (migration 003) // 4 — adds workspace_cache table (migration 004) @@ -277,7 +277,7 @@ export interface SessionSummary { /** * Thrown by `querySessionSummary` when the graph contains no indexed files. * The export command catches this and shows "Index your workspace first" - * without writing any file (FR-005). + * without writing any file. */ export class EmptyGraphError extends Error { constructor() { diff --git a/packages/exporters/src/mermaid/preview.ts b/packages/exporters/src/mermaid/preview.ts index 7dd4977..e96ff12 100644 --- a/packages/exporters/src/mermaid/preview.ts +++ b/packages/exporters/src/mermaid/preview.ts @@ -12,8 +12,8 @@ import { MERMAID_INIT_DIRECTIVE } from "./theme.js"; /** * Bounded diagram kind for the preview tab. `flowchart` and `classDiagram` - * are routable since slice 029 PR-B; `sequenceDiagram` stays explicit - * `unsupported` until slice 031 ships the sequence serializer. + * are routable; `sequenceDiagram` stays explicit `unsupported` until the + * sequence serializer ships. */ export type MermaidDiagramKind = "flowchart" | "classDiagram" | "sequenceDiagram"; @@ -26,7 +26,7 @@ export type MermaidPreviewTheme = "light" | "dark"; /** * Full option payload for {@link generateMermaidPreview}. Mirrors the - * slice-027 scoped serializer surface and adds the diagram discriminator + * scoped serializer surface and adds the diagram discriminator * and resolved theme used by the preview tab. */ export interface MermaidPreviewOptions { @@ -93,8 +93,8 @@ function titleForOptions(options: MermaidPreviewOptions): string { /** * Pure preview router. Builds the Mermaid source text for the requested - * diagram + scope combination by delegating to the slice-027 scoped flowchart - * serializer or the slice-028 class-diagram serializer. Never performs + * diagram + scope combination by delegating to the scoped flowchart + * serializer or the class-diagram serializer. Never performs * filesystem, DOM, or network work. * * Errors raised by the underlying serializer (empty / oversized / unsupported @@ -102,7 +102,7 @@ function titleForOptions(options: MermaidPreviewOptions): string { * variants so callers can render the failure reason without try/catch noise. * * `sequenceDiagram` is recognised but returns explicit `unsupported` until - * slice 031 ships the sequence serializer. + * the sequence serializer ships. */ export function generateMermaidPreview( subgraph: WorkspaceSubgraph, @@ -113,7 +113,7 @@ export function generateMermaidPreview( return { status: "unsupported", options, - reason: "Sequence preview is unavailable until slice 031.", + reason: "Sequence preview is unavailable until trace export is supported.", }; } diff --git a/packages/exporters/src/mermaid/scopedSerializer.ts b/packages/exporters/src/mermaid/scopedSerializer.ts index 4659202..2c162ca 100644 --- a/packages/exporters/src/mermaid/scopedSerializer.ts +++ b/packages/exporters/src/mermaid/scopedSerializer.ts @@ -23,9 +23,7 @@ export { /** * Bounded discriminator for the diagram shape produced by - * {@link serializeToScopedMermaid}. `flowchart` is the slice-016/027 default; - * `classDiagram` lands in slice 028; `sequenceDiagram` is reserved for slice - * 031. + * {@link serializeToScopedMermaid}. `flowchart` is the default. */ export type MermaidDiagram = "flowchart" | "classDiagram" | "sequenceDiagram"; @@ -34,7 +32,7 @@ export type MermaidDiagram = "flowchart" | "classDiagram" | "sequenceDiagram"; * to export. `workspace` and `file` are the original scopes; `visible` exports * an explicit node/edge id set (the rendered `VisibleView`, so an export matches * exactly what the user sees after lenses/filters/depth). `symbol-callers` / - * `symbol-callees` are pre-declared so later slices add behavior without + * `symbol-callees` are pre-declared so behavior can be added without * changing the option type. */ export type MermaidScope = @@ -56,8 +54,7 @@ export type MermaidDirection = "auto" | "TB" | "LR" | "BT" | "RL"; /** Full option payload accepted by the scoped serializer. */ export interface ScopedMermaidOptions { /** - * Required since slice 028. The `flowchart` branch is byte-identical to the - * slice-027 path; the `classDiagram` branch delegates to + * The `classDiagram` branch delegates to * `serializeToClassDiagram` and ignores `granularity` (forced to `"symbol"`) * and `direction` (Mermaid classDiagram has no direction token). */ @@ -69,7 +66,7 @@ export interface ScopedMermaidOptions { /** * Required when `diagram === "sequenceDiagram"`. Holds the active webview * trace route the serializer turns into ordered participants and steps. - * Slice-031 wire-through; ignored by the flowchart and classDiagram branches. + * Ignored by the flowchart and classDiagram branches. * Callers that already validate the snapshot themselves may still pass it * here so `serializeToScopedMermaid` can re-validate and fail closed. */ @@ -77,7 +74,7 @@ export interface ScopedMermaidOptions { /** * Opt out of the workspace granularity floor. User-facing export paths leave * this unset so a `workspace` scope never descends to `symbol` (see - * {@link clampGranularityToScope}). The slice-016 legacy `serializeToMermaid` + * {@link clampGranularityToScope}). The legacy `serializeToMermaid` * shim sets it `true` to preserve its byte-identical symbol-level output for * the snapshot/fuzz callers that predate the floor. */ @@ -132,7 +129,7 @@ export type ScopeExtractionResult = // Per-axis behavior lives in scope.ts / granularity.ts / direction.ts / // validator.ts — all re-exported above for consumers of @dextree/exporters. // --------------------------------------------------------------------------- -// Output formatting helpers. Mirror the slice-016 serializer.ts contract so +// Output formatting helpers. Mirror the serializer.ts contract so // the legacy shim and the new scoped path emit byte-identical node + edge // lines (only the `graph ` header differs). // --------------------------------------------------------------------------- diff --git a/packages/exporters/src/mermaid/sequenceDiagram.ts b/packages/exporters/src/mermaid/sequenceDiagram.ts index 7bd1369..835c000 100644 --- a/packages/exporters/src/mermaid/sequenceDiagram.ts +++ b/packages/exporters/src/mermaid/sequenceDiagram.ts @@ -74,8 +74,7 @@ function classParticipantLabel(node: GraphNode): string { * quote-escape pass produces `\\"` and the subsequent backslash pass * double-escapes the backslash we just wrote, breaking round-trip parsing. * Also strips newlines and carriage returns since Mermaid line-terminates - * on them. Flagged by CodeQL "Incomplete string escaping" on the prior - * single-replace pattern. + * on them. A single-replace pattern here leaves an incomplete string escape. */ function escapeMermaidLabel(label: string): string { return label @@ -97,10 +96,10 @@ function buildParticipants( // Track non-class participant ids so a cyclic trace that revisits the same // file or top-level symbol produces one participant, not N duplicates. Class // participants are already deduped via `classMap`. Method participants are - // folded into their enclosing class. CodeRabbit flagged that a cap check on + // folded into their enclosing class. Without this dedup, a cap check on // `participants.length` would falsely return `oversized` for valid cyclic - // traces without this dedup — but the same duplication would also have - // emitted duplicate `participant Foo as bar` lines in the serialized output. + // traces — and the same duplication would also have emitted duplicate + // `participant Foo as bar` lines in the serialized output. const seenNonClassIds = new Set(); // Methods can be re-visited too; dedupe the sourceNodeIds we attach to the // enclosing class so the participant's source list doesn't grow unbounded diff --git a/packages/exporters/src/mermaid/serializer.ts b/packages/exporters/src/mermaid/serializer.ts index 1f18517..72c65e1 100644 --- a/packages/exporters/src/mermaid/serializer.ts +++ b/packages/exporters/src/mermaid/serializer.ts @@ -9,10 +9,10 @@ export interface MermaidSerializeOptions { } /** - * Slice-016 compatibility shim. Delegates to {@link serializeToScopedMermaid} + * Compatibility shim. Delegates to {@link serializeToScopedMermaid} * with the workspace / symbol / auto defaults. * - * Preserves two slice-016 invariants that the new scoped path does not + * Preserves two invariants that the new scoped path does not * guarantee on its own: * * 1. Throws `Error("Graph has no nodes to export")` on an empty workspace @@ -20,8 +20,8 @@ export interface MermaidSerializeOptions { * 2. Emits `graph TD` as the second line (Mermaid alias of `graph TB`) so * existing snapshot tests stay byte-identical. * - * Slated for removal in slice 029 once the preview panel becomes the only - * consumer of the legacy entry point. + * Slated for removal once the preview panel becomes the only consumer of + * the legacy entry point. */ export function serializeToMermaid( subgraph: WorkspaceSubgraph, diff --git a/packages/exporters/src/mermaid/validator.ts b/packages/exporters/src/mermaid/validator.ts index 200676d..a53651f 100644 --- a/packages/exporters/src/mermaid/validator.ts +++ b/packages/exporters/src/mermaid/validator.ts @@ -7,7 +7,7 @@ import type { MermaidGranularity, ScopedExportValidation } from "./scopedSeriali * * - `soft` — beyond this the diagram is still exported but the result is * flagged `warning` so the UI can surface a non-blocking "large diagram" - * notice (the slice-033 status-bar "soft cap"). + * notice (the status-bar "soft cap"). * - `hard` — beyond this the export is refused (`oversized`); the diagram is * too dense to be legible. * diff --git a/packages/extension/src/cache/workspaceRegistry.ts b/packages/extension/src/cache/workspaceRegistry.ts index 4792000..5c3a627 100644 --- a/packages/extension/src/cache/workspaceRegistry.ts +++ b/packages/extension/src/cache/workspaceRegistry.ts @@ -1,5 +1,5 @@ /** - * Global workspace registry for the workspace switcher (slice 024). + * Global workspace registry for the workspace switcher. * * Maintains a JSON file under `globalStorageUri` that maps each indexed * workspaceRoot to its DuckDB path. This is the only durable way for the diff --git a/packages/extension/src/commands/exportMermaid.ts b/packages/extension/src/commands/exportMermaid.ts index dc21178..ceb00d3 100644 --- a/packages/extension/src/commands/exportMermaid.ts +++ b/packages/extension/src/commands/exportMermaid.ts @@ -22,10 +22,10 @@ export interface ExportMermaidCommandDependencies { /** * Default preview options used when the command opens the preview tab from - * the command palette or the existing graph-toolbar export button. Slice 029 - * deliberately removes the slice 027/028 QuickPick chain (Diagram / Scope / - * Granularity / Direction) in favour of inline controls on the preview tab - * itself (US2 in PR-B). The `theme` here is a host-side default that the + * the command palette or the existing graph-toolbar export button. The + * QuickPick chain (Diagram / Scope / Granularity / Direction) was removed in + * favour of inline controls on the preview tab itself. The `theme` here is a + * host-side default that the * webview re-resolves against the live VS Code theme on inline rerender; * for the initial open it is good enough to thread `light` through the * router so the source generation is deterministic. @@ -43,13 +43,13 @@ const DEFAULT_PREVIEW_OPTIONS: MermaidPreviewOptions = { }; /** - * `dextree.exportMermaid` command body (slice 029). + * `dextree.exportMermaid` command body. * - * Before slice 029 this command walked the user through a 4-step QuickPick - * (Diagram → Scope → Granularity → Direction) and a save dialog. Slice 029 - * replaces both surfaces with the Mermaid preview tab, which hosts the same - * controls inline (US2) and offers `.mmd` / `.svg` / `.png` / clipboard / - * Markdown-snippet output actions (US3) without ever closing. + * This command previously walked the user through a 4-step QuickPick + * (Diagram → Scope → Granularity → Direction) and a save dialog. Both + * surfaces are now replaced with the Mermaid preview tab, which hosts the + * same controls inline and offers `.mmd` / `.svg` / `.png` / clipboard / + * Markdown-snippet output actions without ever closing. * * In PR-A the command only opens the preview at workspace + symbol + * flowchart + auto defaults; inline controls and output actions ship in @@ -82,7 +82,7 @@ export function createExportMermaidCommand( /** * Execute an inferred Mermaid export. Used by selection-aware entry points - * (slice 030, US1) and focused export commands (slice 030, US3). + * and focused export commands. */ export async function executeInferredMermaidExport( dependencies: ExportMermaidCommandDependencies, @@ -165,7 +165,7 @@ export async function startInferredMermaidExport( } /** - * Slice 031 (US1) — `dextree.exportTraceSequence` command body. Receives the + * `dextree.exportTraceSequence` command body. Receives the * webview's `TraceSequenceSnapshot` as the first arg, re-validates it against * the current workspace subgraph (fail-closed for empty / unsupported / * oversized routes), serializes to Mermaid sequence syntax, and writes the diff --git a/packages/extension/src/commands/indexWorkspace.ts b/packages/extension/src/commands/indexWorkspace.ts index 0eb7afc..ea4311a 100644 --- a/packages/extension/src/commands/indexWorkspace.ts +++ b/packages/extension/src/commands/indexWorkspace.ts @@ -111,7 +111,7 @@ export function createIndexWorkspaceCommand( }); await indexer.clearWorkspace(root.uri.fsPath); - // Framework detection runs once before the per-file loop (slice 018). + // Framework detection runs once before the per-file loop. // Result is cached inside the indexer and consumed by each indexFile call. try { const frameworks = await indexer.detectWorkspaceFrameworks(root.uri.fsPath); diff --git a/packages/extension/src/commands/switchWorkspace.ts b/packages/extension/src/commands/switchWorkspace.ts index f5d135a..d79a104 100644 --- a/packages/extension/src/commands/switchWorkspace.ts +++ b/packages/extension/src/commands/switchWorkspace.ts @@ -1,5 +1,5 @@ /** - * `dextree.switchWorkspace` command (slice 024). + * `dextree.switchWorkspace` command. * * Reads the global workspace registry, shows a quick-pick of indexed * workspaces, and pushes the selected workspace's graph into the open panel. diff --git a/packages/extension/src/extension.ts b/packages/extension/src/extension.ts index 6ad1ef0..da57245 100644 --- a/packages/extension/src/extension.ts +++ b/packages/extension/src/extension.ts @@ -248,7 +248,7 @@ export async function activate(context: ActivationContext): Promise { })); }); - // Slice 029 PR-B — wire inline-control rerenders. The webview posts + // Wire inline-control rerenders. The webview posts // `requestMermaidPreview` whenever the user changes a control; the handler // pulls the latest indexed subgraph for the active workspace and runs it // through the same preview router the `dextree.exportMermaid` command uses. @@ -422,7 +422,7 @@ export async function activate(context: ActivationContext): Promise { }, }), ), - // Slice 030 — selection-aware and focused Mermaid export commands. + // Selection-aware and focused Mermaid export commands. // All commands delegate to the same inferred-export path so behavior // stays consistent and fail-closed. vscode.commands.registerCommand("dextree.exportCallers", async () => { diff --git a/packages/extension/src/watcher/workspaceWatcher.ts b/packages/extension/src/watcher/workspaceWatcher.ts index ed36f20..190cd2b 100644 --- a/packages/extension/src/watcher/workspaceWatcher.ts +++ b/packages/extension/src/watcher/workspaceWatcher.ts @@ -37,7 +37,7 @@ export function createWorkspaceWatcher( async function processEvent(event: WatcherEvent): Promise { const filePath = event.uri.fsPath; - // FR-002 guard: silently skip if workspace has not been indexed yet + // Silently skip if workspace has not been indexed yet try { const indexer = await getIndexer(); const allFiles = await indexer.getAllFiles(); diff --git a/packages/extension/src/webview/App.tsx b/packages/extension/src/webview/App.tsx index a7b671b..80f5933 100644 --- a/packages/extension/src/webview/App.tsx +++ b/packages/extension/src/webview/App.tsx @@ -27,7 +27,7 @@ import type { MermaidPreviewFileFormat } from "./preview/exportPreview.js"; type AppScene = "graph" | "workspaces" | "mermaid-preview"; /** - * Tab identity for the editor-style strip (slice 033 US1). Distinct from + * Tab identity for the editor-style strip. Distinct from * {@link AppScene}: "trace" is a *variant* of the graph scene (driven by * GraphView's internal trace state), not a separate scene — so it maps back to * the "graph" scene when activated. @@ -35,7 +35,7 @@ type AppScene = "graph" | "workspaces" | "mermaid-preview"; type TabKey = "graph" | "mermaid" | "trace" | "workspaces"; // --------------------------------------------------------------------------- -// State model — discriminated union (FR-002, FR-008) +// State model — discriminated union // --------------------------------------------------------------------------- interface AppState { @@ -88,7 +88,7 @@ function reducer(state: AppState, action: AppAction): AppState { } // --------------------------------------------------------------------------- -// Tab strip (slice 033 US1) +// Tab strip // --------------------------------------------------------------------------- interface TabDescriptor { @@ -351,10 +351,10 @@ export function App({ vscodeApi }: AppProps) { [showSourceOnly, state.edges, displayNodeIds], ); - // ---- Tab strip model (slice 033 US1) -------------------------------------- + // ---- Tab strip model ------------------------------------------------------ // The active tab derives from activeScene. "trace" is a graph-scene variant // owned by GraphView; at the App level it stays disabled until trace wiring - // lands (phase 5 / T032), so it never shows as the active tab here. + // lands, so it never shows as the active tab here. const activeTabKey: TabKey = activeScene === "workspaces" ? "workspaces" @@ -413,8 +413,8 @@ export function App({ vscodeApi }: AppProps) { } if (activeScene === "mermaid-preview") { - // The "Back to graph" action moved into the panel toolbar (slice 033 - // Phase 4); App no longer renders a separate preview topbar. + // The "Back to graph" action moved into the panel toolbar; App no + // longer renders a separate preview topbar. return (
void; onZoomReset: () => void; /** - * Workspace actions relocated from the legacy right-rail panel (slice 033). + * Workspace actions relocated from the legacy right-rail panel. * The whole group renders only when `onReindex` is provided, so GraphView * usages that don't own these handlers keep the mockup-clean toolbar. */ @@ -239,7 +239,7 @@ export function GraphToolbar({
- {/* Group: Workspace actions (relocated from legacy right panel, slice 033) */} + {/* Group: Workspace actions (relocated from legacy right panel) */} {onReindex !== undefined && (