From faa6febab40035c9483381d95577d6233e775cc9 Mon Sep 17 00:00:00 2001 From: Dominikus Nold Date: Sat, 28 Mar 2026 23:15:03 +0100 Subject: [PATCH 1/4] docs: unify core docs portal UX --- README.md | 4 +- docs/_config.yml | 3 + docs/_data/nav.yml | 164 +++ docs/_includes/breadcrumbs.html | 19 + docs/_includes/expertise-filter.html | 7 + docs/_includes/search.html | 5 + docs/_includes/sidebar-nav.html | 34 + docs/_includes/theme-toggle.html | 16 + docs/_layouts/default.html | 281 ++--- docs/architecture/implementation-status.md | 3 + docs/architecture/overview.md | 3 + docs/assets/js/filters.js | 63 + docs/assets/js/search-index.json | 14 + docs/assets/js/search.js | 143 +++ docs/assets/js/theme.js | 26 + docs/assets/main.scss | 1028 ++++++++++++----- docs/core-cli/debug-logging.md | 3 + docs/core-cli/init.md | 3 + docs/core-cli/modes.md | 3 + docs/core-cli/module.md | 3 + docs/core-cli/upgrade.md | 5 +- docs/getting-started/README.md | 4 + docs/getting-started/installation.md | 45 +- docs/getting-started/quickstart.md | 3 + docs/getting-started/where-to-start.md | 162 +++ docs/guides/ai-ide-workflow.md | 4 +- docs/guides/ide-integration.md | 6 +- docs/index.md | 62 +- docs/migration/migration-guide.md | 281 ++--- docs/module-system/bootstrap-checklist.md | 3 + docs/module-system/custom-registries.md | 3 + docs/module-system/installing-modules.md | 3 + docs/module-system/marketplace.md | 3 + docs/module-system/module-marketplace.md | 3 + docs/reference/authentication.md | 3 + docs/reference/bridge-registry.md | 4 +- docs/reference/commands.md | 3 + docs/reference/documentation-url-contract.md | 5 +- openspec/CHANGE_ORDER.md | 1 + .../CHANGE_VALIDATION.md | 46 + .../TDD_EVIDENCE.md | 105 ++ .../design.md | 35 + .../proposal.md | 47 + .../specs/core-docs-client-search/spec.md | 21 + .../specs/core-docs-data-driven-nav/spec.md | 20 + .../specs/core-docs-expertise-paths/spec.md | 21 + .../specs/core-docs-theme-toggle/spec.md | 21 + .../tasks.md | 36 + scripts/check-docs-commands.py | 81 ++ .../unit/docs/test_docs_validation_scripts.py | 82 ++ tests/unit/docs/test_release_docs_parity.py | 6 +- tests/unit/test_core_docs_site_contract.py | 83 ++ 52 files changed, 2383 insertions(+), 649 deletions(-) create mode 100644 docs/_data/nav.yml create mode 100644 docs/_includes/breadcrumbs.html create mode 100644 docs/_includes/expertise-filter.html create mode 100644 docs/_includes/search.html create mode 100644 docs/_includes/sidebar-nav.html create mode 100644 docs/_includes/theme-toggle.html create mode 100644 docs/assets/js/filters.js create mode 100644 docs/assets/js/search-index.json create mode 100644 docs/assets/js/search.js create mode 100644 docs/assets/js/theme.js create mode 100644 docs/getting-started/where-to-start.md create mode 100644 openspec/changes/docs-13-core-nav-search-theme-roles/CHANGE_VALIDATION.md create mode 100644 openspec/changes/docs-13-core-nav-search-theme-roles/TDD_EVIDENCE.md create mode 100644 openspec/changes/docs-13-core-nav-search-theme-roles/design.md create mode 100644 openspec/changes/docs-13-core-nav-search-theme-roles/proposal.md create mode 100644 openspec/changes/docs-13-core-nav-search-theme-roles/specs/core-docs-client-search/spec.md create mode 100644 openspec/changes/docs-13-core-nav-search-theme-roles/specs/core-docs-data-driven-nav/spec.md create mode 100644 openspec/changes/docs-13-core-nav-search-theme-roles/specs/core-docs-expertise-paths/spec.md create mode 100644 openspec/changes/docs-13-core-nav-search-theme-roles/specs/core-docs-theme-toggle/spec.md create mode 100644 openspec/changes/docs-13-core-nav-search-theme-roles/tasks.md create mode 100644 tests/unit/test_core_docs_site_contract.py diff --git a/README.md b/README.md index 8c448afe..485d6111 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,13 @@ # SpecFact CLI > **The "swiss knife" CLI that turns any codebase into a clear, safe, and shippable workflow.** -> Keep backlog, specs, tests, and code in sync so AI-assisted changes do not break production. +> Keep backlog, specs, tests, and code in sync so changes made by people or AI copilots do not break production. > Works for brand-new projects and long-lived codebases - even if you are new to coding. **No API keys required. Works offline. Zero vendor lock-in.** +SpecFact CLI does **not** include built-in AI. It is a deterministic local CLI that can be paired with IDE slash-command prompts so your chosen AI copilot can invoke SpecFact as part of a command chain. + [![PyPI version](https://img.shields.io/pypi/v/specfact-cli.svg?color=22c55e)](https://pypi.org/project/specfact-cli/) [![Python versions](https://img.shields.io/pypi/pyversions/specfact-cli.svg)](https://pypi.org/project/specfact-cli/) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE) diff --git a/docs/_config.yml b/docs/_config.yml index 3802b04a..112ece46 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -6,6 +6,9 @@ description: >- Complete documentation for SpecFact CLI - Brownfield-first CLI: Reverse engineer legacy Python → specs → enforced contracts. baseurl: "" # Custom domain at root, no baseurl needed url: "https://docs.specfact.io" # Custom domain +docs_home_url: "https://docs.specfact.io" +core_cli_docs_url: "https://docs.specfact.io" +modules_docs_url: "https://modules.specfact.io" # Build settings markdown: kramdown diff --git a/docs/_data/nav.yml b/docs/_data/nav.yml new file mode 100644 index 00000000..be45bbc3 --- /dev/null +++ b/docs/_data/nav.yml @@ -0,0 +1,164 @@ +- section: Getting Started + items: + - title: Where to Start + url: /getting-started/where-to-start/ + expertise: [beginner] + - title: Installation + url: /getting-started/installation/ + expertise: [beginner] + - title: Quickstart + url: /getting-started/quickstart/ + expertise: [beginner] + - title: Bootstrap Checklist + url: /module-system/bootstrap-checklist/ + expertise: [beginner, intermediate] + - title: AI IDE Workflow + url: /guides/ai-ide-workflow/ + expertise: [beginner, intermediate] + +- section: Core CLI + items: + - title: specfact init + url: /core-cli/init/ + expertise: [beginner, intermediate] + - title: specfact module + url: /core-cli/module/ + expertise: [beginner, intermediate] + - title: specfact upgrade + url: /core-cli/upgrade/ + expertise: [beginner, intermediate] + - title: Operational Modes + url: /core-cli/modes/ + expertise: [intermediate, advanced] + - title: Debug Logging + url: /core-cli/debug-logging/ + expertise: [advanced] + +- section: Module System + items: + - title: Installing Modules + url: /module-system/installing-modules/ + expertise: [beginner, intermediate] + - title: Module Marketplace + url: /module-system/module-marketplace/ + expertise: [beginner, intermediate] + - title: Marketplace Bundles + url: /module-system/marketplace/ + expertise: [intermediate] + - title: Custom Registries + url: /module-system/custom-registries/ + expertise: [advanced] + - title: Module Bootstrap Checklist + url: /module-system/bootstrap-checklist/ + expertise: [beginner, intermediate] + +- section: Architecture + items: + - title: Overview + url: /architecture/overview/ + expertise: [intermediate, advanced] + - title: Implementation Status + url: /architecture/implementation-status/ + expertise: [advanced] + - title: Module System + url: /architecture/module-system/ + expertise: [advanced] + - title: Interface Contracts + url: /architecture/interface-contracts/ + expertise: [advanced] + - title: Component Graph + url: /architecture/component-graph/ + expertise: [advanced] + - title: Data Flow + url: /architecture/data-flow/ + expertise: [advanced] + - title: State Machines + url: /architecture/state-machines/ + expertise: [advanced] + +- section: Workflows + items: + - title: AI IDE Workflow + url: /guides/ai-ide-workflow/ + expertise: [beginner, intermediate] + - title: Agile & Scrum Workflows + url: /guides/agile-scrum-workflows/ + expertise: [intermediate] + - title: Command Chains + url: /guides/command-chains/ + expertise: [intermediate, advanced] + - title: Contract Testing Workflow + url: /guides/contract-testing-workflow/ + expertise: [advanced] + - title: Team Collaboration Workflow + url: /guides/team-collaboration-workflow/ + expertise: [intermediate] + - title: OpenSpec Journey + url: /guides/openspec-journey/ + expertise: [intermediate] + +- section: Integrations + items: + - title: Integrations Overview + url: /guides/integrations-overview/ + expertise: [intermediate] + - title: GitHub Adapter + url: /adapters/github/ + expertise: [intermediate] + - title: Azure DevOps Adapter + url: /adapters/azuredevops/ + expertise: [intermediate] + - title: DevOps Adapter Integration + url: /guides/devops-adapter-integration/ + expertise: [intermediate, advanced] + - title: Custom Bridges + url: /guides/creating-custom-bridges/ + expertise: [advanced] + +- section: Migration + items: + - title: Migration Guide + url: /migration/migration-guide/ + expertise: [intermediate] + - title: CLI Reorganization + url: /migration/migration-cli-reorganization/ + expertise: [intermediate, advanced] + - title: OpenSpec Migration + url: /migration/openspec-migration/ + expertise: [intermediate] + +- section: Reference + items: + - title: Command Reference + url: /reference/commands/ + expertise: [intermediate, advanced] + - title: Core vs Modules URL Contract + url: /reference/documentation-url-contract/ + expertise: [advanced] + - title: Authentication + url: /reference/authentication/ + expertise: [intermediate, advanced] + - title: Bridge Registry + url: /reference/bridge-registry/ + expertise: [advanced] + - title: Directory Structure + url: /reference/directory-structure/ + expertise: [advanced] + - title: Module Contracts + url: /reference/module-contracts/ + expertise: [advanced] + - title: Module Categories + url: /reference/module-categories/ + expertise: [intermediate] + - title: Module Security + url: /reference/module-security/ + expertise: [advanced] + - title: ProjectBundle Schema + url: /reference/projectbundle-schema/ + expertise: [advanced] + - title: Dependency Resolution + url: /reference/dependency-resolution/ + expertise: [advanced] + - title: Thorough Codebase Validation + url: /reference/thorough-codebase-validation/ + expertise: [advanced] diff --git a/docs/_includes/breadcrumbs.html b/docs/_includes/breadcrumbs.html new file mode 100644 index 00000000..aa11dedd --- /dev/null +++ b/docs/_includes/breadcrumbs.html @@ -0,0 +1,19 @@ +{% unless page.url == '/' %} + +{% endunless %} diff --git a/docs/_includes/expertise-filter.html b/docs/_includes/expertise-filter.html new file mode 100644 index 00000000..a8341bd1 --- /dev/null +++ b/docs/_includes/expertise-filter.html @@ -0,0 +1,7 @@ +
+ + + + + +
diff --git a/docs/_includes/search.html b/docs/_includes/search.html new file mode 100644 index 00000000..44daa3f3 --- /dev/null +++ b/docs/_includes/search.html @@ -0,0 +1,5 @@ + diff --git a/docs/_includes/sidebar-nav.html b/docs/_includes/sidebar-nav.html new file mode 100644 index 00000000..62f76a5e --- /dev/null +++ b/docs/_includes/sidebar-nav.html @@ -0,0 +1,34 @@ + diff --git a/docs/_includes/theme-toggle.html b/docs/_includes/theme-toggle.html new file mode 100644 index 00000000..e4c504eb --- /dev/null +++ b/docs/_includes/theme-toggle.html @@ -0,0 +1,16 @@ + diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html index 54121368..6900d48f 100644 --- a/docs/_layouts/default.html +++ b/docs/_layouts/default.html @@ -5,7 +5,7 @@ {% seo %} - + @@ -14,84 +14,135 @@ {% if jekyll.environment == 'production' and site.google_analytics %} {% include google-analytics.html %} {% endif %} - + + diff --git a/docs/architecture/implementation-status.md b/docs/architecture/implementation-status.md index 8b9415b0..b2f0e594 100644 --- a/docs/architecture/implementation-status.md +++ b/docs/architecture/implementation-status.md @@ -3,6 +3,9 @@ layout: default title: Architecture Implementation Status permalink: /architecture/implementation-status/ description: Implemented vs planned architecture capabilities. +keywords: [implementation status, roadmap, architecture] +audience: [team, enterprise] +expertise_level: [advanced] --- # Architecture Implementation Status diff --git a/docs/architecture/overview.md b/docs/architecture/overview.md index 4e9c617f..4802e89d 100644 --- a/docs/architecture/overview.md +++ b/docs/architecture/overview.md @@ -4,6 +4,9 @@ title: Architecture permalink: /architecture/overview/ redirect_from: - /reference/architecture/ +keywords: [architecture, module system, runtime, registry] +audience: [team, enterprise] +expertise_level: [intermediate, advanced] --- # Architecture diff --git a/docs/assets/js/filters.js b/docs/assets/js/filters.js new file mode 100644 index 00000000..9ac8a9bb --- /dev/null +++ b/docs/assets/js/filters.js @@ -0,0 +1,63 @@ +(function() { + var pills = document.querySelectorAll('.expertise-pill'); + var countEl = document.querySelector('.expertise-count'); + if (!pills.length) return; + + var stored = localStorage.getItem('specfact-expertise') || 'all'; + + function applyFilter(level) { + // Update pills + pills.forEach(function(p) { + p.classList.toggle('active', p.getAttribute('data-level') === level); + }); + + var items = document.querySelectorAll('.docs-nav li[data-expertise]'); + var total = items.length; + var visible = 0; + + items.forEach(function(li) { + if (level === 'all') { + li.classList.remove('hidden-by-filter'); + visible++; + } else { + var expertise = (li.getAttribute('data-expertise') || '').split(','); + if (expertise.indexOf(level) !== -1) { + li.classList.remove('hidden-by-filter'); + visible++; + } else { + li.classList.add('hidden-by-filter'); + } + } + }); + + // Hide bundle sections with no visible items + document.querySelectorAll('.docs-nav-bundle').forEach(function(details) { + var visibleItems = details.querySelectorAll('li:not(.hidden-by-filter)'); + if (visibleItems.length === 0 && level !== 'all') { + details.classList.add('hidden-by-filter'); + } else { + details.classList.remove('hidden-by-filter'); + } + }); + + // Update count + if (countEl) { + if (level === 'all') { + countEl.textContent = ''; + } else { + countEl.textContent = visible + ' of ' + total; + } + } + + localStorage.setItem('specfact-expertise', level); + } + + pills.forEach(function(pill) { + pill.addEventListener('click', function() { + applyFilter(pill.getAttribute('data-level')); + }); + }); + + // Apply stored filter + applyFilter(stored); +})(); diff --git a/docs/assets/js/search-index.json b/docs/assets/js/search-index.json new file mode 100644 index 00000000..87c67689 --- /dev/null +++ b/docs/assets/js/search-index.json @@ -0,0 +1,14 @@ +--- +layout: null +permalink: /assets/js/search-index.json +--- +{% assign pages_with_title = "" | split: "" %}{% for page in site.pages %}{% if page.title %}{% assign pages_with_title = pages_with_title | push: page %}{% endif %}{% endfor %}[{% for page in pages_with_title %} + { + "url": "{{ page.url | relative_url }}", + "title": {{ page.title | jsonify }}, + "keywords": {{ page.keywords | default: "" | jsonify }}, + "audience": {{ page.audience | default: "" | jsonify }}, + "expertise_level": {{ page.expertise_level | default: "" | jsonify }}, + "content": {{ page.content | strip_html | truncatewords: 200 | jsonify }} + }{% unless forloop.last %},{% endunless %}{% endfor %} +] diff --git a/docs/assets/js/search.js b/docs/assets/js/search.js new file mode 100644 index 00000000..8a6b2dff --- /dev/null +++ b/docs/assets/js/search.js @@ -0,0 +1,143 @@ +(function() { + var searchRoot = document.querySelector('.docs-search'); + var searchInput = document.querySelector('.docs-search-input'); + var searchResults = document.querySelector('.docs-search-results'); + if (!searchRoot || !searchInput || !searchResults) return; + + var lunrIndex = null; + var searchData = null; + var debounceTimer = null; + var highlightedIndex = -1; + + function loadIndex() { + if (lunrIndex) return Promise.resolve(); + var indexUrl = searchRoot.getAttribute('data-search-index-url') || '/assets/js/search-index.json'; + return fetch(indexUrl) + .then(function(r) { return r.json(); }) + .then(function(data) { + searchData = data; + lunrIndex = lunr(function() { + this.ref('url'); + this.field('title', { boost: 10 }); + this.field('keywords', { boost: 5 }); + this.field('content'); + data.forEach(function(doc) { + var entry = { + url: doc.url, + title: doc.title || '', + keywords: Array.isArray(doc.keywords) ? doc.keywords.join(' ') : (doc.keywords || ''), + content: doc.content || '' + }; + this.add(entry); + }.bind(this)); + }); + }); + } + + function getDoc(url) { + for (var i = 0; i < searchData.length; i++) { + if (searchData[i].url === url) return searchData[i]; + } + return null; + } + + function renderResults(results) { + highlightedIndex = -1; + if (results.length === 0) { + searchResults.innerHTML = '
No results found
'; + searchResults.style.display = 'block'; + return; + } + + var html = ''; + results.slice(0, 10).forEach(function(result) { + var doc = getDoc(result.ref); + if (!doc) return; + var snippet = (doc.content || '').substring(0, 120) + '...'; + var tags = ''; + var audience = Array.isArray(doc.audience) ? doc.audience : []; + var expertise = Array.isArray(doc.expertise_level) ? doc.expertise_level : []; + audience.concat(expertise).forEach(function(tag) { + if (tag) tags += '' + tag + ''; + }); + + html += ''; + html += '
' + (doc.title || '') + '
'; + html += '
' + snippet + '
'; + if (tags) html += '
' + tags + '
'; + html += '
'; + }); + + searchResults.innerHTML = html; + searchResults.style.display = 'block'; + } + + function doSearch(query) { + if (!lunrIndex || query.length < 2) { + searchResults.style.display = 'none'; + return; + } + try { + var results = lunrIndex.search(query + '*'); + renderResults(results); + } catch (e) { + try { + var results = lunrIndex.search(query); + renderResults(results); + } catch (e2) { + searchResults.style.display = 'none'; + } + } + } + + searchInput.addEventListener('focus', function() { + loadIndex(); + }); + + searchInput.addEventListener('input', function() { + clearTimeout(debounceTimer); + var query = searchInput.value.trim(); + debounceTimer = setTimeout(function() { doSearch(query); }, 150); + }); + + searchInput.addEventListener('keydown', function(e) { + var items = searchResults.querySelectorAll('.docs-search-result'); + if (e.key === 'ArrowDown') { + e.preventDefault(); + highlightedIndex = Math.min(highlightedIndex + 1, items.length - 1); + updateHighlight(items); + } else if (e.key === 'ArrowUp') { + e.preventDefault(); + highlightedIndex = Math.max(highlightedIndex - 1, 0); + updateHighlight(items); + } else if (e.key === 'Enter' && highlightedIndex >= 0 && items[highlightedIndex]) { + e.preventDefault(); + items[highlightedIndex].click(); + } else if (e.key === 'Escape') { + searchResults.style.display = 'none'; + searchInput.blur(); + } + }); + + function updateHighlight(items) { + items.forEach(function(item, i) { + item.classList.toggle('highlighted', i === highlightedIndex); + }); + } + + // Close results when clicking outside + document.addEventListener('click', function(e) { + if (!e.target.closest('.docs-search')) { + searchResults.style.display = 'none'; + } + }); + + // Keyboard shortcut: Ctrl+K / Cmd+K + document.addEventListener('keydown', function(e) { + if ((e.ctrlKey || e.metaKey) && e.key === 'k') { + e.preventDefault(); + searchInput.focus(); + searchInput.select(); + } + }); +})(); diff --git a/docs/assets/js/theme.js b/docs/assets/js/theme.js new file mode 100644 index 00000000..444fb975 --- /dev/null +++ b/docs/assets/js/theme.js @@ -0,0 +1,26 @@ +// Theme initialization - runs in to prevent FOUC +(function() { + var stored = localStorage.getItem('specfact-theme'); + var theme = stored || (window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark'); + document.documentElement.setAttribute('data-theme', theme); +})(); + +function toggleTheme() { + var current = document.documentElement.getAttribute('data-theme') || 'dark'; + var next = current === 'dark' ? 'light' : 'dark'; + document.documentElement.setAttribute('data-theme', next); + localStorage.setItem('specfact-theme', next); + + // Update toggle button icons + var sunIcon = document.querySelector('.theme-toggle .icon-sun'); + var moonIcon = document.querySelector('.theme-toggle .icon-moon'); + if (sunIcon && moonIcon) { + sunIcon.style.display = next === 'dark' ? 'none' : 'block'; + moonIcon.style.display = next === 'dark' ? 'block' : 'none'; + } + + // Re-render mermaid diagrams if available + if (typeof rerenderMermaid === 'function') { + rerenderMermaid(next); + } +} diff --git a/docs/assets/main.scss b/docs/assets/main.scss index e6f0ade4..823131ae 100644 --- a/docs/assets/main.scss +++ b/docs/assets/main.scss @@ -1,215 +1,357 @@ --- # Jekyll frontmatter required for SCSS processing -# Explicit permalink to prevent Jekyll from applying default permalink pattern permalink: /assets/main.css --- @import "minima"; -// Custom styling for SpecFact CLI documentation -// These styles override minima theme defaults - -:root { - /* SpecFact.io color scheme - Documentation theme */ - --primary-color: #64ffda; - --primary-hover: #7affeb; +// ============================================================================ +// Dark theme (default) +// ============================================================================ +[data-theme="dark"] { + --primary-color: #57e6c4; + --primary-hover: #6eefd3; --text-color: #ccd6f6; --text-light: #8892b0; --text-muted: #495670; --bg-color: #0a192f; --bg-light: #112240; --bg-alt: #1d2d50; - --border-color: rgba(100, 255, 218, 0.1); - --border-hover: rgba(100, 255, 218, 0.3); + --border-color: rgba(87, 230, 196, 0.12); + --border-hover: rgba(87, 230, 196, 0.3); --code-bg: #1d2d50; - --link-color: #64ffda; - --link-hover: #7affeb; + --link-color: #57e6c4; + --link-hover: #6eefd3; + --search-bg: #1d2d50; + --search-border: rgba(87, 230, 196, 0.2); + --card-bg: #112240; + --card-border: rgba(87, 230, 196, 0.15); + --breadcrumb-color: #8892b0; + --badge-bg: rgba(87, 230, 196, 0.12); + --badge-color: #57e6c4; + --filter-bg: #1d2d50; + color-scheme: dark; +} + +// ============================================================================ +// Light theme +// ============================================================================ +[data-theme="light"] { + --primary-color: #0d9488; + --primary-hover: #0f766e; + --text-color: #1a1a2e; + --text-light: #475569; + --text-muted: #94a3b8; + --bg-color: #ffffff; + --bg-light: #f8fafc; + --bg-alt: #f1f5f9; + --border-color: #e2e8f0; + --border-hover: #cbd5e1; + --code-bg: #f1f5f9; + --link-color: #0d9488; + --link-hover: #0f766e; + --search-bg: #ffffff; + --search-border: #cbd5e1; + --card-bg: #f8fafc; + --card-border: #e2e8f0; + --breadcrumb-color: #64748b; + --badge-bg: #f0fdfa; + --badge-color: #0d9488; + --filter-bg: #f1f5f9; + color-scheme: light; +} + +// System preference fallback (when no data-theme attribute) +@media (prefers-color-scheme: light) { + :root:not([data-theme]) { + --primary-color: #0d9488; + --primary-hover: #0f766e; + --text-color: #1a1a2e; + --text-light: #475569; + --text-muted: #94a3b8; + --bg-color: #ffffff; + --bg-light: #f8fafc; + --bg-alt: #f1f5f9; + --border-color: #e2e8f0; + --border-hover: #cbd5e1; + --code-bg: #f1f5f9; + --link-color: #0d9488; + --link-hover: #0f766e; + --search-bg: #ffffff; + --search-border: #cbd5e1; + --card-bg: #f8fafc; + --card-border: #e2e8f0; + --breadcrumb-color: #64748b; + --badge-bg: #f0fdfa; + --badge-color: #0d9488; + --filter-bg: #f1f5f9; + color-scheme: light; + } +} + +@media (prefers-color-scheme: dark) { + :root:not([data-theme]) { + --primary-color: #57e6c4; + --primary-hover: #6eefd3; + --text-color: #ccd6f6; + --text-light: #8892b0; + --text-muted: #495670; + --bg-color: #0a192f; + --bg-light: #112240; + --bg-alt: #1d2d50; + --border-color: rgba(87, 230, 196, 0.12); + --border-hover: rgba(87, 230, 196, 0.3); + --code-bg: #1d2d50; + --link-color: #57e6c4; + --link-hover: #6eefd3; + --search-bg: #1d2d50; + --search-border: rgba(87, 230, 196, 0.2); + --card-bg: #112240; + --card-border: rgba(87, 230, 196, 0.15); + --breadcrumb-color: #8892b0; + --badge-bg: rgba(87, 230, 196, 0.12); + --badge-color: #57e6c4; + --filter-bg: #1d2d50; + color-scheme: dark; + } +} + +// ============================================================================ +// Themed scrollbars +// ============================================================================ +* { + scrollbar-width: thin; + scrollbar-color: var(--border-hover) var(--bg-light); +} + +::-webkit-scrollbar { width: 8px; height: 8px; } +::-webkit-scrollbar-track { background: var(--bg-light); } +::-webkit-scrollbar-thumb { + background: var(--border-hover); + border-radius: 4px; + &:hover { background: var(--text-muted); } } -// Override body styles with !important to ensure they apply +// ============================================================================ +// Base styles +// ============================================================================ body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !important; line-height: 1.7 !important; color: var(--text-color) !important; background-color: var(--bg-color) !important; -webkit-font-smoothing: antialiased; + transition: background-color 0.2s, color 0.2s; } -// Header styling +// ============================================================================ +// Header +// ============================================================================ .site-header { - border-bottom: 2px solid var(--border-color); + border-bottom: 1px solid var(--border-color); background-color: var(--bg-light); - padding: 1rem 0; - + padding: 0.75rem 0; + transition: background-color 0.2s; + .site-title { - font-size: 1.5rem; + font-size: 1.35rem; font-weight: 700; color: var(--primary-color); text-decoration: none; - - &:hover { - color: var(--primary-hover); - } + &:hover { color: var(--primary-hover); } } - + .site-nav { + display: flex; + align-items: center; + .page-link { color: var(--text-color); font-weight: 500; margin: 0 0.5rem; text-decoration: none; transition: color 0.2s; - - &:hover { - color: var(--primary-color); - } + &:hover { color: var(--primary-color); } } } } -// Main content area - minima uses .page-content with .wrapper +// GitHub link in header +.github-link { + display: inline-flex; + align-items: center; + color: var(--text-color); + margin-left: 0.75rem; + padding: 0.4rem; + border: 1px solid var(--border-color); + border-radius: 0.375rem; + transition: color 0.2s, border-color 0.2s; + &:hover { + color: var(--primary-color); + border-color: var(--primary-color); + } + svg { width: 18px; height: 18px; fill: currentColor; } +} + +// Theme toggle button +.theme-toggle { + background: none; + border: 1px solid var(--border-color); + border-radius: 0.375rem; + padding: 0.35rem 0.5rem; + cursor: pointer; + color: var(--text-light); + display: inline-flex; + align-items: center; + margin-left: 0.5rem; + transition: color 0.2s, border-color 0.2s; + + &:hover { + color: var(--primary-color); + border-color: var(--primary-color); + } + + svg { display: block; } +} + +// Show correct icon per theme +[data-theme="dark"] .theme-toggle .icon-sun { display: none; } +[data-theme="dark"] .theme-toggle .icon-moon { display: block; } +[data-theme="light"] .theme-toggle .icon-sun { display: block; } +[data-theme="light"] .theme-toggle .icon-moon { display: none; } + +// ============================================================================ +// Page content area +// ============================================================================ .page-content { padding: 2rem 0; color: var(--text-color) !important; background-color: var(--bg-color) !important; + transition: background-color 0.2s; } -// Ensure all text elements have proper color .page-content, -.page-content * { - color: inherit; -} +.page-content * { color: inherit; } -// Page content styling (scoped to docs-content to avoid conflicts) +// ============================================================================ +// Docs content area +// ============================================================================ .docs-content { - padding: 2rem 0; + flex: 1 1 0%; + min-width: 0; + max-width: 900px; + padding: 1.5rem 2rem; + overflow-wrap: anywhere; + word-break: break-word; color: var(--text-color) !important; background-color: var(--bg-color) !important; - + h1 { - font-size: 2.5rem; + font-size: 2.25rem; font-weight: 800; margin-bottom: 1rem; color: var(--text-color) !important; - border-bottom: 3px solid var(--primary-color); + border-bottom: 2px solid var(--primary-color); padding-bottom: 0.5rem; } - + h2 { - font-size: 2rem; + font-size: 1.75rem; font-weight: 700; margin-top: 2rem; - margin-bottom: 1rem; + margin-bottom: 0.75rem; color: var(--text-color) !important; } - + h3 { - font-size: 1.5rem; + font-size: 1.35rem; font-weight: 600; margin-top: 1.5rem; - margin-bottom: 0.75rem; + margin-bottom: 0.5rem; color: var(--text-color) !important; } - + h4 { - font-size: 1.25rem; + font-size: 1.15rem; font-weight: 600; margin-top: 1rem; margin-bottom: 0.5rem; color: var(--text-color) !important; } - - p { - margin-bottom: 1rem; - color: var(--text-color) !important; - } - - // Ensure all text in docs-content is visible - * { - color: inherit; - } - - // Links + + p { margin-bottom: 1rem; color: var(--text-color) !important; } + * { color: inherit; } + a { color: var(--link-color); text-decoration: none; font-weight: 500; transition: color 0.2s; - - &:hover { - color: var(--link-hover); - text-decoration: underline; - } + &:hover { color: var(--link-hover); text-decoration: underline; } } - - // Lists + ul, ol { margin-bottom: 1rem; padding-left: 2rem; color: var(--text-color) !important; - li { - margin-bottom: 0.5rem; + margin-bottom: 0.4rem; color: var(--text-color) !important; - a { color: var(--link-color) !important; - - &:hover { - color: var(--link-hover) !important; - } + &:hover { color: var(--link-hover) !important; } } } } - - // Tables (common in command reference) + + // Tables table { width: 100%; border-collapse: collapse; margin: 1.5rem 0; background-color: var(--bg-color) !important; - + border: 1px solid var(--border-color); + border-radius: 0.375rem; + overflow-x: auto; + display: block; + th, td { - padding: 0.75rem; - border: 1px solid var(--border-color); + padding: 0.6rem 0.75rem; + border-bottom: 1px solid var(--border-color); color: var(--text-color) !important; + text-align: left; } - + th { background-color: var(--bg-light) !important; font-weight: 600; + font-size: 0.9rem; color: var(--text-color) !important; } - - tr { - background-color: var(--bg-color) !important; - } - - tr:nth-child(even) { - background-color: var(--bg-light) !important; - } + + tr { background-color: var(--bg-color) !important; } + tr:nth-child(even) { background-color: var(--bg-light) !important; } } - - // Code blocks - Rouge syntax highlighting + + // Code blocks .highlighter-rouge { background-color: var(--code-bg) !important; border: 1px solid var(--border-color); - border-radius: 0.5rem; + border-left: 3px solid var(--primary-color); + border-radius: 0.375rem; margin-bottom: 1rem; font-family: 'JetBrains Mono', 'Fira Code', monospace !important; - + .highlight { background-color: var(--code-bg) !important; - pre { background-color: var(--code-bg) !important; border: none; - border-radius: 0.5rem; + border-radius: 0.375rem; padding: 1rem; overflow-x: auto; margin: 0; color: var(--text-color) !important; - code { background-color: transparent !important; padding: 0; @@ -220,18 +362,17 @@ body { } } } - - // Code blocks (fallback for non-Rouge) + pre { background-color: var(--code-bg) !important; border: 1px solid var(--border-color); - border-radius: 0.5rem; + border-left: 3px solid var(--primary-color); + border-radius: 0.375rem; padding: 1rem; overflow-x: auto; margin-bottom: 1rem; color: var(--text-color) !important; font-family: 'JetBrains Mono', 'Fira Code', monospace !important; - code { background-color: transparent !important; padding: 0; @@ -240,282 +381,549 @@ body { font-family: 'JetBrains Mono', 'Fira Code', monospace !important; } } - - // Inline code + code { background-color: var(--code-bg) !important; - padding: 0.2rem 0.4rem; + padding: 0.15rem 0.35rem; border-radius: 0.25rem; - font-size: 0.9em; + font-size: 0.88em; border: 1px solid var(--border-color); color: var(--text-color) !important; font-family: 'JetBrains Mono', 'Fira Code', monospace !important; } - - // Rouge syntax highlighting spans - dark theme colors for readability + + // Rouge dark syntax highlighting .highlight { - span { - background-color: transparent !important; - color: var(--text-color) !important; - } - - // Syntax highlighting colors (dark theme optimized) - .c { color: #8892b0 !important; } // Comments - muted gray-blue - .k { color: #ff6b9d !important; } // Keywords - pink/red - .l { color: #64ffda !important; } // Literals - cyan - .n { color: var(--text-color) !important; } // Names - .o { color: #ff6b9d !important; } // Operators - pink - .p { color: #ccd6f6 !important; } // Punctuation - light text - .cm { color: #8892b0 !important; } // Comment multiline - .cp { color: #8892b0 !important; } // Comment preproc - .c1 { color: #8892b0 !important; } // Comment single - .cs { color: #8892b0 !important; } // Comment special - .gd { color: #ff6b9d !important; } // Generic deleted - .ge { font-style: italic !important; } // Generic emph - .gr { color: #ff6b9d !important; } // Generic error - .gh { color: var(--text-color) !important; font-weight: bold !important; } // Generic heading - .gi { color: #64ffda !important; } // Generic inserted - cyan - .go { color: #8892b0 !important; } // Generic output - .gp { color: #8892b0 !important; } // Generic prompt - .gs { font-weight: bold !important; } // Generic strong - .gu { color: var(--text-color) !important; font-weight: bold !important; } // Generic subheading - .gt { color: #ff6b9d !important; } // Generic traceback - .kc { color: #64ffda !important; } // Keyword constant - cyan - .kd { color: #ff6b9d !important; } // Keyword declaration - pink - .kn { color: #ff6b9d !important; } // Keyword namespace - .kp { color: #ff6b9d !important; } // Keyword pseudo - .kr { color: #ff6b9d !important; } // Keyword reserved - .kt { color: #ff6b9d !important; } // Keyword type - .ld { color: #64ffda !important; } // Literal date - cyan - .m { color: #64ffda !important; } // Literal number - cyan - .s { color: #a8e6cf !important; } // Literal string - light green - .na { color: #64ffda !important; } // Name attribute - cyan - .nb { color: #64ffda !important; } // Name builtin - cyan - .nc { color: #c792ea !important; } // Name class - purple - .no { color: #64ffda !important; } // Name constant - cyan - .nd { color: #c792ea !important; } // Name decorator - purple - .ni { color: #c792ea !important; } // Name entity - purple - .ne { color: #ff6b9d !important; font-weight: bold !important; } // Name exception - .nf { color: #c792ea !important; } // Name function - purple - .nl { color: #64ffda !important; } // Name label - cyan - .nn { color: var(--text-color) !important; } // Name namespace - .nx { color: var(--text-color) !important; } // Name other - .py { color: var(--text-color) !important; } // Name property - .nt { color: #64ffda !important; } // Name tag - cyan (YAML keys) - .nv { color: #ffd93d !important; } // Name variable - yellow - .ow { color: #ff6b9d !important; } // Operator word - .w { color: #8892b0 !important; } // Text whitespace - .mf { color: #64ffda !important; } // Literal number float - .mh { color: #64ffda !important; } // Literal number hex - .mi { color: #64ffda !important; } // Literal number integer - .mo { color: #64ffda !important; } // Literal number oct - .sb { color: #a8e6cf !important; } // Literal string backtick - .sc { color: #a8e6cf !important; } // Literal string char - .sd { color: #8892b0 !important; } // Literal string doc - .s2 { color: #a8e6cf !important; } // Literal string double - .se { color: #a8e6cf !important; } // Literal string escape - .sh { color: #a8e6cf !important; } // Literal string heredoc - .si { color: #a8e6cf !important; } // Literal string interpol - .sx { color: #a8e6cf !important; } // Literal string other - .sr { color: #a8e6cf !important; } // Literal string regex - .s1 { color: #a8e6cf !important; } // Literal string single - .ss { color: #a8e6cf !important; } // Literal string symbol - .bp { color: var(--text-color) !important; } // Name builtin pseudo - .vc { color: #ffd93d !important; } // Name variable class - yellow - .vg { color: #ffd93d !important; } // Name variable global - yellow - .vi { color: #ffd93d !important; } // Name variable instance - yellow - .il { color: #64ffda !important; } // Literal number integer long - } - - // Blockquotes + span { background-color: transparent !important; } + } + blockquote { - border-left: 4px solid var(--primary-color); + border-left: 3px solid var(--primary-color); padding-left: 1rem; margin: 1rem 0; color: var(--text-light); font-style: italic; } - - // Horizontal rules - hr { - border: none; - border-top: 2px solid var(--border-color); - margin: 2rem 0; - } - - // Emoji and special elements - .emoji { - font-size: 1.2em; - } - - // Primary callout sections + + hr { border: none; border-top: 1px solid var(--border-color); margin: 2rem 0; } + .primary { background-color: var(--bg-light); - border-left: 4px solid var(--primary-color); + border-left: 3px solid var(--primary-color); padding: 1rem; margin: 1.5rem 0; border-radius: 0.25rem; } } -// Docs layout with left navigation +// ============================================================================ +// Dark theme syntax highlighting +// ============================================================================ +[data-theme="dark"] .docs-content .highlight { + .c, .cm, .cp, .c1, .cs { color: #8892b0 !important; } + .k, .kd, .kn, .kp, .kr, .kt { color: #ff6b9d !important; } + .o, .ow { color: #ff6b9d !important; } + .l, .ld, .m, .mf, .mh, .mi, .mo, .il { color: #57e6c4 !important; } + .kc { color: #57e6c4 !important; } + .s, .sb, .sc, .s2, .se, .sh, .si, .sx, .sr, .s1, .ss { color: #a8e6cf !important; } + .sd { color: #8892b0 !important; } + .n { color: #ccd6f6 !important; } + .na, .nb, .no, .nl, .nt { color: #57e6c4 !important; } + .nc, .nd, .ni, .nf { color: #c792ea !important; } + .ne { color: #ff6b9d !important; font-weight: bold !important; } + .nv, .vc, .vg, .vi { color: #ffd93d !important; } + .nn, .nx, .py, .bp { color: #ccd6f6 !important; } + .p { color: #ccd6f6 !important; } + .w { color: #8892b0 !important; } + .gd, .gr, .gt { color: #ff6b9d !important; } + .gi { color: #57e6c4 !important; } + .ge { font-style: italic !important; } + .gs { font-weight: bold !important; } + .gh, .gu { color: #ccd6f6 !important; font-weight: bold !important; } + .go, .gp { color: #8892b0 !important; } +} + +// ============================================================================ +// Light theme syntax highlighting +// ============================================================================ +[data-theme="light"] .docs-content .highlight { + .c, .cm, .cp, .c1, .cs { color: #6a737d !important; } + .k, .kd, .kn, .kp, .kr, .kt { color: #d73a49 !important; } + .o, .ow { color: #d73a49 !important; } + .l, .ld, .m, .mf, .mh, .mi, .mo, .il { color: #005cc5 !important; } + .kc { color: #005cc5 !important; } + .s, .sb, .sc, .s2, .se, .sh, .si, .sx, .sr, .s1, .ss { color: #032f62 !important; } + .sd { color: #6a737d !important; } + .n { color: #24292e !important; } + .na { color: #005cc5 !important; } + .nb { color: #005cc5 !important; } + .nc, .nd, .ni, .nf { color: #6f42c1 !important; } + .ne { color: #d73a49 !important; font-weight: bold !important; } + .nl, .nt { color: #22863a !important; } + .no { color: #005cc5 !important; } + .nv, .vc, .vg, .vi { color: #e36209 !important; } + .nn, .nx, .py, .bp { color: #24292e !important; } + .p { color: #24292e !important; } + .w { color: #6a737d !important; } + .gd, .gr, .gt { color: #d73a49 !important; } + .gi { color: #22863a !important; } + .ge { font-style: italic !important; } + .gs { font-weight: bold !important; } + .gh, .gu { color: #24292e !important; font-weight: bold !important; } + .go, .gp { color: #6a737d !important; } +} + +// ============================================================================ +// Layout — override minima's narrow .wrapper +// ============================================================================ + +// Minima default is max-width ~740px — far too narrow for a sidebar + content layout. +// Override globally and let each section control its own constraints. +.wrapper { + max-width: none !important; + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; +} + .wrapper.docs-layout { - max-width: 1200px; - margin: 0 auto; - padding: 2rem 1rem; + max-width: 100%; + margin: 0; + padding: 0; display: flex; - gap: 2rem; - align-items: flex-start; + gap: 0; + align-items: stretch; + min-height: calc(100vh - 8rem); } +// ============================================================================ +// Sidebar +// ============================================================================ .docs-sidebar { - flex: 0 0 260px; + flex: 0 0 270px; + min-width: 270px; border-right: 1px solid var(--border-color); background-color: var(--bg-light); - padding: 1.5rem 1rem; + padding: 1.25rem 1rem; position: sticky; - top: 4rem; - max-height: calc(100vh - 4rem); + top: 0; + height: 100vh; overflow-y: auto; + scrollbar-width: thin; + transition: background-color 0.2s; } .docs-sidebar-title { - font-size: 1.25rem; + font-size: 1.1rem; font-weight: 700; - margin: 0 0 1rem 0; -} - -.docs-sidebar-title a { - color: var(--primary-color); - text-decoration: none; -} - -.docs-sidebar-title a:hover { - color: var(--primary-hover); - text-decoration: underline; + margin: 0 0 0.75rem 0; + a { + color: var(--primary-color); + text-decoration: none; + &:hover { color: var(--primary-hover); text-decoration: underline; } + } } .docs-nav { - font-size: 0.95rem; + font-size: 0.875rem; + line-height: 1.5; } .docs-nav-section { font-weight: 600; - margin: 1rem 0 0.5rem 0; + margin: 1.25rem 0 0.35rem 0; color: var(--text-light); text-transform: uppercase; - letter-spacing: 0.05em; - font-size: 0.8rem; + letter-spacing: 0.06em; + font-size: 0.7rem; } .docs-nav ul { list-style: none; - margin: 0 0 0.5rem 0; + margin: 0 0 0.25rem 0; padding-left: 0; } .docs-nav li { - margin-bottom: 0.35rem; + margin-bottom: 0.15rem; } .docs-nav a { color: var(--text-color); text-decoration: none; + display: block; + padding: 0.2rem 0.5rem; + border-radius: 0.25rem; + transition: color 0.15s, background-color 0.15s; + &:hover { + color: var(--primary-color); + background-color: var(--bg-alt); + } + &.active { + color: var(--primary-color); + background-color: var(--bg-alt); + font-weight: 600; + border-left: 2px solid var(--primary-color); + padding-left: calc(0.5rem - 2px); + } } -.docs-nav a:hover { - color: var(--primary-color); - text-decoration: underline; +// Bundle collapsible sections +.docs-nav-bundle { + margin-bottom: 0.25rem; + + summary { + font-weight: 600; + color: var(--text-color); + cursor: pointer; + padding: 0.3rem 0.5rem; + border-radius: 0.25rem; + list-style: none; + display: flex; + align-items: center; + gap: 0.35rem; + transition: color 0.15s; + + &:hover { color: var(--primary-color); } + + &::before { + content: ''; + display: inline-block; + width: 0; + height: 0; + border-left: 5px solid var(--text-light); + border-top: 4px solid transparent; + border-bottom: 4px solid transparent; + transition: transform 0.2s; + } + + &::-webkit-details-marker { display: none; } + } + + &[open] > summary::before { + transform: rotate(90deg); + } + + ul { + padding-left: 1rem; + margin-top: 0.15rem; + } } -.docs-content { - flex: 1 1 auto; - min-width: 0; +// ============================================================================ +// Search +// ============================================================================ +.docs-search { + position: relative; + margin-bottom: 0.75rem; } -// Footer styling -.site-footer { - border-top: 2px solid var(--border-color); +.docs-search-input { + width: 100%; + padding: 0.45rem 0.65rem; + font-size: 0.8rem; + font-family: inherit; + background-color: var(--search-bg); + color: var(--text-color); + border: 1px solid var(--search-border); + border-radius: 0.375rem; + outline: none; + transition: border-color 0.2s; + box-sizing: border-box; + + &::placeholder { color: var(--text-muted); } + &:focus { border-color: var(--primary-color); } +} + +.docs-search-shortcut { + position: absolute; + right: 0.5rem; + top: 50%; + transform: translateY(-50%); + font-size: 0.65rem; + color: var(--text-muted); + border: 1px solid var(--border-color); + border-radius: 0.2rem; + padding: 0.1rem 0.3rem; + pointer-events: none; +} + +.docs-search-results { + position: absolute; + top: 100%; + left: 0; + right: 0; background-color: var(--bg-light); - padding: 2rem 0; - margin-top: 3rem; + border: 1px solid var(--border-color); + border-radius: 0.375rem; + margin-top: 0.25rem; + max-height: 320px; + overflow-y: auto; + z-index: 100; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + display: none; +} + +.docs-search-result { + padding: 0.5rem 0.65rem; + cursor: pointer; + border-bottom: 1px solid var(--border-color); + transition: background-color 0.1s; + + &:last-child { border-bottom: none; } + &:hover, &.highlighted { background-color: var(--bg-alt); } + + .result-title { + font-weight: 600; + font-size: 0.85rem; + color: var(--text-color); + margin-bottom: 0.15rem; + } + + .result-snippet { + font-size: 0.75rem; + color: var(--text-light); + line-height: 1.4; + } + + .result-tags { + display: flex; + gap: 0.25rem; + margin-top: 0.25rem; + flex-wrap: wrap; + } + + .result-tag { + font-size: 0.6rem; + padding: 0.1rem 0.35rem; + border-radius: 0.2rem; + background-color: var(--badge-bg); + color: var(--badge-color); + font-weight: 500; + } +} + +.docs-search-empty { + padding: 0.75rem; text-align: center; + color: var(--text-muted); + font-size: 0.8rem; +} + +// ============================================================================ +// Expertise filter +// ============================================================================ +.docs-expertise-filter { + display: flex; + align-items: center; + gap: 0.35rem; + margin-bottom: 0.75rem; + flex-wrap: wrap; +} + +.expertise-pill { + font-size: 0.65rem; + padding: 0.2rem 0.5rem; + border-radius: 1rem; + border: 1px solid var(--border-color); + background: none; color: var(--text-light); - font-size: 0.9rem; - - .footer-heading { + cursor: pointer; + font-family: inherit; + transition: all 0.15s; + + &:hover { border-color: var(--primary-color); color: var(--primary-color); } + + &.active { + background-color: var(--primary-color); + color: var(--bg-color); + border-color: var(--primary-color); font-weight: 600; - margin-bottom: 0.5rem; - color: var(--text-color); } - +} + +.expertise-count { + font-size: 0.6rem; + color: var(--text-muted); + margin-left: auto; +} + +// ============================================================================ +// Breadcrumbs +// ============================================================================ +.docs-breadcrumbs { + font-size: 0.8rem; + color: var(--breadcrumb-color); + margin-bottom: 1.25rem; + padding-bottom: 0.5rem; + border-bottom: 1px solid var(--border-color); + + a { + color: var(--breadcrumb-color); + text-decoration: none; + &:hover { color: var(--primary-color); text-decoration: underline; } + } + + .separator { + margin: 0 0.35rem; + color: var(--text-muted); + } + + .current { color: var(--text-color); font-weight: 500; } +} + +// ============================================================================ +// Find Your Path cards +// ============================================================================ +.path-cards { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 1rem; + margin: 1.5rem 0 2rem; +} + +.path-card { + background-color: var(--card-bg); + border: 1px solid var(--card-border); + border-radius: 0.5rem; + padding: 1.25rem; + transition: border-color 0.2s, box-shadow 0.2s; + + &:hover { + border-color: var(--primary-color); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + } + + h3 { + font-size: 1rem; + font-weight: 700; + margin: 0 0 0.5rem 0; + color: var(--primary-color) !important; + border: none !important; + padding: 0 !important; + } + + p { + font-size: 0.85rem; + color: var(--text-light) !important; + margin-bottom: 0.75rem; + } + + ul { + list-style: none; + padding-left: 0; + margin: 0; + li { + margin-bottom: 0.3rem; + font-size: 0.85rem; + a { font-weight: 500; } + } + } +} + +// ============================================================================ +// Footer +// ============================================================================ +.site-footer { + border-top: 1px solid var(--border-color); + background-color: var(--bg-light); + padding: 1.5rem 0; + margin-top: 0; + text-align: center; + color: var(--text-light); + font-size: 0.85rem; + transition: background-color 0.2s; + .footer-col-wrapper { display: flex; justify-content: center; flex-wrap: wrap; gap: 2rem; } - + a { color: var(--link-color); - - &:hover { - color: var(--link-hover); - } + text-decoration: none; + &:hover { color: var(--link-hover); text-decoration: underline; } + } + + .footer-links { + display: flex; + justify-content: center; + gap: 1.5rem; + flex-wrap: wrap; + margin-top: 0.75rem; + } + + .footer-summary, + .footer-tagline { + margin: 0; + } + + .footer-tagline { + margin-top: 0.2rem; + } + + .footer-trademark { + font-size: 0.72rem; + color: var(--text-muted); + margin-top: 0.75rem; + max-width: 700px; + margin-left: auto; + margin-right: auto; + line-height: 1.5; + } + + .footer-separator { + border: none; + border-top: 1px solid var(--border-color); + margin: 1rem auto; + max-width: 400px; } } -// Responsive design +// ============================================================================ +// Responsive +// ============================================================================ @media screen and (max-width: 768px) { - .docs-layout { - padding: 1.5rem 1rem; + .wrapper.docs-layout { flex-direction: column; } .docs-sidebar { position: static; + height: auto; max-height: none; border-right: none; border-bottom: 1px solid var(--border-color); margin-bottom: 1rem; + flex: none; + min-width: 0; } - .site-header { - .site-title { - font-size: 1.25rem; - } - - .site-nav { - .page-link { - margin: 0 0.25rem; - font-size: 0.9rem; - } - } + .docs-content { + max-width: 100%; + padding: 1rem; } - - .page-content { - h1 { - font-size: 2rem; - } - - h2 { - font-size: 1.75rem; - } - - h3 { - font-size: 1.25rem; - } + + .path-cards { grid-template-columns: 1fr; } + + .site-header { + .site-title { font-size: 1.15rem; } + .site-nav .page-link { margin: 0 0.25rem; font-size: 0.85rem; } } - - .site-footer { - .footer-col-wrapper { - flex-direction: column; - gap: 1rem; - } + + .docs-content { + h1 { font-size: 1.75rem; } + h2 { font-size: 1.5rem; } + h3 { font-size: 1.15rem; } } + + .site-footer .footer-col-wrapper { flex-direction: column; gap: 1rem; } } -// Mermaid diagram styling +// ============================================================================ +// Mermaid diagrams +// ============================================================================ .mermaid { background-color: var(--bg-light) !important; padding: 1.5rem; @@ -523,56 +931,42 @@ body { border: 1px solid var(--border-color); margin: 1.5rem 0; overflow-x: auto; - - svg { - background-color: transparent !important; - } - - // Ensure text is visible - text { - fill: var(--text-color) !important; - } - - // Node styling - .node rect, - .node circle, - .node ellipse, - .node polygon { + transition: background-color 0.2s; + + svg { background-color: transparent !important; } + text { fill: var(--text-color) !important; } + + .node rect, .node circle, .node ellipse, .node polygon { fill: var(--bg-alt) !important; stroke: var(--primary-color) !important; } - - // Edge/arrow styling - .edgePath path, - .flowchart-link { - stroke: var(--primary-color) !important; - } - - .arrowheadPath { - fill: var(--primary-color) !important; - } - - // Label styling + + .edgePath path, .flowchart-link { stroke: var(--primary-color) !important; } + .arrowheadPath { fill: var(--primary-color) !important; } + .edgeLabel { background-color: var(--bg-light) !important; color: var(--text-color) !important; } - - .edgeLabel text { - fill: var(--text-color) !important; - } + .edgeLabel text { fill: var(--text-color) !important; } } -// Print styles +// ============================================================================ +// Print +// ============================================================================ @media print { - .site-header, - .site-footer { - display: none; - } - - .page-content { - max-width: 100%; - padding: 0; - } + .site-header, .site-footer, .docs-sidebar { display: none; } + .page-content { max-width: 100%; padding: 0; } + .docs-layout { display: block; } } +// ============================================================================ +// Sidebar filtering (expertise) +// ============================================================================ +.docs-nav li[data-expertise].hidden-by-filter { + display: none; +} + +.docs-nav-bundle.hidden-by-filter { + display: none; +} diff --git a/docs/core-cli/debug-logging.md b/docs/core-cli/debug-logging.md index 632532fd..adfcc9c4 100644 --- a/docs/core-cli/debug-logging.md +++ b/docs/core-cli/debug-logging.md @@ -5,6 +5,9 @@ permalink: /core-cli/debug-logging/ redirect_from: - /debug-logging/ - /reference/debug-logging/ +keywords: [debug, logging, diagnostics, troubleshooting] +audience: [team, enterprise] +expertise_level: [advanced] --- diff --git a/docs/core-cli/init.md b/docs/core-cli/init.md index afe0480f..b87c67b7 100644 --- a/docs/core-cli/init.md +++ b/docs/core-cli/init.md @@ -3,6 +3,9 @@ layout: default title: specfact init permalink: /core-cli/init/ description: Reference for the specfact init command - bootstrap SpecFact in a repository with profiles, IDE setup, and dependency installation. +keywords: [init, bootstrap, ide, profiles] +audience: [solo, team, enterprise] +expertise_level: [beginner, intermediate] --- # specfact init diff --git a/docs/core-cli/modes.md b/docs/core-cli/modes.md index f2e601fe..77da5257 100644 --- a/docs/core-cli/modes.md +++ b/docs/core-cli/modes.md @@ -5,6 +5,9 @@ permalink: /core-cli/modes/ redirect_from: - /modes/ - /reference/modes/ +keywords: [modes, copilot, cicd, runtime] +audience: [team, enterprise] +expertise_level: [intermediate, advanced] --- # Operational Modes diff --git a/docs/core-cli/module.md b/docs/core-cli/module.md index 289a7ef1..8219dca5 100644 --- a/docs/core-cli/module.md +++ b/docs/core-cli/module.md @@ -3,6 +3,9 @@ layout: default title: specfact module permalink: /core-cli/module/ description: Reference for the specfact module command group - install, manage, search, and configure marketplace modules. +keywords: [module, install, registry, marketplace] +audience: [solo, team, enterprise] +expertise_level: [beginner, intermediate] --- # specfact module diff --git a/docs/core-cli/upgrade.md b/docs/core-cli/upgrade.md index a2e93f48..0545b63c 100644 --- a/docs/core-cli/upgrade.md +++ b/docs/core-cli/upgrade.md @@ -3,6 +3,9 @@ layout: default title: specfact upgrade permalink: /core-cli/upgrade/ description: Reference for the specfact upgrade command - check for and install SpecFact CLI updates. +keywords: [upgrade, updates, cli-version] +audience: [solo, team, enterprise] +expertise_level: [beginner, intermediate] --- # specfact upgrade @@ -45,4 +48,4 @@ specfact upgrade -y ## Related - [Migration Guide](/migration/migration-guide/) - version migration guidance -- [Migration 0.16 to 0.19](/migration/migration-0.16-to-0.19/) - specific version migration steps +- [Command Reference](/reference/commands/) - current grouped command surface diff --git a/docs/getting-started/README.md b/docs/getting-started/README.md index 4a7a7581..1b272e1c 100644 --- a/docs/getting-started/README.md +++ b/docs/getting-started/README.md @@ -6,6 +6,10 @@ permalink: /getting-started/ # Getting Started with SpecFact CLI +## Start Here + +- **[Where to Start](where-to-start.md)** - New-user overview: what SpecFact is for, what core owns, and what to do next + ## Installation - **[Installation Guide](installation.md)** - All installation options (uvx, pip, Docker, GitHub Actions) diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md index d89123e9..72ce4be2 100644 --- a/docs/getting-started/installation.md +++ b/docs/getting-started/installation.md @@ -2,6 +2,9 @@ layout: default title: Getting Started with SpecFact CLI permalink: /getting-started/installation/ +keywords: [install, setup, bootstrap, cli] +audience: [solo, team] +expertise_level: [beginner] --- # Getting Started with SpecFact CLI @@ -22,11 +25,11 @@ uvx specfact-cli@latest --help **Best for**: Quick testing, CI/CD, one-off commands -**Limitations**: CLI-only mode uses AST-based analysis which may show 0 features for simple test cases. For better results, use interactive AI Assistant mode (Option 2). +**Limitations**: CLI-only mode uses deterministic local analysis and may show limited results for very small test cases. If you want IDE slash-command workflows with your own AI copilot, use the installed CLI setup in Option 2. -### Option 2: pip (Interactive AI Assistant Mode) +### Option 2: pip (Installed CLI + IDE Prompt Mode) -**Required for**: IDE integration, slash commands, enhanced feature detection +**Required for**: local `specfact` command availability, IDE integration, and slash-command workflows ```bash # System-wide @@ -79,7 +82,7 @@ specfact init --install-deps specfact init ide --ide cursor --install-deps ``` -**Note**: Interactive mode requires Python 3.11+ and automatically uses your IDE workspace (no `--repo .` needed in slash commands). +**Important**: SpecFact CLI does **not** ship with built-in AI. `specfact init ide` installs prompt templates for supported IDEs so your chosen AI copilot can call SpecFact commands in a guided workflow. ### Option 3: Container @@ -158,33 +161,33 @@ jobs: ### Operational Modes -SpecFact CLI supports two operational modes: +SpecFact CLI supports two practical ways of working: -- **CLI-only Mode** (uvx): Fast, AST-based analysis for automation +- **CLI-only Mode** (uvx): Fast, deterministic CLI usage for automation - Works immediately with `uvx specfact-cli@latest` - No installation required - - May show 0 features for simple test cases (AST limitations) + - Uses local CLI analysis only - Best for: CI/CD, quick testing, one-off commands -- **Interactive AI Assistant Mode** (pip + `specfact init --profile ...`): Enhanced semantic understanding +- **Installed CLI + IDE Prompt Mode** (pip + `specfact init --profile ...` + optional `specfact init ide`) - Requires `pip install specfact-cli` and first-run bundle selection (`--profile` or `--install`) - - Better feature detection and semantic understanding - - IDE integration with slash commands - - Automatically uses IDE workspace (no `--repo .` needed) - - Best for: Development, legacy code analysis, complex projects + - Gives you a stable local `specfact` command plus mounted workflow groups + - Adds IDE prompt templates and slash commands when you run `specfact init ide` + - Lets your chosen AI copilot orchestrate SpecFact commands; the CLI itself remains deterministic + - Best for: development teams, brownfield analysis, guided IDE workflows **Mode Selection**: ```bash # CLI-only mode (uvx - no installation) -uvx specfact-cli@latest import from-code my-project --repo . +uvx specfact-cli@latest --help -# Interactive mode (pip + specfact init - recommended) +# Installed CLI + IDE prompt mode # After: pip install specfact-cli && specfact init # Then use slash commands in IDE: /specfact.01-import legacy-api --repo . ``` -**Note**: Mode is auto-detected based on whether `specfact` command is available and IDE integration is set up. +**Note**: Slash commands live in your IDE, not in the CLI runtime. They are prompt templates that guide your AI copilot to call SpecFact commands in the right order. ### Installed Command Topology @@ -246,7 +249,7 @@ This will guide you through creating: - First features and stories - Protocol state machine -**With IDE Integration (Interactive AI Assistant Mode):** +**With IDE Integration (Prompt Templates + Your AI Copilot):** ```bash # Step 1: Install SpecFact CLI @@ -325,7 +328,7 @@ specfact init # Step 4: Use slash command in IDE chat /specfact.01-import legacy-api -# Or let the AI assistant prompt you for bundle name and other options +# Or let your IDE copilot walk through the prompt-driven flow ``` **Important for IDE Integration**: @@ -333,9 +336,9 @@ specfact init - Interactive mode automatically uses your IDE workspace (no `--repo .` needed in interactive mode) - Slash commands use numbered format: `/specfact.01-import`, `/specfact.02-plan`, etc. (numbered for workflow ordering) - Commands follow natural progression: 01-import → 02-plan → 03-review → 04-sdd → 05-enforce → 06-sync -- The AI assistant will prompt you for bundle names and confidence thresholds if not provided -- Better feature detection than CLI-only mode (semantic understanding vs AST-only) -- **Do NOT use `--mode copilot` with IDE slash commands** - IDE integration automatically provides enhanced prompts +- Your IDE copilot can guide the slash-command flow if the prompt supports follow-up questions +- The CLI still performs deterministic command execution and validation +- **Do NOT use `--mode copilot` as a synonym for built-in AI** - IDE integration is prompt-driven orchestration around the CLI **CLI-Only Mode (Alternative - for CI/CD or when IDE integration is not available):** @@ -356,7 +359,7 @@ specfact --mode copilot import from-code my-project \ cat analysis.md ``` -**Note**: `--mode copilot` is for CLI usage only. When using IDE integration, use slash commands (e.g., `/specfact.01-import`) instead - IDE integration automatically provides enhanced prompts without needing the `--mode copilot` flag. +**Note**: When using IDE integration, use slash commands (for example `/specfact.01-import`) instead of assuming the CLI itself becomes AI-powered. The IDE prompt layer is what connects your copilot to SpecFact. See [IDE Integration Guide](../guides/ide-integration.md) for detailed setup instructions. diff --git a/docs/getting-started/quickstart.md b/docs/getting-started/quickstart.md index e247f9f8..21185bc2 100644 --- a/docs/getting-started/quickstart.md +++ b/docs/getting-started/quickstart.md @@ -5,6 +5,9 @@ permalink: /getting-started/quickstart/ redirect_from: - /getting-started/first-steps/ description: Get SpecFact CLI running in under 5 minutes - install, bootstrap, and analyze your first codebase. +keywords: [quickstart, first-run, bootstrap, analysis] +audience: [solo, team] +expertise_level: [beginner] --- # 5-Minute Quickstart diff --git a/docs/getting-started/where-to-start.md b/docs/getting-started/where-to-start.md new file mode 100644 index 00000000..07b0a499 --- /dev/null +++ b/docs/getting-started/where-to-start.md @@ -0,0 +1,162 @@ +--- +layout: default +title: Where to Start with SpecFact CLI +permalink: /getting-started/where-to-start/ +description: New-user overview for what SpecFact CLI is for, what the core CLI does, and which next step to take after installation. +keywords: [getting started, where to start, onboarding, core cli, what is specfact for] +audience: [solo, team, enterprise] +expertise_level: [beginner] +--- + +# Where to Start with SpecFact CLI + +You installed the CLI. The next question is usually not "what command exists?" but "what should I actually use this for?" + +This page is the short answer. + +## What SpecFact is for + +SpecFact helps teams turn real engineering work into a structured, traceable workflow: + +- bootstrap a repository with a consistent CLI and IDE setup +- install only the workflow modules you actually need +- reverse-engineer an existing codebase into project structure and features +- connect planning, specs, validation, and governance through mounted command groups +- keep the core CLI lean while moving module-specific depth into the modules docs portal + +SpecFact CLI does **not** include built-in AI. If you use Cursor, Copilot, Claude Code, or another supported IDE, SpecFact provides prompt templates and slash commands so your chosen copilot can invoke the deterministic CLI in a guided workflow. + +If you are starting from an existing repository, SpecFact is primarily a **brownfield-first** tool. It helps you understand what you already have before you start inventing new process around it. + +## Core CLI vs Modules + +The easiest mental model is: + +| If you want to... | Start here | +| --- | --- | +| Install, bootstrap, update, or manage the runtime | **Core CLI docs** | +| Decide which workflow bundles you need | **Core first**, then hand off to **modules docs** | +| Run backlog, project, code, spec, or govern workflows in depth | **Modules docs** | + +The core CLI owns the platform entry points: + +- `specfact init` +- `specfact module` +- `specfact upgrade` + +Installed modules then mount the workflow groups: + +- `specfact project ...` +- `specfact backlog ...` +- `specfact code ...` +- `specfact spec ...` +- `specfact govern ...` + +## Quick decision guide + +**"I just installed SpecFact and I need to..."** + +| I need to... | Go here next | +| --- | --- | +| Understand the smallest useful first run | [5-Minute Quickstart](/getting-started/quickstart/) | +| Bootstrap this repo correctly | [specfact init](/core-cli/init/) | +| Decide which workflow bundles to install | [Installing Modules](/module-system/installing-modules/) and [modules docs overview](https://modules.specfact.io/) | +| Analyze an existing codebase | [5-Minute Quickstart](/getting-started/quickstart/) | +| Set up IDE prompts to use SpecFact with your AI copilot | [AI IDE Workflow](/guides/ai-ide-workflow/) | +| See the full command surface after install | [Command Reference](/reference/commands/) | + +## Recommended first paths + +### Path 1: "I have a repo and want SpecFact to tell me what is there" + +This is the most common entry point. + +1. Install the CLI +2. Run `specfact init --profile solo-developer` +3. Run `specfact code import --repo .` +4. Check `specfact project health-check` + +Start here: + +- [Installation](/getting-started/installation/) +- [5-Minute Quickstart](/getting-started/quickstart/) + +### Path 2: "I want to understand which parts of SpecFact I actually need" + +Start with the core runtime, then decide which mounted workflow groups belong in your setup. + +1. Bootstrap the CLI with `specfact init` +2. Review module installation and grouped command families +3. Continue into the modules portal for bundle-specific guidance + +Start here: + +- [specfact init](/core-cli/init/) +- [Installing Modules](/module-system/installing-modules/) +- [Modules Docs Home](https://modules.specfact.io/) + +### Path 3: "I want a shared team workflow, not just a local CLI" + +Once the CLI is installed, the next step is usually IDE setup, grouped commands, and repeatable review or validation flows. + +Start here: + +- [AI IDE Workflow](/guides/ai-ide-workflow/) +- [Command Reference](/reference/commands/) +- [Migration Guide](/migration/migration-guide/) + +## What happens after install + +```mermaid +graph TD + A["Install SpecFact CLI"] --> B["Bootstrap with specfact init"] + B --> C{"What do you need next?"} + C --> D["Analyze an existing repo
specfact code import"] + C --> E["Install workflow bundles
specfact module / specfact init --install"] + C --> F["Set up IDE prompts
specfact init ide"] + E --> G["Use grouped commands
project / backlog / code / spec / govern"] + D --> G + F --> G + G --> H["Go deeper in modules.specfact.io
for bundle-specific workflows"] +``` + +## Good first commands + +```bash +# Install or update bootstrap state +specfact init --profile solo-developer + +# See which modules are available +specfact module search + +# See what is installed +specfact module list + +# Analyze the current repository +specfact code import my-project --repo . + +# Check resulting state +specfact project health-check +``` + +## If you only remember one thing + +Start with **core docs** when you are asking: + +- how do I install this? +- how do I bootstrap the runtime? +- what command groups appear after module install? +- how do I move from installation to first useful result? + +Switch to **modules docs** when you are asking: + +- which workflow bundle solves my problem? +- how does backlog/project/spec/govern work in detail? +- what are the full runbooks, examples, and module-specific guides? + +## Next pages + +- [5-Minute Quickstart](/getting-started/quickstart/) +- [specfact init](/core-cli/init/) +- [Installing Modules](/module-system/installing-modules/) +- [Modules Docs Home](https://modules.specfact.io/) diff --git a/docs/guides/ai-ide-workflow.md b/docs/guides/ai-ide-workflow.md index a46023ba..71508558 100644 --- a/docs/guides/ai-ide-workflow.md +++ b/docs/guides/ai-ide-workflow.md @@ -14,7 +14,9 @@ redirect_from: ## Overview -SpecFact CLI integrates with AI-assisted IDEs through slash commands that enable a seamless workflow: **SpecFact finds gaps → AI IDE fixes them → SpecFact validates**. This guide explains the complete workflow from setup to validation. +SpecFact CLI integrates with AI-assisted IDEs through slash commands that enable a seamless workflow: **SpecFact finds gaps -> AI IDE helps apply changes -> SpecFact validates**. This guide explains the complete workflow from setup to validation. + +SpecFact CLI itself does **not** contain built-in AI. The AI lives in your IDE of choice. SpecFact provides prompt templates and deterministic commands so that copilot-driven work stays grounded in the CLI workflow. **Key Benefits**: diff --git a/docs/guides/ide-integration.md b/docs/guides/ide-integration.md index 091c84a8..87514a95 100644 --- a/docs/guides/ide-integration.md +++ b/docs/guides/ide-integration.md @@ -11,13 +11,15 @@ permalink: /guides/ide-integration/ **CLI-First Approach**: SpecFact works offline, requires no account, and integrates with your existing workflow. Works with VS Code, Cursor, GitHub Actions, pre-commit hooks, or any IDE. No platform to learn, no vendor lock-in. +**Important**: SpecFact CLI does **not** provide built-in AI. IDE integration means SpecFact installs prompt templates and slash commands that your chosen IDE copilot can use to run SpecFact as part of a guided command chain. + **Terminal Output**: The CLI automatically detects embedded terminals (Cursor, VS Code) and CI/CD environments, adapts formatting automatically, and falls back to ASCII-safe rendering when the active terminal encoding cannot display UTF-8 symbols. See [Troubleshooting](troubleshooting.md#terminal-output-issues) for details. --- ## Overview -SpecFact CLI supports IDE integration through **prompt templates** that work with various AI-assisted IDEs. These templates are copied to IDE-specific locations and automatically registered by the IDE as slash commands. +SpecFact CLI supports IDE integration through **prompt templates** that work with various AI-assisted IDEs. These templates are copied to IDE-specific locations and automatically registered by the IDE as slash commands. The AI stays in your IDE; SpecFact remains the deterministic CLI the prompts call. **See real examples**: [Integration Showcases](../examples/integration-showcases/) - 5 complete examples showing bugs fixed via IDE integrations @@ -95,7 +97,7 @@ Once initialized, you can use slash commands directly in your IDE's AI chat: /specfact.validate --repo . ``` -The IDE automatically recognizes these commands and provides enhanced prompts. +The IDE automatically recognizes these commands and exposes the corresponding prompt templates. Those prompts then guide your AI copilot to call SpecFact commands. --- diff --git a/docs/index.md b/docs/index.md index 5e0289df..f184bfa3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,6 +3,9 @@ layout: default title: SpecFact CLI Documentation description: Core CLI docs for runtime lifecycle, command topology, and official module integration. permalink: / +keywords: [specfact, core-cli, runtime, module-system, architecture] +audience: [solo, team, enterprise] +expertise_level: [beginner, intermediate, advanced] --- # SpecFact CLI Documentation @@ -11,8 +14,55 @@ SpecFact CLI is a contract-first Python CLI that keeps backlogs, specs, tests, a For module-specific workflows (backlog, governance, adapters), see [modules.specfact.io](https://modules.specfact.io/). +Use the shared portal navigation to move between **Docs Home**, **Core CLI**, and **Modules** without changing interaction patterns. + --- +## Find Your Path + +
+
+

New User

+

Start with the core install and bootstrap path before adding workflow bundles.

+ +
+
+

Team Lead

+

Set up shared runtime conventions, IDE flows, and team-level operating guidance.

+ +
+
+

Platform Owner

+

Use the architecture and registry references to operate SpecFact as shared platform infrastructure.

+ +
+
+

Module Operator

+

Manage installed bundles from core docs, then hand off to modules docs for bundle-owned workflows.

+ +
+
+ ## Core Platform The `specfact-cli` package provides the stable platform surface: @@ -44,6 +94,13 @@ Installed modules mount workflows under `project`, `backlog`, `code`, `spec`, an - **[Implementation Status](/architecture/implementation-status/)** - Implemented vs planned - **[ADRs](/architecture/adr/)** - Architecture decision records +## Workflows + +- **[AI IDE Workflow](/guides/ai-ide-workflow/)** - Bootstrap editor integrations around the CLI +- **[Agile & Scrum Workflows](/guides/agile-scrum-workflows/)** - Team routines anchored in the core runtime +- **[Command Chains](/guides/command-chains/)** - Compose core and module commands safely +- **[Contract Testing Workflow](/guides/contract-testing-workflow/)** - Core validation and contract-first delivery + ## Reference - **[Command Reference](/reference/commands/)** - Full command surface @@ -55,7 +112,6 @@ Installed modules mount workflows under `project`, `backlog`, `code`, `spec`, an ## Migration - **[Migration Guide](/migration/migration-guide/)** - Version upgrade guidance -- **[0.16 to 0.19 Migration](/migration/migration-0.16-to-0.19/)** - Specific version steps - **[CLI Reorganization](/migration/migration-cli-reorganization/)** - Command surface changes - **[OpenSpec Migration](/migration/openspec-migration/)** - OPSX workflow migration @@ -64,5 +120,5 @@ Installed modules mount workflows under `project`, `backlog`, `code`, `spec`, an For in-depth module workflows, visit the canonical modules site: - **[Modules Docs Home](https://modules.specfact.io/)** - Backlog, project, spec, govern -- **[Module Development](https://modules.specfact.io/guides/module-development/)** - Build your own modules -- **[Publishing Modules](https://modules.specfact.io/guides/publishing-modules/)** - Publish to marketplace +- **[Module Development](https://modules.specfact.io/authoring/module-development/)** - Build your own modules +- **[Publishing Modules](https://modules.specfact.io/authoring/publishing-modules/)** - Publish to marketplace diff --git a/docs/migration/migration-guide.md b/docs/migration/migration-guide.md index 9bb3f155..ac10ac7f 100644 --- a/docs/migration/migration-guide.md +++ b/docs/migration/migration-guide.md @@ -5,238 +5,181 @@ permalink: /migration/migration-guide/ redirect_from: - /migration-guide/ - /guides/migration-guide/ +description: Current migration guidance for upgrading SpecFact CLI, moving to grouped commands, and importing from external workflows. +keywords: [migration, upgrade path, grouped commands, openspec, speckit] +audience: [team, enterprise] +expertise_level: [intermediate] --- # Migration Guide -> **Decision tree and workflow for migrating between SpecFact CLI versions and from other tools** +Use this guide when you are moving an existing repo or team workflow onto the current SpecFact CLI model. ---- - -## Overview - -This guide helps you decide when and how to migrate: - -- **Between SpecFact CLI versions** - When upgrading to a new version -- **From other tools** - When migrating from Spec-Kit, OpenSpec, or other SDD tools -- **Between project structures** - When restructuring your project bundles - ---- - -## Migration Decision Tree - -``` -Start: What do you need to migrate? - -├─ Upgrading SpecFact CLI version? -│ ├─ Minor version (0.19 → 0.20)? -│ │ └─ → Usually automatic, check [Version-Specific Migration Guides](#version-specific-migrations) -│ ├─ Major version (0.x → 1.0)? -│ │ └─ → Check breaking changes, use [Version-Specific Migration Guides](#version-specific-migrations) -│ └─ CLI reorganization (pre-0.16 → 0.16+)? -│ └─ → See [CLI Reorganization Migration](migration-cli-reorganization.md) -│ -├─ Migrating from Spec-Kit? -│ └─ → See [Spec-Kit Journey Guide](../guides/speckit-journey.md) -│ -├─ Migrating from OpenSpec? -│ └─ → See [OpenSpec Journey Guide](../guides/openspec-journey.md) -│ -└─ Restructuring project bundles? - └─ → See [Project Bundle Management](../reference/commands.md#project---project-bundle-management) -``` - ---- - -## Version-Specific Migrations - -### Migration from 0.16 to 0.19+ - -**Breaking Changes**: CLI command reorganization - -**Migration Steps**: - -1. Review [CLI Reorganization Migration Guide](migration-cli-reorganization.md) -2. Update scripts and CI/CD pipelines -3. Test commands in development environment -4. Update documentation references +This page is intentionally focused on the active `0.4x.y` line. It does not try to preserve every historical transition. If you are running a very old install, treat that as a staged migration: first get onto the modern grouped command surface, then validate your repo and bundle state. -**Related**: [Migration 0.16 to 0.19](migration-0.16-to-0.19.md) +## What this guide covers ---- - -### Migration from Pre-0.16 to 0.16+ +- Upgrading the core CLI to the current release line +- Moving from removed flat commands to grouped commands +- Importing existing work from external toolchains such as Spec-Kit or OpenSpec +- Revalidating bundles, sync flows, and docs links after the migration -**Breaking Changes**: Major CLI reorganization +## Start here -**Migration Steps**: +Choose the path that matches your situation: -1. Review [CLI Reorganization Migration Guide](migration-cli-reorganization.md) -2. Update all command references -3. Migrate plan bundles to new schema -4. Update CI/CD configurations +1. **You already use modern grouped commands** such as `specfact project`, `specfact backlog`, `specfact code`, `specfact spec`, and `specfact govern`. + Upgrade the CLI, check installed modules, and run validation. +2. **Your scripts still use older flat commands** such as `specfact plan`, `specfact import`, `specfact sync`, `specfact validate`, or `specfact enforce`. + Update those scripts to the grouped command surface before rolling the change out. +3. **You are moving from another structured workflow tool** such as Spec-Kit or OpenSpec. + Import first, review the generated project state, then enable ongoing bridge sync only after the imported state looks correct. -**Related**: [CLI Reorganization Migration](migration-cli-reorganization.md) +## 1. Upgrade the active CLI ---- +Check the current version first: -## Tool Migration Workflows +```bash +specfact --version +specfact upgrade --check-only +``` -### Migrating from Spec-Kit +If an update is available: -**Workflow**: Use External Tool Integration Chain +```bash +specfact upgrade +``` -1. Import from Spec-Kit via bridge adapter -2. Review imported plan -3. Set up bidirectional sync (optional) -4. Enforce SDD compliance +After the upgrade: -**Detailed Guide**: [Spec-Kit Journey Guide](../guides/speckit-journey.md) +```bash +specfact module list +specfact module search +``` -**Command Chain**: [External Tool Integration Chain](../guides/command-chains.md#3-external-tool-integration-chain) +Use those commands to confirm the CLI still sees the installed workflow modules and registries you expect. ---- +## 2. Move to the grouped command surface -### Migrating from OpenSpec +The current CLI is lean core plus mounted command groups. Core-owned commands stay at the root: -**Workflow**: Use External Tool Integration Chain +- `specfact init` +- `specfact module` +- `specfact upgrade` -1. Import from OpenSpec via bridge adapter -2. Review imported change proposals -3. Set up DevOps sync (optional) -4. Enforce SDD compliance +Workflow capabilities are mounted under grouped families: -**Detailed Guide**: [OpenSpec Journey Guide](../guides/openspec-journey.md) +- `specfact project ...` +- `specfact backlog ...` +- `specfact code ...` +- `specfact spec ...` +- `specfact govern ...` -**Command Chain**: [External Tool Integration Chain](../guides/command-chains.md#3-external-tool-integration-chain) +If your automation still uses older flat command paths, update them now. ---- +### Common replacements -## Project Structure Migrations +| Old pattern | Current replacement | +| --- | --- | +| `specfact plan ...` | `specfact project ...` | +| `specfact import ...` | `specfact code import ...` or `specfact project import ...` | +| `specfact sync ...` | `specfact project sync ...` | +| `specfact analyze ...` | `specfact code analyze ...` | +| `specfact drift ...` | `specfact code drift ...` | +| `specfact validate ...` | `specfact code validate ...` or `specfact spec validate ...` | +| `specfact repro ...` | `specfact code repro ...` | +| `specfact enforce ...` | `specfact govern enforce ...` | +| `specfact patch ...` | `specfact govern patch ...` | -### Migrating Between Project Bundles +Use the canonical mapping in the [Command Reference](../reference/commands.md) when updating shell scripts, CI jobs, IDE prompts, or internal docs. -**When to use**: Restructuring projects, splitting/merging bundles +## 3. Rebaseline the project after the upgrade -**Commands**: +Once the command surface is current, refresh the repo state you depend on: ```bash -# Export from old bundle -specfact project export --bundle old-bundle --persona - -# Create new bundle -specfact code import new-bundle --repo . - -# Import to new bundle (manual editing may be required) -specfact project import --bundle new-bundle --persona --source exported.md +specfact project health-check +specfact project regenerate ``` -**Related**: [Project Bundle Management](../reference/commands.md#project---project-bundle-management) - ---- - -## Plan Schema Migrations - -### Upgrading Plan Bundles - -**When to use**: When plan bundles are on an older schema version - -**Command**: +If you operate specific bundles directly: ```bash -# Regenerate all bundles -specfact project regenerate - -# Regenerate specific bundle -specfact project regenerate --bundle +specfact project snapshot --bundle +specfact project version --bundle ``` -**Benefits**: +This is the point where you should catch stale bundle metadata, missing generated assets, or drift between the project state and the current CLI expectations. -- Improved performance -- New features and metadata -- Better compatibility +## 4. Migrate from external toolchains -**Related**: [Project Commands](../reference/commands.md#project---project-bundle-management) - ---- +### From Spec-Kit -## Migration Workflow Examples - -### Example 1: Upgrading SpecFact CLI +If your repo still starts from Spec-Kit assets, import first and keep sync optional until you trust the imported state: ```bash -# 1. Check current version -specfact --version - -# 2. Review migration guide for target version -# See: guides/migration-*.md - -# 3. Upgrade SpecFact CLI -pip install --upgrade specfact-cli +specfact code import from-bridge --adapter speckit --repo . --dry-run +specfact code import from-bridge --adapter speckit --repo . --write +specfact project devops-flow --stage develop --bundle +``` -# 4. Regenerate plan bundles -specfact project regenerate +Only enable ongoing sync after review: -# 5. Test commands -specfact project health-check +```bash +specfact project sync bridge --adapter speckit --bundle --repo . --bidirectional ``` ---- +For the fuller walkthrough, see [Spec-Kit Journey Guide](../guides/speckit-journey.md). -### Example 2: Migrating from Spec-Kit +### From OpenSpec -```bash -# 1. Import from Spec-Kit -specfact code import from-bridge --repo . --adapter speckit --write +If you are moving existing OpenSpec project context into SpecFact-backed workflows: -# 2. Review imported plan +```bash +specfact project sync bridge --adapter openspec --mode read-only --bundle --repo . specfact project devops-flow --stage develop --bundle - -# 3. Set up bidirectional sync (optional) -specfact project sync bridge --adapter speckit --bundle --bidirectional --watch - -# 4. Enforce SDD compliance -specfact govern enforce sdd --bundle ``` -**Related**: [Spec-Kit Journey Guide](../guides/speckit-journey.md) - ---- - -## Troubleshooting Migrations +Keep the first pass read-only until the imported state is reviewed. Then enable the sync mode you actually want. -### Common Issues +For OpenSpec-specific context changes, see [OpenSpec OPSX Migration](openspec-migration.md). -**Issue**: Plan bundles fail to regenerate +## 5. Validate the migrated state -**Solution**: +After any migration, run the checks that prove the new setup is usable: ```bash -# Check bundle health +specfact module list specfact project health-check - -# Regenerate if needed -specfact project regenerate --bundle +specfact govern enforce sdd --bundle +specfact spec validate --bundle ``` -**Issue**: Imported plans have missing data +Pick the bundle that matters most first. Once one representative bundle passes, roll the same checks across the rest of the repo. -**Solution**: +## 6. Update team-facing surfaces -1. Review import logs -2. Use `project devops-flow --stage develop` to identify gaps -3. Use `project health-check` to check status -4. Re-import if needed +Do not stop at the CLI invocation itself. Migration is incomplete if these still point to the old world: -**Related**: [Troubleshooting Guide](../guides/troubleshooting.md) +- CI workflows +- local shell scripts +- AI IDE prompt packs +- onboarding docs +- internal runbooks ---- +The most common failure mode is that the repo has already migrated, but prompts and automation still tell people to use removed flat commands. + +## Historical note + +Older version-specific migrations such as the `0.16 -> 0.19` transition are historical only. They should not be used as the primary upgrade path for teams already operating on the `0.4x.y` line. + +If you discover a repo that still depends on those assumptions, first update its command surface to the grouped model, then follow this guide. -## See Also +## See also -- [Command Chains Reference](../guides/command-chains.md) - Complete workflows -- Common Tasks Index - Quick reference -- [Spec-Kit Journey Guide](../guides/speckit-journey.md) - Spec-Kit migration -- [OpenSpec Journey Guide](../guides/openspec-journey.md) - OpenSpec migration -- [Troubleshooting Guide](../guides/troubleshooting.md) - Common issues +- [specfact upgrade](../core-cli/upgrade.md) +- [Command Reference](../reference/commands.md) +- [CLI Reorganization Migration](migration-cli-reorganization.md) +- [OpenSpec OPSX Migration](openspec-migration.md) +- [Spec-Kit Journey Guide](../guides/speckit-journey.md) +- [Troubleshooting Guide](../guides/troubleshooting.md) diff --git a/docs/module-system/bootstrap-checklist.md b/docs/module-system/bootstrap-checklist.md index bb33bc2d..28d2b057 100644 --- a/docs/module-system/bootstrap-checklist.md +++ b/docs/module-system/bootstrap-checklist.md @@ -5,6 +5,9 @@ permalink: /module-system/bootstrap-checklist/ redirect_from: - /getting-started/module-bootstrap-checklist/ description: Quick checklist to verify official workflow bundles are installed and discoverable in user/project scope. +keywords: [bootstrap, checklist, installed modules, discovery] +audience: [solo, team] +expertise_level: [beginner, intermediate] --- # Module Bootstrap Checklist diff --git a/docs/module-system/custom-registries.md b/docs/module-system/custom-registries.md index 57a7fca2..c05a0617 100644 --- a/docs/module-system/custom-registries.md +++ b/docs/module-system/custom-registries.md @@ -5,6 +5,9 @@ permalink: /module-system/custom-registries/ redirect_from: - /guides/custom-registries/ description: Add, list, and manage custom module registries with trust levels and priority. +keywords: [custom registries, private registry, trust levels] +audience: [team, enterprise] +expertise_level: [advanced] --- # Custom registries diff --git a/docs/module-system/installing-modules.md b/docs/module-system/installing-modules.md index b5e84cc3..96c31367 100644 --- a/docs/module-system/installing-modules.md +++ b/docs/module-system/installing-modules.md @@ -5,6 +5,9 @@ permalink: /module-system/installing-modules/ redirect_from: - /guides/installing-modules/ description: Install, list, show, enable, disable, uninstall, and upgrade SpecFact modules. +keywords: [install modules, module command, marketplace, registries] +audience: [solo, team, enterprise] +expertise_level: [beginner, intermediate] --- # Installing Modules diff --git a/docs/module-system/marketplace.md b/docs/module-system/marketplace.md index e349699a..1bb30d0d 100644 --- a/docs/module-system/marketplace.md +++ b/docs/module-system/marketplace.md @@ -6,6 +6,9 @@ permalink: /module-system/marketplace/ redirect_from: - /guides/marketplace/ description: Official SpecFact bundle IDs, trust tiers, and bundle dependency behavior. +keywords: [bundles, official modules, trust tiers] +audience: [solo, team, enterprise] +expertise_level: [intermediate] --- # Marketplace Bundles diff --git a/docs/module-system/module-marketplace.md b/docs/module-system/module-marketplace.md index 18ffae06..3ce148ff 100644 --- a/docs/module-system/module-marketplace.md +++ b/docs/module-system/module-marketplace.md @@ -5,6 +5,9 @@ permalink: /module-system/module-marketplace/ redirect_from: - /guides/module-marketplace/ description: Registry model, discovery priority, trust semantics, and security checks for SpecFact modules. +keywords: [marketplace, module discovery, trust, registry] +audience: [solo, team, enterprise] +expertise_level: [beginner, intermediate] --- # Module Marketplace diff --git a/docs/reference/authentication.md b/docs/reference/authentication.md index 774b862f..421c6b3e 100644 --- a/docs/reference/authentication.md +++ b/docs/reference/authentication.md @@ -2,6 +2,9 @@ layout: default title: Authentication permalink: /reference/authentication/ +keywords: [authentication, credentials, providers] +audience: [team, enterprise] +expertise_level: [intermediate, advanced] --- # Authentication diff --git a/docs/reference/bridge-registry.md b/docs/reference/bridge-registry.md index e7e48161..897ed33a 100644 --- a/docs/reference/bridge-registry.md +++ b/docs/reference/bridge-registry.md @@ -2,6 +2,9 @@ layout: default title: Bridge Registry permalink: /reference/bridge-registry/ +keywords: [bridge registry, adapters, integrations] +audience: [team, enterprise] +expertise_level: [advanced] --- # Bridge Registry @@ -50,4 +53,3 @@ Lifecycle protocol reporting now uses the effective runtime interface: The summary format is: `Protocol-compliant: / modules (Full=, Partial=, Legacy=)` - diff --git a/docs/reference/commands.md b/docs/reference/commands.md index 47462ac0..75cc4462 100644 --- a/docs/reference/commands.md +++ b/docs/reference/commands.md @@ -2,6 +2,9 @@ layout: default title: Command Reference permalink: /reference/commands/ +keywords: [command reference, cli surface, command groups] +audience: [solo, team, enterprise] +expertise_level: [intermediate, advanced] --- # Command Reference diff --git a/docs/reference/documentation-url-contract.md b/docs/reference/documentation-url-contract.md index 680476e6..b8053d3e 100644 --- a/docs/reference/documentation-url-contract.md +++ b/docs/reference/documentation-url-contract.md @@ -3,6 +3,9 @@ layout: default title: Documentation URL contract (core and modules) permalink: /reference/documentation-url-contract/ description: Rules for linking between docs.specfact.io and modules.specfact.io; canonical ownership of paths. +keywords: [docs contract, handoff, core vs modules] +audience: [team, enterprise] +expertise_level: [advanced] --- # Documentation URL contract (core and modules) @@ -15,7 +18,7 @@ The **authoritative** URL and ownership rules for **both** documentation sites a ## Quick rules for core contributors -1. **Do not assume** `https://modules.specfact.io/guides//` exists because core uses `/guides//`. Modules uses `/guides/...`, `/bundles/.../`, `/integrations/.../`, and root paths such as `/brownfield-engineer/` depending on the page—**always** verify the target file’s `permalink` in `specfact-cli-modules`. +1. **Do not assume** a modules guide lives at `/guides//` just because core uses `/guides//`. Modules uses `/guides/...`, `/bundles/.../`, `/integrations/.../`, and root paths such as `/brownfield-engineer/` depending on the page—**always** verify the target file’s `permalink` in `specfact-cli-modules`. 2. **Handoff pages** (see OpenSpec `docs-07-core-handoff-conversion`) must point to the **modules canonical URL** for each topic, with a short summary and prerequisites on core. 3. **Internal core links** must continue to resolve on `docs.specfact.io` per published `permalink` (docs review gate / parity tests). diff --git a/openspec/CHANGE_ORDER.md b/openspec/CHANGE_ORDER.md index 768c7f1d..43f32509 100644 --- a/openspec/CHANGE_ORDER.md +++ b/openspec/CHANGE_ORDER.md @@ -116,6 +116,7 @@ The 2026-03-22 clean-code plan adds one new cross-repo change pair and re-sequen | docs | 06 | docs-05-core-site-ia-restructure | [#438](https://github.com/nold-ai/specfact-cli/issues/438) | docs-04; Parent Feature: [#356](https://github.com/nold-ai/specfact-cli/issues/356) | | docs | 07 | docs-07-core-handoff-conversion | [#439](https://github.com/nold-ai/specfact-cli/issues/439) | docs-05-core-site-ia-restructure; modules-repo/docs-06-modules-site-ia-restructure | | docs | 08 | docs-12-docs-validation-ci | [#440](https://github.com/nold-ai/specfact-cli/issues/440) | docs-05-core-site-ia-restructure; docs-07-core-handoff-conversion; modules-repo/docs-06 through docs-10 | +| docs | 09 | docs-13-core-nav-search-theme-roles | [#458](https://github.com/nold-ai/specfact-cli/issues/458) | docs-05-core-site-ia-restructure; docs-07-core-handoff-conversion; docs-12-docs-validation-ci; modules-repo/docs-13-nav-search-theme-roles (design parity only, no content ownership coupling) | ### Docs refactoring plan addendum (2026-03-23) diff --git a/openspec/changes/docs-13-core-nav-search-theme-roles/CHANGE_VALIDATION.md b/openspec/changes/docs-13-core-nav-search-theme-roles/CHANGE_VALIDATION.md new file mode 100644 index 00000000..2b39e6d3 --- /dev/null +++ b/openspec/changes/docs-13-core-nav-search-theme-roles/CHANGE_VALIDATION.md @@ -0,0 +1,46 @@ +# Change Validation: docs-13-core-nav-search-theme-roles + +Date: 2026-03-28 + +## Scope Reviewed + +- `proposal.md` +- `tasks.md` +- `design.md` +- `specs/core-docs-data-driven-nav/spec.md` +- `specs/core-docs-client-search/spec.md` +- `specs/core-docs-expertise-paths/spec.md` +- `specs/core-docs-theme-toggle/spec.md` +- related dependency context: + - `openspec/CHANGE_ORDER.md` + - `openspec/config.yaml` + - prior docs changes `docs-05-core-site-ia-restructure`, `docs-07-core-handoff-conversion`, `docs-12-docs-validation-ci` + +## Validation Commands + +```bash +openspec validate docs-13-core-nav-search-theme-roles --strict +``` + +Result: + +```text +Change 'docs-13-core-nav-search-theme-roles' is valid +``` + +## Findings + +- No schema or artifact-format validation errors remain after converting the new capability specs to delta format. +- The change is correctly scoped as a core-docs UX follow-up to the earlier IA/handoff/validation sequence. +- The proposal preserves the core-vs-modules content ownership boundary while allowing visual and interaction parity with the modules-site UX direction. + +## Dependency Notes + +- `docs-05-core-site-ia-restructure` remains the structural prerequisite because the new navigation layer assumes the post-restructure core IA. +- `docs-07-core-handoff-conversion` remains a guardrail so improved landing/navigation UX does not reintroduce module-owned content into core docs. +- `docs-12-docs-validation-ci` remains the validation foundation for keeping the new navigation/search assets and metadata coherent. + +## Recommendation + +- Proceed with `docs-13-core-nav-search-theme-roles` as the core counterpart to the modules-site UX refinement work. +- Keep implementation focused on the core-docs shell and discoverability layer, not on changing content ownership or rebuilding module tutorials in core. diff --git a/openspec/changes/docs-13-core-nav-search-theme-roles/TDD_EVIDENCE.md b/openspec/changes/docs-13-core-nav-search-theme-roles/TDD_EVIDENCE.md new file mode 100644 index 00000000..e2629879 --- /dev/null +++ b/openspec/changes/docs-13-core-nav-search-theme-roles/TDD_EVIDENCE.md @@ -0,0 +1,105 @@ +# TDD Evidence + +## Implemented Scope + +- Added shared-portal docs shell parity for the core site: + - data-driven sidebar navigation in `docs/_data/nav.yml` + - shared includes for breadcrumbs, search, expertise filter, sidebar nav, and theme toggle + - Jekyll-generated search index and client-side search/filter/theme scripts + - refreshed landing page entry paths and enriched front matter on core pages +- Extended docs validation so `scripts/check-docs-commands.py` also verifies nav targets against published core routes. +- Added contract coverage for the shared portal shell in `tests/unit/test_core_docs_site_contract.py` and updated docs validation tests. + +## Verification Run + +### Passed + +1. Focused docs contract and parity tests + +```bash +PATH=/home/dom/git/nold-ai/specfact-cli/.venv/bin:$PATH \ +PYTHONPATH=/home/dom/git/nold-ai/specfact-cli-worktrees/feature/docs-13-core-nav-search-theme-roles/src \ +/home/dom/git/nold-ai/specfact-cli/.venv/bin/python -m pytest \ + tests/unit/test_core_docs_site_contract.py \ + tests/unit/docs/test_release_docs_parity.py \ + tests/unit/docs/test_docs_validation_scripts.py -q +``` + +Result: + +- `38 passed` + +2. Docs command validation + +```bash +PATH=/home/dom/git/nold-ai/specfact-cli/.venv/bin:$PATH \ +PYTHONPATH=/home/dom/git/nold-ai/specfact-cli-worktrees/feature/docs-13-core-nav-search-theme-roles/src \ +/home/dom/git/nold-ai/specfact-cli/.venv/bin/python scripts/check-docs-commands.py +``` + +Result: + +- `check-docs-commands: OK (110 unique command prefix(es) checked)` + +3. Cross-site handoff validation against live `modules.specfact.io` + +```bash +PATH=/home/dom/git/nold-ai/specfact-cli/.venv/bin:$PATH \ +PYTHONPATH=/home/dom/git/nold-ai/specfact-cli-worktrees/feature/docs-13-core-nav-search-theme-roles/src \ +/home/dom/git/nold-ai/specfact-cli/.venv/bin/python scripts/check-cross-site-links.py --warn-only +``` + +Result: + +- `check-cross-site-links: OK (24 unique modules.specfact.io URL(s) checked)` + +4. Jekyll build + +```bash +cd docs +bundle install +bundle exec jekyll build +``` + +Result: + +- Build completed successfully + +5. Formatting + +```bash +PATH=/home/dom/git/nold-ai/specfact-cli/.venv/bin:$PATH \ +/home/dom/git/nold-ai/specfact-cli/.venv/bin/ruff format . --check +``` + +Result: + +- Passed after formatting `tests/unit/test_core_docs_site_contract.py` + +6. Type check baseline + +```bash +PATH=/home/dom/git/nold-ai/specfact-cli/.venv/bin:$PATH \ +/home/dom/git/nold-ai/specfact-cli/.venv/bin/basedpyright \ + --pythonpath /home/dom/git/nold-ai/specfact-cli/.venv/bin/python +``` + +Result: + +- `0 errors, 6545 warnings, 0 notes` +- Warnings are existing repository baseline outside this change scope. + +7. OpenSpec validation + +```bash +openspec validate docs-13-core-nav-search-theme-roles --strict +``` + +Result: + +- `Change 'docs-13-core-nav-search-theme-roles' is valid` + +## Environment Notes + +- `bundle exec jekyll build` initially failed because the worktree did not have the required Jekyll gems installed. Running `bundle install` in `docs/` resolved that. +- The repo’s `scripts/yaml-tools.sh lint` could not be used from this environment because the available `yamllint` entrypoint points to a missing interpreter (`/usr/bin/python`) and the canonical repo `.venv` does not have `yamllint` installed. This is an environment/tooling issue, not a docs-13 regression. diff --git a/openspec/changes/docs-13-core-nav-search-theme-roles/design.md b/openspec/changes/docs-13-core-nav-search-theme-roles/design.md new file mode 100644 index 00000000..9bba5b38 --- /dev/null +++ b/openspec/changes/docs-13-core-nav-search-theme-roles/design.md @@ -0,0 +1,35 @@ +# Design: Core Docs UX Refactor As A Counterpart To Modules-Site Navigation Improvements + +## Summary + +This change adds an interactive UX layer to the already-restructured core docs site. It does not revisit the core-vs-modules content boundary established by earlier docs changes. Instead, it improves discoverability and readability through data-driven navigation, client-side search, expertise-aware entry paths, persisted theme selection, and a more coherent page shell. + +## Scope Boundaries + +- The core site remains focused on platform/runtime concerns +- Module-owned workflow depth remains on `modules.specfact.io` +- Any parity with the modules site is directional, not literal: shared interaction patterns are acceptable, but IA and links remain core-specific +- Existing docs validation and handoff-conversion changes remain the guardrails for cross-site correctness + +## UX Goals + +- Make it obvious where new users should start +- Reduce friction for experienced users who want command/reference pages quickly +- Improve scanning of the sidebar and landing page +- Support both dark and light reading environments +- Keep the shell visually coherent across the core and modules sites without merging content ownership + +## Proposed Building Blocks + +- A structured navigation data file describing the existing core-docs IA sections +- Include partials for sidebar rendering, search input/results, expertise or audience filter controls, theme toggle, and optional breadcrumbs +- A Jekyll-generated search index derived from page front matter and content excerpts +- Browser-side scripts for search, theme persistence, and filter behavior +- Front matter enrichment on core pages so they can participate in filtering and search ranking + +## Risks And Guardrails + +- Search and filters must not expose module-owned pages as if they were core-owned canonical docs +- Landing-page role paths must continue to hand off to modules docs where appropriate instead of recreating module tutorials in core +- Styling refresh should preserve readability and not destabilize the existing Jekyll build/published layout +- Validation should catch broken links or stale navigation references after the refactor diff --git a/openspec/changes/docs-13-core-nav-search-theme-roles/proposal.md b/openspec/changes/docs-13-core-nav-search-theme-roles/proposal.md new file mode 100644 index 00000000..8a964fdd --- /dev/null +++ b/openspec/changes/docs-13-core-nav-search-theme-roles/proposal.md @@ -0,0 +1,47 @@ +# Change: Refine Core Docs UX With Data-Driven Navigation, Search, Theme, And Audience Paths + +## Why + +The core docs site at `docs.specfact.io` was restructured by `docs-05-core-site-ia-restructure`, handoff pages were cleaned up by `docs-07-core-handoff-conversion`, and validation was added by `docs-12-docs-validation-ci`. But the overall reading experience is still utilitarian and harder to scan than it needs to be. The site lacks client-side search, expertise-guided navigation, theme toggling, and a clearer visual shell for the header/footer and page layout. Users still need to work too hard to answer basic questions like where to start, which pages are beginner-friendly, and how to jump to the right core CLI reference quickly. + +The modules docs now have a richer navigation/search/theme model. The core site should follow with a counterpart change tailored to core-platform content so the two sites feel coherent while preserving the core-vs-modules ownership boundary. + +## What Changes + +- Move core docs sidebar navigation to a data-driven source so navigation structure is easier to evolve without hardcoded layout drift +- Add client-side search for core docs pages using Jekyll-generated search metadata and Lunr.js +- Add expertise and audience-oriented navigation support so users can filter for beginner/intermediate/advanced material and quickly find the right starting path +- Add a light/dark theme toggle with persisted preference and core-doc-friendly styling updates +- Refresh overall page shell with clearer header/footer treatment, cleaner sidebar/content hierarchy, and breadcrumb support where useful +- Update the core landing page so it offers clearer role-based and task-based entry points without reintroducing module-owned content +- Enrich core docs front matter where needed to support search/filter/navigation metadata + +## Capabilities + +### New Capabilities + +- `core-docs-data-driven-nav`: core docs navigation is driven from structured data rather than hardcoded sidebar markup +- `core-docs-client-search`: users can search core docs content from the sidebar/header experience +- `core-docs-expertise-paths`: users can filter and discover core docs by expertise level and entry path +- `core-docs-theme-toggle`: core docs support persisted light/dark theme preference + +### Modified Capabilities + +- `core-docs-progressive-nav`: the existing progressive core-docs IA is enhanced with richer interaction, filtering, and visual hierarchy +- `documentation-alignment`: the landing and navigation continue to separate core-runtime guidance from module-owned workflow content while improving discoverability + +## Impact + +- Affected docs: `docs/_layouts/default.html`, `docs/index.md`, core reference/guide/getting-started pages that need search/filter metadata, and footer/header/navigation partials if introduced +- New docs assets likely include data-driven nav config, include partials, and browser-side scripts for search/theme/filter behavior +- Validation follow-up should reuse the existing docs validation change rather than duplicating command/link rules +- Cross-repo alignment: visual/navigation parity should remain compatible with the modules-site UX direction without assuming identical IA or content ownership + +## Source Tracking + + +- **GitHub Issue**: #458 +- **Issue URL**: https://github.com/nold-ai/specfact-cli/issues/458 +- **Repository**: nold-ai/specfact-cli +- **Last Synced Status**: synced +- **Sanitized**: true diff --git a/openspec/changes/docs-13-core-nav-search-theme-roles/specs/core-docs-client-search/spec.md b/openspec/changes/docs-13-core-nav-search-theme-roles/specs/core-docs-client-search/spec.md new file mode 100644 index 00000000..37a8c309 --- /dev/null +++ b/openspec/changes/docs-13-core-nav-search-theme-roles/specs/core-docs-client-search/spec.md @@ -0,0 +1,21 @@ +# Capability: core-docs-client-search + +## ADDED Requirements + +### Requirement: Core docs pages SHALL be searchable from a client-side index + +Core docs pages SHALL be searchable from the site experience using a client-side index built from repository content. + +#### Scenario: Search returns matching core CLI reference pages + +- **GIVEN** the core docs site search is available +- **WHEN** a user searches for a known core term such as `init`, `module`, or `architecture` +- **THEN** the results include the corresponding core docs pages +- **AND** the results use core docs metadata and content excerpts from the built site + +#### Scenario: Search stays within core-owned docs scope + +- **GIVEN** the core docs site search index is generated +- **WHEN** the index is built +- **THEN** it only includes pages owned by the core docs site +- **AND** it does not present module-site pages as if they were local core pages diff --git a/openspec/changes/docs-13-core-nav-search-theme-roles/specs/core-docs-data-driven-nav/spec.md b/openspec/changes/docs-13-core-nav-search-theme-roles/specs/core-docs-data-driven-nav/spec.md new file mode 100644 index 00000000..3368a55f --- /dev/null +++ b/openspec/changes/docs-13-core-nav-search-theme-roles/specs/core-docs-data-driven-nav/spec.md @@ -0,0 +1,20 @@ +# Capability: core-docs-data-driven-nav + +## ADDED Requirements + +### Requirement: Core docs navigation SHALL render from structured navigation data + +Core docs navigation SHALL be rendered from a structured data source rather than duplicated as hardcoded sidebar markup. + +#### Scenario: Sidebar renders from structured core navigation data + +- **GIVEN** the core docs site is built +- **WHEN** a user visits a page on `docs.specfact.io` +- **THEN** the sidebar navigation is rendered from a structured data source +- **AND** the rendered sections still reflect the core IA owned by the core docs site + +#### Scenario: Navigation updates do not require hardcoded layout edits + +- **GIVEN** a core docs section link changes +- **WHEN** the navigation data source is updated +- **THEN** the sidebar rendering reflects the change without duplicating the link structure in hardcoded template markup diff --git a/openspec/changes/docs-13-core-nav-search-theme-roles/specs/core-docs-expertise-paths/spec.md b/openspec/changes/docs-13-core-nav-search-theme-roles/specs/core-docs-expertise-paths/spec.md new file mode 100644 index 00000000..465e783e --- /dev/null +++ b/openspec/changes/docs-13-core-nav-search-theme-roles/specs/core-docs-expertise-paths/spec.md @@ -0,0 +1,21 @@ +# Capability: core-docs-expertise-paths + +## ADDED Requirements + +### Requirement: Core docs SHALL expose expertise-aware or role-aware entry paths + +Core docs SHALL expose expertise-aware or role-aware paths that help users find the right entry points for their current level. + +#### Scenario: Expertise filter narrows visible navigation options + +- **GIVEN** the core docs navigation includes expertise-aware metadata +- **WHEN** a user selects a specific expertise level +- **THEN** the visible navigation emphasizes pages relevant to that level +- **AND** the selection persists across page loads + +#### Scenario: Landing page offers clear entry paths without reintroducing module-owned tutorials + +- **GIVEN** the core docs landing page is updated +- **WHEN** a new or returning user arrives at the site +- **THEN** the page highlights clear core-docs starting paths by task or audience +- **AND** any module-specific depth continues to link out to the modules site rather than being duplicated in core diff --git a/openspec/changes/docs-13-core-nav-search-theme-roles/specs/core-docs-theme-toggle/spec.md b/openspec/changes/docs-13-core-nav-search-theme-roles/specs/core-docs-theme-toggle/spec.md new file mode 100644 index 00000000..b5c470d5 --- /dev/null +++ b/openspec/changes/docs-13-core-nav-search-theme-roles/specs/core-docs-theme-toggle/spec.md @@ -0,0 +1,21 @@ +# Capability: core-docs-theme-toggle + +## ADDED Requirements + +### Requirement: Core docs SHALL support a persisted light/dark theme toggle + +Core docs SHALL support a persisted light/dark theme toggle for the docs site shell. + +#### Scenario: User toggles theme and preference persists + +- **GIVEN** the core docs site is loaded +- **WHEN** a user switches between light and dark theme +- **THEN** the site updates its color theme accordingly +- **AND** the selected preference persists across page reloads + +#### Scenario: Theme styling preserves readability for core docs content + +- **GIVEN** the core docs include command examples, reference pages, and long-form explanatory content +- **WHEN** the user reads the site in either theme +- **THEN** text, navigation, and code blocks remain readable +- **AND** the shell styling does not obscure canonical links or content hierarchy diff --git a/openspec/changes/docs-13-core-nav-search-theme-roles/tasks.md b/openspec/changes/docs-13-core-nav-search-theme-roles/tasks.md new file mode 100644 index 00000000..9575657e --- /dev/null +++ b/openspec/changes/docs-13-core-nav-search-theme-roles/tasks.md @@ -0,0 +1,36 @@ +## 1. Change Setup And Spec Deltas + +- [x] 1.1 Update `openspec/CHANGE_ORDER.md` with `docs-13-core-nav-search-theme-roles` +- [x] 1.2 Add `core-docs-data-driven-nav` capability spec +- [x] 1.3 Add `core-docs-client-search` capability spec +- [x] 1.4 Add `core-docs-expertise-paths` capability spec +- [x] 1.5 Add `core-docs-theme-toggle` capability spec +- [x] 1.6 Extend `core-docs-progressive-nav` / `documentation-alignment` where needed for the new interactive UX layer + +## 2. Navigation And Layout + +- [x] 2.1 Define a structured navigation data source for the core docs sections created by `docs-05-core-site-ia-restructure` +- [x] 2.2 Replace hardcoded core sidebar navigation with include-driven rendering from that data source +- [x] 2.3 Add breadcrumb or equivalent orientation treatment where it improves core-site navigation clarity +- [x] 2.4 Refine header/footer/page shell styling for a cleaner docs.specfact.io reading experience + +## 3. Search, Theme, And Filters + +- [x] 3.1 Add a Jekyll-generated search index for core docs pages with title and metadata fields +- [x] 3.2 Add client-side search UX for core docs using the generated index +- [x] 3.3 Add a persisted light/dark theme toggle for the core docs site +- [x] 3.4 Add expertise-level filtering and/or entry-path cues for core docs navigation + +## 4. Content Metadata And Landing Page + +- [x] 4.1 Enrich affected core docs pages with front matter needed for search and expertise-aware navigation +- [x] 4.2 Update `docs/index.md` so the core landing page gives clearer role-based or task-based entry paths while preserving core-vs-modules ownership boundaries +- [x] 4.3 Ensure any handoff links to modules-owned content remain canonical and do not regress `docs-07-core-handoff-conversion` + +## 5. Verification + +- [x] 5.1 Run `bundle exec jekyll build` for the core docs site and verify the build stays clean +- [x] 5.2 Verify the data-driven navigation renders correct core sections and links +- [x] 5.3 Verify search returns expected results for known core CLI and architecture keywords +- [x] 5.4 Verify theme toggle and expertise/path selection persist across page loads +- [x] 5.5 Verify docs validation remains green with the new navigation/search assets and enriched front matter diff --git a/scripts/check-docs-commands.py b/scripts/check-docs-commands.py index 23bfd79a..2dccac53 100644 --- a/scripts/check-docs-commands.py +++ b/scripts/check-docs-commands.py @@ -9,6 +9,7 @@ import sys from pathlib import Path +import yaml from beartype import beartype from icontract import ensure from rich.console import Console @@ -235,6 +236,85 @@ def _scan_docs_for_command_validation(docs_root: Path) -> tuple[set[tuple[str, . return seen, failures +@beartype +def _extract_front_matter(text: str) -> dict[str, str]: + if not text.startswith("---\n"): + return {} + + lines = text.splitlines() + end_index = None + for index in range(1, len(lines)): + if lines[index].strip() == "---": + end_index = index + break + if end_index is None: + return {} + + metadata: dict[str, str] = {} + for raw_line in lines[1:end_index]: + if ":" not in raw_line: + continue + key, value = raw_line.split(":", 1) + metadata[key.strip()] = value.strip().strip('"').strip("'") + return metadata + + +@beartype +def _published_route_for_path(path: Path, metadata: dict[str, str]) -> str: + permalink = metadata.get("permalink") + route = permalink or f"/{path.stem}/" + if route != "/" and not route.endswith("/"): + route += "/" + return route + + +@beartype +def _build_published_docs_index(docs_root: Path) -> dict[str, Path]: + route_to_path: dict[str, Path] = {} + for md_path in sorted(docs_root.rglob("*.md")): + rel = md_path.relative_to(_REPO_ROOT) + if "_site" in rel.parts or "vendor" in rel.parts: + continue + metadata = _extract_front_matter(md_path.read_text(encoding="utf-8")) + route_to_path[_published_route_for_path(md_path, metadata)] = md_path + return route_to_path + + +@beartype +def _iter_nav_urls(nav_data: list[dict[str, object]]) -> list[str]: + urls: list[str] = [] + for section in nav_data: + for item in section.get("items", []) or []: + url = item.get("url") + if isinstance(url, str): + urls.append(url) + for bundle in section.get("bundles", []) or []: + for item in bundle.get("items", []) or []: + url = item.get("url") + if isinstance(url, str): + urls.append(url) + return urls + + +@beartype +def _validate_nav_targets(docs_root: Path) -> list[str]: + nav_path = docs_root / "_data" / "nav.yml" + if not nav_path.is_file(): + return [f"{nav_path.relative_to(_REPO_ROOT)}: missing nav data file"] + + nav_data = yaml.safe_load(nav_path.read_text(encoding="utf-8")) or [] + if not isinstance(nav_data, list): + return [f"{nav_path.relative_to(_REPO_ROOT)}: nav data must be a list"] + + route_index = _build_published_docs_index(docs_root) + failures: list[str] = [] + for raw_url in _iter_nav_urls(nav_data): + url = raw_url if raw_url == "/" else raw_url.rstrip("/") + "/" + if url not in route_index: + failures.append(f"{nav_path.relative_to(_REPO_ROOT)}: unknown docs route {raw_url}") + return failures + + @beartype @ensure(lambda result: result in (0, 1), "exit code must be 0 or 1") def main() -> int: @@ -244,6 +324,7 @@ def main() -> int: return 1 seen, failures = _scan_docs_for_command_validation(docs_root) + failures.extend(_validate_nav_targets(docs_root)) if failures: _ERR.print("Docs command validation failed:", markup=False) diff --git a/tests/unit/docs/test_docs_validation_scripts.py b/tests/unit/docs/test_docs_validation_scripts.py index a47b4084..64c48159 100644 --- a/tests/unit/docs/test_docs_validation_scripts.py +++ b/tests/unit/docs/test_docs_validation_scripts.py @@ -1,6 +1,7 @@ from __future__ import annotations import importlib.util +import textwrap from pathlib import Path @@ -75,3 +76,84 @@ def test_cross_site_url_stops_at_markdown_delimiters() -> None: line = "| `https://modules.specfact.io/foo/bar/` |" urls = mod._urls_from_line(line) assert urls == ["https://modules.specfact.io/foo/bar/"] + + +def test_validate_nav_targets_accepts_known_routes(tmp_path: Path) -> None: + mod = _load_check_docs_commands() + mod._REPO_ROOT = tmp_path + + docs_root = tmp_path / "docs" + (docs_root / "_data").mkdir(parents=True) + (docs_root / "index.md").write_text( + textwrap.dedent( + """\ + --- + title: Home + permalink: / + --- + """ + ), + encoding="utf-8", + ) + (docs_root / "getting-started.md").write_text( + textwrap.dedent( + """\ + --- + title: Getting Started + permalink: /getting-started/ + --- + """ + ), + encoding="utf-8", + ) + (docs_root / "_data" / "nav.yml").write_text( + textwrap.dedent( + """\ + - section: Start + items: + - title: Home + url: / + expertise: [beginner] + - title: Getting Started + url: /getting-started/ + expertise: [beginner] + """ + ), + encoding="utf-8", + ) + + assert mod._validate_nav_targets(docs_root) == [] + + +def test_validate_nav_targets_reports_unknown_route(tmp_path: Path) -> None: + mod = _load_check_docs_commands() + mod._REPO_ROOT = tmp_path + + docs_root = tmp_path / "docs" + (docs_root / "_data").mkdir(parents=True) + (docs_root / "index.md").write_text( + textwrap.dedent( + """\ + --- + title: Home + permalink: / + --- + """ + ), + encoding="utf-8", + ) + (docs_root / "_data" / "nav.yml").write_text( + textwrap.dedent( + """\ + - section: Start + items: + - title: Missing + url: /missing/ + expertise: [beginner] + """ + ), + encoding="utf-8", + ) + + failures = mod._validate_nav_targets(docs_root) + assert failures == ["docs/_data/nav.yml: unknown docs route /missing/"] diff --git a/tests/unit/docs/test_release_docs_parity.py b/tests/unit/docs/test_release_docs_parity.py index 64af7b08..d0595d8f 100644 --- a/tests/unit/docs/test_release_docs_parity.py +++ b/tests/unit/docs/test_release_docs_parity.py @@ -128,6 +128,8 @@ def _resolve_internal_docs_target( stripped = _normalize_jekyll_relative_url(raw_link.strip()) if not stripped or stripped.startswith("#"): return None, None, None + if "{{" in stripped and "site." in stripped: + return None, None, None parsed = urlparse(stripped) if parsed.scheme in {"mailto", "javascript", "tel"}: @@ -287,7 +289,9 @@ def test_top_navigation_exposes_docs_home_core_cli_and_modules() -> None: assert ">Docs Home<" in layout assert ">Core CLI<" in layout assert ">Modules<" in layout - _assert_mentions_modules_docs_site(layout) + assert "{{ site.docs_home_url }}" in layout + assert "{{ site.core_cli_docs_url }}" in layout + assert "{{ site.modules_docs_url }}" in layout def test_command_reference_and_docs_readme_link_to_modules_canonical_site() -> None: diff --git a/tests/unit/test_core_docs_site_contract.py b/tests/unit/test_core_docs_site_contract.py new file mode 100644 index 00000000..50ee8b67 --- /dev/null +++ b/tests/unit/test_core_docs_site_contract.py @@ -0,0 +1,83 @@ +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[2] +DOCS_CONFIG = REPO_ROOT / "docs" / "_config.yml" +DOCS_INDEX = REPO_ROOT / "docs" / "index.md" +DOCS_LAYOUT = REPO_ROOT / "docs" / "_layouts" / "default.html" +OUTDATED_DOCS_HOSTS = ( + "modules.docs.specfact.io", + "cli.docs.specfact.io", + "nold-ai.github.io/specfact-cli-modules", + "nold-ai.github.io/specfact-cli", +) + + +def _read(path: Path) -> str: + return path.read_text(encoding="utf-8") + + +def test_core_docs_config_targets_public_core_domain() -> None: + config = _read(DOCS_CONFIG) + + assert 'url: "https://docs.specfact.io"' in config + assert 'baseurl: ""' in config + assert 'docs_home_url: "https://docs.specfact.io"' in config + assert 'core_cli_docs_url: "https://docs.specfact.io"' in config + assert 'modules_docs_url: "https://modules.specfact.io"' in config + + +def test_core_landing_page_marks_core_repo_as_canonical_owner() -> None: + index = _read(DOCS_INDEX) + + assert "This site covers the core platform" in index + assert "module-specific workflows" in index + assert "shared portal navigation" in index + assert "https://modules.specfact.io/" in index + assert "nold-ai.github.io/specfact-cli" not in index + + +def test_core_layout_exposes_shared_cross_site_navigation() -> None: + layout = _read(DOCS_LAYOUT) + + assert ">Docs Home<" in layout + assert ">Core CLI<" in layout + assert ">Modules<" in layout + assert "{{ site.docs_home_url }}" in layout + assert "{{ site.core_cli_docs_url }}" in layout + assert "{{ site.modules_docs_url }}" in layout + + +def test_core_layout_exposes_shared_portal_features() -> None: + layout = _read(DOCS_LAYOUT) + + assert "{% include theme-toggle.html %}" in layout + assert "{% include search.html %}" in layout + assert "{% include expertise-filter.html %}" in layout + assert "{% include sidebar-nav.html %}" in layout + assert "{% include breadcrumbs.html %}" in layout + assert "search.js" in layout + assert "filters.js" in layout + + +def test_core_layout_keeps_sidebar_core_focused() -> None: + layout = _read(DOCS_LAYOUT) + + assert "Core CLI Docs" in layout + assert ( + "Getting Started, Core CLI, Module System, Architecture, Workflows, Integrations, Migration, and Reference" + in layout + ) + assert "Official Modules Docs" not in layout + + +def test_docs_tree_does_not_reference_retired_public_hosts() -> None: + skip_parts = frozenset({"vendor", "_site", ".bundle", ".jekyll-cache"}) + for path in REPO_ROOT.joinpath("docs").rglob("*"): + if not path.is_file(): + continue + if skip_parts.intersection(path.parts): + continue + text = _read(path) + for host in OUTDATED_DOCS_HOSTS: + assert host not in text, f"{path} still references retired host {host}" From 1f7fa5bbcf1b7b1f80c1371aa3083f8a65d595d3 Mon Sep 17 00:00:00 2001 From: Dominikus Nold Date: Sat, 28 Mar 2026 23:46:13 +0100 Subject: [PATCH 2/4] Fix docs-13 core review findings --- docs/_includes/breadcrumbs.html | 15 +- docs/_includes/expertise-filter.html | 8 +- docs/_includes/theme-toggle.html | 2 +- docs/_layouts/default.html | 5 +- docs/assets/js/filters.js | 6 + docs/assets/js/search.js | 139 +++++++++++++----- docs/assets/js/theme.js | 20 ++- docs/assets/main.scss | 9 -- docs/getting-started/installation.md | 25 ++-- docs/getting-started/where-to-start.md | 4 +- docs/guides/ai-ide-workflow.md | 11 +- docs/index.md | 2 +- docs/migration/migration-guide.md | 16 +- docs/reference/documentation-url-contract.md | 2 +- .../TDD_EVIDENCE.md | 71 ++++++++- .../tasks.md | 16 +- scripts/check-docs-commands.py | 10 +- tests/unit/test_core_docs_site_contract.py | 52 +++++-- 18 files changed, 303 insertions(+), 110 deletions(-) diff --git a/docs/_includes/breadcrumbs.html b/docs/_includes/breadcrumbs.html index aa11dedd..aa048009 100644 --- a/docs/_includes/breadcrumbs.html +++ b/docs/_includes/breadcrumbs.html @@ -2,16 +2,25 @@