diff --git a/.config/opencode/archived/with-context.ts b/.config/opencode/archived/with-context.ts new file mode 100644 index 0000000..80decf5 --- /dev/null +++ b/.config/opencode/archived/with-context.ts @@ -0,0 +1,1285 @@ +import type { Plugin } from '@opencode-ai/plugin'; +import { tool } from '@opencode-ai/plugin'; +import { + writeNote as mcpWriteNote, + readNote as mcpReadNote, + listNotes as mcpListNotes, + searchNotes as mcpSearchNotes, + healthCheck as mcpHealthCheck, + setProjectContext as mcpSetProjectContext, + getNoteMetadata as mcpGetNoteMetadata, + deleteNote as mcpDeleteNote, + batchWriteNotes as mcpBatchWriteNotes, + listTemplatesHandler as mcpListTemplates, + createFromTemplateHandler as mcpCreateFromTemplate, + ingestNotes as mcpIngestNotes, + syncNotes as mcpSyncNotes, + teleportNotes as mcpTeleportNotes, + // Session management tools + startSession as mcpStartSession, + pauseSession as mcpPauseSession, + resumeSession as mcpResumeSession, + endSession as mcpEndSession, + getSessionStatus as mcpGetSessionStatus, + // Changelog and todo tools + addChangelogEntry as mcpAddChangelogEntry, + getSessionChangelog as mcpGetSessionChangelog, + getCommitSuggestion as mcpGetCommitSuggestion, + addTodo as mcpAddTodo, + updateTodo as mcpUpdateTodo, + listTodos as mcpListTodos, + // Configuration tools + setupNotes as mcpSetupNotes, + validateConfigTool as mcpValidateConfig, + previewDelegationTool as mcpPreviewDelegation, + // Vault organization tools + analyzeVaultStructureHandler as mcpAnalyzeVaultStructure, + reorganizeNotesHandler as mcpReorganizeNotes, + generateOrganizationPlanHandler as mcpGenerateOrganizationPlan, + // Content editing tools + updateFrontmatter as mcpUpdateFrontmatter, + replaceSection as mcpReplaceSection, +} from 'with-context-mcp/tools'; + +/** + * WithContext OpenCode Plugin - Enhanced Version + * + * Provides project-scoped note management for OpenCode sessions + * Integrates with Obsidian and other note-taking apps via with-context-mcp + * + * All tools are defined inline for easy distribution and deployment + * + * Note: Full auto-tracking capabilities require OpenCode plugin API enhancements. + * Current version provides all MCP tools as native OpenCode tools. + */ +export const WithContextPlugin: Plugin = async ({ project: _project, directory: _directory }) => { + // Initialize plugin state + const config = { + vaultPath: process.env.OBSIDIAN_VAULT_PATH || process.env.HOME + '/Documents/Vault', + basePath: process.env.PROJECT_BASE_PATH || 'Projects', + }; + + return { + // Event hook for session lifecycle + event: async ({ event }) => { + // Silent cleanup on session idle + if (event.type === 'session.idle') { + // No-op: cleanup if needed + // Note: Full session status display requires access to SessionManager + // which needs to be initialized within tool context + } + }, + + // Custom tools - all defined inline + tool: { + // ==================== Status Tool ==================== + with_context_status: tool({ + description: 'Check WithContext plugin status and configuration', + args: {}, + async execute(_args, _ctx) { + return JSON.stringify( + { + status: 'active', + config, + version: '3.0.6', + tools: 32, + custom_commands: 3, + features: { + filename_slugification: true, + path_resolution: 'auto-detect-from-git', + ascii_only_output: true, + type_safety: 'zero-warnings', + project_folder_optional: '26 tools auto-detect project', + }, + note: 'Most tools auto-detect project from git context. Session lifecycle tools still require explicit project_folder.', + }, + null, + 2 + ); + }, + }), + + // ==================== Write Note Tool ==================== + write_note: tool({ + description: + 'Write or update a markdown note in the project folder. Supports create, overwrite, append, and prepend modes. Filenames are automatically slugified (lowercase, spaces/special chars become hyphens). Well-known files like README, CHANGELOG, LICENSE preserve their case.', + args: { + path: tool.schema + .string() + .describe( + 'Relative path to the note within the project folder (e.g., "CHANGELOG.md" or "docs/api.md"). Filenames are auto-slugified: "My Notes" becomes "my-notes.md"' + ), + content: tool.schema.string().describe('Content to write to the note'), + mode: tool.schema + .enum(['create', 'overwrite', 'append', 'prepend']) + .optional() + .describe( + 'Write mode: create (fail if exists), overwrite (replace), append (add to end), or prepend (add to beginning). Default: overwrite' + ), + }, + async execute(args, _ctx) { + try { + const result = await mcpWriteNote({ + path: args.path, + content: args.content, + mode: args.mode || 'overwrite', + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Read Note Tool ==================== + read_note: tool({ + description: 'Read the content of a markdown note from the project folder.', + args: { + path: tool.schema + .string() + .describe( + 'Relative path to the note within the project folder (e.g., "CHANGELOG.md" or "docs/api.md")' + ), + }, + async execute(args, _ctx) { + try { + const result = await mcpReadNote({ + path: args.path, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== List Notes Tool ==================== + list_notes: tool({ + description: + 'List all notes in a folder within the project. Supports fuzzy finding to search for notes by filename.', + args: { + path: tool.schema + .string() + .optional() + .describe('Optional: Relative path to a subfolder (defaults to project root)'), + fuzzy_query: tool.schema + .string() + .optional() + .describe( + 'Optional: Fuzzy search query to filter notes by filename (e.g., "test" matches "test-file.md", "testing.md")' + ), + limit: tool.schema + .number() + .optional() + .describe('Optional: Maximum number of results to return (default: 50)'), + min_score: tool.schema + .number() + .optional() + .describe( + 'Optional: Minimum fuzzy match score threshold 0-1 (default: 0.3, higher = stricter)' + ), + include_highlights: tool.schema + .boolean() + .optional() + .describe('Optional: Include match highlights in results (default: true)'), + }, + async execute(args, _ctx) { + try { + const result = await mcpListNotes({ + path: args.path, + fuzzy_query: args.fuzzy_query, + limit: args.limit ?? 50, + min_score: args.min_score, + include_highlights: args.include_highlights ?? true, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Update Frontmatter Tool ==================== + update_frontmatter: tool({ + description: + 'Update frontmatter in a markdown note. Supports merge mode (add/update fields while preserving others) or replace mode (overwrite entire frontmatter). Enforces read-before-write.', + args: { + path: tool.schema + .string() + .describe('Relative path to the note within the project folder'), + frontmatter: tool.schema + .record(tool.schema.string(), tool.schema.unknown()) + .describe('Frontmatter fields to add or update as key-value pairs'), + mode: tool.schema + .enum(['merge', 'replace']) + .describe( + 'Update mode: merge (add/update fields, preserve others) or replace (overwrite entire frontmatter)' + ), + project_folder: tool.schema + .string() + .optional() + .describe('Optional: Project folder name in vault (auto-detects if omitted)'), + }, + async execute(args, _ctx) { + try { + const result = await mcpUpdateFrontmatter({ + path: args.path, + frontmatter: args.frontmatter, + mode: args.mode, + project_folder: args.project_folder, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Replace Section Tool ==================== + replace_section: tool({ + description: + 'Replace a section in a markdown note by heading. Supports content-only (default), full, or heading-only replacement modes. Can create section if missing. Enforces read-before-write.', + args: { + path: tool.schema + .string() + .describe('Relative path to the note within the project folder'), + heading: tool.schema + .string() + .describe( + 'Heading text to find (without # symbols, e.g., "Installation" not "## Installation")' + ), + content: tool.schema.string().describe('New content for the section'), + mode: tool.schema + .enum(['content-only', 'full', 'heading-only']) + .optional() + .describe( + 'Replace mode: content-only (default, replace only section content), full (replace both heading and content), heading-only (replace only heading text, preserve content)' + ), + level: tool.schema + .number() + .int() + .min(1) + .max(6) + .optional() + .describe('Optional: Filter by heading level (1-6) to disambiguate duplicate headings'), + index: tool.schema + .number() + .int() + .min(0) + .optional() + .describe( + 'Optional: Which occurrence to replace if duplicates exist (0-based, use to disambiguate)' + ), + preview: tool.schema + .boolean() + .optional() + .describe( + 'Optional: Preview changes without applying them. Returns before/after comparison (default: false)' + ), + createIfMissing: tool.schema + .boolean() + .optional() + .describe( + 'Optional: Create section at end of file if not found. Only applies to content-only mode (default: false)' + ), + project_folder: tool.schema + .string() + .optional() + .describe('Optional: Project folder name in vault (auto-detects if omitted)'), + }, + async execute(args, _ctx) { + try { + const result = await mcpReplaceSection({ + path: args.path, + heading: args.heading, + content: args.content, + mode: args.mode as 'content-only' | 'full' | 'heading-only' | undefined, + level: args.level, + index: args.index, + preview: args.preview ?? false, + createIfMissing: args.createIfMissing ?? false, + project_folder: args.project_folder, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Search Notes Tool ==================== + search_notes: tool({ + description: + 'Search for notes by content within the project folder. Returns matching files with snippets showing context around matches.', + args: { + query: tool.schema.string().describe('Search query text to find in note contents'), + case_sensitive: tool.schema + .boolean() + .optional() + .describe('Whether to perform case-sensitive search (default: false)'), + limit: tool.schema + .number() + .optional() + .describe('Maximum number of results to return (default: 10)'), + }, + async execute(args, _ctx) { + try { + const result = await mcpSearchNotes({ + query: args.query, + + case_sensitive: args.case_sensitive ?? false, + limit: args.limit ?? 10, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Health Check Tool ==================== + health_check: tool({ + description: + 'Perform a comprehensive health check of the with-context-mcp environment. ' + + 'Validates environment variables, Obsidian API connection, and configuration. ' + + 'Returns detailed status and recommendations for fixing any issues. Fast (< 2 seconds).', + args: { + project_folder: tool.schema + .string() + .optional() + .describe('Optional: Project folder to check for .withcontextconfig.jsonc'), + }, + async execute(args, _ctx) { + try { + const result = await mcpHealthCheck({ + project_folder: args.project_folder, + }); + return JSON.stringify(result, null, 2); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Set Project Context Tool ==================== + set_project_context: tool({ + description: + 'Set the project folder context for this session. All subsequent operations will use this folder unless overridden.', + args: { + project_folder: tool.schema + .string() + .describe('The project folder name within the vault (e.g., "my-web-app")'), + }, + async execute(args, _ctx) { + try { + const result = await mcpSetProjectContext({ + project_folder: args.project_folder, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Get Note Metadata Tool ==================== + get_note_metadata: tool({ + description: + 'Get metadata about a note including word count, line count, frontmatter, tags, and headings.', + args: { + path: tool.schema + .string() + .describe('Relative path to the note within the project folder'), + }, + async execute(args, _ctx) { + try { + const result = await mcpGetNoteMetadata({ + path: args.path, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Delete Note Tool ==================== + delete_note: tool({ + description: + 'Delete a markdown note from the project folder. Requires explicit confirmation. Lists file metadata (size, line count, preview) before deletion for safety verification.', + args: { + path: tool.schema.string().describe('Relative path to the note to delete'), + confirm: tool.schema.boolean().describe('Must be set to true to confirm deletion'), + }, + async execute(args, _ctx) { + try { + const result = await mcpDeleteNote({ + path: args.path, + confirm: args.confirm, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Batch Write Notes Tool ==================== + batch_write_notes: tool({ + description: + 'Write multiple notes at once. Processes each note independently and returns a summary with per-note status.', + args: { + notes: tool.schema + .array( + tool.schema.object({ + path: tool.schema + .string() + .describe('Relative path to the note within the project folder'), + content: tool.schema.string().describe('Content to write to the note'), + mode: tool.schema + .enum(['create', 'overwrite', 'append']) + .optional() + .describe( + 'Write mode: create (fail if exists), overwrite (replace), or append (add to end). Default: overwrite' + ), + }) + ) + .describe('Array of notes to write'), + }, + async execute(args, _ctx) { + try { + const result = await mcpBatchWriteNotes({ + notes: args.notes.map((note) => ({ + path: note.path, + content: note.content, + mode: (note.mode || 'overwrite') as 'create' | 'overwrite' | 'append', + })), + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== List Templates Tool ==================== + list_templates: tool({ + description: + 'List all available note templates with their descriptions and required variables.', + args: {}, + async execute(_args, _ctx) { + try { + const result = await mcpListTemplates({}); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Create From Template Tool ==================== + create_from_template: tool({ + description: + 'Create a new note from a template. Templates support variable substitution and auto-fill common variables like date and time.', + args: { + template_name: tool.schema.string().describe('Name of the template to use'), + filename: tool.schema + .string() + .describe('Filename for the new note (e.g., "CHANGELOG.md" or "docs/meeting.md")'), + variables: tool.schema + .record(tool.schema.string(), tool.schema.string()) + .optional() + .describe( + 'Variables to substitute in the template (e.g., {"version": "1.0.0", "author": "John"})' + ), + }, + async execute(args, _ctx) { + try { + const result = await mcpCreateFromTemplate({ + template_name: args.template_name, + filename: args.filename, + variables: args.variables, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Ingest Notes Tool ==================== + ingest_notes: tool({ + description: + 'Ingest local documentation files to Obsidian vault. Scans the current project for documentation files based on .withcontextconfig.jsonc delegation rules and copies them to the vault.', + args: { + dry_run: tool.schema + .boolean() + .optional() + .describe('If true, show what would be ingested without actually writing files'), + delete_local_files: tool.schema + .boolean() + .optional() + .describe( + 'If true, delete local files after successful ingestion. Requires explicit confirmation.' + ), + force_delete: tool.schema + .boolean() + .optional() + .describe('If true, skip safety checks when deleting. Use with caution!'), + }, + async execute(args, _ctx) { + try { + const result = await mcpIngestNotes({ + dry_run: args.dry_run ?? false, + delete_local_files: args.delete_local_files ?? false, + force_delete: args.force_delete ?? false, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Sync Notes Tool ==================== + sync_notes: tool({ + description: + 'Bidirectionally sync documentation files between local project and Obsidian vault. Files are synced based on .withcontextconfig.jsonc delegation rules and moved between locations (deleted from source after successful copy).', + args: { + dry_run: tool.schema + .boolean() + .optional() + .describe('If true, show what would be synced without actually moving files'), + }, + async execute(args, _ctx) { + try { + const result = await mcpSyncNotes({ + dry_run: args.dry_run ?? false, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Teleport Notes Tool ==================== + teleport_notes: tool({ + description: + 'Teleport documentation files from Obsidian vault to local project. Downloads files from the vault back to the local project.', + args: { + dry_run: tool.schema + .boolean() + .optional() + .describe('If true, show what would be teleported without actually writing files'), + delete_from_vault: tool.schema + .boolean() + .optional() + .describe( + 'If true, delete files from vault after successful teleport. Use with caution!' + ), + force_delete: tool.schema + .boolean() + .optional() + .describe('If true, skip safety checks when deleting. Use with extreme caution!'), + }, + async execute(args, _ctx) { + try { + const result = await mcpTeleportNotes({ + dry_run: args.dry_run ?? false, + delete_from_vault: args.delete_from_vault ?? false, + force_delete: args.force_delete ?? false, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Setup Notes Tool ==================== + setup_notes: tool({ + description: + 'Intelligent documentation setup for the project. Scans repository structure, analyzes documentation files, and generates smart delegation rules in .withcontextconfig.jsonc. Provides recommendations for vault vs local placement.', + args: { + project_root: tool.schema + .string() + .optional() + .describe('Project root directory (defaults to current working directory)'), + force: tool.schema.boolean().optional().describe('If true, overwrite existing config'), + create_structure: tool.schema + .boolean() + .optional() + .describe('If true, create recommended folder structure in vault (default: true)'), + project_folder: tool.schema + .string() + .optional() + .describe('Project folder name in vault (required if create_structure is true)'), + auto_apply: tool.schema + .boolean() + .optional() + .describe('If true, skip confirmation prompts'), + }, + async execute(args, _ctx) { + try { + const result = await mcpSetupNotes({ + project_root: args.project_root, + force: args.force ?? false, + create_structure: args.create_structure ?? true, + project_folder: args.project_folder, + auto_apply: args.auto_apply ?? false, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Validate Config Tool ==================== + validate_config: tool({ + description: + 'Validate .withcontextconfig.jsonc for errors and warnings. Provides detailed feedback on configuration issues including schema validation, pattern conflicts, and best practice recommendations.', + args: { + project_root: tool.schema.string().describe('Project root directory'), + config_path: tool.schema + .string() + .optional() + .describe('Path to config file (defaults to .withcontextconfig.jsonc)'), + }, + async execute(args, _ctx) { + try { + const result = await mcpValidateConfig({ + project_root: args.project_root, + config_path: args.config_path, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Preview Delegation Tool ==================== + preview_delegation: tool({ + description: + 'Preview which files will be delegated to vault vs kept local based on configuration patterns. Useful for testing patterns before syncing. Shows reasoning for decisions and allows filtering.', + args: { + project_root: tool.schema.string().describe('Project root directory'), + config_path: tool.schema + .string() + .optional() + .describe('Path to config file (defaults to .withcontextconfig.jsonc)'), + file_patterns: tool.schema + .array(tool.schema.string()) + .optional() + .describe('Glob patterns for files to preview (default: ["**/*.md"])'), + limit: tool.schema + .number() + .optional() + .describe('Maximum number of files to show per category (default: 100)'), + show_reasoning: tool.schema + .boolean() + .optional() + .describe('Show reasoning for each delegation decision (default: false)'), + vault_only: tool.schema.boolean().optional().describe('Show only files going to vault'), + local_only: tool.schema.boolean().optional().describe('Show only files staying local'), + specific_files: tool.schema + .array(tool.schema.string()) + .optional() + .describe('Preview delegation for specific files only'), + }, + async execute(args, _ctx) { + try { + const result = await mcpPreviewDelegation({ + project_root: args.project_root, + config_path: args.config_path, + file_patterns: args.file_patterns, + limit: args.limit ?? 100, + show_reasoning: args.show_reasoning ?? false, + vault_only: args.vault_only ?? false, + local_only: args.local_only ?? false, + specific_files: args.specific_files, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Start Session Tool ==================== + start_session: tool({ + description: + 'Start a new development session for the project. Creates a new session and persists it to vault. Sets the project context for subsequent operations.', + args: { + project_folder: tool.schema + .string() + .describe('Project folder name in vault (e.g., "my-project")'), + message: tool.schema + .string() + .optional() + .describe('Optional message to describe session purpose'), + }, + async execute(args, _ctx) { + try { + const result = await mcpStartSession({ + project_folder: args.project_folder, + message: args.message, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Pause Session Tool ==================== + pause_session: tool({ + description: + 'Pause the current active session. Saves session state to vault and clears timers. Session can be resumed later with resume_session.', + args: { + project_folder: tool.schema + .string() + .optional() + .describe( + 'Optional: Project folder name in vault (auto-detects from current context if omitted)' + ), + }, + async execute(args, _ctx) { + try { + const result = await mcpPauseSession({ + project_folder: args.project_folder, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Resume Session Tool ==================== + resume_session: tool({ + description: + 'Resume a paused session. If session_id is provided, loads that specific session from vault. Otherwise, resumes the most recent paused session.', + args: { + project_folder: tool.schema + .string() + .optional() + .describe( + 'Optional: Project folder name in vault (auto-detects from current context if omitted)' + ), + session_id: tool.schema + .string() + .optional() + .describe('Optional session ID to resume (defaults to most recent paused session)'), + }, + async execute(args, _ctx) { + try { + const result = await mcpResumeSession({ + project_folder: args.project_folder, + session_id: args.session_id, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== End Session Tool ==================== + end_session: tool({ + description: + 'Complete and archive the current session. Marks session as completed, saves final state to vault archive, and clears active session. Generates comprehensive summary.', + args: { + project_folder: tool.schema + .string() + .optional() + .describe( + 'Optional: Project folder name in vault (auto-detects from current context if omitted)' + ), + message: tool.schema + .string() + .optional() + .describe('Optional completion message or summary'), + }, + async execute(args, _ctx) { + try { + const result = await mcpEndSession({ + project_folder: args.project_folder, + message: args.message, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Get Session Status Tool ==================== + get_session_status: tool({ + description: + 'Get current session status and comprehensive details. Returns session information including ID, status, duration, files tracked, todos, changelog entries, git context, and metadata.', + args: { + project_folder: tool.schema + .string() + .optional() + .describe('Optional: Project folder name in vault (auto-detects if omitted)'), + }, + async execute(args, _ctx) { + try { + const result = await mcpGetSessionStatus({ + project_folder: args.project_folder, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Add Changelog Entry Tool ==================== + add_changelog_entry: tool({ + description: + 'Add a changelog entry to the current session. User provides type and message for semi-automatic tracking. Entry is immediately persisted to session state.', + args: { + project_folder: tool.schema + .string() + .optional() + .describe( + 'Optional: Project folder name in vault (auto-detects from current context if omitted)' + ), + type: tool.schema + .enum(['feature', 'fix', 'refactor', 'docs', 'test', 'chore']) + .describe('Type of change (conventional commit type)'), + message: tool.schema.string().describe('Description of the change'), + files: tool.schema + .array(tool.schema.string()) + .optional() + .describe('Optional: Files affected by this change'), + breaking: tool.schema + .boolean() + .optional() + .describe('Optional: Whether this is a breaking change'), + }, + async execute(args, _ctx) { + try { + const result = await mcpAddChangelogEntry({ + project_folder: args.project_folder, + type: args.type as 'feature' | 'fix' | 'refactor' | 'docs' | 'test' | 'chore', + message: args.message, + files: args.files, + breaking: args.breaking, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Get Session Changelog Tool ==================== + get_session_changelog: tool({ + description: + 'View changelog for the current session. Returns all entries grouped by type with file counts and breaking change indicators.', + args: { + project_folder: tool.schema + .string() + .optional() + .describe('Optional: Project folder name in vault (auto-detects if omitted)'), + }, + async execute(args, _ctx) { + try { + const result = await mcpGetSessionChangelog({ + project_folder: args.project_folder, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Get Commit Suggestion Tool ==================== + get_commit_suggestion: tool({ + description: + 'Generate a conventional commit message from session changelog. Analyzes entries to determine primary type and formats message. Includes all changes as bullet points and detects breaking changes.', + args: { + project_folder: tool.schema + .string() + .optional() + .describe('Optional: Project folder name in vault (auto-detects if omitted)'), + conventional: tool.schema + .boolean() + .optional() + .describe('Use conventional commit format (default: true)'), + }, + async execute(args, _ctx) { + try { + const result = await mcpGetCommitSuggestion({ + project_folder: args.project_folder, + conventional: args.conventional ?? true, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Add Todo Tool ==================== + add_todo: tool({ + description: + 'Add a todo to the current session. Todos persist across sessions and are tracked per project. Immediately saved to session state in vault.', + args: { + project_folder: tool.schema + .string() + .optional() + .describe( + 'Optional: Project folder name in vault (auto-detects from current context if omitted)' + ), + content: tool.schema.string().describe('Todo content/description'), + priority: tool.schema + .enum(['high', 'medium', 'low']) + .optional() + .describe('Priority level (default: medium)'), + }, + async execute(args, _ctx) { + try { + const result = await mcpAddTodo({ + project_folder: args.project_folder, + content: args.content, + priority: (args.priority as 'high' | 'medium' | 'low') ?? 'medium', + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Update Todo Tool ==================== + update_todo: tool({ + description: + 'Update todo status or priority. Automatically sets completedAt timestamp when marked as completed. Changes are immediately persisted to vault.', + args: { + project_folder: tool.schema + .string() + .optional() + .describe( + 'Optional: Project folder name in vault (auto-detects from current context if omitted)' + ), + todo_id: tool.schema.string().describe('Todo ID to update'), + status: tool.schema + .enum(['pending', 'in_progress', 'completed', 'cancelled']) + .optional() + .describe('New status'), + priority: tool.schema.enum(['high', 'medium', 'low']).optional().describe('New priority'), + }, + async execute(args, _ctx) { + try { + const result = await mcpUpdateTodo({ + project_folder: args.project_folder, + todo_id: args.todo_id, + status: args.status as + | 'pending' + | 'in_progress' + | 'completed' + | 'cancelled' + | undefined, + priority: args.priority as 'high' | 'medium' | 'low' | undefined, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== List Todos Tool ==================== + list_todos: tool({ + description: + 'List todos from current session with optional filters. Returns todos grouped by status with counts and priority indicators. Can filter by status and/or priority.', + args: { + project_folder: tool.schema + .string() + .optional() + .describe('Optional: Project folder name in vault (auto-detects if omitted)'), + status: tool.schema + .enum(['pending', 'in_progress', 'completed', 'cancelled']) + .optional() + .describe('Filter by status'), + priority: tool.schema + .enum(['high', 'medium', 'low']) + .optional() + .describe('Filter by priority'), + }, + async execute(args, _ctx) { + try { + const result = await mcpListTodos({ + project_folder: args.project_folder, + status: args.status as + | 'pending' + | 'in_progress' + | 'completed' + | 'cancelled' + | undefined, + priority: args.priority as 'high' | 'medium' | 'low' | undefined, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Analyze Vault Structure Tool ==================== + analyze_vault_structure: tool({ + description: + 'Analyze vault structure and content. Scans all markdown files, extracts metadata (headings, frontmatter, links, tags), categorizes files, identifies orphans, and builds comprehensive statistics.', + args: { + exclude_patterns: tool.schema + .array(tool.schema.string()) + .optional() + .describe( + 'Optional: Glob patterns to exclude from analysis (e.g., ["*.tmp", "drafts/*"])' + ), + include_categories: tool.schema + .boolean() + .optional() + .describe( + 'Optional: Whether to include category statistics in results (default: true)' + ), + include_orphans: tool.schema + .boolean() + .optional() + .describe( + 'Optional: Whether to identify orphan files (no incoming/outgoing links, default: true)' + ), + max_file_size_mb: tool.schema + .number() + .optional() + .describe('Optional: Maximum file size in MB to analyze (default: 10)'), + max_files: tool.schema + .number() + .optional() + .describe('Optional: Maximum number of files to analyze (for limiting large vaults)'), + }, + async execute(args, _ctx) { + try { + const result = await mcpAnalyzeVaultStructure({ + exclude_patterns: args.exclude_patterns, + include_categories: args.include_categories ?? true, + include_orphans: args.include_orphans ?? true, + max_file_size_mb: args.max_file_size_mb ?? 10, + max_files: args.max_files, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + + // ==================== Reorganize Vault Tool ==================== + reorganize_vault: tool({ + description: + 'Execute vault reorganization based on an organization plan. Supports move and rename operations with dry-run mode (enabled by default), automatic link updates, rollback on failure, and confidence-based filtering.', + args: { + plan: tool.schema + .object({ + suggestions: tool.schema + .array( + tool.schema.object({ + type: tool.schema + .enum(['rename', 'move', 'both']) + .describe('Type of reorganization operation'), + currentPath: tool.schema + .string() + .describe('Current file path relative to vault root'), + suggestedPath: tool.schema + .string() + .optional() + .describe('Suggested new path (for move operations)'), + suggestedName: tool.schema + .string() + .optional() + .describe('Suggested new name (for rename operations)'), + reason: tool.schema + .string() + .describe('Human-readable reason for this suggestion'), + confidence: tool.schema.number().describe('Confidence score (0-1)'), + impact: tool.schema + .object({ + affectedFiles: tool.schema.number().optional(), + linksToUpdate: tool.schema.number().optional(), + potentialBrokenLinks: tool.schema.array(tool.schema.string()).optional(), + complexity: tool.schema.enum(['low', 'medium', 'high']).optional(), + }) + .optional() + .describe('Impact assessment for this operation'), + targetCategory: tool.schema + .string() + .optional() + .describe('Target category after reorganization'), + }) + ) + .describe('List of reorganization suggestions'), + estimatedImpact: tool.schema + .object({ + filesToMove: tool.schema.number().optional(), + filesToRename: tool.schema.number().optional(), + linksToUpdate: tool.schema.number().optional(), + filesRequiringLinkUpdates: tool.schema.number().optional(), + estimatedDuration: tool.schema.number().optional(), + hasRiskyOperations: tool.schema.boolean().optional(), + }) + .optional() + .describe('Overall estimated impact of executing the plan'), + warnings: tool.schema + .array( + tool.schema.object({ + severity: tool.schema.enum(['info', 'warning', 'error']), + filePath: tool.schema.string().optional(), + message: tool.schema.string(), + suggestion: tool.schema.string().optional(), + }) + ) + .optional() + .describe('List of warnings about the plan'), + summary: tool.schema.string().optional().describe('High-level summary of the plan'), + requiresManualReview: tool.schema.boolean().optional(), + }) + .describe('The reorganization plan to execute (from analyze_vault_structure)'), + dry_run: tool.schema + .boolean() + .optional() + .describe( + 'If true, preview operations without making changes (default: true for safety)' + ), + update_links: tool.schema + .boolean() + .optional() + .describe('If true, automatically update links in other files (default: true)'), + create_backup: tool.schema + .boolean() + .optional() + .describe('If true, create backups before executing (default: true for safety)'), + min_confidence: tool.schema + .number() + .optional() + .describe('Minimum confidence threshold for executing operations (default: 0.7)'), + }, + async execute(args, _ctx) { + try { + const result = await mcpReorganizeNotes({ + plan: args.plan as unknown as Parameters[0]['plan'], + dry_run: args.dry_run ?? true, + update_links: args.update_links ?? true, + create_backup: args.create_backup ?? true, + min_confidence: args.min_confidence ?? 0.7, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + generate_organization_plan: tool({ + description: + 'Generate an organization plan using a preset strategy. Analyzes vault structure and applies preset rules to create comprehensive reorganization suggestions. Use this BEFORE reorganize_notes.', + args: { + preset_id: tool.schema + .string() + .describe( + 'Preset to apply: "clean", "minimal", "docs-as-code", or "research". Use list_presets for details.' + ), + min_confidence: tool.schema + .number() + .optional() + .describe('Minimum confidence threshold for including suggestions (default: 0.7)'), + exclude_files: tool.schema + .array(tool.schema.string()) + .optional() + .describe('File patterns to exclude from analysis (glob patterns)'), + custom_rules: tool.schema + .array( + tool.schema.object({ + name: tool.schema.string(), + priority: tool.schema.number(), + pattern: tool.schema.string(), + targetPath: tool.schema.string(), + confidence: tool.schema.number(), + reason: tool.schema.string(), + }) + ) + .optional() + .describe('Additional custom rules to apply after preset rules'), + max_file_size_mb: tool.schema + .number() + .optional() + .describe('Maximum file size to analyze in MB (default: 10)'), + }, + async execute(args, _ctx) { + try { + const result = await mcpGenerateOrganizationPlan({ + preset_id: args.preset_id, + min_confidence: args.min_confidence ?? 0.7, + exclude_files: args.exclude_files, + custom_rules: args.custom_rules as + | Array<{ + name: string; + priority: number; + pattern: string; + targetPath: string; + confidence: number; + reason: string; + }> + | undefined, + max_file_size_mb: args.max_file_size_mb ?? 10, + }); + return result; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + return JSON.stringify({ success: false, error: message }, null, 2); + } + }, + }), + }, + }; +}; + +// Default export for plugin loading +export default WithContextPlugin; diff --git a/.config/opencode/command/analyze-vault.md b/.config/opencode/command/analyze-vault.md new file mode 100644 index 0000000..b7168ce --- /dev/null +++ b/.config/opencode/command/analyze-vault.md @@ -0,0 +1,294 @@ +--- +description: Analyze vault structure and organization +agent: general +subtask: true +--- + +# Analyze Vault Structure + +This command performs a comprehensive analysis of your vault's structure, content, and organization. It scans all markdown files, extracts metadata, categorizes content, and identifies opportunities for improvement. + +## What This Command Does + +The vault analyzer performs deep structural analysis: + +### Content Scanning + +- Scans all markdown files in the project folder +- Extracts frontmatter metadata (tags, dates, categories) +- Analyzes headings hierarchy and structure +- Identifies internal and external links +- Extracts inline tags and keywords +- Calculates file statistics (size, word count, etc.) + +### Organization Analysis + +- Categorizes files by type (guides, tutorials, reference, architecture, etc.) +- Analyzes folder structure and depth +- Identifies orphaned files (no incoming/outgoing links) +- Detects naming patterns and conventions +- Builds link graph showing connections between notes +- Calculates organization health metrics + +### Output Includes + +- **Summary**: Total files, folders, size, and health score +- **Folder Statistics**: File counts, average depth, naming patterns +- **Categories**: Files grouped by content type with statistics +- **Orphans**: Isolated files that could be better connected +- **Link Analysis**: Most referenced files, broken links +- **Recommendations**: Suggestions for improving organization + +## Example Output + +``` +=== Vault Structure Analysis === + +Project: my-awesome-project +Total Files: 45 markdown files +Total Size: 2.34 MB +Health Score: 78/100 + +=== Folder Structure === + +docs/ (32 files, 1.8 MB) + guides/ (12 files) + tutorials/ (8 files) + architecture/ (6 files) + decisions/ (5 files) + reference/ (6 files) + +=== Content Categories === + +Guides (task-oriented): 12 files (26.7%) +Tutorials (learning): 8 files (17.8%) +Architecture (explanation): 11 files (24.4%) +Reference (information): 6 files (13.3%) +Uncategorized: 8 files (17.8%) + +=== Orphaned Files === + +Found 4 orphaned files with no links: + - docs/old-notes.md (0 incoming, 0 outgoing) + - drafts/temp.md (0 incoming, 0 outgoing) + - research/abandoned.md (1 outgoing, 0 incoming) + +=== Link Analysis === + +Total Links: 234 + Internal: 198 (84.6%) + External: 36 (15.4%) + +Most Referenced Files: + 1. docs/architecture/overview.md (23 incoming links) + 2. docs/guides/quick-start.md (18 incoming links) + 3. README.md (15 incoming links) + +=== Recommendations === + +1. Connect orphaned files or consider archiving +2. Add more cross-references between guides and tutorials +3. Create index files for large folders (guides/, reference/) +4. Consider moving 3 files to more appropriate categories +5. Standardize file naming (found mixed conventions) +``` + +## Your Task + +Execute the analyze_vault_structure tool immediately with options based on user arguments: + +```javascript +// Parse optional arguments +const args = '$ARGUMENTS'; +const noCategories = args.includes('--no-categories'); +const noOrphans = args.includes('--no-orphans'); +const maxFilesMatch = args.match(/--max-files[=\s](\d+)/); +const maxFiles = maxFilesMatch ? parseInt(maxFilesMatch[1]) : undefined; + +const result = await analyze_vault_structure({ + include_categories: !noCategories, + include_orphans: !noOrphans, + max_file_size_mb: 10, + max_files: maxFiles, + exclude_patterns: ['drafts/*', '*.tmp', 'archive/*'], +}); + +return result; +``` + +**Usage Examples:** + +- `/analyze-vault` - Full analysis with all features +- `/analyze-vault --no-categories` - Skip content categorization +- `/analyze-vault --no-orphans` - Skip orphan detection +- `/analyze-vault --max-files 500` - Limit to 500 files + +## Analysis Options + +### exclude_patterns (optional) + +Glob patterns for files/folders to skip: + +```javascript +exclude_patterns: ['drafts/*', '*.tmp', 'archive/*', '.trash/*']; +``` + +### include_categories (optional, default: true) + +Whether to categorize files by content type (guides, tutorials, reference, etc.): + +```javascript +include_categories: true; // Analyze and group by category +include_categories: false; // Skip categorization +``` + +### include_orphans (optional, default: true) + +Whether to identify orphaned files with no links: + +```javascript +include_orphans: true; // Find isolated files +include_orphans: false; // Skip orphan detection +``` + +### max_file_size_mb (optional, default: 10) + +Skip files larger than this size: + +```javascript +max_file_size_mb: 10; // Skip files over 10 MB +``` + +### max_files (optional) + +Limit total number of files analyzed (useful for large vaults): + +```javascript +max_files: 500; // Analyze first 500 files only +``` + +## Understanding the Results + +### Health Score (0-100) + +Indicates overall vault organization quality: + +- **90-100**: Excellent organization, consistent structure +- **70-89**: Good organization, minor improvements possible +- **50-69**: Moderate organization, several areas need attention +- **Below 50**: Poor organization, significant restructuring recommended + +### Categories + +Files are classified using the Diátaxis framework: + +- **Guides** (task-oriented): How-to documentation +- **Tutorials** (learning-oriented): Step-by-step learning paths +- **Reference** (information-oriented): API docs, specifications +- **Architecture** (understanding-oriented): Design decisions, explanations +- **Uncategorized**: Files that don't fit clear patterns + +### Orphaned Files + +Files with no connections to the rest of your vault: + +- **No incoming links**: Nothing references this file +- **No outgoing links**: This file doesn't reference others +- **Both**: Completely isolated + +Consider linking orphans or archiving if obsolete. + +### Link Analysis + +Shows how notes connect: + +- **High incoming links**: Core reference documents +- **High outgoing links**: Hub or index pages +- **Broken links**: References to missing files + +## Common Use Cases + +### 1. Initial Vault Assessment + +```javascript +analyze_vault_structure({ + project_folder: 'my-project', + include_categories: true, + include_orphans: true, +}); +``` + +Understand current state before reorganization. + +### 2. Identify Cleanup Targets + +```javascript +analyze_vault_structure({ + project_folder: 'my-project', + include_orphans: true, + exclude_patterns: ['archive/*'], +}); +``` + +Find files to archive or delete. + +### 3. Verify Organization + +```javascript +analyze_vault_structure({ + project_folder: 'my-project', + include_categories: true, +}); +``` + +Check if files are properly categorized. + +### 4. Performance Analysis + +```javascript +analyze_vault_structure({ + project_folder: 'large-project', + max_files: 1000, + max_file_size_mb: 5, +}); +``` + +Analyze large vaults efficiently. + +## Guidelines for Agents + +When running this command: + +1. **ONLY use the analyze_vault_structure tool** - Do NOT perform manual analysis +2. **Present results clearly** - Show full output with key highlights +3. **Explain findings** - Help user understand what the analysis means +4. **Do NOT**: + - Manually read files or scan directories + - Parse markdown or extract metadata yourself + - Build statistics or link graphs manually + - The tool does everything automatically +5. **Your role is to**: + - Call the tool with appropriate parameters + - Present and explain the results + - Suggest next steps based on findings + +## Next Steps After Analysis + +Based on the analysis results: + +1. **If orphans found**: Review and either link or archive them +2. **If health score low**: Consider running `/reorganize-notes` +3. **If categories mixed**: Move files to appropriate folders +4. **If broken links**: Fix or remove invalid references +5. **If naming inconsistent**: Standardize file names + +## Related Commands + +- `/reorganize-notes` - Execute reorganization plan based on analysis +- `/setup-notes` - Configure documentation architecture +- `/validate-config` - Validate configuration +- `/sync-notes` - Sync files between local and vault + +--- + +_The analyze-vault-structure tool uses intelligent content analysis to provide actionable insights about your vault's organization and health._ diff --git a/.config/opencode/command/ingest-notes.md b/.config/opencode/command/ingest-notes.md new file mode 100644 index 0000000..b40e7ae --- /dev/null +++ b/.config/opencode/command/ingest-notes.md @@ -0,0 +1,99 @@ +--- +description: Ingest local documentation files to Obsidian vault +agent: general +subtask: true +--- + +# Ingest Notes + +Scans the current project for documentation files based on `.withcontextconfig.jsonc` delegation rules and copies them to the Obsidian vault. + +## What This Command Does + +This command copies documentation files from your local project to the Obsidian vault: + +- Scans project for files matching vault patterns in `.withcontextconfig.jsonc` +- Copies matched files to vault preserving directory structure +- Optionally deletes local files after successful copy +- Provides dry-run preview mode + +**Prerequisites:** + +- `.withcontextconfig.jsonc` must exist (run `/setup-notes` first if not) +- Configuration defines which files have delegation decision "vault" + +## Your Task + +Execute the ingest_notes tool immediately with dry-run by default for safety: + +```javascript +// Check for flags in arguments +const args = '$ARGUMENTS'; +const shouldExecute = args.includes('--execute'); +const shouldDelete = args.includes('--delete'); +const forceDelete = args.includes('--force-delete'); + +const result = await ingest_notes({ + dry_run: !shouldExecute, + delete_local_files: shouldDelete, + force_delete: forceDelete, +}); + +return result; +``` + +**Usage:** + +- `/ingest-notes` - Preview what will be copied (safe, dry-run mode) +- `/ingest-notes --execute` - Copy files to vault (keeps local files) +- `/ingest-notes --execute --delete` - Copy and delete local files +- `/ingest-notes --execute --delete --force-delete` - Force delete even on errors + +**Important:** Use `--delete` flag only if you want to remove local files after copying! + +## Parameters + +### dry_run (optional, default: false) + +Preview mode - shows what will happen without making changes: + +```javascript +dry_run: true; // Preview only +dry_run: false; // Execute for real +``` + +### delete_local_files (optional, default: false) + +Whether to delete local files after successful copy to vault: + +```javascript +delete_local_files: false; // Keep local files (default) +delete_local_files: true; // Delete local files after copy +``` + +### force_delete (optional, default: false) + +Force deletion of local files even if some files had errors: + +```javascript +force_delete: false; // Don't delete if errors occurred (default) +force_delete: true; // Delete even if some files failed +``` + +## Important Notes + +- **Local files are NOT deleted by default** - set `delete_local_files: true` explicitly if desired +- **Always preview first** - Use `dry_run: true` before executing +- **The tool automatically checks** for `.withcontextconfig.jsonc` existence +- **Directory structure is preserved** in the vault + +## Related Commands + +- `/setup-notes` - Create configuration file +- `/preview-notes-delegation` - Preview which files will be ingested +- `/sync-notes` - Bidirectional sync (moves files both ways) +- `/validate-notes-config` - Validate configuration + +--- + +_The ingest-notes tool copies local documentation to vault based on delegation rules._ diff --git a/.config/opencode/command/preview-notes-delegation.md b/.config/opencode/command/preview-notes-delegation.md new file mode 100644 index 0000000..564af07 --- /dev/null +++ b/.config/opencode/command/preview-notes-delegation.md @@ -0,0 +1,193 @@ +--- +description: Preview which documentation files will be delegated to vault vs local +agent: general +subtask: true +--- + +# Preview Notes Delegation + +Previews which files in your project will be delegated to the Obsidian vault versus kept in the local repository based on `.withcontextconfig.jsonc` patterns. + +## What This Command Does + +This command analyzes your project files and shows delegation decisions **before** performing any sync operations: + +**Analysis Features:** + +1. **File Discovery** - Scans project for documentation files matching patterns +2. **Delegation Decision** - Applies configuration rules to determine vault vs local +3. **Categorization** - Groups files by destination (vault/local) +4. **Reasoning** - Optionally shows why each file was categorized +5. **Filtering** - Can show only vault files or only local files + +**Prerequisites:** + +- `.withcontextconfig.jsonc` must exist (run `/setup-notes` first if not) + +**Tool Priority:** +First try to use the WithContext plugin's `preview_delegation` tool. If not available, fallback to the with-context MCP server's `preview_delegation` tool. + +## Your Task + +Execute the preview_delegation tool immediately with options based on user arguments: + +```javascript +// Parse optional arguments +const args = '$ARGUMENTS'; +const vaultOnly = args.includes('--vault-only'); +const localOnly = args.includes('--local-only'); +const noReasoning = args.includes('--no-reasoning'); +const limitMatch = args.match(/--limit[=\s](\d+)/); +const limit = limitMatch ? parseInt(limitMatch[1]) : 100; + +const result = await preview_delegation({ + project_root: process.cwd(), + show_reasoning: !noReasoning, + limit: limit, + vault_only: vaultOnly, + local_only: localOnly, +}); + +return result; +``` + +**Usage Examples:** + +- `/preview-notes-delegation` - Full preview with reasoning +- `/preview-notes-delegation --vault-only` - Show only vault files +- `/preview-notes-delegation --local-only` - Show only local files +- `/preview-notes-delegation --limit 20` - Limit to 20 files per category +- `/preview-notes-delegation --no-reasoning` - Hide detailed reasoning + +## Optional Parameters + +The user can customize the preview with flags: + +**`--vault-only`** - Show only files going to vault + +```javascript +preview_delegation({ + project_root: '/path/to/project', + vault_only: true, +}); +``` + +**`--local-only`** - Show only files staying local + +```javascript +preview_delegation({ + project_root: '/path/to/project', + local_only: true, +}); +``` + +**`--limit N`** - Limit results per category (default: 100) + +```javascript +preview_delegation({ + project_root: '/path/to/project', + limit: 20, +}); +``` + +**`--no-reasoning`** - Hide reasoning details + +```javascript +preview_delegation({ + project_root: '/path/to/project', + show_reasoning: false, +}); +``` + +## Example Output + +``` +================================================================================ +DELEGATION PREVIEW +================================================================================ + +Configuration: /path/to/project/.withcontextconfig.jsonc +Total files: 23 + • Vault: 15 + • Local: 8 + +-------------------------------------------------------------------------------- +FILES TO DELEGATE TO VAULT (15 total, showing 15) +-------------------------------------------------------------------------------- + + → docs/guides/getting-started.md + Reason: Matches vault pattern 'docs/guides/**' + → docs/tutorials/installation.md + Reason: Matches vault pattern 'docs/tutorials/**' + → CHANGELOG.md + Reason: Matches vault pattern 'CHANGELOG.md' + → docs/architecture/decisions/001-use-typescript.md + Reason: Matches vault pattern 'docs/architecture/**' + + ... and 11 more files + +-------------------------------------------------------------------------------- +FILES TO KEEP LOCAL (8 total, showing 8) +-------------------------------------------------------------------------------- + + [OK] README.md + Reason: Matches local pattern 'README.md' + [OK] CONTRIBUTING.md + Reason: Matches local pattern 'CONTRIBUTING.md' + [OK] src/utils/README.md + Reason: Matches local pattern 'src/**/*.md' + [OK] tests/fixtures/sample.md + Reason: Matches local pattern 'tests/**/*.md' + + ... and 4 more files + +================================================================================ +``` + +## Important + +- **Execute autonomously** - Parse user flags and call the tool with correct parameters +- **No file modifications** - This is a preview-only command (safe to run anytime) +- **Trust the tool output** - Delegation logic is comprehensive +- **Show full preview** - Don't truncate unless using --limit flag +- **DO NOT manually scan** directories - rely entirely on the tool + +## Use Cases + +**Before first sync:** + +``` +/preview-notes-delegation +``` + +Verify patterns work as expected before moving files. + +**Testing new patterns:** +After editing `.withcontextconfig.jsonc`, preview to verify changes. + +**Debugging delegation:** + +``` +/preview-notes-delegation --vault-only +``` + +See only files that will be moved to vault. + +**Quick summary:** + +``` +/preview-notes-delegation --limit 10 --no-reasoning +``` + +Get a quick overview without detailed reasoning. + +## Related Commands + +- `/validate-notes-config` - Validate configuration before previewing +- `/setup-notes` - Create or regenerate configuration +- `/sync-notes` - Perform actual synchronization after previewing +- `/ingest-notes` - Move files to vault after previewing + +--- + +_The preview-notes-delegation command helps you test and verify delegation patterns before making any file changes._ diff --git a/.config/opencode/command/reorganize-notes.md b/.config/opencode/command/reorganize-notes.md new file mode 100644 index 0000000..5f7c9c6 --- /dev/null +++ b/.config/opencode/command/reorganize-notes.md @@ -0,0 +1,623 @@ +--- +description: Reorganize vault with AI-assisted suggestions +agent: general +subtask: true +--- + +# Reorganize Notes + +This command executes a comprehensive vault reorganization based on an intelligent organization plan. It supports moving and renaming files with automatic link updates, dry-run preview, rollback capability, and safety checks. + +## Quick Start (Ideal Workflow) + +This command generates and executes vault reorganization plans instantly using presets: + +```javascript +// Check for preset and execution flags +const args = '$ARGUMENTS'; +const shouldExecute = args.includes('--execute'); +const presetMatch = args.match(/--preset[=\s](\w+)/); +const preset = presetMatch ? presetMatch[1] : 'clean'; +const minConfMatch = args.match(/--min-confidence[=\s](0\.\d+)/); +const minConfidence = minConfMatch ? parseFloat(minConfMatch[1]) : 0.7; + +// Generate organization plan with preset +const planResult = await generate_organization_plan({ + preset_id: preset, + min_confidence: minConfidence, +}); + +// Parse plan from result +const planData = JSON.parse(planResult); +const plan = planData.plan; + +// Execute reorganization (dry-run by default for safety) +const result = await reorganize_notes({ + plan: plan, + dry_run: !shouldExecute, + update_links: true, + create_backup: true, + min_confidence: minConfidence, +}); + +return result; +``` + +**Usage:** + +- `/reorganize-notes` - Preview with 'clean' preset (dry-run) +- `/reorganize-notes --execute` - Execute with 'clean' preset +- `/reorganize-notes --preset minimal` - Preview with 'minimal' preset +- `/reorganize-notes --preset docs-as-code --execute` - Execute with custom preset +- `/reorganize-notes --min-confidence 0.9` - Use higher confidence threshold + +**Available Presets:** + +- `clean` (default) - Moves docs to vault, keeps README/LICENSE local +- `minimal` - Keep most local, only move ADRs and research +- `docs-as-code` - Mirrors repository structure in vault +- `research` - Heavy vault usage with cross-linking + +## What This Command Does + +The vault reorganizer performs safe, intelligent file operations: + +### Reorganization Operations + +- **Move**: Relocate files to more appropriate folders +- **Rename**: Standardize file naming conventions +- **Both**: Move and rename simultaneously +- **Link Updates**: Automatically fix all references to moved/renamed files +- **Validation**: Check for conflicts and potential issues before execution + +### Safety Features + +- **Dry-Run Mode**: Preview all operations without making changes (enabled by default) +- **Confidence Filtering**: Only execute high-confidence suggestions +- **Automatic Backups**: Create backups before modifying files (optional) +- **Rollback Support**: Undo operations if something goes wrong +- **Link Integrity**: Ensure no links break during reorganization +- **Impact Assessment**: Show affected files and potential issues + +### Workflow + +1. **Analyze** → Run `/analyze-vault` to understand current structure +2. **Plan** → Create reorganization plan (manual or AI-generated) +3. **Preview** → Run with `dry_run: true` to see what will happen +4. **Execute** → Run with `dry_run: false` to apply changes +5. **Verify** → Check results and ensure links are intact + +## Example Output + +### Dry-Run Preview + +``` +=== Vault Reorganization (DRY RUN) === + +Project: my-project +Plan: 12 operations (8 moves, 4 renames) +Confidence Threshold: 0.7 + +=== Operations to Execute === + +1. MOVE docs/random-notes.md → docs/guides/getting-started.md + Reason: Content is a task-oriented guide + Confidence: 0.92 + Impact: 3 files will need link updates + +2. RENAME docs/guide.md → docs/guides/api-guide.md + Reason: Standardize naming convention + Confidence: 0.85 + Impact: 5 files will need link updates + +3. MOVE docs/architecture-notes.md → docs/architecture/decisions/001-database-choice.md + Reason: Fits ADR format + Confidence: 0.88 + Impact: 2 files will need link updates + +... (9 more operations) + +=== Impact Summary === + +Total Operations: 12 +Files to Move: 8 +Files to Rename: 4 +Links to Update: 47 across 23 files +Estimated Duration: 5 seconds +Risky Operations: 0 + +=== Warnings === + +⚠️ WARNING: File "docs/old-guide.md" is referenced by external projects + Suggestion: Update external references manually after reorganization + +✓ All operations passed validation checks +✓ No conflicts detected +✓ Link integrity will be maintained + +=== Next Steps === + +To execute this plan, run: + reorganize_notes({ ..., dry_run: false }) + +IMPORTANT: Dry-run mode is ENABLED by default for safety! +``` + +### Execution Results + +``` +=== Vault Reorganization Complete === + +Project: my-project +Mode: EXECUTION (changes applied) + +=== Operations Executed === + +✓ Moved docs/random-notes.md → docs/guides/getting-started.md + Updated 3 links in other files +✓ Renamed docs/guide.md → docs/guides/api-guide.md + Updated 5 links in other files +✓ Moved docs/architecture-notes.md → docs/architecture/decisions/001-database-choice.md + Updated 2 links in other files + +... (9 more successful operations) + +=== Summary === + +Total Operations: 12 +Successful: 12 (100%) +Failed: 0 +Links Updated: 47 across 23 files +Duration: 3.2 seconds + +✓ All operations completed successfully +✓ All links updated and verified +✓ No broken links detected +``` + +## Your Task + +Execute the reorganization workflow immediately with instant preset-based planning: + +The command generates a plan and executes it in one call, with dry-run by default for safety. + +See "Quick Start" section above for the complete implementation. + +**Important Notes:** + +- Always preview first (dry-run mode is the default) +- Use `--execute` flag to apply changes +- Backups are created automatically when executing +- Links are updated automatically to prevent breakage + +## Alternative: Manual Plan (Advanced) + +If you need custom organization beyond presets, you can create a manual plan. See full documentation for plan structure format. + +**Still follow the same workflow: Generate → Preview → Confirm → Execute** + +--- + +## Advanced: Create Manual Plan + +Based on the analysis, create a reorganization plan manually. The plan structure: + +```javascript +{ + suggestions: [ + { + type: "move", // or "rename" or "both" + currentPath: "docs/random-file.md", + suggestedPath: "docs/guides/proper-location.md", // for move + suggestedName: "standardized-name.md", // for rename + reason: "Content is a task-oriented guide", + confidence: 0.92, // 0-1 scale + impact: { + affectedFiles: 3, + linksToUpdate: 5, + potentialBrokenLinks: [], + complexity: "low" // or "medium", "high" + }, + targetCategory: "guides" + }, + // ... more suggestions + ], + estimatedImpact: { + filesToMove: 8, + filesToRename: 4, + linksToUpdate: 47, + filesRequiringLinkUpdates: 23, + estimatedDuration: 5, // seconds + hasRiskyOperations: false + }, + warnings: [ + { + severity: "warning", + filePath: "docs/old-guide.md", + message: "File is referenced by external projects", + suggestion: "Update external references manually" + } + ], + summary: "Reorganize 12 files to improve vault structure", + requiresManualReview: false +} +``` + +### Step 3: Preview & Execute + +**ALWAYS preview first!** Then get user confirmation before executing: + +```javascript +// Preview +const preview = await reorganize_notes({ + project_folder: 'my-project', + plan: manualPlan, + dry_run: true, // CRITICAL: Preview first! + update_links: true, + create_backup: true, + min_confidence: 0.7, +}); + +// Show preview to user, get confirmation + +// Execute (only after user confirms) +const result = await reorganize_notes({ + project_folder: 'my-project', + plan: manualPlan, + dry_run: false, + update_links: true, + create_backup: true, + min_confidence: 0.7, +}); +``` + +--- + +## Safety Requirements + +**⚠️ CRITICAL SAFETY RULES ⚠️** + +1. **NEVER** execute with `dry_run: false` without explicit user confirmation! + +2. **ALWAYS** run dry-run preview first +3. **ALWAYS** show user the preview results including: + - Number of operations (moves, renames) + - Files that will be affected + - Links that will be updated + - Any warnings or risks +4. **ALWAYS** ask user for explicit confirmation: + +**User Confirmation Template:** + +> "I've previewed the reorganization plan using the **[preset_name]** preset. Here's what will happen: +> +> **Operations:** +> +> - Move X files to appropriate folders +> - Rename Y files for consistency +> - Update Z links across N files +> +> **Key Changes:** +> [Show 3-5 most significant operations] +> +> **Safety:** +> +> - ✓ Backups will be created +> - ✓ Links will be automatically updated +> - ✓ Rollback available if needed +> +> **This operation will modify your vault!** +> +> Do you want to proceed with the reorganization? (yes/no)" + +Only if user confirms "yes", then execute: + +```javascript +reorganize_notes({ + project_folder: 'my-project', + plan: { + /* same plan */ + }, + dry_run: false, // Execute for real + update_links: true, + create_backup: true, + min_confidence: 0.7, +}); +``` + +### Step 5: Verify Results + +After execution, verify the results: + +- Show summary of operations +- Confirm all links updated successfully +- Report any failures or warnings +- Suggest running `/analyze-vault` again to verify improvements + +## Plan Structure Details + +### Suggestion Object + +Each suggestion must include: + +- **type**: `"move"`, `"rename"`, or `"both"` +- **currentPath**: Current file path (relative to vault root) +- **suggestedPath**: New path for move operations (optional) +- **suggestedName**: New name for rename operations (optional) +- **reason**: Why this change is suggested (human-readable) +- **confidence**: Score from 0.0 to 1.0 (higher = more confident) +- **impact**: Assessment of operation impact (optional but recommended) +- **targetCategory**: Target category after reorganization (optional) + +### Impact Assessment + +- **affectedFiles**: How many files reference this file +- **linksToUpdate**: How many links will need updating +- **potentialBrokenLinks**: Paths that might break +- **complexity**: `"low"`, `"medium"`, or `"high"` + +### Confidence Scoring + +- **0.9-1.0**: Very high confidence, safe to auto-execute +- **0.7-0.9**: High confidence, review recommended +- **0.5-0.7**: Medium confidence, manual review required +- **Below 0.5**: Low confidence, skip unless manually approved + +Use `min_confidence` parameter to filter operations. + +## Safety Parameters + +### dry_run (default: true) + +**ALWAYS TRUE BY DEFAULT FOR SAFETY!** + +```javascript +dry_run: true; // Preview only, no changes (DEFAULT) +dry_run: false; // Execute for real (requires confirmation!) +``` + +### update_links (default: true) + +```javascript +update_links: true; // Fix all links automatically (recommended) +update_links: false; // Don't update links (may break references) +``` + +### create_backup (default: true) + +```javascript +create_backup: true; // Create backups before changes (recommended) +create_backup: false; // Skip backups (faster but riskier) +``` + +### min_confidence (default: 0.7) + +```javascript +min_confidence: 0.7; // Only execute high-confidence operations +min_confidence: 0.5; // Include medium-confidence operations +min_confidence: 0.9; // Only very high-confidence operations +``` + +## Best Practices + +### ✅ DO: + +1. **Use presets** - Start with `generate_organization_plan` and a preset +2. **Preview first** - Always run with `dry_run: true` before executing +3. **Get confirmation** - Show user the preview and wait for approval +4. **Enable backups** - Keep `create_backup: true` (default) +5. **Update links** - Keep `update_links: true` (default) to maintain integrity +6. **Start conservative** - Use `min_confidence: 0.8` or higher for first run +7. **Test incrementally** - Start with a small subset if unsure + +### ❌ DON'T: + +1. **Don't skip dry-run** - Never execute without previewing first +2. **Don't ignore warnings** - Review and address all warnings in the plan +3. **Don't disable backups** - Always keep backups enabled unless very confident +4. **Don't rush execution** - Give user time to review preview +5. **Don't skip link updates** - Links will break if you don't update them +6. **Don't use low confidence** - Avoid `min_confidence < 0.7` unless you've reviewed manually + +### Ideal Workflow Summary: + +``` +generate_organization_plan (preset) + → reorganize_notes (dry_run=true) + → SHOW TO USER + GET CONFIRMATION + → reorganize_notes (dry_run=false) +``` + +## Example Usage Scenarios + +### Scenario 1: Quick Reorganization with Preset (RECOMMENDED) + +```javascript +// Single command generates smart plan +const plan = await generate_organization_plan({ + project_folder: 'my-project', + preset_id: 'clean', + min_confidence: 0.8, +}); + +// Preview +const preview = await reorganize_notes({ + project_folder: 'my-project', + plan: plan, + dry_run: true, +}); + +// [Show to user, get confirmation] + +// Execute +const result = await reorganize_notes({ + project_folder: 'my-project', + plan: plan, + dry_run: false, // Only after user confirms! +}); +``` + +### Scenario 2: Conservative Reorganization + +```javascript +// Only execute very high-confidence operations +await reorganize_notes({ + project_folder: 'my-project', + plan: plan, + dry_run: false, + min_confidence: 0.9, // Very conservative + create_backup: true, // Extra safety + update_links: true, +}); +``` + +### Scenario 3: Targeted Reorganization + +```javascript +// Move specific files to better locations +const plan = { + suggestions: [ + { + type: 'move', + currentPath: 'docs/random-notes.md', + suggestedPath: 'docs/guides/getting-started.md', + reason: 'Content is a getting started guide', + confidence: 0.95, + impact: { complexity: 'low' }, + }, + { + type: 'rename', + currentPath: 'docs/guide.md', + suggestedName: 'api-guide.md', + reason: 'Standardize naming', + confidence: 0.9, + impact: { complexity: 'low' }, + }, + ], + summary: 'Move and rename 2 files', +}; +``` + +## Guidelines for Agents + +When running this command: + +1. **ALWAYS follow the workflow**: + - Analyze → Plan → Preview → Confirm → Execute → Verify +2. **NEVER skip dry-run preview**: + - Always show user what will happen before executing +3. **NEVER execute without confirmation**: + - Explicitly ask user to confirm before `dry_run: false` +4. **Present clear summaries**: + - Show what operations will be performed + - Explain impact and risks + - Highlight warnings +5. **Do NOT**: + - Move or rename files manually + - Update links yourself + - Skip validation steps + - Execute destructive operations without permission +6. **Your role is to**: + - Orchestrate the workflow safely + - Present information clearly + - Protect user from mistakes + - Ensure vault integrity + +## Safety Reminders + +### ⚠️ CRITICAL SAFETY RULES ⚠️ + +1. **Dry-run is DEFAULT**: `dry_run: true` unless explicitly set to `false` +2. **Always preview first**: Show user dry-run results before executing +3. **Require confirmation**: Never execute with `dry_run: false` without asking +4. **Backups recommended**: Keep `create_backup: true` unless user explicitly disables +5. **Link integrity**: Keep `update_links: true` to prevent broken references +6. **Test with low confidence**: Start with `min_confidence: 0.9` for first run + +### What Can Go Wrong? + +- **Broken links**: If `update_links: false`, references will break +- **Lost files**: If backups disabled and operation fails mid-way +- **Name conflicts**: Moving to path that already exists +- **External references**: Links from outside the vault won't be updated + +## Common Reorganization Patterns + +### Pattern 1: Category-Based Organization + +Move files to folders by content type: + +``` +docs/ + guides/ # Task-oriented how-to docs + tutorials/ # Learning-oriented step-by-step + reference/ # Information-oriented API docs + architecture/ # Understanding-oriented design docs + decisions/ # ADRs (Architecture Decision Records) +``` + +### Pattern 2: Feature-Based Organization + +Group by project feature or module: + +``` +docs/ + auth/ # Authentication docs + database/ # Database docs + api/ # API docs + deployment/ # Deployment docs +``` + +### Pattern 3: Audience-Based Organization + +Organize by reader type: + +``` +docs/ + users/ # End-user documentation + developers/ # Developer guides + operators/ # Operations/deployment docs + contributors/ # Contribution guides +``` + +## Error Handling + +The tool handles errors gracefully: + +- **Conflict detection**: Prevents overwriting existing files +- **Rollback support**: Reverts changes if operation fails mid-way +- **Partial success**: Reports which operations succeeded/failed +- **Link validation**: Verifies no links broke after reorganization + +If errors occur: + +1. Check the error messages for details +2. Review the failed operations list +3. Fix conflicts manually if needed +4. Re-run with adjusted plan + +## Related Commands + +- `/analyze-vault` - Analyze vault structure before reorganizing +- `/setup-notes` - Configure documentation architecture +- `/validate-config` - Validate configuration +- `/sync-notes` - Sync files after reorganization + +## Performance Considerations + +Large reorganizations may take time: + +- **Small vaults** (< 100 files): Nearly instant +- **Medium vaults** (100-500 files): Few seconds +- **Large vaults** (500+ files): 10-30 seconds +- **Very large vaults** (1000+ files): 30-60 seconds + +Link updates are the slowest part. Consider: + +- Batch similar operations together +- Use `max_files` in analysis to limit scope +- Run during off-hours for very large vaults + +--- + +_The reorganize-notes tool provides safe, intelligent vault reorganization with automatic link updates, dry-run preview, and rollback support to maintain vault integrity._ diff --git a/.config/opencode/command/setup-notes.md b/.config/opencode/command/setup-notes.md new file mode 100644 index 0000000..7a2774c --- /dev/null +++ b/.config/opencode/command/setup-notes.md @@ -0,0 +1,300 @@ +--- +description: Intelligently analyze and setup documentation architecture for the project +agent: general +subtask: true +--- + +# Intelligent Documentation Setup + +**NEW in v2.1**: This command now uses intelligent analysis to understand your project and recommend optimal documentation architecture based on best practices! + +## What This Command Does + +This enhanced command performs a **4-phase intelligent analysis**: + +### Phase 1: Repository Analysis + +- Scans your project to identify all documentation files +- Detects project type (MCP server, library, monorepo, CLI, web app, etc.) +- Catalogs existing documentation patterns and folders +- Identifies framework (React, Next.js, Express, etc.) + +### Phase 2: README Validation + +- Analyzes README.md completeness and health (0-100 score) +- Validates all markdown links to ensure they won't break +- Checks for self-containment (README must work without vault access) +- Identifies missing sections (badges, quick start, installation, usage) +- **Ensures README links won't point to files that will move to vault** + +### Phase 3: Intelligent Recommendations + +- Recommends LOCAL vs VAULT delegation based on: + - **Diátaxis framework** (tutorials, guides, reference, explanation) + - Project type and structure + - Best practices for documentation organization +- **LOCAL (Repository)**: Essential files that must work without vault + - README.md, CONTRIBUTING.md, LICENSE, AGENTS.md + - Inline code documentation (src/\*\*/\*.md) + - Quick references and getting started guides +- **VAULT (Obsidian)**: Deep research and detailed exploration + - Detailed guides and tutorials + - Architecture Decision Records (ADRs) + - Research notes and investigations + - Meeting notes and explorations + +### Phase 4: Configuration & Setup + +- Creates intelligent `.withcontextconfig.jsonc` based on analysis +- Suggests vault folder structure (docs/guides, docs/architecture, etc.) +- Provides actionable next steps and README fixes +- Optionally creates recommended folder structure in vault + +## Documentation Delegation Philosophy + +### LOCAL = Essential & Quick Reference + +**Purpose**: Files critical for onboarding and getting started, must work without vault + +**Examples**: + +- README.md - Project overview, badges, installation, quick start +- CONTRIBUTING.md - How to contribute +- LICENSE - Legal requirements +- src/\*\*/\*.md - Inline code documentation +- Quick reference guides (1-2 pages) + +**Key Rule**: README must be **self-contained** - no broken links to vault files! + +### VAULT = Deep Research & Exploration + +**Purpose**: Detailed exploration, architecture decisions, research notes + +**Examples**: + +- docs/guides/\*\* - Detailed how-to guides (task-oriented) +- docs/tutorials/\*\* - Step-by-step learning paths (learning-oriented) +- docs/architecture/\*\* - Architecture docs and ADRs (understanding-oriented) +- docs/reference/\*\* - API documentation (information-oriented) +- docs/research/\*\* - Research notes and investigations +- CHANGELOG.md - Detailed change history + +## Example Output + +``` +=== Intelligent Documentation Setup === + +✓ No existing configuration found + +📊 Analyzing repository documentation... + +=== Documentation Analysis === + +Project: my-awesome-project +Type: library +Total Docs: 15 files + +✓ README.md (234 lines) + Health Score: 75/100 + Links: 8 total + ⚠ 2 warning(s) + +=== README Health Report === + +Health Score: 75/100 +✓ Has badges +⚠ Missing quick start section +✓ Has installation instructions +✓ Has usage examples +⚠ Has dependencies on vault content + +Warnings: + No quick start or getting started section found + Found 1 broken or problematic link(s) + Line 45: Link target will move to vault: docs/architecture/decisions.md + +=== Documentation Architecture Recommendations === + +Project Type: library +Total Documentation Files: 15 + +Recommendations based on: +- Diátaxis framework (tutorials, guides, reference, explanation) +- Local = Essential (README, contributing, inline docs, quick reference) +- Vault = Deep Research (detailed guides, architecture, ADRs, explorations) +- README must be self-contained and work without vault access + +⚠ README currently has dependencies on vault content - needs fixing + +Keep LOCAL: 18 pattern(s) +Move to VAULT: 12 pattern(s) + +Suggested vault folders: + - docs/guides + - docs/tutorials + - docs/architecture/decisions + +README changes needed: + Fix 1 broken or problematic link(s): + - Line 45: Remove or update link to "docs/architecture/decisions.md" (will move to vault) + Add a "Quick Start" or "Getting Started" section + +=== Next Steps === + +1. Review .withcontextconfig.jsonc and customize if needed +2. Fix README issues highlighted above +3. Apply recommended README changes: + Fix broken link at line 45 + Add a "Quick Start" or "Getting Started" section +4. Use /sync-notes or /ingest-notes to migrate files to vault +5. Run /validate-config to ensure configuration is valid +``` + +## Your Task + +Execute the setup_notes tool immediately with options based on user arguments: + +```javascript +// Parse optional arguments +const args = '$ARGUMENTS'; +const noStructure = args.includes('--no-structure'); +const force = args.includes('--force'); + +// Get project folder name from current directory +const projectFolder = process.cwd().split('/').pop(); + +const result = await setup_notes({ + project_folder: projectFolder, + create_structure: !noStructure, + force: force, +}); + +return result; +``` + +**Usage Examples:** + +- `/setup-notes` - Full setup with vault folder creation +- `/setup-notes --no-structure` - Skip creating vault folders +- `/setup-notes --force` - Overwrite existing configuration + +## Configuration Format (v2.1.0) + +The generated `.withcontextconfig.jsonc` will have: + +```jsonc +{ + "$schema": "https://raw.githubusercontent.com/boxpositron/with-context-mcp/main/src/config/config-schema.json", + + // Configuration generated based on repository analysis + // Project: [detected-project-name] + // Type: [mcp-server|library|application|monorepo|cli] + + "version": "2.1", + "defaultBehavior": "local", + + // Intelligent vault patterns based on analysis + "vault": [ + // Patterns recommended based on your project structure + ], + + // Intelligent local patterns based on analysis + "local": [ + // Essential repository files and inline docs + ], + + "conflictResolution": "local-wins", +} +``` + +## Best Practices Applied + +The intelligent setup follows these frameworks and principles: + +### Diátaxis Framework + +- **Tutorials** (learning-oriented) → vault: docs/tutorials/ +- **How-to guides** (task-oriented) → vault: docs/guides/ +- **Reference** (information-oriented) → vault: docs/reference/, local: quick-ref.md +- **Explanation** (understanding-oriented) → vault: docs/architecture/ + +### Architecture Decision Records (ADRs) + +- Store in `docs/architecture/decisions/` or `architecture/decisions/` +- Keep template: context, decision, consequences +- Use Michael Nygard's format + +### README Best Practices + +- Must be self-contained (works without vault) +- No broken links to vault-delegated files +- Has badges, installation, usage, quick start +- Links only to files that stay in repository + +### Docs-as-Code + +- Markdown format +- Version controlled +- Clear organization +- Consistent naming + +## Guidelines for Agents + +When running this command: + +1. **ONLY use the setup_notes tool** - Do NOT perform manual analysis or file operations +2. **Trust the tool's output** - The intelligent engine has scanned the repo and knows what it found +3. **Present the results clearly** - Show the full tool output to the user +4. **Do NOT**: + - Manually read files to analyze the project + - Create configuration files directly + - Parse README or validate links manually + - Scan directories yourself +5. **The tool handles everything**: + - Repository scanning + - README validation + - Link integrity checks + - Configuration generation + - Folder structure creation +6. **Your role is to**: + - Call the tool with appropriate parameters + - Present the results to the user + - Suggest next steps based on tool output + +## Migration from Legacy Format + +If `.withcontextignore` exists: + +- Automatically migrates to new `.withcontextconfig.jsonc` format +- Creates backup as `.withcontextignore.backup` +- Preserves pattern intent (negations become `local` patterns) + +## Related Commands + +- `/validate-config` - Validate configuration against schema +- `/preview-delegation` - Preview which files will be delegated +- `/sync-notes` - Bidirectional sync between local and vault +- `/ingest-notes` - Copy local documentation to vault +- `/teleport-notes` - Download documentation from vault to local + +## Key Differences from Old Version + +**Old behavior** (v2.0): + +- Used generic template configuration +- No project analysis +- No README validation +- Manual pattern selection + +**New behavior** (v2.1+): + +- Intelligent analysis of actual project structure +- README health scoring and link validation +- Project-type-specific recommendations +- Ensures README self-containment +- Follows documentation best practices (Diátaxis, ADRs) +- Actionable, specific feedback + +--- + +_The intelligent setup-notes uses the documentation analyzer to provide context-aware recommendations based on your actual repository structure and best practices._ diff --git a/.config/opencode/command/sync-notes.md b/.config/opencode/command/sync-notes.md new file mode 100644 index 0000000..46f4798 --- /dev/null +++ b/.config/opencode/command/sync-notes.md @@ -0,0 +1,111 @@ +--- +description: Bidirectionally sync documentation files between local project and Obsidian vault +agent: general +subtask: true +--- + +# Sync Notes + +Bidirectionally synchronizes documentation files between local project and Obsidian vault. Files are moved based on delegation rules (deleted from source after successful copy). + +## What This Command Does + +This command performs bidirectional synchronization: + +- **Local → Vault**: Files matching "vault" patterns are moved from local to vault +- **Vault → Local**: Files matching "local" patterns are moved from vault to local +- **Move operation**: Files are DELETED from source after successful copy +- **Structure preserved**: Directory structure is maintained in both directions +- **Dry-run preview**: See what will happen before executing + +**Prerequisites:** + +- `.withcontextconfig.jsonc` must exist (run `/setup-notes` first if not) +- Configuration defines which files are delegated to vault vs local + +## Your Task + +Execute the sync_notes tool immediately with dry-run by default for safety: + +```javascript +// Check for --execute flag in arguments +const args = '$ARGUMENTS'; +const shouldExecute = args.includes('--execute'); + +const result = await sync_notes({ + dry_run: !shouldExecute, +}); + +return result; +``` + +**Usage:** + +- `/sync-notes` - Preview changes (safe, dry-run mode) +- `/sync-notes --execute` - Execute sync for real (moves and deletes files) + +**Important:** This is a destructive operation - files are DELETED from source after successful copy. Always preview first! + +## Parameters + +### dry_run (optional, default: false) + +Preview mode - shows what will happen without making changes: + +```javascript +dry_run: true; // Preview only +dry_run: false; // Execute for real +``` + +## Sync Behavior + +**Files with delegation decision "vault":** + +- Moved from local → vault +- Deleted from local after successful copy + +**Files with delegation decision "local":** + +- Moved from vault → local +- Deleted from vault after successful copy + +**Important notes:** + +- Only files matching `.withcontextconfig.jsonc` patterns are synced +- Directory structure is preserved in both locations +- Files are DELETED from source automatically (this is a MOVE operation, not COPY) +- The tool checks for configuration existence automatically + +## Example Output + +``` +=== Sync Results === + +Files moved from local to vault: 12 + - docs/guides/getting-started.md + - docs/architecture/decisions/001-use-typescript.md + - CHANGELOG.md + ... (9 more files) + +Files moved from vault to local: 3 + - README.md + - CONTRIBUTING.md + - src/utils/README.md + +Total files deleted from source: 15 +Errors: 0 + +⚠️ Source files were deleted after successful copy (expected behavior) +``` + +## Related Commands + +- `/setup-notes` - Create configuration file +- `/preview-notes-delegation` - Preview sync decisions +- `/ingest-notes` - One-way copy to vault (keeps local files) +- `/teleport-notes` - One-way download from vault (keeps vault files) +- `/validate-notes-config` - Validate configuration + +--- + +_The sync-notes tool performs bidirectional synchronization with automatic source deletion._ diff --git a/.config/opencode/command/teleport-notes.md b/.config/opencode/command/teleport-notes.md new file mode 100644 index 0000000..6f11f28 --- /dev/null +++ b/.config/opencode/command/teleport-notes.md @@ -0,0 +1,115 @@ +--- +description: Teleport documentation files from Obsidian vault to local project +agent: general +subtask: true +--- + +# Teleport Notes + +Downloads documentation files from the Obsidian vault back to the local project based on `.withcontextconfig.jsonc` delegation rules. + +## What This Command Does + +This command downloads files from vault to local project: + +- Scans vault for files matching vault patterns in `.withcontextconfig.jsonc` +- Copies matched files to local project preserving directory structure +- Optionally deletes vault files after successful copy +- Provides dry-run preview mode + +**Prerequisites:** + +- `.withcontextconfig.jsonc` must exist (run `/setup-notes` first if not) +- Configuration defines which files have delegation decision "vault" + +## Your Task + +Execute the teleport_notes tool immediately with dry-run by default for safety: + +```javascript +// Check for flags in arguments +const args = '$ARGUMENTS'; +const shouldExecute = args.includes('--execute'); +const shouldDelete = args.includes('--delete'); +const forceDelete = args.includes('--force-delete'); + +const result = await teleport_notes({ + dry_run: !shouldExecute, + delete_from_vault: shouldDelete, + force_delete: forceDelete, +}); + +return result; +``` + +**Usage:** + +- `/teleport-notes` - Preview what will be downloaded (safe, dry-run mode) +- `/teleport-notes --execute` - Download files from vault (keeps vault files) +- `/teleport-notes --execute --delete` - Download and delete vault files +- `/teleport-notes --execute --delete --force-delete` - Force delete even on errors + +**Important:** Use `--delete` flag only if you want to remove vault files after downloading! + +## Parameters + +### dry_run (optional, default: false) + +Preview mode - shows what will happen without making changes: + +```javascript +dry_run: true; // Preview only +dry_run: false; // Execute for real +``` + +### delete_from_vault (optional, default: false) + +Whether to delete vault files after successful copy to local: + +```javascript +delete_from_vault: false; // Keep vault files (default) +delete_from_vault: true; // Delete vault files after copy +``` + +### force_delete (optional, default: false) + +Force deletion of vault files even if some files had errors: + +```javascript +force_delete: false; // Don't delete if errors occurred (default) +force_delete: true; // Delete even if some files failed +``` + +## Important Notes + +- **Vault files are NOT deleted by default** - set `delete_from_vault: true` explicitly if desired +- **Always preview first** - Use `dry_run: true` before executing +- **The tool automatically checks** for `.withcontextconfig.jsonc` existence +- **Directory structure is preserved** in the local project + +## Example Output + +``` +=== Teleport Results === + +Files teleported from vault: 15 + - docs/guides/getting-started.md → docs/guides/getting-started.md + - docs/architecture/decisions/001-use-typescript.md → docs/architecture/decisions/001-use-typescript.md + - CHANGELOG.md → CHANGELOG.md + ... (12 more files) + +Vault files deleted: 0 (kept in vault) +Errors: 0 +``` + +## Related Commands + +- `/setup-notes` - Create configuration file +- `/preview-notes-delegation` - Preview which files will be teleported +- `/sync-notes` - Bidirectional sync (moves files both ways) +- `/ingest-notes` - One-way copy to vault +- `/validate-notes-config` - Validate configuration + +--- + +_The teleport-notes tool downloads vault documentation to local project based on delegation rules._ diff --git a/.config/opencode/command/validate-notes-config.md b/.config/opencode/command/validate-notes-config.md new file mode 100644 index 0000000..b8a0c1e --- /dev/null +++ b/.config/opencode/command/validate-notes-config.md @@ -0,0 +1,113 @@ +--- +description: Validate .withcontextconfig.jsonc for errors and warnings +agent: general +subtask: true +--- + +# Validate Notes Configuration + +Validates the `.withcontextconfig.jsonc` file for syntax errors, structural issues, and provides detailed feedback on configuration problems. + +## What This Command Does + +This command performs comprehensive validation of your documentation delegation configuration: + +**Validation Checks:** + +1. **File Existence** - Verifies `.withcontextconfig.jsonc` exists +2. **Syntax Validation** - Checks for valid JSON/JSONC syntax +3. **Schema Validation** - Validates against the configuration schema +4. **Semantic Validation** - Checks for logical issues: + - Pattern conflicts between `vault` and `local` arrays + - Invalid glob patterns + - Missing required fields + - Deprecated or unknown configuration options +5. **Best Practices** - Provides recommendations and warnings + +**Prerequisites:** + +- `.withcontextconfig.jsonc` must exist (run `/setup-notes` first if not) + +**Tool Priority:** +First try to use the WithContext plugin's `validate_config` tool. If not available, fallback to the with-context MCP server's `validate_config` tool. + +## Your Task + +Execute the validate_config tool immediately: + +```javascript +const result = await validate_config({ + project_root: process.cwd(), +}); + +return result; +``` + +The tool output includes: + +- Configuration path and validation status +- All errors (critical issues that must be fixed) +- All warnings (non-critical issues to address) +- Info messages (helpful suggestions) +- Suggested next steps + +## Example Output + +``` +=== Configuration Validation === + +Configuration: /path/to/project/.withcontextconfig.jsonc +Status: ✓ Valid + +Warnings (2): + • Pattern 'docs/**/*.md' in vault array may conflict with 'docs/internal/**' in local array + Resolution: 'local-wins' strategy will prioritize local patterns + • Consider adding more specific patterns for better control + +Info (1): + • Configuration follows v2.1 format + • Using recommended 'local-wins' conflict resolution + +Next Steps: + 1. Review pattern conflicts highlighted above + 2. Run /preview-notes-delegation to see how files will be categorized + 3. Use /sync-notes when ready to synchronize files +``` + +## Important + +- **Execute autonomously** - Do NOT ask questions, just call the tool and report results +- **Trust the tool output** - The validator has comprehensive checks built-in +- **Show full validation report** - Include all errors, warnings, and info messages +- **Provide context** - Explain what each issue means and how to fix it +- **DO NOT manually parse** the config file - rely entirely on the tool + +## Common Validation Issues + +**Syntax Errors:** + +- Missing commas, quotes, or brackets +- Invalid JSONC comments +- Trailing commas in wrong places + +**Schema Errors:** + +- Missing `version` field +- Invalid `defaultBehavior` value (must be "local" or "vault") +- Invalid `conflictResolution` value + +**Semantic Errors:** + +- Overlapping patterns in `vault` and `local` arrays +- Invalid glob patterns +- Patterns that will never match any files + +## Related Commands + +- `/setup-notes` - Create or regenerate configuration +- `/preview-notes-delegation` - Preview delegation decisions +- `/sync-notes` - Synchronize files based on validated configuration + +--- + +_The validate-notes-config command ensures your configuration is correct before performing sync operations._ diff --git a/.withcontextconfig.jsonc b/.withcontextconfig.jsonc index b373bd6..986e45b 100644 --- a/.withcontextconfig.jsonc +++ b/.withcontextconfig.jsonc @@ -3,168 +3,79 @@ // Configuration generated based on repository analysis // Project: dotfiles - // Type: dotfiles (macOS development environment configuration) - // Total Documentation Files: 17 (excluding node_modules) - // - // This configuration follows the Diátaxis framework and dotfiles best practices: - // - LOCAL = Essential files that must work for anyone cloning the repo - // - VAULT = Deep research, detailed guides, and cross-project knowledge + // Type: unknown "version": "2.1", - "defaultBehavior": "vault", - // ----------------------------------------------------------------------------- - // VAULT PATTERNS - Documentation delegated to Obsidian for deep research - // ----------------------------------------------------------------------------- - // These patterns identify documentation that should be stored in the vault - // for cross-project knowledge sharing, detailed guides, and research notes. + // Default behavior for files not matching any patterns + "defaultBehavior": "local", + // Patterns for files to delegate to Obsidian vault + // Based on Diátaxis framework: guides, tutorials, reference, architecture "vault": [ - // Detailed guides and tutorials (task-oriented, learning-oriented) - "docs/guides/**/*.md", - "docs/tutorials/**/*.md", - "docs/how-to/**/*.md", - - // Architecture decisions and explanations (understanding-oriented) - "docs/architecture/**/*.md", - "docs/decisions/**/*.md", - "docs/adr/**/*.md", - - // Research and investigation notes - "docs/research/**/*.md", - "docs/investigations/**/*.md", - "docs/explorations/**/*.md", - - // Detailed reference documentation (information-oriented) - "docs/reference/**/*.md", - "docs/api/**/*.md", - - // Changelog and historical documentation - "CHANGELOG.md", - "**/CHANGELOG.md", - "HISTORY.md", - "**/HISTORY.md", - - // Meeting notes and collaboration - "docs/meetings/**/*.md", - "docs/notes/**/*.md" + "CHANGELOG.md" ], - // ----------------------------------------------------------------------------- - // LOCAL PATTERNS - Essential repository documentation - // ----------------------------------------------------------------------------- - // These patterns keep critical files in the repository that must be - // accessible without vault access (onboarding, setup, quick reference). - + // Patterns for files to keep in local repository + // Essential files for repository operation and quick reference "local": [ - // Root documentation - Essential project documentation - "/README.md", - "/AGENTS.md", - "/CONTRIBUTING.md", - "/LICENSE", - "/LICENSE.md", - "/CODE_OF_CONDUCT.md", - - // Setup and installation - Must be accessible locally for bootstrapping - "/setup-mac.sh", - "/INSTALL.md", - "/INSTALLATION.md", - "/SETUP.md", - - // Component-specific READMEs - Keep with their configurations - ".config/nvim/README.md", - ".config/ghostty/README.md", - ".config/wezterm/README.md", - ".config/ohmyposh/README.md", - ".config/zellij/README.md", - ".config/direnv/README.md", - ".config/aerospace/README.md", - - // Generic pattern for any component READMEs - ".config/*/README.md", - ".config/**/README.md", - - // OpenCode configuration - All AI agent and command documentation stays local - // This includes all markdown files, even those in node_modules subdirectories - ".config/opencode/", - ".config/opencode/**", - ".config/opencode/**/*.md", - - // Work in progress - Keep drafts local until ready - "notes/", - "notes/**", - "scratch.md", - "todo.md", - "TODO.md", - "**/drafts/", - "**/drafts/**", - "**/*.draft.md", - "**/*.wip.md", - "**/*-draft.md", - "**/*-wip.md", - "**/scratch/**", - - // Sensitive content - Never delegate to vault - ".env", - ".env.*", - ".envrc", - "**/*.secret.md", - "**/.secrets/", - "**/.secrets/**", - "**/confidential/**", - "**/*credentials*.md", - "**/*secrets*.md", - "**/*apikey*.md", - - // Version control and system files - Infrastructure files - ".git/", - ".git/**", - ".gitignore", - ".gitmodules", - ".gitattributes", - ".DS_Store", - "**/.DS_Store", - "*.log", - "**/*.log", - ".rgignore", - ".opencommit", - - // Build artifacts and dependencies - Never delegate - "node_modules/", - "node_modules/**", - "vendor/", - "vendor/**", - "dist/", - "dist/**", - "build/", - "build/**", - "out/", - "out/**", - "*.lock", - "**/*.lock", - "lazy-lock.json", - "**/lazy-lock.json", - "package-lock.json", - "**/package-lock.json", - - // Local binaries and scripts - System-specific executables - ".local/bin/**", - "local_servers/**", - - // Personal notes - Keep local unless explicitly needed in vault - "NOTES.md", - "PERSONAL.md", - "SCRATCHPAD.md", - - // Quick reference guides - 1-2 page references stay local - "QUICKSTART.md", - "QUICK_REFERENCE.md", - "CHEATSHEET.md", - "**/QUICKSTART.md", - "**/QUICK_REFERENCE.md", - "**/CHEATSHEET.md" + // Root documentation (essential project files) + "README.md", + "/README.md", + "/CONTRIBUTING.md", + "/LICENSE", + "/AGENTS.md", + + // OpenCode configuration and documentation (must stay local per AGENTS.md) + ".config/opencode/**", + "opencode.json", + + // Component READMEs (stay with their configurations) + ".config/*/README.md", + + // Setup scripts and installation docs + "setup-mac.sh", + "INSTALL.md", + + // Work-in-progress and personal notes + "notes/**", + "scratch.md", + "NOTES.md", + "PERSONAL.md", + "todo.md", + + // Sensitive information + "**/*.secret.md", + "**/confidential/**", + + // Code documentation + "src/**/*.md", + "tests/**/*.md", + "examples/**/*.md", + + // Build artifacts and dependencies + "dist/**", + "node_modules/**", + "build/**", + "coverage/**", + + // Version control and IDE + ".git/**", + ".github/**", + ".vscode/**", + ".idea/**", + + // Draft files + "**/*.draft.md", + "**/*.wip.md", + + // Environment and config files + ".env*", + "*.config.*", + "package.json", + "tsconfig.json" ], - // When conflicts occur, local patterns take precedence + // Conflict resolution strategy "conflictResolution": "local-wins" }