diff --git a/.github/workflows/docs-review.yml b/.github/workflows/docs-review.yml index d6223ca..96f3289 100644 --- a/.github/workflows/docs-review.yml +++ b/.github/workflows/docs-review.yml @@ -9,6 +9,8 @@ on: - "**/*.md" - "**/*.mdc" - "docs/**" + - "scripts/check-docs-commands.py" + - "tests/unit/test_check_docs_commands_script.py" - "tests/unit/docs/test_docs_review.py" - ".github/workflows/docs-review.yml" push: @@ -17,6 +19,8 @@ on: - "**/*.md" - "**/*.mdc" - "docs/**" + - "scripts/check-docs-commands.py" + - "tests/unit/test_check_docs_commands_script.py" - "tests/unit/docs/test_docs_review.py" - ".github/workflows/docs-review.yml" workflow_dispatch: @@ -44,7 +48,7 @@ jobs: - name: Install docs review dependencies run: | python -m pip install --upgrade pip - python -m pip install pytest + python -m pip install pytest click typer PyYAML beartype icontract rich pydantic specfact-cli - name: Run docs review suite run: | @@ -53,6 +57,13 @@ jobs: python -m pytest tests/unit/docs/test_docs_review.py -q 2>&1 | tee "$DOCS_REVIEW_LOG" exit "${PIPESTATUS[0]:-$?}" + - name: Validate docs commands and cross-site links + run: | + mkdir -p logs/docs-review + DOCS_COMMAND_LOG="logs/docs-review/docs-command-validation_$(date -u +%Y%m%d_%H%M%S).log" + python scripts/check-docs-commands.py 2>&1 | tee "$DOCS_COMMAND_LOG" + exit "${PIPESTATUS[0]:-$?}" + - name: Upload docs review logs if: always() uses: actions/upload-artifact@v4 diff --git a/docs/adapters/azuredevops.md b/docs/adapters/azuredevops.md index bd969a2..33d05f7 100644 --- a/docs/adapters/azuredevops.md +++ b/docs/adapters/azuredevops.md @@ -412,7 +412,7 @@ raw_format = proposal.source_tracking.source_metadata.get("raw_format") # "mark When exporting from stored bundles, the adapter uses raw content if available to preserve 100% fidelity, even when syncing to a different adapter (e.g., ADO → GitHub). -**See**: [Cross-Adapter Sync Guide](../guides/devops-adapter-integration.md#cross-adapter-sync-lossless-round-trip-migration) for complete documentation. +**See**: [Cross-Adapter Sync Guide](/integrations/devops-adapter-overview/#cross-adapter-sync-lossless-round-trip-migration) for complete documentation. ## Source Tracking Matching @@ -558,5 +558,5 @@ specfact project sync bridge --adapter ado --mode export-only \ - **[Backlog Adapter Patterns](./backlog-adapter-patterns.md)** - Patterns for backlog adapters - **[GitHub Adapter](./github.md)** - GitHub adapter documentation -- **[Validation Integration](../validation-integration.md)** - Validation with change proposals -- **[DevOps Adapter Integration](../guides/devops-adapter-integration.md)** - DevOps workflow integration +- **[Thorough codebase validation](/reference/thorough-codebase-validation/)** - Validation and release-readiness guidance +- **[DevOps Adapter Integration](/integrations/devops-adapter-overview/)** - DevOps workflow integration diff --git a/docs/adapters/backlog-adapter-patterns.md b/docs/adapters/backlog-adapter-patterns.md index 675ca5b..322e9f6 100644 --- a/docs/adapters/backlog-adapter-patterns.md +++ b/docs/adapters/backlog-adapter-patterns.md @@ -491,6 +491,6 @@ When implementing new backlog adapters: - **[GitHub Adapter Documentation](./github.md)** - GitHub adapter reference - **[Azure DevOps Adapter Documentation](./azuredevops.md)** - Azure DevOps adapter reference -- **[DevOps Adapter Integration Guide](../guides/devops-adapter-integration.md)** - Complete integration guide for GitHub and ADO -- **[Validation Integration](../validation-integration.md)** - Validation with change proposals -- **[Bridge Adapter Interface](../bridge-adapter-interface.md)** - Base adapter interface +- **[DevOps Adapter Integration Guide](/integrations/devops-adapter-overview/)** - Complete integration guide for GitHub and ADO +- **[Thorough codebase validation](/reference/thorough-codebase-validation/)** - Validation and release-readiness guidance +- **[Adapter development guide](/authoring/adapter-development/)** - Base adapter interface and implementation patterns diff --git a/docs/adapters/github.md b/docs/adapters/github.md index e49f04f..89db407 100644 --- a/docs/adapters/github.md +++ b/docs/adapters/github.md @@ -354,7 +354,7 @@ specfact project sync bridge --adapter github --mode export-only \ After a successful run, each change’s `openspec/changes//proposal.md` will contain a **Source Tracking** block with the new issue number and URL. Use that section to link the PR and keep backlog in sync. -For public repos, add `--sanitize` when exporting so content is sanitized before creating issues. See [DevOps Adapter Integration](../guides/devops-adapter-integration.md) and the [sync bridge command reference](../reference/commands.md#sync-bridge). +For public repos, add `--sanitize` when exporting so content is sanitized before creating issues. See [DevOps Adapter Integration](/integrations/devops-adapter-overview/) and the [sync bridge command reference](/reference/commands/#project-sync-bridge). ### Updating Archived Change Proposals @@ -385,7 +385,7 @@ This ensures archived issues get updated with: - Enhanced comment formatting - Latest status information -See [DevOps Adapter Integration Guide](../guides/devops-adapter-integration.md#updating-archived-change-proposals) for complete documentation. +See [DevOps Adapter Integration Guide](/integrations/devops-adapter-overview/#updating-archived-change-proposals) for complete documentation. ## Lossless Content Preservation @@ -403,11 +403,11 @@ raw_format = proposal.source_tracking.source_metadata.get("raw_format") # "mark When exporting from stored bundles, the adapter uses raw content if available to preserve 100% fidelity, even when syncing to a different adapter (e.g., GitHub → ADO). -**See**: [Cross-Adapter Sync Guide](../guides/devops-adapter-integration.md#cross-adapter-sync-lossless-round-trip-migration) for complete documentation. +**See**: [Cross-Adapter Sync Guide](/integrations/devops-adapter-overview/#cross-adapter-sync-lossless-round-trip-migration) for complete documentation. ## Related Documentation - **[Backlog Adapter Patterns](./backlog-adapter-patterns.md)** - Patterns for backlog adapters - **[Azure DevOps Adapter](./azuredevops.md)** - Azure DevOps adapter documentation -- **[Validation Integration](../validation-integration.md)** - Validation with change proposals -- **[DevOps Adapter Integration](../guides/devops-adapter-integration.md)** - DevOps workflow integration +- **[Thorough codebase validation](/reference/thorough-codebase-validation/)** - Validation and release-readiness guidance +- **[DevOps Adapter Integration](/integrations/devops-adapter-overview/)** - DevOps workflow integration diff --git a/docs/bundles/backlog/policy-engine.md b/docs/bundles/backlog/policy-engine.md index 57338aa..f573b40 100644 --- a/docs/bundles/backlog/policy-engine.md +++ b/docs/bundles/backlog/policy-engine.md @@ -14,9 +14,9 @@ Use SpecFact policy commands to scaffold, validate, and improve policy configura The policy engine currently supports: -- `specfact policy init` to scaffold `.specfact/policy.yaml` from a built-in template. -- `specfact policy validate` to evaluate configured rules deterministically against policy input artifacts. -- `specfact policy suggest` to generate confidence-scored, patch-ready recommendations (no automatic writes). +- `specfact backlog policy init` to scaffold `.specfact/policy.yaml` from a built-in template. +- `specfact backlog policy validate` to evaluate configured rules deterministically against policy input artifacts. +- `specfact backlog policy suggest` to generate confidence-scored, patch-ready recommendations (no automatic writes). ## Commands @@ -25,7 +25,7 @@ The policy engine currently supports: Create a starter policy configuration file: ```bash -specfact policy init --repo . --template scrum +specfact backlog policy init --repo . --template scrum ``` Supported templates: @@ -38,7 +38,7 @@ Supported templates: Interactive mode (template prompt): ```bash -specfact policy init --repo . +specfact backlog policy init --repo . ``` The command writes `.specfact/policy.yaml`. Use `--force` to overwrite an existing file. @@ -48,7 +48,7 @@ The command writes `.specfact/policy.yaml`. Use `--force` to overwrite an existi Run policy checks with deterministic output: ```bash -specfact policy validate --repo . --format both +specfact backlog policy validate --repo . --format both ``` Artifact resolution order when `--snapshot` is omitted: @@ -59,20 +59,20 @@ Artifact resolution order when `--snapshot` is omitted: You can still override with an explicit path: ```bash -specfact policy validate --repo . --snapshot ./snapshot.json --format both +specfact backlog policy validate --repo . --snapshot ./snapshot.json --format both ``` Filter and scope output: ```bash # only one rule family, max 20 findings -specfact policy validate --repo . --rule scrum.dor --limit 20 --format json +specfact backlog policy validate --repo . --rule scrum.dor --limit 20 --format json # item-centric grouped output -specfact policy validate --repo . --group-by-item --format both +specfact backlog policy validate --repo . --group-by-item --format both # in grouped mode, --limit applies to item groups -specfact policy validate --repo . --group-by-item --limit 4 --format json +specfact backlog policy validate --repo . --group-by-item --limit 4 --format json ``` Output formats: @@ -88,20 +88,20 @@ When config is missing or invalid, the command prints a docs hint pointing back Generate suggestions from validation findings: ```bash -specfact policy suggest --repo . +specfact backlog policy suggest --repo . ``` Suggestion shaping options: ```bash # suggestions for one rule family, limited output -specfact policy suggest --repo . --rule scrum.dod --limit 10 +specfact backlog policy suggest --repo . --rule scrum.dod --limit 10 # grouped suggestions by backlog item index -specfact policy suggest --repo . --group-by-item +specfact backlog policy suggest --repo . --group-by-item # grouped mode limits item groups, not per-item fields -specfact policy suggest --repo . --group-by-item --limit 4 +specfact backlog policy suggest --repo . --group-by-item --limit 4 ``` Suggestions include confidence scores and patch-ready structure, but no file is modified automatically. diff --git a/docs/bundles/backlog/refinement.md b/docs/bundles/backlog/refinement.md index e47d2b3..5f168ed 100644 --- a/docs/bundles/backlog/refinement.md +++ b/docs/bundles/backlog/refinement.md @@ -785,7 +785,6 @@ Templates are automatically loaded in priority order (custom templates override 1. **Project templates** (`.specfact/templates/backlog/`) - Highest priority, overrides built-in 2. **Built-in templates** (`resources/templates/backlog/`) - Included with package -3. **Legacy location** (`src/specfact_cli/templates/`) - Fallback for backward compatibility Within each location, templates are loaded from: diff --git a/docs/getting-started/README.md b/docs/getting-started/README.md index 5bb43b3..a9a3b95 100644 --- a/docs/getting-started/README.md +++ b/docs/getting-started/README.md @@ -45,11 +45,10 @@ specfact project --help Flat root commands were removed. Use the mounted grouped command forms: -- `specfact validate ...` -> `specfact code validate ...` -- `specfact code repro ...` -> `specfact code repro ...` -- `specfact sync ...` -> `specfact project sync ...` -- `specfact govern enforce ...` -> `specfact govern enforce ...` -- `specfact policy ...` -> `specfact backlog policy ...` +- root-level `validate` moved under `specfact code validate ...` +- root-level `sync` moved under `specfact project sync ...` +- root-level policy actions moved under `specfact backlog policy ...` +- grouped command surfaces such as `specfact code repro ...` and `specfact govern enforce ...` remain current First-run bundle selection examples: diff --git a/docs/getting-started/first-steps.md b/docs/getting-started/first-steps.md index ab95f76..debe556 100644 --- a/docs/getting-started/first-steps.md +++ b/docs/getting-started/first-steps.md @@ -6,7 +6,7 @@ permalink: /getting-started/first-steps/ # Legacy Workflow Note -This page described older `specfact plan`, `specfact generate`, `specfact contract`, or `specfact sdd constitution` workflows that are not part of the current public mounted CLI in this repository. The detailed command examples previously documented here were removed because they no longer match the command surface exposed by `specfact --help`. +This page described older plan-generation, contract, and constitution workflows that are not part of the current public mounted CLI in this repository. The detailed command examples previously documented here were removed because they no longer match the command surface exposed by `specfact --help`. Use the current mounted entrypoints instead: diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md index 565165a..1d811cd 100644 --- a/docs/getting-started/installation.md +++ b/docs/getting-started/installation.md @@ -493,7 +493,7 @@ specfact --version # Get help specfact --help -specfact --help +specfact project --help # Inspect currently mounted project workflows specfact project --help @@ -535,4 +535,4 @@ hatch run format hatch run lint ``` -See [CONTRIBUTING.md](../../CONTRIBUTING.md) for detailed contribution guidelines. +See the [repository contributing guide](https://github.com/nold-ai/specfact-cli-modules/blob/dev/CONTRIBUTING.md) for detailed contribution guidelines. diff --git a/docs/getting-started/tutorial-backlog-refine-ai-ide.md b/docs/getting-started/tutorial-backlog-refine-ai-ide.md index c157444..167eaa2 100644 --- a/docs/getting-started/tutorial-backlog-refine-ai-ide.md +++ b/docs/getting-started/tutorial-backlog-refine-ai-ide.md @@ -170,9 +170,9 @@ If your team uses **custom fields** (e.g. Azure DevOps custom process templates) ## Related Documentation -- **[Backlog Refinement Guide](../guides/backlog-refinement.md)** — Full reference: templates, options, export/import, DoR -- **[Story scope and specification level](../guides/backlog-refinement.md#story-scope-and-specification-level)** — Underspecification, over-specification, fit-for-scope -- **[Definition of Ready (DoR)](../guides/backlog-refinement.md#step-45-definition-of-ready-dor-validation-optional)** — DoR configuration and validation +- **[Backlog Refinement Guide](/bundles/backlog/refinement/)** — Full reference: templates, options, export/import, DoR +- **[Story scope and specification level](/bundles/backlog/refinement/#story-scope-and-specification-level)** — Underspecification, over-specification, fit-for-scope +- **[Definition of Ready (DoR)](/bundles/backlog/refinement/#step-45-definition-of-ready-dor-validation-optional)** — DoR configuration and validation - **[Template Customization](../guides/template-customization.md)** — Custom templates for advanced teams - **[Custom Field Mapping](../guides/custom-field-mapping.md)** — ADO custom field mapping - **[IDE Integration](../guides/ide-integration.md)** — Set up slash commands in Cursor, VS Code, etc. diff --git a/docs/getting-started/tutorial-daily-standup-sprint-review.md b/docs/getting-started/tutorial-daily-standup-sprint-review.md index 368f6eb..b4488b2 100644 --- a/docs/getting-started/tutorial-daily-standup-sprint-review.md +++ b/docs/getting-started/tutorial-daily-standup-sprint-review.md @@ -65,7 +65,7 @@ specfact backlog ceremony standup ado If you're **not** in a clone (e.g. different directory), use one of: -- **`.nold-ai/specfact-backlog.yaml`** in the project (see [Project backlog context](../guides/devops-adapter-integration.md#project-backlog-context-specfactbacklogyaml)) +- **`.nold-ai/specfact-backlog.yaml`** in the project (see [Project backlog context](/integrations/devops-adapter-overview/#project-backlog-context-specfactbacklogyaml)) - **Environment variables**: `SPECFACT_GITHUB_REPO_OWNER`, `SPECFACT_GITHUB_REPO_NAME` or `SPECFACT_ADO_ORG`, `SPECFACT_ADO_PROJECT` - **CLI options**: `--repo-owner` / `--repo-name` or `--ado-org` / `--ado-project` @@ -214,5 +214,5 @@ supported. Use it with the **`specfact.backlog-daily`** slash prompt for interac ## Related Documentation - **[Agile/Scrum Workflows](../guides/agile-scrum-workflows.md)** — Daily standup, iteration/sprint, unassigned items, blockers-first -- **[DevOps Adapter Integration](../guides/devops-adapter-integration.md)** — Project backlog context (`.nold-ai/specfact-backlog.yaml`), env vars, **Git fallback (auto-detect from clone)** for GitHub and Azure DevOps -- **[Backlog Refinement Guide](../guides/backlog-refinement.md)** — Template-driven refinement (complementary to daily standup) +- **[DevOps Adapter Integration](/integrations/devops-adapter-overview/)** — Project backlog context (`.nold-ai/specfact-backlog.yaml`), env vars, **Git fallback (auto-detect from clone)** for GitHub and Azure DevOps +- **[Backlog Refinement Guide](/bundles/backlog/refinement/)** — Template-driven refinement (complementary to daily standup) diff --git a/docs/getting-started/tutorial-openspec-speckit.md b/docs/getting-started/tutorial-openspec-speckit.md index ee01927..2ce11b0 100644 --- a/docs/getting-started/tutorial-openspec-speckit.md +++ b/docs/getting-started/tutorial-openspec-speckit.md @@ -1,3 +1,9 @@ +--- +layout: default +title: OpenSpec and Speckit Legacy Workflow Note +permalink: /getting-started/tutorial-openspec-speckit/ +--- + # Legacy Workflow Note This page referenced command groups or workflow steps that are no longer part of the current public mounted CLI in this repository. The old examples were removed to avoid directing readers to unavailable commands. diff --git a/docs/guides/README.md b/docs/guides/README.md index 36f2949..3706ae6 100644 --- a/docs/guides/README.md +++ b/docs/guides/README.md @@ -29,14 +29,14 @@ Practical module-owned guides for official bundles, adapters, publishing, and wo - **[IDE Integration](ide-integration.md)** - Set up slash commands in your IDE - **[CoPilot Mode](copilot-mode.md)** - Using `--mode copilot` on CLI commands -- **[DevOps Adapter Integration](devops-adapter-integration.md)** - Integrate with GitHub Issues, Azure DevOps, Linear, Jira for backlog tracking -- **[Backlog Refinement](backlog-refinement.md)** - AI-assisted template-driven refinement with filtering and DoR checks +- **[DevOps Adapter Integration](/integrations/devops-adapter-overview/)** - Integrate with GitHub Issues, Azure DevOps, Linear, Jira for backlog tracking +- **[Backlog Refinement](/bundles/backlog/refinement/)** - AI-assisted template-driven refinement with filtering and DoR checks - **[Specmatic Integration](specmatic-integration.md)** - API contract testing with Specmatic - **[Troubleshooting](troubleshooting.md)** - Common issues and solutions - **[Installing Modules](installing-modules.md)** - Install, list, show, search, enable/disable, uninstall, and upgrade modules - **[Module Marketplace](module-marketplace.md)** - Discovery priority, trust vs origin semantics, and security model -- **[Custom registries](custom-registries.md)** - Add, list, remove registries; trust levels and priority -- **[Publishing modules](publishing-modules.md)** - Package, sign, and publish modules to a registry +- **[Custom registries](/authoring/custom-registries/)** - Add, list, remove registries; trust levels and priority +- **[Publishing modules](/authoring/publishing-modules/)** - Package, sign, and publish modules to a registry - **[Module Signing and Key Rotation](module-signing-and-key-rotation.md)** - Public key placement, signing workflow, CI verification, rotation, and revocation runbook - **[Competitive Analysis](competitive-analysis.md)** - How SpecFact compares to other tools - **[Operational Modes](../reference/modes.md)** - CI/CD vs CoPilot modes diff --git a/docs/guides/agile-scrum-workflows.md b/docs/guides/agile-scrum-workflows.md index 0d9db58..61a18e3 100644 --- a/docs/guides/agile-scrum-workflows.md +++ b/docs/guides/agile-scrum-workflows.md @@ -114,16 +114,16 @@ Use the `policy` command group to run deterministic readiness checks before spri ```bash # Validate configured policy rules against a snapshot -specfact policy validate --repo . --format both +specfact backlog policy validate --repo . --format both # Generate confidence-scored, patch-ready suggestions (no automatic writes) -specfact policy suggest --repo . +specfact backlog policy suggest --repo . ``` Policy configuration is loaded from `.specfact/policy.yaml` and supports Scrum (`dor_required_fields`, `dod_required_fields`), Kanban column entry/exit requirements, and SAFe PI readiness fields. -**🆕 NEW: Backlog Refinement Integration** - Use `specfact backlog ceremony refinement` to standardize backlog items from GitHub Issues, Azure DevOps, and other tools into template-compliant format before importing into project bundles. See [Backlog Refinement Guide](backlog-refinement.md) for complete documentation. +**🆕 NEW: Backlog Refinement Integration** - Use `specfact backlog ceremony refinement` to standardize backlog items from GitHub Issues, Azure DevOps, and other tools into template-compliant format before importing into project bundles. See [Backlog Refinement Guide](/bundles/backlog/refinement/) for complete documentation. **Tutorial**: For an end-to-end daily standup and sprint review walkthrough (auto-detect repo, view standup, post comment, interactive, Copilot export), see **[Tutorial: Daily Standup and Sprint Review](../getting-started/tutorial-daily-standup-sprint-review.md)**. @@ -136,7 +136,7 @@ Use **`specfact backlog ceremony standup `** to list your standup items - **GitHub**: When run from a **GitHub** clone (e.g. `https://github.com/owner/repo` or `git@github.com:owner/repo.git`), SpecFact infers `repo_owner` and `repo_name` from `git remote get-url origin`. - **Azure DevOps**: When run from an **ADO** clone (e.g. `https://dev.azure.com/org/project/_git/repo`; SSH keys: `git@ssh.dev.azure.com:v3/org/project/repo`; other SSH: `user@dev.azure.com:v3/org/project/repo`), SpecFact infers `org` and `project` from the remote URL. -Override with `.nold-ai/specfact-backlog.yaml`, environment variables (`SPECFACT_GITHUB_REPO_OWNER`, `SPECFACT_ADO_ORG`, etc.), or CLI options when not in the repo or to override. See [Project backlog context](../guides/devops-adapter-integration.md#project-backlog-context-specfactbacklogyaml). +Override with `.nold-ai/specfact-backlog.yaml`, environment variables (`SPECFACT_GITHUB_REPO_OWNER`, `SPECFACT_ADO_ORG`, etc.), or CLI options when not in the repo or to override. See [Project backlog context](/integrations/devops-adapter-overview/#project-backlog-context-specfactbacklogyaml). ### End-to-End Example: One Standup Session @@ -643,7 +643,7 @@ rules: dependencies: false # Optional ``` -**See**: [Backlog Refinement Guide](backlog-refinement.md#definition-of-ready-dor) for DoR validation in backlog refinement workflow. +**See**: [Backlog Refinement Guide](/bundles/backlog/refinement/#definition-of-ready-dor) for DoR validation in backlog refinement workflow. ### DoR Checklist @@ -829,7 +829,7 @@ specfact backlog ceremony refinement github --persona product-owner --framework - Filters by sprint, release, iteration for agile workflows - Preserves original backlog data for round-trip synchronization -**See**: [Backlog Refinement Guide](backlog-refinement.md) for complete documentation. +**See**: [Backlog Refinement Guide](/bundles/backlog/refinement/) for complete documentation. ### Target Sprint Assignment diff --git a/docs/guides/brownfield-examples.md b/docs/guides/brownfield-examples.md index b87ba77..1e342ff 100644 --- a/docs/guides/brownfield-examples.md +++ b/docs/guides/brownfield-examples.md @@ -48,4 +48,4 @@ Outcome: compatibility, generated test artifacts, and bundle enforcement are che - [Brownfield modernization](/guides/brownfield-modernization/) - [Cross-module chains](/guides/cross-module-chains/) -- [Contract testing workflow](/guides/contract-testing-workflow/) +- [Contract testing workflow](/contract-testing-workflow/) diff --git a/docs/guides/command-chains.md b/docs/guides/command-chains.md index 5c512f8..ba4b668 100644 --- a/docs/guides/command-chains.md +++ b/docs/guides/command-chains.md @@ -18,7 +18,7 @@ specfact module install nold-ai/specfact-backlog Use this before any workflow that depends on bundle-owned prompts or templates. -Related: [AI IDE workflow](/guides/ai-ide-workflow/) +Related: [AI IDE workflow](/ai-ide-workflow/) ## 2. Brownfield intake and contract discovery @@ -54,7 +54,7 @@ specfact spec generate-tests api/openapi.yaml Use this chain when you are validating a contract update and need generated test coverage before release review. -Related: [Contract testing workflow](/guides/contract-testing-workflow/) +Related: [Contract testing workflow](/contract-testing-workflow/) ## 5. Daily review and cleanup diff --git a/docs/guides/common-tasks.md b/docs/guides/common-tasks.md index f3b17fd..857a68f 100644 --- a/docs/guides/common-tasks.md +++ b/docs/guides/common-tasks.md @@ -8,7 +8,7 @@ redirect_from: # Legacy Workflow Note -This page described older `specfact plan`, `specfact generate`, `specfact contract`, or `specfact sdd constitution` workflows that are not part of the current public mounted CLI in this repository. The detailed command examples previously documented here were removed because they no longer match the command surface exposed by `specfact --help`. +This page described older plan-generation, contract, and constitution workflows that are not part of the current public mounted CLI in this repository. The detailed command examples previously documented here were removed because they no longer match the command surface exposed by `specfact --help`. Use the current mounted entrypoints instead: diff --git a/docs/guides/custom-field-mapping.md b/docs/guides/custom-field-mapping.md index dfc69b3..30d3523 100644 --- a/docs/guides/custom-field-mapping.md +++ b/docs/guides/custom-field-mapping.md @@ -639,6 +639,6 @@ If work item types are not being normalized: ## Related Documentation -- [Backlog Refinement Guide](./backlog-refinement.md) - Complete guide to backlog refinement +- [Backlog Refinement Guide](/bundles/backlog/refinement/) - Complete guide to backlog refinement - [ADO Adapter Documentation](../adapters/backlog-adapter-patterns.md) - ADO adapter patterns - [Field Mapper API Reference](../reference/architecture.md) - Technical architecture details diff --git a/docs/guides/daily-devops-routine.md b/docs/guides/daily-devops-routine.md index 92ea433..d7cc3ce 100644 --- a/docs/guides/daily-devops-routine.md +++ b/docs/guides/daily-devops-routine.md @@ -38,7 +38,7 @@ specfact code import legacy-api --repo . Refresh IDE resources when the workflow depends on installed prompts, then import or refresh the project bundle before deeper validation. -Reference: [AI IDE workflow](/guides/ai-ide-workflow/) +Reference: [AI IDE workflow](/ai-ide-workflow/) ## 4. Midday quality review @@ -49,7 +49,7 @@ specfact spec validate --bundle legacy-api Run the review bundle on your changed files and validate the affected contracts while the context is still fresh. -Reference: [Contract testing workflow](/guides/contract-testing-workflow/) +Reference: [Contract testing workflow](/contract-testing-workflow/) ## 5. End-of-day release readiness diff --git a/docs/guides/dual-stack-enrichment.md b/docs/guides/dual-stack-enrichment.md index 61c60d4..236d2dd 100644 --- a/docs/guides/dual-stack-enrichment.md +++ b/docs/guides/dual-stack-enrichment.md @@ -8,7 +8,7 @@ redirect_from: # Legacy Workflow Note -This page described older `specfact plan`, `specfact generate`, `specfact contract`, or `specfact sdd constitution` workflows that are not part of the current public mounted CLI in this repository. The detailed command examples previously documented here were removed because they no longer match the command surface exposed by `specfact --help`. +This page described older plan-generation, contract, and constitution workflows that are not part of the current public mounted CLI in this repository. The detailed command examples previously documented here were removed because they no longer match the command surface exposed by `specfact --help`. Use the current mounted entrypoints instead: diff --git a/docs/guides/ide-integration.md b/docs/guides/ide-integration.md index f49ff0b..2bb7e80 100644 --- a/docs/guides/ide-integration.md +++ b/docs/guides/ide-integration.md @@ -6,7 +6,7 @@ permalink: /guides/ide-integration/ # Legacy Workflow Note -This page described older `specfact plan`, `specfact generate`, `specfact contract`, or `specfact sdd constitution` workflows that are not part of the current public mounted CLI in this repository. The detailed command examples previously documented here were removed because they no longer match the command surface exposed by `specfact --help`. +This page described older plan-generation, contract, and constitution workflows that are not part of the current public mounted CLI in this repository. The detailed command examples previously documented here were removed because they no longer match the command surface exposed by `specfact --help`. Use the current mounted entrypoints instead: diff --git a/docs/guides/integrations-overview.md b/docs/guides/integrations-overview.md index c219397..ebf102d 100644 --- a/docs/guides/integrations-overview.md +++ b/docs/guides/integrations-overview.md @@ -83,7 +83,7 @@ SpecFact CLI integrations fall into four main categories: ## Testing & Validation -> **New in v0.24.0**: [Sidecar Validation](./sidecar-validation.md) - Validate external codebases without modifying source code +> **New in v0.24.0**: [Sidecar Validation](/bundles/codebase/sidecar-validation/) - Validate external codebases without modifying source code ### Specmatic Integration @@ -133,7 +133,7 @@ SpecFact CLI integrations fall into four main categories: **Key difference**: Sidecar validation provides **external codebase validation** without source modification, while standard SpecFact workflows analyze and modify your own codebase. -**See also**: [Sidecar Validation Guide](./sidecar-validation.md) | [Command Chains - Sidecar Validation](./command-chains.md#5-sidecar-validation-chain) +**See also**: [Sidecar Validation Guide](/bundles/codebase/sidecar-validation/) | [Command Chains - Sidecar Validation](/guides/command-chains/#5-sidecar-validation-chain) --- @@ -173,7 +173,7 @@ SpecFact CLI integrations fall into four main categories: **Why this matters**: This feature allows you to use SpecFact's specification-driven development approach while working within your existing agile DevOps workflows. Change proposals become backlog items, and backlog items become change proposals—keeping everything in sync automatically. -**See also**: [DevOps Adapter Integration Guide](./devops-adapter-integration.md) | [GitHub Adapter Reference](../adapters/github.md) | [Azure DevOps Adapter Reference](../adapters/azuredevops.md) | [Backlog Adapter Patterns](../adapters/backlog-adapter-patterns.md) +**See also**: [DevOps Adapter Integration Guide](/integrations/devops-adapter-overview/) | [GitHub Adapter Reference](/adapters/github/) | [Azure DevOps Adapter Reference](/adapters/azuredevops/) | [Backlog Adapter Patterns](/adapters/backlog-adapter-patterns/) --- @@ -212,7 +212,7 @@ SpecFact CLI integrations fall into four main categories: **Why this matters**: DevOps teams often create backlog items with informal, unstructured descriptions. Backlog refinement helps enforce corporate standards while maintaining lossless synchronization with your backlog tools, enabling seamless integration into agile workflows. -**See also**: [Backlog Refinement Guide](./backlog-refinement.md) | [DevOps Adapter Integration Guide](./devops-adapter-integration.md) +**See also**: [Backlog Refinement Guide](/bundles/backlog/refinement/) | [DevOps Adapter Integration Guide](/integrations/devops-adapter-overview/) --- @@ -309,9 +309,9 @@ Start: What do you need? | **Spec-Kit** | Interactive spec authoring for new features | `/speckit.specify` | [Spec-Kit Journey](./speckit-journey.md) | | **OpenSpec** | Specification anchoring and change tracking | `openspec validate` | [OpenSpec Journey](./openspec-journey.md) | | **Specmatic** | API contract testing and validation | `spec validate` | [Specmatic Integration](./specmatic-integration.md) | -| **Sidecar Validation** 🆕 | Validate external codebases without modifying source | `validate sidecar init/run` | [Sidecar Validation](./sidecar-validation.md) | -| **DevOps Adapter** | Sync proposals to backlog tools | `sync bridge --adapter github` | [DevOps Integration](./devops-adapter-integration.md) | -| **Backlog Refinement** 🆕 | Standardize backlog items with templates | `backlog refine github --sprint "Sprint 1"` | [Backlog Refinement](./backlog-refinement.md) | +| **Sidecar Validation** 🆕 | Validate external codebases without modifying source | `validate sidecar init/run` | [Sidecar Validation](/bundles/codebase/sidecar-validation/) | +| **DevOps Adapter** | Sync proposals to backlog tools | `sync bridge --adapter github` | [DevOps Integration](/integrations/devops-adapter-overview/) | +| **Backlog Refinement** 🆕 | Standardize backlog items with templates | `backlog refine github --sprint "Sprint 1"` | [Backlog Refinement](/bundles/backlog/refinement/) | | **AI IDE** | AI-assisted development workflows | `init --ide cursor` | [AI IDE Workflow](./ai-ide-workflow.md) | --- diff --git a/docs/guides/migration-cli-reorganization.md b/docs/guides/migration-cli-reorganization.md index 4190d4c..95bf948 100644 --- a/docs/guides/migration-cli-reorganization.md +++ b/docs/guides/migration-cli-reorganization.md @@ -8,7 +8,7 @@ redirect_from: # Legacy Workflow Note -This page described older `specfact plan`, `specfact generate`, `specfact contract`, or `specfact sdd constitution` workflows that are not part of the current public mounted CLI in this repository. The detailed command examples previously documented here were removed because they no longer match the command surface exposed by `specfact --help`. +This page described older plan-generation, contract, and constitution workflows that are not part of the current public mounted CLI in this repository. The detailed command examples previously documented here were removed because they no longer match the command surface exposed by `specfact --help`. Use the current mounted entrypoints instead: diff --git a/docs/guides/migration-guide.md b/docs/guides/migration-guide.md index 05d579a..9df948c 100644 --- a/docs/guides/migration-guide.md +++ b/docs/guides/migration-guide.md @@ -8,7 +8,7 @@ redirect_from: # Legacy Workflow Note -This page described older `specfact plan`, `specfact generate`, `specfact contract`, or `specfact sdd constitution` workflows that are not part of the current public mounted CLI in this repository. The detailed command examples previously documented here were removed because they no longer match the command surface exposed by `specfact --help`. +This page described older plan-generation, contract, and constitution workflows that are not part of the current public mounted CLI in this repository. The detailed command examples previously documented here were removed because they no longer match the command surface exposed by `specfact --help`. Use the current mounted entrypoints instead: diff --git a/docs/guides/module-marketplace.md b/docs/guides/module-marketplace.md index 2e6560e..9007294 100644 --- a/docs/guides/module-marketplace.md +++ b/docs/guides/module-marketplace.md @@ -16,7 +16,7 @@ For the curated official bundle list and trust/dependency quick reference, see - **Official registry**: (index: `registry/index.json`) - **Marketplace module id format**: `namespace/name` (e.g. `nold-ai/specfact-backlog`). Marketplace modules must use this format; flat names are allowed only for custom/local modules with a warning. -- **Custom registries**: You can add private or third-party registries. See [Custom registries](custom-registries.md) for adding, listing, removing, trust levels, and priority. +- **Custom registries**: You can add private or third-party registries. See [Custom registries](/authoring/custom-registries/) for adding, listing, removing, trust levels, and priority. ## Custom registries and search @@ -96,7 +96,7 @@ Public key for runtime verification: Scope boundary: - This change set hardens local and bundled module safety. -- For publishing your own modules to a registry, see [Publishing modules](publishing-modules.md). +- For publishing your own modules to a registry, see [Publishing modules](/authoring/publishing-modules/). ## Marketplace vs Local Modules diff --git a/docs/guides/openspec-journey.md b/docs/guides/openspec-journey.md index 9b963ba..9ffaab3 100644 --- a/docs/guides/openspec-journey.md +++ b/docs/guides/openspec-journey.md @@ -458,7 +458,7 @@ This separation enables: - [Command Chains Reference](command-chains.md) - Complete workflows including [External Tool Integration Chain](command-chains.md#3-external-tool-integration-chain) - [Common Tasks Index](common-tasks.md) - Quick reference for OpenSpec integration tasks -- [DevOps Adapter Integration](devops-adapter-integration.md) - GitHub Issues and backlog tracking +- [DevOps Adapter Integration](/integrations/devops-adapter-overview/) - GitHub Issues and backlog tracking - [Team Collaboration Workflow](team-collaboration-workflow.md) - Team collaboration patterns ### Related Commands @@ -469,7 +469,7 @@ This separation enables: ### Related Examples -- [OpenSpec Integration Examples](../examples/) - Real-world integration examples +- [Brownfield examples](/guides/brownfield-examples/) - Real-world integration examples ### Getting Started @@ -482,7 +482,7 @@ This separation enables: ### **Try It Now** ✅ -1. **[DevOps Adapter Integration Guide](devops-adapter-integration.md)** - Export OpenSpec proposals to GitHub Issues +1. **[DevOps Adapter Integration Guide](/integrations/devops-adapter-overview/)** - Export OpenSpec proposals to GitHub Issues 2. **[Commands Reference](../reference/commands.md#sync-bridge)** - Complete `sync bridge` documentation 3. **[OpenSpec Documentation](https://github.com/nold-ai/openspec)** - Learn OpenSpec basics @@ -500,7 +500,7 @@ This separation enables: ## 🔗 Related Documentation -- **[DevOps Adapter Integration](devops-adapter-integration.md)** - GitHub Issues and backlog tracking +- **[DevOps Adapter Integration](/integrations/devops-adapter-overview/)** - GitHub Issues and backlog tracking - **[Spec-Kit Journey](speckit-journey.md)** - Similar guide for Spec-Kit integration - **[Brownfield Engineer Guide](brownfield-engineer.md)** - Complete brownfield modernization workflow - **[Commands Reference](../reference/commands.md)** - Complete command documentation diff --git a/docs/guides/speckit-comparison.md b/docs/guides/speckit-comparison.md index fa8c707..1f354b3 100644 --- a/docs/guides/speckit-comparison.md +++ b/docs/guides/speckit-comparison.md @@ -352,7 +352,7 @@ OpenSpec focuses on specification anchoring and change tracking, while SpecFact 1. **[Brownfield Engineer Guide](brownfield-engineer.md)** - Complete modernization workflow 2. **[Spec-Kit Journey](speckit-journey.md)** - Migration from Spec-Kit -3. **[Examples](../examples/)** - Real-world examples +3. **[Brownfield examples](/guides/brownfield-examples/)** - Real-world examples --- diff --git a/docs/guides/template-customization.md b/docs/guides/template-customization.md index 042610f..8a308a8 100644 --- a/docs/guides/template-customization.md +++ b/docs/guides/template-customization.md @@ -174,5 +174,5 @@ body_patterns: ## Related Documentation -- [Backlog Refinement Guide](./backlog-refinement.md) - Using templates for refinement +- [Backlog Refinement Guide](/bundles/backlog/refinement/) - Using templates for refinement - [Command Reference](../reference/commands.md) - CLI command options diff --git a/docs/guides/troubleshooting.md b/docs/guides/troubleshooting.md index dc7ecb2..831adc9 100644 --- a/docs/guides/troubleshooting.md +++ b/docs/guides/troubleshooting.md @@ -8,7 +8,7 @@ redirect_from: # Legacy Workflow Note -This page described older `specfact plan`, `specfact generate`, `specfact contract`, or `specfact sdd constitution` workflows that are not part of the current public mounted CLI in this repository. The detailed command examples previously documented here were removed because they no longer match the command surface exposed by `specfact --help`. +This page described older plan-generation, contract, and constitution workflows that are not part of the current public mounted CLI in this repository. The detailed command examples previously documented here were removed because they no longer match the command surface exposed by `specfact --help`. Use the current mounted entrypoints instead: diff --git a/docs/guides/use-cases.md b/docs/guides/use-cases.md index 2d5daf2..a85c40a 100644 --- a/docs/guides/use-cases.md +++ b/docs/guides/use-cases.md @@ -8,7 +8,7 @@ redirect_from: # Legacy Workflow Note -This page described older `specfact plan`, `specfact generate`, `specfact contract`, or `specfact sdd constitution` workflows that are not part of the current public mounted CLI in this repository. The detailed command examples previously documented here were removed because they no longer match the command surface exposed by `specfact --help`. +This page described older plan-generation, contract, and constitution workflows that are not part of the current public mounted CLI in this repository. The detailed command examples previously documented here were removed because they no longer match the command surface exposed by `specfact --help`. Use the current mounted entrypoints instead: diff --git a/docs/guides/workflows.md b/docs/guides/workflows.md index 1ce4851..6238709 100644 --- a/docs/guides/workflows.md +++ b/docs/guides/workflows.md @@ -36,10 +36,10 @@ Use `specfact init ide` again after module upgrades so bundle-owned prompts and ## Focused deep dives -- [AI IDE workflow](/guides/ai-ide-workflow/) for prompt/bootstrap-aware IDE usage -- [Contract testing workflow](/guides/contract-testing-workflow/) for Specmatic validation, compatibility, test generation, and mocks +- [AI IDE workflow](/ai-ide-workflow/) for prompt/bootstrap-aware IDE usage +- [Contract testing workflow](/contract-testing-workflow/) for Specmatic validation, compatibility, test generation, and mocks - [Agile/Scrum workflows](/guides/agile-scrum-workflows/) for backlog ceremonies and persona flows -- [Team collaboration workflow](/guides/team-collaboration-workflow/) for persona export/import and lock-based editing +- [Team collaboration workflow](/team-collaboration-workflow/) for persona export/import and lock-based editing ## Bundle references used by these workflows diff --git a/docs/integrations/devops-adapter-overview.md b/docs/integrations/devops-adapter-overview.md index 96d8de0..ee0688e 100644 --- a/docs/integrations/devops-adapter-overview.md +++ b/docs/integrations/devops-adapter-overview.md @@ -20,13 +20,13 @@ your backlog system: ```bash # Deterministic policy validation with JSON + Markdown output -specfact policy validate --repo . --format both +specfact backlog policy validate --repo . --format both # AI-assisted suggestions with confidence scores and patch-ready output -specfact policy suggest --repo . +specfact backlog policy suggest --repo . ``` -Both commands read `.specfact/policy.yaml`. `policy suggest` never writes changes automatically; it emits +Both commands read `.specfact/policy.yaml`. `specfact backlog policy suggest` never writes changes automatically; it emits recommendations you can review and apply explicitly in your normal workflow. ## Overview diff --git a/docs/module-publishing-guide.md b/docs/module-publishing-guide.md index e359ff8..fb13b39 100644 --- a/docs/module-publishing-guide.md +++ b/docs/module-publishing-guide.md @@ -1,6 +1,15 @@ +--- +layout: default +title: Module Publishing Guide +permalink: /module-publishing-guide/ +--- + # Module Publishing Guide -This guide describes how to publish modules to the SpecFact CLI marketplace registry. +This legacy note predates the current authoring IA. For the maintained publishing workflow, use +[Publishing modules](/authoring/publishing-modules/). + +The checklist below remains a useful quick reference for the registry data you need to prepare. ## Prerequisites diff --git a/docs/reference/architecture.md b/docs/reference/architecture.md index 82588c8..8dc72bd 100644 --- a/docs/reference/architecture.md +++ b/docs/reference/architecture.md @@ -11,7 +11,7 @@ SpecFact CLI is a contract-first Python CLI with a production-ready module regis ## Current Architecture Status - Module system is **production-ready** (introduced in `v0.27`) and is the default command-loading path. -- Architecture commands such as `specfact architecture derive|validate|trace` are **planned** and tracked in OpenSpec change `architecture-01-solution-layer`. +- An architecture command group is **planned** and tracked in OpenSpec change `architecture-01-solution-layer`; it is not part of the current mounted CLI. - Protocol FSM modeling exists in data models; a full runtime FSM engine is still planned. ## Layer Model @@ -60,7 +60,7 @@ Common manifest fields: - Extension/security optional: `schema_extensions`, `service_bridges`, `publisher`, `integrity` See also: -- [Module Development Guide](../guides/module-development.md) +- [Module Development Guide](/authoring/module-development/) - [Module Contracts](module-contracts.md) - [Module Security](module-security.md) @@ -78,7 +78,7 @@ Current implementation note: - Mode **detection is implemented**. - Some advanced mode-specific behavior remains roadmap/planned and is tracked in OpenSpec. -- See [Implementation Status](../architecture/implementation-status.md) for implemented vs planned details. +- Implemented-vs-planned details are tracked in OpenSpec change `architecture-01-solution-layer`. ## Adapter Architecture @@ -109,7 +109,7 @@ All adapters implement: `BridgeProbe`/sync flows use detection and capabilities to select adapters and choose sync behavior safely. See also: -- [Adapter Development Guide](../guides/adapter-development.md) +- [Adapter Development Guide](/authoring/adapter-development/) - [Bridge Registry](bridge-registry.md) ## Change Tracking and Protocol Scope @@ -120,7 +120,6 @@ See also: Status and roadmap references: -- [Implementation Status](../architecture/implementation-status.md) - OpenSpec change `architecture-01-solution-layer` ## Error Handling Conventions @@ -155,11 +154,10 @@ Use `ProjectBundle` for current architecture descriptions unless explicitly disc ## Architecture Decisions -- ADR index: [Architecture ADRs](../architecture/adr/README.md) -- Initial ADR: [ADR-0001 Module-First Architecture](../architecture/adr/0001-module-first-architecture.md) +Formal ADR pages are not yet published on the modules docs site. The current architecture baseline and planned follow-up work are tracked in OpenSpec change `architecture-01-solution-layer`. ## Related Docs -- [Architecture Docs Index](../architecture/README.md) -- [Implementation Status](../architecture/implementation-status.md) - [Directory Structure](directory-structure.md) +- [Module Development Guide](/authoring/module-development/) +- [Adapter Development Guide](/authoring/adapter-development/) diff --git a/docs/reference/command-syntax-policy.md b/docs/reference/command-syntax-policy.md index 2992786..60bde48 100644 --- a/docs/reference/command-syntax-policy.md +++ b/docs/reference/command-syntax-policy.md @@ -11,7 +11,7 @@ This policy defines how command examples must be documented so docs stay consist ## Core Rule -Always document commands exactly as implemented by `specfact --help` in the current release. +Always document commands exactly as implemented by the relevant current help entrypoint in the current release, such as `specfact project --help` or `specfact backlog --help`. - Do not assume all commands use the same bundle argument style. - Do not convert positional bundle arguments to `--bundle` unless the command explicitly supports it. diff --git a/docs/reference/directory-structure.md b/docs/reference/directory-structure.md index c6f1f7f..86b553e 100644 --- a/docs/reference/directory-structure.md +++ b/docs/reference/directory-structure.md @@ -6,7 +6,7 @@ permalink: /directory-structure/ # Legacy Workflow Note -This page described older `specfact plan`, `specfact generate`, `specfact contract`, or `specfact sdd constitution` workflows that are not part of the current public mounted CLI in this repository. The detailed command examples previously documented here were removed because they no longer match the command surface exposed by `specfact --help`. +This page described older plan-generation, contract, and constitution workflows that are not part of the current public mounted CLI in this repository. The detailed command examples previously documented here were removed because they no longer match the command surface exposed by `specfact --help`. Use the current mounted entrypoints instead: diff --git a/docs/reference/feature-keys.md b/docs/reference/feature-keys.md index ee01927..199ad63 100644 --- a/docs/reference/feature-keys.md +++ b/docs/reference/feature-keys.md @@ -1,3 +1,9 @@ +--- +layout: default +title: Feature Keys Legacy Workflow Note +permalink: /reference/feature-keys/ +--- + # Legacy Workflow Note This page referenced command groups or workflow steps that are no longer part of the current public mounted CLI in this repository. The old examples were removed to avoid directing readers to unavailable commands. diff --git a/docs/reference/parameter-standard.md b/docs/reference/parameter-standard.md index 951c313..251bfad 100644 --- a/docs/reference/parameter-standard.md +++ b/docs/reference/parameter-standard.md @@ -1,6 +1,12 @@ +--- +layout: default +title: Parameter Standard Legacy Workflow Note +permalink: /reference/parameter-standard/ +--- + # Legacy Workflow Note -This page described older `specfact plan`, `specfact generate`, `specfact contract`, or `specfact sdd constitution` workflows that are not part of the current public mounted CLI in this repository. The detailed command examples previously documented here were removed because they no longer match the command surface exposed by `specfact --help`. +This page described older plan-generation, contract, and constitution workflows that are not part of the current public mounted CLI in this repository. The detailed command examples previously documented here were removed because they no longer match the command surface exposed by `specfact --help`. Use the current mounted entrypoints instead: diff --git a/docs/reference/specmatic.md b/docs/reference/specmatic.md index 666fb65..9d8fd94 100644 --- a/docs/reference/specmatic.md +++ b/docs/reference/specmatic.md @@ -1,3 +1,9 @@ +--- +layout: default +title: Specmatic API Reference +permalink: /reference/specmatic/ +--- + # Specmatic API Reference > **API Reference for Specmatic Integration** @@ -362,8 +368,8 @@ The module caches the detection result to avoid repeated checks. ## Related Documentation -- **[Specmatic Integration Guide](../guides/specmatic-integration.md)** - User guide with examples -- **[Spec Commands Reference](./commands.md#spec-commands)** - CLI command reference +- **[Specmatic Integration Guide](/specmatic-integration/)** - User guide with examples +- **[Spec command reference](/reference/commands/)** - CLI command reference - **[Specmatic Documentation](https://docs.specmatic.io/)** - Official Specmatic documentation --- diff --git a/docs/reference/telemetry.md b/docs/reference/telemetry.md index f325641..3b9da3e 100644 --- a/docs/reference/telemetry.md +++ b/docs/reference/telemetry.md @@ -1,3 +1,9 @@ +--- +layout: default +title: Privacy-First Telemetry +permalink: /reference/telemetry/ +--- + # Privacy-First Telemetry (Optional) > **Opt-in analytics that highlight how SpecFact prevents brownfield regressions.** @@ -507,6 +513,5 @@ Only if you explicitly opt in. We recommend enabling telemetry in CI/CD to track **Related docs:** -- [`docs/guides/brownfield-faq.md`](../guides/brownfield-faq.md) – Brownfield workflows -- [`docs/guides/brownfield-roi.md`](../guides/brownfield-roi.md) – Quantifying the savings -- [`docs/examples/brownfield-django-modernization.md`](../examples/brownfield-django-modernization.md) – Example pipeline +- [Brownfield FAQ and ROI](/guides/brownfield-faq-and-roi/) - Brownfield workflows and quantifying the savings +- [Brownfield examples](/guides/brownfield-examples/) - Example modernization pipelines diff --git a/docs/reference/thorough-codebase-validation.md b/docs/reference/thorough-codebase-validation.md index df8fd1e..1d6e28f 100644 --- a/docs/reference/thorough-codebase-validation.md +++ b/docs/reference/thorough-codebase-validation.md @@ -70,7 +70,7 @@ specfact code repro --repo --sidecar --sidecar-bundle - Then sidecar validation runs: unannotated detection, harness generation, CrossHair/Specmatic on generated harnesses. No files in the target repo are modified. - If CrossHair is not installed or the bundle is invalid, sidecar is skipped or partial with clear messaging; non-zero exit only for main check failures (sidecar can be advisory). -See [Sidecar Validation Guide](/guides/sidecar-validation/) for setup and bundle configuration. +See [Sidecar Validation Guide](/bundles/codebase/sidecar-validation/) for setup and bundle configuration. ## 4. Dogfooding (SpecFact CLI on itself) diff --git a/openspec/changes/docs-12-docs-validation-ci/TDD_EVIDENCE.md b/openspec/changes/docs-12-docs-validation-ci/TDD_EVIDENCE.md new file mode 100644 index 0000000..3c50067 --- /dev/null +++ b/openspec/changes/docs-12-docs-validation-ci/TDD_EVIDENCE.md @@ -0,0 +1,254 @@ +# TDD Evidence + +## Verification Evidence + +### 0. Failing evidence + +Pre-fix validation run from `2026-03-27T23:12:35+01:00`: + +```bash +python3 scripts/check-docs-commands.py +``` + +Failing excerpt: + +```text +docs/bundles/backlog/policy-engine.md:28: [command] Unknown command example: specfact policy init --repo . --template scrum +docs/bundles/backlog/policy-engine.md:41: [command] Unknown command example: specfact policy init --repo . +docs/bundles/backlog/policy-engine.md:51: [command] Unknown command example: specfact policy validate --repo . --format both +docs/bundles/backlog/policy-engine.md:91: [command] Unknown command example: specfact policy suggest --repo . +docs/reference/commands.md:13: [command] Unknown command example: specfact --help +docs/bundles/backlog/refinement.md:788: [legacy-resource] Legacy core-owned resource reference: src/specfact_cli/templates +``` + +This captured the initial failing state before the validator and docs fixes were completed. + +### 0.1 Repo-wide failing command audit after matcher fix + +Pre-cleanup audit run from `2026-03-28T00:03:00+01:00`: + +```bash +python3 - <<'PY' +from pathlib import Path +import importlib.util +repo = Path('.').resolve() +path = repo / 'scripts' / 'check-docs-commands.py' +spec = importlib.util.spec_from_file_location('check_docs_commands', path) +mod = importlib.util.module_from_spec(spec) +spec.loader.exec_module(mod) +paths = sorted(p.resolve() for p in (repo / 'docs').rglob('*.md')) +valid = mod._build_valid_command_paths() +findings = mod._validate_command_examples(paths, valid) +for finding in findings[:300]: + rel = finding.source.relative_to(repo) + print(f"{rel}:{finding.line_number}: {finding.message}") +print(f"TOTAL_FINDINGS={len(findings)}") +PY +``` + +Failing excerpt: + +```text +docs/getting-started/README.md:48: Unknown command example: specfact validate ... +docs/guides/agile-scrum-workflows.md:117: Unknown command example: specfact policy validate --repo . --format both +docs/integrations/devops-adapter-overview.md:23: Unknown command example: specfact policy validate --repo . --format both +docs/reference/architecture.md:14: Unknown command example: specfact architecture derive|validate|trace +TOTAL_FINDINGS=39 +``` + +This exposed the remaining stale former command references outside the original bundle-only validation scope. + +### 0.2 Docs review warning snapshot before cleanup + +Pre-cleanup docs review run from `2026-03-28T00:19:32+01:00`: + +```bash +python3 -m pytest tests/unit/docs/test_docs_review.py -q +``` + +Failing excerpt: + +```text +UserWarning: Pre-existing docs files missing front matter (6): +docs/getting-started/tutorial-openspec-speckit.md +docs/module-publishing-guide.md +docs/reference/feature-keys.md +docs/reference/parameter-standard.md +docs/reference/specmatic.md +docs/reference/telemetry.md +UserWarning: Pre-existing broken authored docs links (56 total): +docs/adapters/azuredevops.md -> ../guides/devops-adapter-integration.md +... +======================== 19 passed, 2 warnings in 0.41s ======================== +``` + +This captured the remaining published-doc warnings before the final stale-link and front-matter cleanup. + +### 1. Validator passes after docs fixes + +Passing run from `2026-03-27T23:19:08+01:00`: + +```bash +python3 scripts/check-docs-commands.py +``` + +Passing excerpt: + +```text +Docs command validation passed with no findings. +``` + +This verifies the scripted checks for implemented command examples, stale core-owned resource paths, and allowed `docs.specfact.io` cross-site URLs all pass after the initial docs fixes. + +### 2. Script unit coverage + +Passing run from `2026-03-27T23:18:24+01:00`: + +```bash +python3 -m pytest tests/unit/test_check_docs_commands_script.py -q +``` + +Passing excerpt: + +```text +..... [100%] +6 passed in 0.31s +``` + +This covers command extraction, command matching, repo-wide docs target discovery, stale legacy resource detection, cross-site link validation, and docs workflow integration. + +### 3. Docs review plus validator regression coverage + +Passing run from `2026-03-27T23:20:13+01:00`: + +```bash +python3 -m pytest tests/unit/docs/test_docs_review.py tests/unit/test_check_docs_commands_script.py -q +``` + +Passing excerpt: + +```text +..................... [100%] +21 passed, 2 warnings in 0.21s +``` + +This earlier run confirmed the new validator and the existing authored-docs checks pass together before the warning cleanup was completed. + +### 4. Review gate stays clean + +Passing run from `2026-03-27T23:21:05+01:00`: + +```bash +specfact code review run scripts/check-docs-commands.py tests/unit/test_check_docs_commands_script.py --no-tests +``` + +Passing excerpt: + +```text +Review completed with no findings. +``` + +This verifies the new script and its tests satisfy the required code-review gate. + +### 5. CI docs-review workflow wiring + +The docs review workflow now includes the validator script and its tests: + +```text +.github/workflows/docs-review.yml +- triggers on changes to scripts/check-docs-commands.py and tests/unit/test_check_docs_commands_script.py +- runs: python scripts/check-docs-commands.py +``` + +This, together with the passing local validator and docs test runs above, provides the end-to-end evidence for the workflow path required by task 5.3. + +### 5.1 Repo-wide published docs command audit passes + +Passing audit run from `2026-03-28T00:07:33+01:00`: + +```bash +python3 - <<'PY' +from pathlib import Path +import importlib.util +repo = Path('.').resolve() +path = repo / 'scripts' / 'check-docs-commands.py' +spec = importlib.util.spec_from_file_location('check_docs_commands', path) +mod = importlib.util.module_from_spec(spec) +spec.loader.exec_module(mod) +paths = mod._iter_validation_docs_paths() +valid = mod._build_valid_command_paths() +findings = mod._validate_command_examples(paths, valid) +for finding in findings[:300]: + rel = finding.source.relative_to(repo) + print(f"{rel}:{finding.line_number}: {finding.message}") +print(f"TOTAL_FINDINGS={len(findings)}") +PY +``` + +Passing excerpt: + +```text +TOTAL_FINDINGS=0 +``` + +This verifies the widened validator catches and clears stale former command references across published module docs, not only bundle reference pages. + +### 5.2 Docs review warnings eliminated + +Passing run from `2026-03-28T00:19:32+01:00`: + +```bash +python3 -m pytest tests/unit/docs/test_docs_review.py -q +``` + +Passing excerpt: + +```text +tests/unit/docs/test_docs_review.py ................... [100%] +============================== 19 passed in 0.43s ============================== +``` + +This verifies the previously tolerated warnings are gone: published docs now have the missing front matter added and the stale internal links updated to current canonical modules-docs routes. + +### 5.3 Combined docs validation suite + +Passing run from `2026-03-28T00:19:32+01:00`: + +```bash +python3 -m pytest tests/unit/docs/test_docs_review.py tests/unit/docs/test_missing_command_docs.py tests/unit/docs/test_bundle_overview_cli_examples.py tests/unit/test_check_docs_commands_script.py -q +``` + +Passing excerpt: + +```text +.............................. [100%] +============================== 30 passed in 4.16s ============================== +``` + +This verifies the docs review gate, bundle command docs checks, overview smoke routing, and the command validator tests all pass together after the warning cleanup. + +### 6. Full repository quality gates + +Passing quality gate sequence completed on `2026-03-27`: + +```bash +hatch run format +hatch run type-check +hatch run lint +hatch run yaml-lint +hatch run verify-modules-signature --require-signature --payload-from-filesystem --enforce-version-bump +hatch run contract-test +hatch run smart-test +hatch run test +``` + +Summary excerpts: + +```text +type-check: 0 errors, 0 warnings, 0 notes +contract-test: 427 passed, 2 warnings +smart-test: 427 passed, 2 warnings +test: 427 passed, 2 warnings in 34.16s +``` + +This confirms the change passes the repository quality gates in the required order. diff --git a/openspec/changes/docs-12-docs-validation-ci/proposal.md b/openspec/changes/docs-12-docs-validation-ci/proposal.md index 871c2a1..cbda2d9 100644 --- a/openspec/changes/docs-12-docs-validation-ci/proposal.md +++ b/openspec/changes/docs-12-docs-validation-ci/proposal.md @@ -2,13 +2,14 @@ ## Why -Documentation command examples can drift from actual module implementations. Cross-site links to docs.specfact.io can break when core pages are moved. This is the modules-side counterpart to the core-side docs-12 change. +Documentation command examples can drift from actual module implementations. Cross-site links to docs.specfact.io can break when core pages are moved. Older published pages can also keep missing front matter or broken internal links after the IA restructure unless they are explicitly cleaned up. This is the modules-side counterpart to the core-side docs-12 change. ## What Changes -- Add a script that extracts command registrations from all `packages/*/src/**/commands.py` and compares against command examples in `docs/bundles/` +- Add a script that extracts command registrations from all `packages/*/src/**/commands.py` and compares against command examples across published module docs under `docs/` - Add cross-site link validation for links from modules docs to core docs - Add checks that docs do not point users at legacy core-owned prompt/template paths when those resources are bundle-owned +- Clean up remaining stale published-doc warnings so the docs review run is warning-free - Integrate into CI workflow ## Capabilities diff --git a/openspec/changes/docs-12-docs-validation-ci/specs/modules-docs-command-validation/spec.md b/openspec/changes/docs-12-docs-validation-ci/specs/modules-docs-command-validation/spec.md index 888abbc..6baa9c7 100644 --- a/openspec/changes/docs-12-docs-validation-ci/specs/modules-docs-command-validation/spec.md +++ b/openspec/changes/docs-12-docs-validation-ci/specs/modules-docs-command-validation/spec.md @@ -1,22 +1,47 @@ +# Modules Docs Command Validation + ## ADDED Requirements ### Requirement: Docs validation SHALL reject stale command and resource references -The modules-side docs validation workflow SHALL reject command examples that do not match implemented bundle commands and SHALL also reject stale references to migrated core-owned resource paths. + +The modules-side docs validation workflow SHALL reject command examples across published module docs that do not match implemented bundle commands and SHALL also reject stale references to migrated core-owned resource paths. #### Scenario: Valid command example passes + - **GIVEN** a docs page references `specfact backlog ceremony standup` - **WHEN** the validation runs - **THEN** it finds a matching registration in the backlog package source - **AND** the check passes +#### Scenario: Published non-bundle docs are validated too + +- **GIVEN** a published module docs page outside `docs/bundles/` contains a command example +- **WHEN** the validation runs +- **THEN** the command example is checked against the implemented mounted command tree +- **AND** stale former command forms are rejected the same way as bundle reference pages + #### Scenario: Invalid command example fails + - **GIVEN** a docs page references `specfact backlog nonexistent` - **WHEN** the validation runs - **THEN** it reports the mismatch - **AND** the check fails #### Scenario: Legacy core-owned resource path reference fails + - **GIVEN** a docs page instructs users to fetch a migrated prompt or template from a legacy core-owned path - **WHEN** the validation runs - **THEN** it reports the stale resource reference - **AND** the check fails + +### Requirement: Published module docs SHALL stay warning-free in docs review + +Published module docs SHALL include Jekyll front matter and valid internal links so the modules docs review run does not rely on warning allowlists for stale pages. + +#### Scenario: Previously tolerated stale docs warnings are removed + +- **GIVEN** a published modules docs page was previously missing front matter or linked to a removed former docs target +- **WHEN** the docs review suite runs +- **THEN** the page is published with required front matter +- **AND** its internal links resolve to current canonical modules docs routes +- **AND** the docs review run completes without warnings diff --git a/openspec/changes/docs-12-docs-validation-ci/tasks.md b/openspec/changes/docs-12-docs-validation-ci/tasks.md index 0fae25b..e55e2ca 100644 --- a/openspec/changes/docs-12-docs-validation-ci/tasks.md +++ b/openspec/changes/docs-12-docs-validation-ci/tasks.md @@ -1,24 +1,27 @@ ## 1. Change Setup -- [ ] 1.1 Update `openspec/CHANGE_ORDER.md` with `docs-12-docs-validation-ci` entry -- [ ] 1.2 Add `modules-docs-command-validation` capability spec +- [x] 1.1 Update `openspec/CHANGE_ORDER.md` with `docs-12-docs-validation-ci` entry +- [x] 1.2 Add `modules-docs-command-validation` capability spec ## 2. Command Validation Script -- [ ] 2.1 Write `scripts/check-docs-commands.py` to extract command registrations from `packages/*/src/**/commands.py` -- [ ] 2.2 Compare extracted commands against code blocks in `docs/bundles/` and `docs/reference/commands.md` -- [ ] 2.3 Flag stale references to legacy core-owned prompt/template locations that were migrated by `packaging-01-bundle-resource-payloads` +- [x] 2.1 Write `scripts/check-docs-commands.py` to extract command registrations from `packages/*/src/**/commands.py` +- [x] 2.2 Compare extracted commands against code blocks in `docs/bundles/` and `docs/reference/commands.md` +- [x] 2.3 Flag stale references to legacy core-owned prompt/template locations that were migrated by `packaging-01-bundle-resource-payloads` +- [x] 2.4 Expand command validation coverage to published module docs across `docs/` ## 3. Cross-Site Link Validation -- [ ] 3.1 Add link validation for cross-site URLs pointing to docs.specfact.io +- [x] 3.1 Add link validation for cross-site URLs pointing to docs.specfact.io ## 4. CI Integration -- [ ] 4.1 Add docs validation step to CI workflow +- [x] 4.1 Add docs validation step to CI workflow ## 5. Verification -- [ ] 5.1 Run validation locally and verify it catches broken examples -- [ ] 5.2 Run validation locally and verify it catches stale core-owned resource path references -- [ ] 5.3 Run CI workflow end-to-end +- [x] 5.1 Run validation locally and verify it catches broken examples +- [x] 5.2 Run validation locally and verify it catches stale core-owned resource path references +- [x] 5.3 Run CI workflow end-to-end via the local docs-review-equivalent validator and test path documented in `TDD_EVIDENCE.md` +- [x] 5.4 Audit repo-wide published docs and remove stale former command references so validation passes with zero findings +- [x] 5.5 Remove the remaining docs-review warnings by adding missing front matter and fixing stale internal links in published docs diff --git a/openspec/specs/enterprise-config-docs/spec.md b/openspec/specs/enterprise-config-docs/spec.md index 88a4eff..6a81188 100644 --- a/openspec/specs/enterprise-config-docs/spec.md +++ b/openspec/specs/enterprise-config-docs/spec.md @@ -1,6 +1,6 @@ # ADDED Requirements -### Requirement: Enterprise configuration docs SHALL cover profiles, overlays, and multi-repo policy +## Requirement: Enterprise configuration docs SHALL cover profiles, overlays, and multi-repo policy Enterprise guidance SHALL explain custom profiles, domain overlays, central configuration, and multi-repo operations using supported commands. diff --git a/openspec/specs/missing-command-docs/spec.md b/openspec/specs/missing-command-docs/spec.md index 19ac640..587e134 100644 --- a/openspec/specs/missing-command-docs/spec.md +++ b/openspec/specs/missing-command-docs/spec.md @@ -1,3 +1,5 @@ +# Missing Command Documentation Specification + ## ADDED Requirements ### Requirement: Missing command reference pages SHALL document the implemented command surface diff --git a/openspec/specs/modules-docs-command-validation/spec.md b/openspec/specs/modules-docs-command-validation/spec.md new file mode 100644 index 0000000..6baa9c7 --- /dev/null +++ b/openspec/specs/modules-docs-command-validation/spec.md @@ -0,0 +1,47 @@ +# Modules Docs Command Validation + +## ADDED Requirements + +### Requirement: Docs validation SHALL reject stale command and resource references + +The modules-side docs validation workflow SHALL reject command examples across published module docs that do not match implemented bundle commands and SHALL also reject stale references to migrated core-owned resource paths. + +#### Scenario: Valid command example passes + +- **GIVEN** a docs page references `specfact backlog ceremony standup` +- **WHEN** the validation runs +- **THEN** it finds a matching registration in the backlog package source +- **AND** the check passes + +#### Scenario: Published non-bundle docs are validated too + +- **GIVEN** a published module docs page outside `docs/bundles/` contains a command example +- **WHEN** the validation runs +- **THEN** the command example is checked against the implemented mounted command tree +- **AND** stale former command forms are rejected the same way as bundle reference pages + +#### Scenario: Invalid command example fails + +- **GIVEN** a docs page references `specfact backlog nonexistent` +- **WHEN** the validation runs +- **THEN** it reports the mismatch +- **AND** the check fails + +#### Scenario: Legacy core-owned resource path reference fails + +- **GIVEN** a docs page instructs users to fetch a migrated prompt or template from a legacy core-owned path +- **WHEN** the validation runs +- **THEN** it reports the stale resource reference +- **AND** the check fails + +### Requirement: Published module docs SHALL stay warning-free in docs review + +Published module docs SHALL include Jekyll front matter and valid internal links so the modules docs review run does not rely on warning allowlists for stale pages. + +#### Scenario: Previously tolerated stale docs warnings are removed + +- **GIVEN** a published modules docs page was previously missing front matter or linked to a removed former docs target +- **WHEN** the docs review suite runs +- **THEN** the page is published with required front matter +- **AND** its internal links resolve to current canonical modules docs routes +- **AND** the docs review run completes without warnings diff --git a/openspec/specs/team-setup-docs/spec.md b/openspec/specs/team-setup-docs/spec.md index 38d60e7..c25db8d 100644 --- a/openspec/specs/team-setup-docs/spec.md +++ b/openspec/specs/team-setup-docs/spec.md @@ -1,6 +1,6 @@ # ADDED Requirements -### Requirement: Team setup docs SHALL cover operational onboarding and resource ownership +## Requirement: Team setup docs SHALL cover operational onboarding and resource ownership Team setup guidance SHALL explain onboarding, shared configuration, role-based workflows, and how bundle-owned prompts/templates are rolled out and kept in sync. diff --git a/pyproject.toml b/pyproject.toml index 074aec1..fa0d8f0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -246,6 +246,7 @@ ignore = [ "tests/**/*" = ["S101", "PLR2004", "T20", "SLF001"] "tools/**/*" = ["T20", "S101", "INP001", "PLR2004"] "packages/**/commands.py" = ["B008"] +"scripts/check-docs-commands.py" = ["N999"] [tool.ruff.lint.isort] force-single-line = false diff --git a/scripts/check-docs-commands.py b/scripts/check-docs-commands.py new file mode 100644 index 0000000..bd28798 --- /dev/null +++ b/scripts/check-docs-commands.py @@ -0,0 +1,298 @@ +#!/usr/bin/env python3 +"""Validate bundle docs command examples, legacy resource paths, and core-doc links.""" + +from __future__ import annotations + +import importlib +import re +import sys +from pathlib import Path +from typing import NamedTuple +from urllib.parse import urlparse + +import click +import yaml +from typer.main import get_command as typer_get_command + + +REPO_ROOT = Path(__file__).resolve().parents[1] +DOCS_ROOT = REPO_ROOT / "docs" +CORE_DOCS_HOST = "docs.specfact.io" +ALLOWED_CORE_DOCS_ROUTES = frozenset({"/", "/reference/documentation-url-contract/"}) +CORE_COMMAND_PREFIXES = frozenset( + { + ("specfact",), + ("specfact", "init"), + ("specfact", "module"), + ("specfact", "upgrade"), + } +) +LEGACY_RESOURCE_PATH_SNIPPETS = ( + ".cursor/commands", + ".claude/commands", + ".claude/instructions", + ".github/prompts", + ".github/instructions", + ".specfact/prompts", + "src/specfact_cli/prompts", + "src/specfact_cli/templates", +) +WORKFLOW_PATH = REPO_ROOT / ".github" / "workflows" / "docs-review.yml" +MARKDOWN_CODE_RE = re.compile(r"`([^`\n]*specfact [^`\n]*)`") +MARKDOWN_LINK_RE = re.compile(r"(? str: + return str(path.relative_to(REPO_ROOT)) + + +def _ensure_package_paths() -> None: + for src_path in sorted((REPO_ROOT / "packages").glob("*/src")): + src = str(src_path) + if src not in sys.path: + sys.path.insert(0, src) + + +def _iter_validation_docs_paths() -> list[Path]: + return sorted(path.resolve() for path in DOCS_ROOT.rglob("*.md")) + + +def _iter_bash_examples(text: str, source: Path) -> list[CommandExample]: + examples: list[CommandExample] = [] + in_bash_block = False + for line_number, raw_line in enumerate(text.splitlines(), start=1): + stripped = raw_line.strip() + if stripped.startswith("```bash"): + in_bash_block = True + continue + if in_bash_block and stripped.startswith("```"): + in_bash_block = False + continue + if in_bash_block and stripped.startswith("specfact "): + examples.append(CommandExample(source=source, line_number=line_number, text=stripped)) + return examples + + +def _iter_inline_examples(text: str, source: Path) -> list[CommandExample]: + examples: list[CommandExample] = [] + for line_number, raw_line in enumerate(text.splitlines(), start=1): + for match in MARKDOWN_CODE_RE.finditer(raw_line): + examples.append(CommandExample(source=source, line_number=line_number, text=match.group(1).strip())) + return examples + + +def _extract_command_examples(path: Path) -> list[CommandExample]: + text = path.read_text(encoding="utf-8") + seen: set[tuple[int, str]] = set() + examples: list[CommandExample] = [] + for example in [*_iter_bash_examples(text, path), *_iter_inline_examples(text, path)]: + key = (example.line_number, example.text) + if key in seen: + continue + seen.add(key) + examples.append(example) + return examples + + +def _load_docs_texts(paths: list[Path]) -> dict[Path, str]: + return {path: path.read_text(encoding="utf-8") for path in paths} + + +def _normalize_command_text(command_text: str) -> list[str]: + normalized = command_text.strip().rstrip(":.,") + return normalized.split() + + +def _collect_click_paths(group: click.Command, prefix: CommandPath) -> set[CommandPath]: + paths: set[CommandPath] = set() + if not isinstance(group, click.Group): + return paths + for name, command in group.commands.items(): + child_prefix = (*prefix, name) + paths.add(child_prefix) + if isinstance(command, click.Group): + paths.update(_collect_click_paths(command, child_prefix)) + return paths + + +def _build_valid_command_paths() -> set[CommandPath]: + _ensure_package_paths() + paths: set[CommandPath] = set(CORE_COMMAND_PREFIXES) + for module_name, attr_name, prefix in MODULE_APP_MOUNTS: + module = importlib.import_module(module_name) + app = getattr(module, attr_name) + click_group = typer_get_command(app) + paths.add(prefix) + paths.update(_collect_click_paths(click_group, prefix)) + return paths + + +def _command_example_is_valid(command_text: str, valid_paths: set[CommandPath]) -> bool: + tokens = _normalize_command_text(command_text) + if not tokens or tokens[0] != "specfact": + return True + if len(tokens) == 1: + return ("specfact",) in valid_paths + if tokens[1].startswith("-"): + return ("specfact",) in valid_paths + prefixes = (tuple(tokens[:length]) for length in range(len(tokens), 0, -1)) + return any(prefix in valid_paths for prefix in prefixes if len(prefix) > 1) + + +def _validate_command_examples(text_by_path: dict[Path, str], valid_paths: set[CommandPath]) -> list[ValidationFinding]: + findings: list[ValidationFinding] = [] + for path, text in text_by_path.items(): + seen: set[tuple[int, str]] = set() + for example in [*_iter_bash_examples(text, path), *_iter_inline_examples(text, path)]: + key = (example.line_number, example.text) + if key in seen: + continue + seen.add(key) + if _command_example_is_valid(example.text, valid_paths): + continue + findings.append( + ValidationFinding( + category="command", + source=example.source, + line_number=example.line_number, + message=f"Unknown command example: {example.text}", + ) + ) + return findings + + +def _validate_legacy_resource_paths(text_by_path: dict[Path, str]) -> list[ValidationFinding]: + findings: list[ValidationFinding] = [] + for path, text in text_by_path.items(): + for line_number, raw_line in enumerate(text.splitlines(), start=1): + for snippet in LEGACY_RESOURCE_PATH_SNIPPETS: + if snippet not in raw_line: + continue + findings.append( + ValidationFinding( + category="legacy-resource", + source=path, + line_number=line_number, + message=f"Legacy core-owned resource reference: {snippet}", + ) + ) + return findings + + +def _normalize_core_docs_route(url: str) -> str | None: + parsed = urlparse(url) + if parsed.scheme not in {"http", "https"} or parsed.netloc != CORE_DOCS_HOST: + return None + route = parsed.path or "/" + if route != "/" and not route.endswith("/"): + route += "/" + return route + + +def _iter_core_docs_urls_from_text(text: str) -> list[str]: + urls: list[str] = [] + for link in MARKDOWN_LINK_RE.findall(text): + urls.append(link) + for link in HTML_HREF_RE.findall(text): + urls.append(link) + return urls + + +def _validate_core_docs_links(text_by_path: dict[Path, str]) -> list[ValidationFinding]: + findings: list[ValidationFinding] = [] + for path, text in text_by_path.items(): + for line_number, raw_line in enumerate(text.splitlines(), start=1): + for url in _iter_core_docs_urls_from_text(raw_line): + route = _normalize_core_docs_route(url) + if route is None or route in ALLOWED_CORE_DOCS_ROUTES: + continue + findings.append( + ValidationFinding( + category="cross-site-link", + source=path, + line_number=line_number, + message=f"Unsupported docs.specfact.io route: {url}", + ) + ) + return findings + + +def _validate_core_docs_config(config_path: Path) -> list[ValidationFinding]: + data = yaml.safe_load(config_path.read_text(encoding="utf-8")) or {} + findings: list[ValidationFinding] = [] + for key in ("docs_home_url", "core_cli_docs_url"): + value = str(data.get(key, "")).strip() + route = _normalize_core_docs_route(value) + if route in ALLOWED_CORE_DOCS_ROUTES: + continue + findings.append( + ValidationFinding( + category="cross-site-link", + source=config_path, + line_number=1, + message=f"{key} must target an allowed docs.specfact.io route: {value or ''}", + ) + ) + return findings + + +def _format_findings(findings: list[ValidationFinding]) -> str: + return "\n".join( + f"{_script_name(finding.source)}:{finding.line_number}: [{finding.category}] {finding.message}" + for finding in findings + ) + + +def _main() -> int: + docs_paths = _iter_validation_docs_paths() + text_by_path = _load_docs_texts(docs_paths) + valid_paths = _build_valid_command_paths() + findings = [ + *_validate_command_examples(text_by_path, valid_paths), + *_validate_legacy_resource_paths(text_by_path), + *_validate_core_docs_links(text_by_path), + *_validate_core_docs_config(DOCS_ROOT / "_config.yml"), + ] + if findings: + sys.stdout.write(_format_findings(findings) + "\n") + return 1 + sys.stdout.write("Docs command validation passed with no findings.\n") + return 0 + + +if __name__ == "__main__": + raise SystemExit(_main()) diff --git a/tests/unit/docs/test_docs_review.py b/tests/unit/docs/test_docs_review.py index 3423298..1f20590 100644 --- a/tests/unit/docs/test_docs_review.py +++ b/tests/unit/docs/test_docs_review.py @@ -500,8 +500,8 @@ def test_daily_devops_routine_bundle_links() -> None: expected_links = { "Morning standup": "[Backlog bundle overview](/bundles/backlog/overview/)", "Refinement": "[Cross-module chains](/guides/cross-module-chains/)", - "Development": "[AI IDE workflow](/guides/ai-ide-workflow/)", - "Review": "[Contract testing workflow](/guides/contract-testing-workflow/)", + "Development": "[AI IDE workflow](/ai-ide-workflow/)", + "Review": "[Contract testing workflow](/contract-testing-workflow/)", "End-of-day": "[Govern enforce](/bundles/govern/enforce/)", } diff --git a/tests/unit/test_check_docs_commands_script.py b/tests/unit/test_check_docs_commands_script.py new file mode 100644 index 0000000..04dfa0b --- /dev/null +++ b/tests/unit/test_check_docs_commands_script.py @@ -0,0 +1,135 @@ +from __future__ import annotations + +from pathlib import Path + +from tests.unit._script_test_utils import load_module_from_path + + +REPO_ROOT = Path(__file__).resolve().parents[2] +SCRIPT_PATH = REPO_ROOT / "scripts" / "check-docs-commands.py" + + +def _load_script(): + return load_module_from_path("check_docs_commands", SCRIPT_PATH) + + +def _script_attr(script, name: str): + return getattr(script, name) + + +def test_extract_command_examples_reads_bash_and_inline_examples(tmp_path: Path) -> None: + script = _load_script() + doc_path = tmp_path / "example.md" + doc_path.write_text( + """ +# Example + +`specfact backlog refine --help` + +```bash +specfact code review run --help +``` +""".strip() + + "\n", + encoding="utf-8", + ) + + examples = _script_attr(script, "_extract_command_examples")(doc_path) + + assert [example.text for example in examples] == [ + "specfact code review run --help", + "specfact backlog refine --help", + ] + + +def test_iter_bash_examples_accepts_fence_suffixes(tmp_path: Path) -> None: + script = _load_script() + doc_path = tmp_path / "fenced.md" + text = """ +```bash {#commands} +specfact backlog refine --help +``` +""".strip() + + examples = _script_attr(script, "_iter_bash_examples")(text, doc_path) + + assert [example.text for example in examples] == ["specfact backlog refine --help"] + + +def test_command_example_is_valid_accepts_longest_matching_prefix() -> None: + script = _load_script() + valid_paths = { + ("specfact",), + ("specfact", "backlog", "refine"), + ("specfact", "code", "review", "run"), + } + + assert _script_attr(script, "_command_example_is_valid")( + "specfact code review run packages/specfact-code-review/src/specfact_code_review/run/commands.py", + valid_paths, + ) + assert not _script_attr(script, "_command_example_is_valid")("specfact backlog nonexistent --help", valid_paths) + + +def test_command_example_is_valid_allows_root_help_but_not_unknown_subgroups() -> None: + script = _load_script() + valid_paths = { + ("specfact",), + ("specfact", "backlog"), + ("specfact", "backlog", "refine"), + } + + assert _script_attr(script, "_command_example_is_valid")("specfact --help", valid_paths) + assert _script_attr(script, "_command_example_is_valid")("specfact -h", valid_paths) + assert not _script_attr(script, "_command_example_is_valid")("specfact policy validate --repo .", valid_paths) + + +def test_validate_legacy_resource_paths_reports_stale_core_owned_paths(tmp_path: Path) -> None: + script = _load_script() + doc_path = tmp_path / "legacy.md" + doc_path.write_text( + "Copy the prompt from src/specfact_cli/prompts/review.md before running the workflow.\n", + encoding="utf-8", + ) + + findings = _script_attr(script, "_validate_legacy_resource_paths")({doc_path: doc_path.read_text(encoding="utf-8")}) + + assert len(findings) == 1 + assert findings[0].category == "legacy-resource" + assert "src/specfact_cli/prompts" in findings[0].message + + +def test_validate_core_docs_links_rejects_unknown_route(tmp_path: Path) -> None: + script = _load_script() + doc_path = tmp_path / "links.md" + doc_path.write_text( + "[Broken](https://docs.specfact.io/missing/page/)\n" + "[Allowed](https://docs.specfact.io/reference/documentation-url-contract/)\n", + encoding="utf-8", + ) + + findings = _script_attr(script, "_validate_core_docs_links")({doc_path: doc_path.read_text(encoding="utf-8")}) + + assert len(findings) == 1 + assert findings[0].category == "cross-site-link" + assert "missing/page" in findings[0].message + + +def test_docs_review_workflow_runs_docs_command_validation() -> None: + workflow = (REPO_ROOT / ".github" / "workflows" / "docs-review.yml").read_text(encoding="utf-8") + + assert "python -m pip install pytest click typer PyYAML beartype icontract rich pydantic specfact-cli" in workflow + assert "python scripts/check-docs-commands.py" in workflow + assert "scripts/check-docs-commands.py" in workflow + assert "tests/unit/test_check_docs_commands_script.py" in workflow + + +def test_iter_validation_docs_paths_scans_repo_wide_docs_tree() -> None: + script = _load_script() + + paths = _script_attr(script, "_iter_validation_docs_paths")() + relative_paths = {path.relative_to(REPO_ROOT).as_posix() for path in paths} + + assert "docs/bundles/backlog/overview.md" in relative_paths + assert "docs/getting-started/README.md" in relative_paths + assert "docs/integrations/devops-adapter-overview.md" in relative_paths