diff --git a/AI.md b/AI.md index 2855e09..7a6ef65 100644 --- a/AI.md +++ b/AI.md @@ -53,21 +53,23 @@ Key files you'll work with: * `information-dense-keywords.md` - The core dictionary content * `README.md` - Project documentation and usage guide -* `docs/roadmaps/ROADMAP.md` - Development priorities and future plans +* `docs/roadmaps/` - Directory for roadmap documents (e.g., `q4-roadmap.md`) +* `docs/plans/` - Directory for planning documents (e.g., `new-feature-plan.md`) +* `docs/specs/` - Directory for specifications (e.g., `api-spec-v2.md`) +* `docs/research/` - Directory for research notes (e.g., `competitor-analysis.md`) * `examples/` - Usage examples and guides * `adrs/` - Architecture decision records * `AI.md` - This shared AI instruction file -* `CLAUDE.md` - Claude-specific instructions -* `GEMINI.md` - Gemini-specific instructions ## Cross-References * [information-dense-keywords.md](information-dense-keywords.md) - The core command dictionary * [README.md](README.md) - Main project documentation -* [docs/roadmaps/ROADMAP.md](docs/roadmaps/ROADMAP.md) - Development roadmap and priorities +* [docs/roadmaps/](docs/roadmaps/) - Directory for roadmap documents +* [docs/plans/](docs/plans/) - Directory for planning documents +* [docs/specs/](docs/specs/) - Directory for specifications +* [docs/research/](docs/research/) - Directory for research notes * [examples/ai-usage-guide.md](examples/ai-usage-guide.md) - AI usage examples -* [CLAUDE.md](CLAUDE.md) - Claude-specific context and instructions -* [GEMINI.md](GEMINI.md) - Gemini-specific context and instructions ## Core Principles @@ -80,4 +82,4 @@ Remember: This project focuses on creating a clear, actionable vocabulary for hu ## AI-Specific Considerations -Each AI assistant should reference this file for common guidance, then refer to their specific instruction file (CLAUDE.md, GEMINI.md, etc.) for platform-specific considerations and capabilities. +Each AI assistant should reference this file for common guidance, then refer to their specific instruction file for platform-specific considerations and capabilities. diff --git a/CLAUDE.md b/CLAUDE.md index 343a665..3f20b8c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -15,5 +15,5 @@ This file provides Claude-specific guidance when working with the Information De - [AI.md](AI.md) - Shared instructions for all AI assistants - [information-dense-keywords.md](information-dense-keywords.md) - The core command dictionary -- [docs/roadmaps/ROADMAP.md](docs/roadmaps/ROADMAP.md) - Development roadmap and priorities +- [docs/roadmaps/](docs/roadmaps/) - Development roadmap and priorities - [GEMINI.md](GEMINI.md) - Gemini-specific context and instructions diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1090e22..e80bdf2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,9 +27,9 @@ The core dictionary is in [`information-dense-keywords.md`](information-dense-ke ### 3. AI Instructions -- [`AI.md`](AI.md) contains shared instructions for all AI assistants -- [`CLAUDE.md`](CLAUDE.md) and [`GEMINI.md`](GEMINI.md) contain model-specific guidance -- Update these files when dictionary changes affect AI behavior +- [`AI.md`](AI.md) contains shared instructions for all AI assistants. +- For model-specific guidance, follow the pattern of `CLAUDE.md` and `GEMINI.md`. +- Update these files when dictionary changes affect AI behavior. ## 🔧 Development Workflow @@ -107,7 +107,7 @@ Good command definition: ## 📚 Resources - [AI Usage Guide](examples/ai-usage-guide.md) - How AIs should use the dictionary -- [Project Roadmap](docs/roadmaps/ROADMAP.md) - Future development plans +- [Project Roadmap](docs/roadmaps/) - Future development plans - [ADRs](adrs/) - Architectural decision records ## 📄 License diff --git a/GEMINI.md b/GEMINI.md index 14fce70..8d38acc 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -15,5 +15,5 @@ This file provides Gemini-specific guidance when working with the Information De - [AI.md](AI.md) - Shared instructions for all AI assistants - [information-dense-keywords.md](information-dense-keywords.md) - The core command dictionary -- [docs/roadmaps/ROADMAP.md](docs/roadmaps/ROADMAP.md) - Development roadmap and priorities +- [docs/roadmaps/](docs/roadmaps/) - Development roadmap and priorities - [CLAUDE.md](CLAUDE.md) - Claude-specific context and instructions diff --git a/README.md b/README.md index 63decdd..29ce398 100644 --- a/README.md +++ b/README.md @@ -155,7 +155,9 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines. - [AI Usage Guide](examples/ai-usage-guide.md) - Detailed implementation guidance - [Command Definitions](information-dense-keywords.md) - Complete command index - [Architecture Decision Records](adrs/) - Design decisions and evolution -- [Roadmap](docs/roadmaps/ROADMAP.md) - Future development plans +- [Roadmap](docs/roadmaps/) - Future development plans + +*Note: Links to `docs/roadmaps/`, `docs/plans/`, etc., are conventions for AI assistants. These directories do not exist in the source repository but should be created in your local project clone.* ## 📄 License diff --git a/tests/dictionary-validator.test.js b/tests/dictionary-validator.test.js index 09ad339..054598e 100644 --- a/tests/dictionary-validator.test.js +++ b/tests/dictionary-validator.test.js @@ -3,6 +3,7 @@ const fs = require('fs'); const path = require('path'); const glob = require('glob'); +const { shouldSkipLink } = require('./lib/link-helper'); class DictionaryValidator { constructor() { @@ -138,8 +139,8 @@ class DictionaryValidator { while ((match = linkPattern.exec(content)) !== null) { const [, linkText, linkPath] = match; - // Skip external links - if (linkPath.startsWith('http://') || linkPath.startsWith('https://')) { + // Skip external links and conceptual docs links, as they are not expected to exist in the repo. + if (shouldSkipLink(linkPath)) { continue; } diff --git a/tests/lib/link-helper.js b/tests/lib/link-helper.js new file mode 100644 index 0000000..8c8c247 --- /dev/null +++ b/tests/lib/link-helper.js @@ -0,0 +1,18 @@ +/** + * Checks if a given link path should be skipped during validation. + * + * @param {string} linkPath - The path of the link to check. + * @returns {boolean} - True if the link should be skipped, false otherwise. + */ +function shouldSkipLink(linkPath) { + // Skip external links (http/https) and conceptual 'docs/' links. + // The 'docs/' directory is a convention for AI-generated content in the user's + // project and is not expected to exist in this source repository. + return ( + linkPath.startsWith('http://') || + linkPath.startsWith('https://') || + linkPath.startsWith('docs/') + ); +} + +module.exports = { shouldSkipLink }; diff --git a/tests/link-validation.test.js b/tests/link-validation.test.js index d45c8b3..a1097f2 100644 --- a/tests/link-validation.test.js +++ b/tests/link-validation.test.js @@ -3,6 +3,7 @@ const fs = require('fs'); const path = require('path'); const glob = require('glob'); +const { shouldSkipLink } = require('./lib/link-helper'); class LinkValidationTest { constructor() { @@ -140,10 +141,16 @@ class LinkValidationTest { relativeLinks.forEach(link => { this.test(`${fileName}: relative link "${link.text}" -> ${link.path}`, () => { const filePath = path.join(this.rootDir, file); + // The link resolution test should not apply to conceptual directories or external URLs. + if (shouldSkipLink(link.path)) { + return; // Skip validation for these paths + } + const resolvedPath = path.resolve(path.dirname(filePath), link.path); + // fs.existsSync works for both files and directories. if (!fs.existsSync(resolvedPath)) { - throw new Error(`Broken relative link: ${link.path} (line ${link.lineNumber})`); + throw new Error(`Broken relative link: target does not exist at ${link.path} (line ${link.lineNumber})`); } }); }); @@ -153,47 +160,20 @@ class LinkValidationTest { testCrossReferences() { console.log('🔗 Testing cross-references...'); - const commandFiles = Array.from(this.linkMap.keys()).filter(file => - file.startsWith('dictionary/') && file.endsWith('.md') - ); - - // Build command name index - const commandIndex = new Map(); - commandFiles.forEach(file => { - const filePath = path.join(this.rootDir, file); - const content = fs.readFileSync(filePath, 'utf8'); - const h1Match = content.match(/^# (.+)/m); - - if (h1Match) { - commandIndex.set(h1Match[1].trim().toLowerCase(), file); - } - }); - - // Test that referenced commands exist - commandFiles.forEach(file => { - const links = this.linkMap.get(file) || []; + this.linkMap.forEach((links, file) => { const fileName = path.basename(file); - const commandLinks = links.filter(link => - link.path.includes('dictionary/') || link.text.includes('**') - ); + links.forEach(link => { + this.test(`${fileName}: cross-reference "${link.text}" -> ${link.path} is valid`, () => { + // Skip external links and conceptual docs links, as they are not expected to exist in the repo. + if (shouldSkipLink(link.path)) { + return; + } + + const targetPath = path.resolve(path.dirname(path.join(this.rootDir, file)), link.path); - commandLinks.forEach(link => { - this.test(`${fileName}: cross-reference "${link.text}" is valid`, () => { - if (link.path.startsWith('dictionary/') || link.path.startsWith('../')) { - // It's a dictionary reference - const normalizedText = link.text.replace(/\*\*/g, '').toLowerCase(); - - if (!commandIndex.has(normalizedText) && !fs.existsSync(path.join(this.rootDir, link.path))) { - // More flexible check - see if it exists as a file - const targetPath = link.path.startsWith('../') - ? path.resolve(path.dirname(path.join(this.rootDir, file)), link.path) - : path.join(this.rootDir, link.path); - - if (!fs.existsSync(targetPath)) { - throw new Error(`Cross-reference target not found: ${link.path}`); - } - } + if (!fs.existsSync(targetPath)) { + throw new Error(`Broken link: target does not exist at ${link.path} (line ${link.lineNumber})`); } }); });