From 1e13fd63f1b31ce84f0e03b6914a90643f394487 Mon Sep 17 00:00:00 2001 From: Dyan Galih Date: Wed, 27 May 2026 00:12:55 +0000 Subject: [PATCH 01/10] feat: generate community extensions index from catalog --- src/specify_cli/community_catalog_docs.py | 94 +++++++++++++++++++ src/specify_cli/extensions/_commands.py | 23 +++++ tests/test_community_catalog_docs.py | 107 ++++++++++++++++++++++ 3 files changed, 224 insertions(+) create mode 100644 src/specify_cli/community_catalog_docs.py create mode 100644 tests/test_community_catalog_docs.py diff --git a/src/specify_cli/community_catalog_docs.py b/src/specify_cli/community_catalog_docs.py new file mode 100644 index 0000000000..d505d8d8f1 --- /dev/null +++ b/src/specify_cli/community_catalog_docs.py @@ -0,0 +1,94 @@ +"""Helpers for rendering the community extensions reference table.""" + +from __future__ import annotations + +import json +from pathlib import Path +from typing import Any + + +ROOT_DIR = Path(__file__).resolve().parents[2] +COMMUNITY_CATALOG_PATH = ROOT_DIR / "extensions" / "catalog.community.json" + + +def _render_cell(value: str) -> str: + return value.replace("\r\n", " ").replace("\r", " ").replace("\n", " ").replace("|", "\\|") + + +def _format_tags(tags: Any) -> str: + if not isinstance(tags, list) or not tags: + return "—" + # Clean first, then filter: a tag of " | " would pass str(tag).strip() but produce + # an empty backtick span after pipe removal, so filter on the cleaned value. + cleaned = [f"`{c}`" for tag in tags if (c := str(tag).replace("|", "").strip())] + return ", ".join(cleaned) if cleaned else "—" + + +def list_community_extensions(path: Path = COMMUNITY_CATALOG_PATH) -> list[dict[str, Any]]: + """Return community extensions sorted alphabetically by name then ID.""" + if not path.exists(): + raise FileNotFoundError( + f"Community catalog not found: {path}. " + "The --markdown flag requires a spec-kit source checkout." + ) + data = json.loads(path.read_text(encoding="utf-8")) + if not isinstance(data, dict): + raise ValueError(f"Expected {path} to contain a JSON object") + extensions = data.get("extensions") + if not isinstance(extensions, dict): + raise ValueError(f"Expected {path} to contain an 'extensions' object") + + rows: list[dict[str, Any]] = [] + for ext_id, ext in extensions.items(): + if not isinstance(ext, dict): + raise ValueError(f"Community extension {ext_id!r} must be a mapping") + rows.append( + { + "name": str(ext.get("name") or ext_id), + "id": str(ext.get("id") or ext_id), + "description": str(ext.get("description") or ""), + "tags": ext.get("tags") or [], + "verified": "Yes" if bool(ext.get("verified")) else "No", + "repository": str(ext.get("repository") or ""), + } + ) + + return sorted(rows, key=lambda row: (row["name"].casefold(), row["id"].casefold())) + + +def render_community_extensions_table(path: Path = COMMUNITY_CATALOG_PATH) -> str: + """Render the community extensions table from catalog.community.json.""" + rows = list_community_extensions(path=path) + if not rows: + raise ValueError("Community catalog has no extensions") + + table_rows: list[list[str]] = [] + for row in rows: + # Escape raw field values *before* composing Markdown syntax so that + # a pipe inside a name or description doesn't break a link target. + safe_name = _render_cell(row["name"]) + link = ( + f"[{safe_name}]({row['repository']})" + if row["repository"] + else safe_name + ) + table_rows.append( + [ + link, + f"`{row['id']}`", + _render_cell(row["description"]), + _format_tags(row["tags"]), + row["verified"], + ] + ) + + headers = ("Extension", "ID", "Description", "Tags", "Verified") + + def render_row(values: list[str]) -> str: + # Values are already escaped; do not re-apply _render_cell here. + return "| " + " | ".join(values) + " |" + + separator = "| " + " | ".join("---" for _ in headers) + " |" + lines = [render_row(list(headers)), separator] + lines.extend(render_row(row) for row in table_rows) + return "\n".join(lines) + "\n" diff --git a/src/specify_cli/extensions/_commands.py b/src/specify_cli/extensions/_commands.py index 3b60b6d52d..732600ffe2 100644 --- a/src/specify_cli/extensions/_commands.py +++ b/src/specify_cli/extensions/_commands.py @@ -704,8 +704,31 @@ def extension_search( tag: Optional[str] = typer.Option(None, "--tag", help="Filter by tag"), author: Optional[str] = typer.Option(None, "--author", help="Filter by author"), verified: bool = typer.Option(False, "--verified", help="Show only verified extensions"), + markdown: bool = typer.Option( + False, + "--markdown", + help=( + "Output the full community catalog as a markdown table " + "(ignores query/tag/author/verified filters)" + ), + ), ): """Search for available extensions in catalog.""" + if markdown: + if query or tag or author or verified: + console.print( + "[yellow]Warning:[/yellow] --markdown outputs the full community catalog " + "and ignores filters (query, --tag, --author, --verified)." + ) + from ..community_catalog_docs import render_community_extensions_table + + try: + typer.echo(render_community_extensions_table()) + except (ValueError, FileNotFoundError) as exc: + console.print(f"[red]Error:[/red] {exc}") + raise typer.Exit(1) + return + from . import ExtensionCatalog, ExtensionError project_root = _require_specify_project() diff --git a/tests/test_community_catalog_docs.py b/tests/test_community_catalog_docs.py new file mode 100644 index 0000000000..15d9c7be69 --- /dev/null +++ b/tests/test_community_catalog_docs.py @@ -0,0 +1,107 @@ +from __future__ import annotations + +import json +from pathlib import Path + +import pytest + +from specify_cli.community_catalog_docs import list_community_extensions, render_community_extensions_table + + +def _write_catalog(tmp_path: Path, extensions: dict) -> Path: + p = tmp_path / "catalog.community.json" + p.write_text(json.dumps({"extensions": extensions}), encoding="utf-8") + return p + + +# --------------------------------------------------------------------------- +# Happy-path tests against the real catalog +# --------------------------------------------------------------------------- + +def test_community_extensions_table_renders() -> None: + table = render_community_extensions_table() + assert "| Extension" in table + assert "| ID" in table + assert "| Description" in table + assert "| Tags" in table + assert "| Verified" in table + + +def test_community_extensions_are_sorted_by_name() -> None: + rows = list_community_extensions() + names = [row["name"] for row in rows] + assert names == sorted(names, key=str.casefold) + + +# --------------------------------------------------------------------------- +# Edge-case tests using synthetic catalogs +# --------------------------------------------------------------------------- + +def test_missing_catalog_file(tmp_path: Path) -> None: + with pytest.raises(FileNotFoundError, match="spec-kit source checkout"): + list_community_extensions(path=tmp_path / "missing.json") + + +def test_malformed_json(tmp_path: Path) -> None: + bad = tmp_path / "bad.json" + bad.write_text("not valid json", encoding="utf-8") + with pytest.raises(json.JSONDecodeError): + list_community_extensions(path=bad) + + +def test_non_dict_root(tmp_path: Path) -> None: + f = tmp_path / "catalog.json" + f.write_text(json.dumps([{"id": "foo"}]), encoding="utf-8") + with pytest.raises(ValueError, match="JSON object"): + list_community_extensions(path=f) + + +def test_missing_extensions_key(tmp_path: Path) -> None: + f = tmp_path / "catalog.json" + f.write_text(json.dumps({"other": {}}), encoding="utf-8") + with pytest.raises(ValueError, match="'extensions' object"): + list_community_extensions(path=f) + + +def test_non_dict_extension_value(tmp_path: Path) -> None: + f = _write_catalog(tmp_path, {"foo": "not-a-dict"}) + with pytest.raises(ValueError, match="must be a mapping"): + list_community_extensions(path=f) + + +def test_empty_catalog_raises(tmp_path: Path) -> None: + f = _write_catalog(tmp_path, {}) + with pytest.raises(ValueError, match="no extensions"): + render_community_extensions_table(path=f) + + +def test_extension_without_repository(tmp_path: Path) -> None: + f = _write_catalog(tmp_path, { + "foo": {"name": "Foo", "id": "foo", "description": "A foo tool", "tags": [], "verified": False, "repository": ""}, + }) + table = render_community_extensions_table(path=f) + assert "Foo" in table + assert "[Foo](" not in table # plain name, no link + + +def test_tags_containing_pipe_do_not_break_table(tmp_path: Path) -> None: + f = _write_catalog(tmp_path, { + # No "id" field — exercises ext_id fallback; tag has pipe — exercises stripping + "foo": {"name": "Foo", "description": "", "tags": ["foo|bar"], "verified": False, "repository": ""}, + }) + table = render_community_extensions_table(path=f) + # pipe stripped from tag value + assert "`foobar`" in table + # id falls back to the dict key when "id" field is absent + assert "`foo`" in table + # row is well-formed: 5-column table has exactly 6 pipe separators per row + foo_row = next(line for line in table.split("\n") if line.startswith("| ") and "Foo" in line) + assert foo_row.count("|") == 6 + + +def test_non_list_tags_renders_em_dash(tmp_path: Path) -> None: + f = _write_catalog(tmp_path, { + "foo": {"name": "Foo", "description": "", "tags": "not-a-list", "verified": False, "repository": ""}, + }) + table = render_community_extensions_table(path=f) + assert "—" in table From 16ce990ef7b1f4c7c2b50c208174ae9acb8d7231 Mon Sep 17 00:00:00 2001 From: Dyan Galih Date: Thu, 28 May 2026 16:55:14 +0000 Subject: [PATCH 02/10] fix: resolve community docs rebase conflicts --- docs/community/extensions.md | 141 +---------------------------- tests/test_utils_assets_imports.py | 13 ++- 2 files changed, 13 insertions(+), 141 deletions(-) diff --git a/docs/community/extensions.md b/docs/community/extensions.md index 6b2df7a5d1..3dbdd8a7e4 100644 --- a/docs/community/extensions.md +++ b/docs/community/extensions.md @@ -7,146 +7,7 @@ The following community-contributed extensions are available in [`catalog.community.json`](https://github.com/github/spec-kit/blob/main/extensions/catalog.community.json): -**Categories** (common values, but any string is allowed): +> Run `specify extension search --markdown` to regenerate this table. -- `docs` — reads, validates, or generates spec artifacts -- `code` — reviews, validates, or modifies source code -- `process` — orchestrates workflow across phases -- `integration` — syncs with external platforms -- `visibility` — reports on project health or progress - -**Effect** (canonical `extension.yml`/catalog values): - -- `read-only` — produces reports without modifying files (displayed as `Read-only` in the table) -- `read-write` — modifies files, creates artifacts, or updates specs (displayed as `Read+Write` in the table) - -> [!TIP] -> Extension authors can declare `category` and `effect` in their `extension.yml` under the `extension:` block. These fields are also available in `catalog.community.json` for tooling and the CLI (`specify extension info`). - -| Extension | Purpose | Category | Effect | URL | -|-----------|---------|----------|--------|-----| -| Agent Assign | Assign specialized Claude Code agents to spec-kit tasks for targeted execution | `process` | Read+Write | [spec-kit-agent-assign](https://github.com/xymelon/spec-kit-agent-assign) | -| Agent Governance | Generate agent-platform repository governance files from Spec Kit metadata | `process` | Read+Write | [spec-kit-agent-governance](https://github.com/bigsmartben/spec-kit-agent-governance) | -| AI-Driven Engineering (AIDE) | A structured 7-step workflow for building new projects from scratch with AI assistants — from vision through implementation | `process` | Read+Write | [aide](https://github.com/mnriem/spec-kit-extensions/tree/main/aide) | -| API Evolve | Managed API contract evolution — breaking-change detection, semver enforcement, deprecation orchestration, and lifecycle gates across REST, GraphQL, and gRPC | `process` | Read+Write | [spec-kit-api-evolve](https://github.com/Quratulain-bilal/spec-kit-api-evolve) | -| Architect Impact Previewer | Predicts architectural impact, complexity, and risks of proposed changes before implementation. | `visibility` | Read-only | [spec-kit-architect-preview](https://github.com/UmmeHabiba1312/spec-kit-architect-preview) | -| Architecture Guard | Framework-agnostic architecture review extension for validating implementation against governance and architecture constitutions, detecting architectural drift, and generating non-blocking refactor tasks | `process` | Read+Write | [spec-kit-architecture-guard](https://github.com/DyanGalih/spec-kit-architecture-guard) | -| Architecture Workflow | Generate or reverse project-level 4+1 architecture views as separate commands | `docs` | Read+Write | [spec-kit-arch](https://github.com/bigsmartben/spec-kit-arch) | -| Archive Extension | Archive merged features into main project memory. | `docs` | Read+Write | [spec-kit-archive](https://github.com/stn1slv/spec-kit-archive) | -| Azure DevOps Integration | Sync user stories and tasks to Azure DevOps work items using OAuth authentication | `integration` | Read+Write | [spec-kit-azure-devops](https://github.com/pragya247/spec-kit-azure-devops) | -| Blueprint | Stay code-literate in AI-driven development: review a complete code blueprint for every task from spec artifacts before /speckit.implement runs | `docs` | Read+Write | [spec-kit-blueprint](https://github.com/chordpli/spec-kit-blueprint) | -| Branch Convention | Configurable branch and folder naming conventions for /specify with presets and custom patterns | `process` | Read+Write | [spec-kit-branch-convention](https://github.com/Quratulain-bilal/spec-kit-branch-convention) | -| Brownfield Bootstrap | Bootstrap spec-kit for existing codebases — auto-discover architecture and adopt SDD incrementally | `process` | Read+Write | [spec-kit-brownfield](https://github.com/Quratulain-bilal/spec-kit-brownfield) | -| BrownKit | Evidence-driven capability discovery, security and QA risk assessment for existing codebases | `process` | Read+Write | [BrownKit](https://github.com/MaksimShevtsov/BrownKit) | -| Bugfix Workflow | Structured bugfix workflow — capture bugs, trace to spec artifacts, and patch specs surgically | `process` | Read+Write | [spec-kit-bugfix](https://github.com/Quratulain-bilal/spec-kit-bugfix) | -| Canon | Adds canon-driven (baseline-driven) workflows: spec-first, code-first, spec-drift. Requires Canon Core preset installation. | `process` | Read+Write | [spec-kit-canon](https://github.com/maximiliamus/spec-kit-canon/tree/master/extension) | -| Catalog CI | Automated validation for spec-kit community catalog entries — structure, URLs, diffs, and linting | `process` | Read-only | [spec-kit-catalog-ci](https://github.com/Quratulain-bilal/spec-kit-catalog-ci) | -| CI Guard | Spec compliance gates for CI/CD — verify specs exist, check drift, and block merges on gaps | `process` | Read-only | [spec-kit-ci-guard](https://github.com/Quratulain-bilal/spec-kit-ci-guard) | -| Checkpoint Extension | Commit the changes made during the middle of the implementation, so you don't end up with just one very large commit at the end | `code` | Read+Write | [spec-kit-checkpoint](https://github.com/aaronrsun/spec-kit-checkpoint) | -| Cleanup Extension | Post-implementation quality gate that reviews changes, fixes small issues (scout rule), creates tasks for medium issues, and generates analysis for large issues | `code` | Read+Write | [spec-kit-cleanup](https://github.com/dsrednicki/spec-kit-cleanup) | -| Coding Standards Drift Control | Generate coding-standards drift reports and remediation tasks for active Spec Kit features | `code` | Read+Write | [spec-kit-coding-standards-drift-control](https://github.com/benizzio/spec-kit-coding-standards-drift-control) | -| Conduct Extension | Orchestrates spec-kit phases via sub-agent delegation to reduce context pollution. | `process` | Read+Write | [spec-kit-conduct-ext](https://github.com/twbrandon7/spec-kit-conduct-ext) | -| Confluence Extension | Create a doc in Confluence summarizing the specifications and planning files | `integration` | Read+Write | [spec-kit-confluence](https://github.com/aaronrsun/spec-kit-confluence) | -| Cost Tracker | Track real LLM dollar cost across SDD workflows — per-feature budgets, per-integration comparison, and finance-ready exports | `visibility` | Read+Write | [spec-kit-cost](https://github.com/Quratulain-bilal/spec-kit-cost) | -| Data Model Diagram | Generates Mermaid ER diagrams from Spec Kit data models after planning | `docs` | Read+Write | [spec-kit-data-model-diagram](https://github.com/benizzio/spec-kit-data-model-diagram) | -| DocGuard — CDD Enforcement | Canonical-Driven Development enforcement. Validates, scores, and traces project documentation with automated checks, AI-driven workflows, and spec-kit hooks. One pinned runtime dependency; pure Node.js otherwise. | `docs` | Read+Write | [spec-kit-docguard](https://github.com/raccioly/docguard) | -| Extensify | Create and validate extensions and extension catalogs | `process` | Read+Write | [extensify](https://github.com/mnriem/spec-kit-extensions/tree/main/extensify) | -| Fix Findings | Automated analyze-fix-reanalyze loop that resolves spec findings until clean | `code` | Read+Write | [spec-kit-fix-findings](https://github.com/Quratulain-bilal/spec-kit-fix-findings) | -| FixIt Extension | Spec-aware bug fixing — maps bugs to spec artifacts, proposes a plan, applies minimal changes | `code` | Read+Write | [spec-kit-fixit](https://github.com/speckit-community/spec-kit-fixit) | -| Fleet Orchestrator | Orchestrate a full feature lifecycle with human-in-the-loop gates across all SpecKit phases | `process` | Read+Write | [spec-kit-fleet](https://github.com/sharathsatish/spec-kit-fleet) | -| GitHub Issues Integration 1 | Generate spec artifacts from GitHub Issues - import issues, sync updates, and maintain bidirectional traceability | `integration` | Read+Write | [spec-kit-github-issues](https://github.com/Fatima367/spec-kit-github-issues) | -| GitHub Issues Integration 2 | Creates and syncs local specs from an existing GitHub issue | `integration` | Read+Write | [spec-kit-issue](https://github.com/aaronrsun/spec-kit-issue) | -| Golden Demo | Extracts acceptance criteria from specs, builds test vectors, and produces a behavioral drift report — complementary to Architecture Guard and CDD | `docs` | Read+Write | [spec-kit-golden-demo](https://github.com/jasstt/spec-kit-golden-demo) | -| Improve Extension | Audits any codebase as a senior advisor and writes prioritized, self-contained spec prompts under specs/ that the spec-kit lifecycle can process | `process` | Read+Write | [spec-kit-improve](https://github.com/d0whc3r/spec-kit-improve) | -| Intake | Normalize PRD, design, and test-case evidence into SDD-ready intake artifacts | `docs` | Read+Write | [spec-kit-intake](https://github.com/bigsmartben/spec-kit-intake) | -| Intelligent Agent Orchestrator | Cross-catalog agent discovery and intelligent prompt-to-command routing | `process` | Read+Write | [spec-kit-orchestrator](https://github.com/pragya247/spec-kit-orchestrator) | -| Iterate | Iterate on spec documents with a two-phase define-and-apply workflow — refine specs mid-implementation and go straight back to building | `docs` | Read+Write | [spec-kit-iterate](https://github.com/imviancagrace/spec-kit-iterate) | -| Jira Integration | Create Jira Epics, Stories, and Issues from spec-kit specifications and task breakdowns with configurable hierarchy and custom field support | `integration` | Read+Write | [spec-kit-jira](https://github.com/mbachorik/spec-kit-jira) | -| Jira Integration (Sync Engine) | Idempotent, drift-aware, fail-closed reconcile engine mirroring spec-kit specs into Jira (Epic per repo, Story per spec, Subtask per phase) | `integration` | Read+Write | [spec-kit-jira-sync](https://github.com/ashbrener/spec-kit-jira-sync) | -| Learning Extension | Generate educational guides from implementations and enhance clarifications with mentoring context | `docs` | Read+Write | [spec-kit-learn](https://github.com/imviancagrace/spec-kit-learn) | -| Linear Integration | Mirror spec-kit feature directories into Linear (filesystem → Linear, reconcile-based, unidirectional). | `integration` | Read+Write | [spec-kit-linear-sync](https://github.com/ashbrener/spec-kit-linear-sync) | -| Loop Engineering | Engineer safe autonomous agent loops for spec-driven development: a maker/checker split, externalized loop state, and stay-the-engineer guardrails against comprehension debt and cognitive surrender | `process` | Read+Write | [spec-kit-loop](https://github.com/formin/spec-kit-loop) | -| MAQA — Multi-Agent & Quality Assurance | Coordinator → feature → QA agent workflow with parallel worktree-based implementation. Language-agnostic. Auto-detects installed board plugins. Optional CI gate. | `process` | Read+Write | [spec-kit-maqa-ext](https://github.com/GenieRobot/spec-kit-maqa-ext) | -| MAQA Azure DevOps Integration | Azure DevOps Boards integration for MAQA — syncs User Stories and Task children as features progress | `integration` | Read+Write | [spec-kit-maqa-azure-devops](https://github.com/GenieRobot/spec-kit-maqa-azure-devops) | -| MAQA CI/CD Gate | Auto-detects GitHub Actions, CircleCI, GitLab CI, and Bitbucket Pipelines. Blocks QA handoff until pipeline is green. | `process` | Read+Write | [spec-kit-maqa-ci](https://github.com/GenieRobot/spec-kit-maqa-ci) | -| MAQA GitHub Projects Integration | GitHub Projects v2 integration for MAQA — syncs draft issues and Status columns as features progress | `integration` | Read+Write | [spec-kit-maqa-github-projects](https://github.com/GenieRobot/spec-kit-maqa-github-projects) | -| MAQA Jira Integration | Jira integration for MAQA — syncs Stories and Subtasks as features progress through the board | `integration` | Read+Write | [spec-kit-maqa-jira](https://github.com/GenieRobot/spec-kit-maqa-jira) | -| MAQA Linear Integration | Linear integration for MAQA — syncs issues and sub-issues across workflow states as features progress | `integration` | Read+Write | [spec-kit-maqa-linear](https://github.com/GenieRobot/spec-kit-maqa-linear) | -| MAQA Trello Integration | Trello board integration for MAQA — populates board from specs, moves cards, real-time checklist ticking | `integration` | Read+Write | [spec-kit-maqa-trello](https://github.com/GenieRobot/spec-kit-maqa-trello) | -| MarkItDown Document Converter | Convert documents (PDF, Word, PowerPoint, Excel, and more) to Markdown for use as spec reference material | `docs` | Read+Write | [spec-kit-markitdown](https://github.com/BenBtg/spec-kit-markitdown) | -| MDE | Minimal model-driven engineering workflow with setup, next, and status commands | `process` | Read+Write | [spec-kit-mde](https://github.com/AI-MDE/spec-kit-mde) | -| Memory Loader | Loads .specify/memory/ files before lifecycle commands so LLM agents have project governance context | `docs` | Read-only | [spec-kit-memory-loader](https://github.com/KevinBrown5280/spec-kit-memory-loader) | -| Memory MD | Spec Kit extension for repository-native Markdown memory that captures durable decisions, bugs, and project context | `docs` | Read+Write | [spec-kit-memory-hub](https://github.com/DyanGalih/spec-kit-memory-hub) | -| MemoryLint | Evidence-driven instruction drift checker: audits agent memory files for boundary, reality, conflict, and redundancy drift. | `process` | Read+Write | [memorylint](https://github.com/RbBtSn0w/spec-kit-extensions/tree/main/memorylint) | -| Microsoft 365 Integration | Fetch Teams messages, meeting transcripts, and SharePoint/OneDrive files as local Markdown for spec generation | `integration` | Read+Write | [spec-kit-m365](https://github.com/BenBtg/spec-kit-m365) | -| Multi-Model Review | Cross-model Spec Kit handoffs for spec authoring, implementation routing, and review. | `process` | Read+Write | [multi-model-review](https://github.com/formin/multi-model-review) | -| Multi-Sites Spec Kit | Multi-site aware specify command with per-site spec folders, auto-increment, and Drupal support | `process` | Read+Write | [spec-kit-multi-sites](https://github.com/teeyo/spec-kit-multi-sites) | -| .NET Framework to Modern .NET Migration | Orchestrate end-to-end .NET Framework to modern .NET migration across 7 phases, with SDD lifecycle integration | `process` | Read+Write | [spec-kit-fx-to-net](https://github.com/RogerBestMsft/spec-kit-FxToNet) | -| Onboard | Contextual onboarding and progressive growth for developers new to spec-kit projects. Explains specs, maps dependencies, validates understanding, and guides the next step | `process` | Read+Write | [spec-kit-onboard](https://github.com/dmux/spec-kit-onboard) | -| Optimize | Audit and optimize AI governance for context efficiency — token budgets, rule health, interpretability, compression, coherence, and echo detection | `process` | Read+Write | [spec-kit-optimize](https://github.com/sakitA/spec-kit-optimize) | -| OWASP LLM Threat Model | OWASP Top 10 for LLM Applications 2025 threat analysis on agent artifacts | `code` | Read-only | [spec-kit-threatmodel](https://github.com/NaviaSamal/spec-kit-threatmodel) | -| Plan Review Gate | Require spec.md and plan.md to be merged via MR/PR before allowing task generation | `process` | Read-only | [spec-kit-plan-review-gate](https://github.com/luno/spec-kit-plan-review-gate) | -| PR Bridge | Auto-generate pull request descriptions, checklists, and summaries from spec artifacts | `process` | Read-only | [spec-kit-pr-bridge-](https://github.com/Quratulain-bilal/spec-kit-pr-bridge-) | -| Presetify | Create and validate presets and preset catalogs | `process` | Read+Write | [presetify](https://github.com/mnriem/spec-kit-extensions/tree/main/presetify) | -| Product Forge | Full product-lifecycle orchestrator for Spec Kit: research → product-spec → plan → tasks → implement → verify → test → release-readiness, across express/lite/standard/v-model modes with human-in-the-loop gates. | `process` | Read+Write | [speckit-product-forge](https://github.com/VaiYav/speckit-product-forge) | -| Product Spec Extension | Generates PRFAQ, Lean PRD, stakeholder summaries, and technical designs from engineering specs | `docs` | Read+Write | [spec-kit-product](https://github.com/d0whc3r/spec-kit-product) | -| Project Health Check | Diagnose a Spec Kit project and report health issues across structure, agents, features, scripts, extensions, and git | `visibility` | Read-only | [spec-kit-doctor](https://github.com/KhawarHabibKhan/spec-kit-doctor) | -| Project Status | Show current SDD workflow progress — active feature, artifact status, task completion, workflow phase, and extensions summary | `visibility` | Read-only | [spec-kit-status](https://github.com/KhawarHabibKhan/spec-kit-status) | -| QA Testing Extension | Systematic QA testing with browser-driven or CLI-based validation of acceptance criteria from spec | `code` | Read-only | [spec-kit-qa](https://github.com/arunt14/spec-kit-qa) | -| RAG Azure Builder | Spec Kit extension for onboarding and operating an Azure RAG stack with guided workflows. | `process` | Read+Write | [spec-kit-extension-rag-azure-builder](https://github.com/Sertxito/spec-kit-extension-rag-azure-builder) | -| Ralph Loop | Autonomous implementation loop using AI agent CLI | `code` | Read+Write | [spec-kit-ralph](https://github.com/Rubiss-Projects/spec-kit-ralph) | -| Reconcile Extension | Reconcile implementation drift by surgically updating feature artifacts. | `docs` | Read+Write | [spec-kit-reconcile](https://github.com/stn1slv/spec-kit-reconcile) | -| Red Team | Adversarial review of specs before /speckit.plan — parallel lens agents surface risks that clarify/analyze structurally can't (prompt injection, integrity gaps, cross-spec drift, silent failures). Produces a structured findings report; no auto-edits to specs. | `docs` | Read+Write | [spec-kit-red-team](https://github.com/ashbrener/spec-kit-red-team) | -| Research Harness | State-externalizing research harness: budgeted exploration, evidence curation, and claim verification for spec-driven development | `process` | Read+Write | [spec-kit-harness](https://github.com/formin/spec-kit-harness) | -| Repository Index | Generate index for existing repo for overview, architecture and module level. | `docs` | Read-only | [spec-kit-repoindex](https://github.com/liuyiyu/spec-kit-repoindex) | -| Reqnroll BDD | Adds Reqnroll BDD planning, Gherkin generation, traceability, safe task injection, handoff, and verification to Spec Kit | `process` | Read+Write | [spec-kit-reqnroll-bdd](https://github.com/LoogacyStudio/spec-kit-reqnroll-bdd) | -| Retro Extension | Sprint retrospective analysis with metrics, spec accuracy assessment, and improvement suggestions | `process` | Read+Write | [spec-kit-retro](https://github.com/arunt14/spec-kit-retro) | -| Retrospective Extension | Post-implementation retrospective with spec adherence scoring, drift analysis, and human-gated spec updates | `docs` | Read+Write | [spec-kit-retrospective](https://github.com/emi-dm/spec-kit-retrospective) | -| Review Extension | Post-implementation comprehensive code review with specialized agents for code quality, comments, tests, error handling, type design, and simplification | `code` | Read-only | [spec-kit-review](https://github.com/ismaelJimenez/spec-kit-review) | -| Ripple | Detect side effects that tests can't catch after implementation — delta-anchored analysis across 9 domain-agnostic categories | `code` | Read+Write | [spec-kit-ripple](https://github.com/chordpli/spec-kit-ripple) | -| SDD Utilities | Resume interrupted workflows, validate project health, and verify spec-to-task traceability | `process` | Read+Write | [speckit-utils](https://github.com/mvanhorn/speckit-utils) | -| Security Review | Full-project secure-by-design security audits plus staged, branch/PR, plan, task, follow-up, and apply reviews | `code` | Read+Write | [spec-kit-security-review](https://github.com/DyanGalih/spec-kit-security-review) | -| SFSpeckit | Enterprise Salesforce SDLC with 18 commands for the full SDD lifecycle. | `process` | Read+Write | [spec-kit-sf](https://github.com/ysumanth06/spec-kit-sf) | -| Ship Release Extension | Automates release pipeline: pre-flight checks, branch sync, changelog generation, CI verification, and PR creation | `process` | Read+Write | [spec-kit-ship](https://github.com/arunt14/spec-kit-ship) | -| Spec Changelog | Auto-generate changelogs and release notes from spec git history and requirement diffs | `docs` | Read-only | [spec-kit-changelog](https://github.com/Quratulain-bilal/spec-kit-changelog) | -| Spec Critique Extension | Dual-lens critical review of spec and plan from product strategy and engineering risk perspectives | `docs` | Read-only | [spec-kit-critique](https://github.com/arunt14/spec-kit-critique) | -| Spec Diagram | Auto-generate Mermaid diagrams of SDD workflow state, feature progress, and task dependencies | `visibility` | Read-only | [spec-kit-diagram-](https://github.com/Quratulain-bilal/spec-kit-diagram-) | -| Spec Kit Discovery Extension | Run technical discovery commands for feasibility, technology selection, scenario-specific technical decisions, legacy codebase assessment, implementation understanding, and proof-of-concept validation | `process` | Read+Write | [spec-kit-discovery](https://github.com/bigsmartben/spec-kit-discovery) | -| Spec Kit Preview | Generate evidence-backed low, mid, or high fidelity previews from Spec Kit artifacts as Markdown or self-contained HTML | `docs` | Read+Write | [spec-kit-preview](https://github.com/bigsmartben/spec-kit-preview) | -| Spec Kit Schedule | Optimal multi-agent task scheduling via CP-SAT — DAG precedence, hallucination-aware caps, file-conflict avoidance, stochastic durations, replanning, and interactive HTML output | `process` | Read+Write | [spec-kit-schedule](https://github.com/jfranc38/spec-kit-schedule) | -| Spec Kit TLDR | Render a feature's spec.md / plan.md into a review-oriented TLDR (self-contained HTML dashboard + PR-native Markdown) that surfaces risks for faster PR review. | `visibility` | Read+Write | [speckit-tldr](https://github.com/qurore/speckit-tldr) | -| Spec Orchestrator | Cross-feature orchestration — track state, select tasks, and detect conflicts across parallel specs | `process` | Read-only | [spec-kit-orchestrator](https://github.com/Quratulain-bilal/spec-kit-orchestrator) | -| Spec Reference Loader | Reads the ## References section from the feature spec and loads only the listed docs into context | `docs` | Read-only | [spec-kit-spec-reference-loader](https://github.com/KevinBrown5280/spec-kit-spec-reference-loader) | -| Spec Refine | Update specs in-place, propagate changes to plan and tasks, and diff impact across artifacts | `process` | Read+Write | [spec-kit-refine](https://github.com/Quratulain-bilal/spec-kit-refine) | -| Spec Roadmap | Capture a durable spec roadmap after the constitution, then review specs against it before and after implementation so spec-specific decisions, outcomes, and constraints are never lost. | `process` | Read+Write | [speckit-roadmap](https://github.com/srobroek/speckit-roadmap) | -| Spec Scope | Effort estimation and scope tracking — estimate work, detect creep, and budget time per phase | `process` | Read-only | [spec-kit-scope-](https://github.com/Quratulain-bilal/spec-kit-scope-) | -| Spec Sync | Detect and resolve drift between specs and implementation. AI-assisted resolution with human approval | `docs` | Read+Write | [spec-kit-sync](https://github.com/bgervin/spec-kit-sync) | -| Spec Trace | Build a requirement → test traceability matrix from spec.md and the test suite — surface untested requirements and orphan tests | `code` | Read+Write | [spec-kit-trace](https://github.com/Quratulain-bilal/spec-kit-trace) | -| Spec Validate | Comprehension validation, review gating, and approval state for spec-kit artifacts — staged quizzes, peer review SLA, and a hard gate before /speckit.implement | `process` | Read+Write | [spec-kit-spec-validate](https://github.com/aeltayeb/spec-kit-spec-validate) | -| Spec2Cloud | Spec-driven workflow tuned for shipping to Azure | `process` | Read+Write | [spec2cloud](https://github.com/Azure-Samples/Spec2Cloud) | -| SpecKit Companion | Live spec-driven progress — lifecycle capture, status, resume, and a turbo pipeline profile | `visibility` | Read+Write | [speckit-companion](https://github.com/alfredoperez/speckit-companion) | -| SpecTest | Auto-generate test scaffolds from spec criteria, map coverage, and find untested requirements | `code` | Read+Write | [spec-kit-spectest](https://github.com/Quratulain-bilal/spec-kit-spectest) | -| Squad Bridge | Bootstrap and synchronize a Squad agent team from your Speckit spec and tasks. | `process` | Read+Write | [spec-kit-squad](https://github.com/jwill824/spec-kit-squad) | -| Staff Review Extension | Staff-engineer-level code review that validates implementation against spec, checks security, performance, and test coverage | `code` | Read-only | [spec-kit-staff-review](https://github.com/arunt14/spec-kit-staff-review) | -| Status Report | Project status, feature progress, and next-action recommendations for spec-driven workflows | `visibility` | Read-only | [Open-Agent-Tools/spec-kit-status](https://github.com/Open-Agent-Tools/spec-kit-status) | -| Superpowers Bridge | Bridges selected Superpowers disciplines into Spec Kit as evidence-first trust gates for agent workflows. | `process` | Read+Write | [superpowers-bridge](https://github.com/RbBtSn0w/spec-kit-extensions/tree/main/superpowers-bridge) | -| Superpowers Implementation Bridge | Thin orchestrator between Spec Kit (design) and Superpowers (implementation). Cross-agent. | `process` | Read+Write | [speckit-superpowers-bridge](https://github.com/lihan3238/speckit-superpowers-bridge) | -| Superspec | Bridges spec-kit with obra/superpowers (brainstorming, TDD, subagent, code-review) into a unified, resumable workflow with graceful degradation and session progress tracking | `process` | Read+Write | [superspec](https://github.com/WangX0111/superspec) | -| Tasks to GitHub Project | Publish and synchronize Spec Kit tasks as cards on a GitHub Project (v2) kanban board, with priority and status sync between spec.md/tasks.md and the board. | `integration` | Read+Write | [spec-kit-tasks-to-project](https://github.com/mancioshell/spec-kit-tasks-to-project) | -| Team Assign | Assign tasks.md items to human engineers, split into subtasks, and generate a per-engineer workboard | `process` | Read+Write | [spec-kit-team-assign](https://github.com/tarunkumarbhati/spec-kit-team-assign) | -| Time Machine | Retroactively apply the full SDD workflow to existing codebases — analyse, spec, and ship feature-by-feature | `process` | Read+Write | [spec-kit-time-machine](https://github.com/teeyo/spec-kit-time-machine) | -| TinySpec | Lightweight single-file workflow for small tasks — skip the heavy multi-step SDD process | `process` | Read+Write | [spec-kit-tinyspec](https://github.com/Quratulain-bilal/spec-kit-tinyspec) | -| Token Budget | Reduces LLM token consumption in Spec Kit workflows: compact artifacts in-place, scope per-phase reading, suppress prose padding, and report token usage | `process` | Read+Write | [spec-kit-token-budget](https://github.com/tinesoft/spec-kit-token-budget) | -| Token Consumption Analyzer | Captures, analyzes, and compares token consumption across SDD workflows | `visibility` | Read-only | [spec-kit-token-analyzer](https://github.com/coderandhiker/spec-kit-token-analyzer) | -| Token Economy | Token routing, measured savings, and context audit workflows | `process` | Read+Write | [spec-kit-token-economy](https://github.com/formin/spec-kit-token-economy) | -| V-Model Extension Pack | Enforces V-Model paired generation of development specs and test specs with full traceability | `docs` | Read+Write | [spec-kit-v-model](https://github.com/leocamello/spec-kit-v-model) | -| Verify Extension | Post-implementation quality gate that validates implemented code against specification artifacts | `code` | Read-only | [spec-kit-verify](https://github.com/ismaelJimenez/spec-kit-verify) | -| Verify Tasks Extension | Detect phantom completions: tasks marked [X] in tasks.md with no real implementation | `code` | Read-only | [spec-kit-verify-tasks](https://github.com/datastone-inc/spec-kit-verify-tasks) | -| Version Guard | Verify tech stack versions against live npm registries before planning and implementation | `process` | Read-only | [spec-kit-version-guard](https://github.com/KevinBrown5280/spec-kit-version-guard) | -| What-if Analysis | Preview the downstream impact (complexity, effort, tasks, risks) of requirement changes before committing to them | `visibility` | Read-only | [spec-kit-whatif](https://github.com/DevAbdullah90/spec-kit-whatif) | -| Wireframe Visual Feedback Loop | SVG wireframe generation, review, and sign-off for spec-driven development. Approved wireframes become spec constraints honored by /speckit.plan, /speckit.tasks, and /speckit.implement | `visibility` | Read+Write | [spec-kit-extension-wireframe](https://github.com/TortoiseWolfe/spec-kit-extension-wireframe) | -| Work IQ | Integrate Microsoft 365 organizational knowledge into spec-driven development workflows | `integration` | Read-only | [spec-kit-workiq](https://github.com/sakitA/spec-kit-workiq) | -| Worktree Isolation | Spawn isolated git worktrees for parallel feature development without checkout switching | `process` | Read+Write | [spec-kit-worktree](https://github.com/Quratulain-bilal/spec-kit-worktree) | -| Worktrees | Default-on worktree isolation for parallel agents — sibling or nested layout | `process` | Read+Write | [spec-kit-worktree-parallel](https://github.com/dango85/spec-kit-worktree-parallel) | To submit your own extension, see the [Extension Publishing Guide](https://github.com/github/spec-kit/blob/main/extensions/EXTENSION-PUBLISHING-GUIDE.md). diff --git a/tests/test_utils_assets_imports.py b/tests/test_utils_assets_imports.py index 8a41fa5e97..cbe9bb4437 100644 --- a/tests/test_utils_assets_imports.py +++ b/tests/test_utils_assets_imports.py @@ -1,10 +1,13 @@ """Regression guard: utility and asset symbols importable from specify_cli.""" +import importlib.metadata +import tomllib +from pathlib import Path + from specify_cli import ( check_tool, merge_json_files, get_speckit_version, CLAUDE_LOCAL_PATH, CLAUDE_NPM_LOCAL_PATH, ) -from pathlib import Path def test_utils_symbols_importable(): assert callable(check_tool) @@ -14,6 +17,14 @@ def test_get_speckit_version_returns_string(): version = get_speckit_version() assert isinstance(version, str) and len(version) > 0 +def test_get_speckit_version_prefers_checked_out_pyproject(monkeypatch): + monkeypatch.setattr(importlib.metadata, "version", lambda name: "0.0.0") + + with open(Path(__file__).resolve().parents[1] / "pyproject.toml", "rb") as f: + expected_version = tomllib.load(f)["project"]["version"] + + assert get_speckit_version() == expected_version + def test_claude_paths_are_paths(): assert isinstance(CLAUDE_LOCAL_PATH, Path) assert isinstance(CLAUDE_NPM_LOCAL_PATH, Path) From efe252f6ae444f32f2e8b91dd73b6b60199657c3 Mon Sep 17 00:00:00 2001 From: Dyan Galih Date: Thu, 28 May 2026 17:07:51 +0000 Subject: [PATCH 03/10] chore: drop unrelated review fixes --- tests/test_utils_assets_imports.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/tests/test_utils_assets_imports.py b/tests/test_utils_assets_imports.py index cbe9bb4437..8a41fa5e97 100644 --- a/tests/test_utils_assets_imports.py +++ b/tests/test_utils_assets_imports.py @@ -1,13 +1,10 @@ """Regression guard: utility and asset symbols importable from specify_cli.""" -import importlib.metadata -import tomllib -from pathlib import Path - from specify_cli import ( check_tool, merge_json_files, get_speckit_version, CLAUDE_LOCAL_PATH, CLAUDE_NPM_LOCAL_PATH, ) +from pathlib import Path def test_utils_symbols_importable(): assert callable(check_tool) @@ -17,14 +14,6 @@ def test_get_speckit_version_returns_string(): version = get_speckit_version() assert isinstance(version, str) and len(version) > 0 -def test_get_speckit_version_prefers_checked_out_pyproject(monkeypatch): - monkeypatch.setattr(importlib.metadata, "version", lambda name: "0.0.0") - - with open(Path(__file__).resolve().parents[1] / "pyproject.toml", "rb") as f: - expected_version = tomllib.load(f)["project"]["version"] - - assert get_speckit_version() == expected_version - def test_claude_paths_are_paths(): assert isinstance(CLAUDE_LOCAL_PATH, Path) assert isinstance(CLAUDE_NPM_LOCAL_PATH, Path) From 4c9a37f886c7ece7c5e35ca3fa7a7453ee5818e8 Mon Sep 17 00:00:00 2001 From: Dyan Galih Date: Thu, 28 May 2026 17:11:45 +0000 Subject: [PATCH 04/10] revert: use upstream main versions --- src/specify_cli/community_catalog_docs.py | 94 ----------------------- 1 file changed, 94 deletions(-) delete mode 100644 src/specify_cli/community_catalog_docs.py diff --git a/src/specify_cli/community_catalog_docs.py b/src/specify_cli/community_catalog_docs.py deleted file mode 100644 index d505d8d8f1..0000000000 --- a/src/specify_cli/community_catalog_docs.py +++ /dev/null @@ -1,94 +0,0 @@ -"""Helpers for rendering the community extensions reference table.""" - -from __future__ import annotations - -import json -from pathlib import Path -from typing import Any - - -ROOT_DIR = Path(__file__).resolve().parents[2] -COMMUNITY_CATALOG_PATH = ROOT_DIR / "extensions" / "catalog.community.json" - - -def _render_cell(value: str) -> str: - return value.replace("\r\n", " ").replace("\r", " ").replace("\n", " ").replace("|", "\\|") - - -def _format_tags(tags: Any) -> str: - if not isinstance(tags, list) or not tags: - return "—" - # Clean first, then filter: a tag of " | " would pass str(tag).strip() but produce - # an empty backtick span after pipe removal, so filter on the cleaned value. - cleaned = [f"`{c}`" for tag in tags if (c := str(tag).replace("|", "").strip())] - return ", ".join(cleaned) if cleaned else "—" - - -def list_community_extensions(path: Path = COMMUNITY_CATALOG_PATH) -> list[dict[str, Any]]: - """Return community extensions sorted alphabetically by name then ID.""" - if not path.exists(): - raise FileNotFoundError( - f"Community catalog not found: {path}. " - "The --markdown flag requires a spec-kit source checkout." - ) - data = json.loads(path.read_text(encoding="utf-8")) - if not isinstance(data, dict): - raise ValueError(f"Expected {path} to contain a JSON object") - extensions = data.get("extensions") - if not isinstance(extensions, dict): - raise ValueError(f"Expected {path} to contain an 'extensions' object") - - rows: list[dict[str, Any]] = [] - for ext_id, ext in extensions.items(): - if not isinstance(ext, dict): - raise ValueError(f"Community extension {ext_id!r} must be a mapping") - rows.append( - { - "name": str(ext.get("name") or ext_id), - "id": str(ext.get("id") or ext_id), - "description": str(ext.get("description") or ""), - "tags": ext.get("tags") or [], - "verified": "Yes" if bool(ext.get("verified")) else "No", - "repository": str(ext.get("repository") or ""), - } - ) - - return sorted(rows, key=lambda row: (row["name"].casefold(), row["id"].casefold())) - - -def render_community_extensions_table(path: Path = COMMUNITY_CATALOG_PATH) -> str: - """Render the community extensions table from catalog.community.json.""" - rows = list_community_extensions(path=path) - if not rows: - raise ValueError("Community catalog has no extensions") - - table_rows: list[list[str]] = [] - for row in rows: - # Escape raw field values *before* composing Markdown syntax so that - # a pipe inside a name or description doesn't break a link target. - safe_name = _render_cell(row["name"]) - link = ( - f"[{safe_name}]({row['repository']})" - if row["repository"] - else safe_name - ) - table_rows.append( - [ - link, - f"`{row['id']}`", - _render_cell(row["description"]), - _format_tags(row["tags"]), - row["verified"], - ] - ) - - headers = ("Extension", "ID", "Description", "Tags", "Verified") - - def render_row(values: list[str]) -> str: - # Values are already escaped; do not re-apply _render_cell here. - return "| " + " | ".join(values) + " |" - - separator = "| " + " | ".join("---" for _ in headers) + " |" - lines = [render_row(list(headers)), separator] - lines.extend(render_row(row) for row in table_rows) - return "\n".join(lines) + "\n" From d6ac19381ccd4c6266f1d8a28f71f84817990b17 Mon Sep 17 00:00:00 2001 From: Dyan Galih Date: Thu, 28 May 2026 17:13:09 +0000 Subject: [PATCH 05/10] Revert "revert: use upstream main versions" This reverts commit a180619d07bb33d344357cdfd03154db56ab9db7. --- tests/test_community_catalog_docs.py | 107 --------------------------- 1 file changed, 107 deletions(-) delete mode 100644 tests/test_community_catalog_docs.py diff --git a/tests/test_community_catalog_docs.py b/tests/test_community_catalog_docs.py deleted file mode 100644 index 15d9c7be69..0000000000 --- a/tests/test_community_catalog_docs.py +++ /dev/null @@ -1,107 +0,0 @@ -from __future__ import annotations - -import json -from pathlib import Path - -import pytest - -from specify_cli.community_catalog_docs import list_community_extensions, render_community_extensions_table - - -def _write_catalog(tmp_path: Path, extensions: dict) -> Path: - p = tmp_path / "catalog.community.json" - p.write_text(json.dumps({"extensions": extensions}), encoding="utf-8") - return p - - -# --------------------------------------------------------------------------- -# Happy-path tests against the real catalog -# --------------------------------------------------------------------------- - -def test_community_extensions_table_renders() -> None: - table = render_community_extensions_table() - assert "| Extension" in table - assert "| ID" in table - assert "| Description" in table - assert "| Tags" in table - assert "| Verified" in table - - -def test_community_extensions_are_sorted_by_name() -> None: - rows = list_community_extensions() - names = [row["name"] for row in rows] - assert names == sorted(names, key=str.casefold) - - -# --------------------------------------------------------------------------- -# Edge-case tests using synthetic catalogs -# --------------------------------------------------------------------------- - -def test_missing_catalog_file(tmp_path: Path) -> None: - with pytest.raises(FileNotFoundError, match="spec-kit source checkout"): - list_community_extensions(path=tmp_path / "missing.json") - - -def test_malformed_json(tmp_path: Path) -> None: - bad = tmp_path / "bad.json" - bad.write_text("not valid json", encoding="utf-8") - with pytest.raises(json.JSONDecodeError): - list_community_extensions(path=bad) - - -def test_non_dict_root(tmp_path: Path) -> None: - f = tmp_path / "catalog.json" - f.write_text(json.dumps([{"id": "foo"}]), encoding="utf-8") - with pytest.raises(ValueError, match="JSON object"): - list_community_extensions(path=f) - - -def test_missing_extensions_key(tmp_path: Path) -> None: - f = tmp_path / "catalog.json" - f.write_text(json.dumps({"other": {}}), encoding="utf-8") - with pytest.raises(ValueError, match="'extensions' object"): - list_community_extensions(path=f) - - -def test_non_dict_extension_value(tmp_path: Path) -> None: - f = _write_catalog(tmp_path, {"foo": "not-a-dict"}) - with pytest.raises(ValueError, match="must be a mapping"): - list_community_extensions(path=f) - - -def test_empty_catalog_raises(tmp_path: Path) -> None: - f = _write_catalog(tmp_path, {}) - with pytest.raises(ValueError, match="no extensions"): - render_community_extensions_table(path=f) - - -def test_extension_without_repository(tmp_path: Path) -> None: - f = _write_catalog(tmp_path, { - "foo": {"name": "Foo", "id": "foo", "description": "A foo tool", "tags": [], "verified": False, "repository": ""}, - }) - table = render_community_extensions_table(path=f) - assert "Foo" in table - assert "[Foo](" not in table # plain name, no link - - -def test_tags_containing_pipe_do_not_break_table(tmp_path: Path) -> None: - f = _write_catalog(tmp_path, { - # No "id" field — exercises ext_id fallback; tag has pipe — exercises stripping - "foo": {"name": "Foo", "description": "", "tags": ["foo|bar"], "verified": False, "repository": ""}, - }) - table = render_community_extensions_table(path=f) - # pipe stripped from tag value - assert "`foobar`" in table - # id falls back to the dict key when "id" field is absent - assert "`foo`" in table - # row is well-formed: 5-column table has exactly 6 pipe separators per row - foo_row = next(line for line in table.split("\n") if line.startswith("| ") and "Foo" in line) - assert foo_row.count("|") == 6 - - -def test_non_list_tags_renders_em_dash(tmp_path: Path) -> None: - f = _write_catalog(tmp_path, { - "foo": {"name": "Foo", "description": "", "tags": "not-a-list", "verified": False, "repository": ""}, - }) - table = render_community_extensions_table(path=f) - assert "—" in table From 7806cc67c26e64195dc58cdb8e75f171e4a97aca Mon Sep 17 00:00:00 2001 From: Dyan Galih Date: Thu, 28 May 2026 17:39:33 +0000 Subject: [PATCH 06/10] fix: align prerelease and docs rendering behavior --- src/specify_cli/community_catalog_docs.py | 107 ++++++++++++++++ src/specify_cli/extensions/__init__.py | 2 +- src/specify_cli/presets/__init__.py | 2 +- tests/test_community_catalog_docs.py | 141 ++++++++++++++++++++++ tests/test_extensions.py | 8 ++ tests/test_presets.py | 6 + 6 files changed, 264 insertions(+), 2 deletions(-) create mode 100644 src/specify_cli/community_catalog_docs.py create mode 100644 tests/test_community_catalog_docs.py diff --git a/src/specify_cli/community_catalog_docs.py b/src/specify_cli/community_catalog_docs.py new file mode 100644 index 0000000000..8d0accb1a0 --- /dev/null +++ b/src/specify_cli/community_catalog_docs.py @@ -0,0 +1,107 @@ +"""Helpers for rendering the community extensions reference table.""" + +from __future__ import annotations + +import json +import re +from pathlib import Path +from typing import Any + + +ROOT_DIR = Path(__file__).resolve().parents[2] +COMMUNITY_CATALOG_PATH = ROOT_DIR / "extensions" / "catalog.community.json" + + +def _render_cell(value: str) -> str: + return value.replace("\r\n", " ").replace("\r", " ").replace("\n", " ").replace("|", "\\|") + + +def _format_inline_code(value: str) -> str: + text = _render_cell(value) + runs = [len(match) for match in re.findall(r"`+", text)] + fence = "`" * (max(runs, default=0) + 1) + return f"{fence}{text}{fence}" + + +def _sanitize_link_target(value: str) -> str: + return value.replace("\r\n", "").replace("\r", "").replace("\n", "").replace("|", "%7C") + + +def _format_tags(tags: Any) -> str: + if not isinstance(tags, list) or not tags: + return "—" + # Clean first, then filter: a tag of " | " would pass str(tag).strip() but produce + # an empty code span after pipe removal, so filter on the cleaned value. + cleaned = [_format_inline_code(c) for tag in tags if (c := str(tag).replace("|", "").strip())] + return ", ".join(cleaned) if cleaned else "—" + + +def list_community_extensions(path: Path = COMMUNITY_CATALOG_PATH) -> list[dict[str, Any]]: + """Return community extensions sorted alphabetically by name then ID.""" + if not path.exists(): + raise FileNotFoundError( + f"Community catalog not found: {path}. " + "The --markdown flag requires a spec-kit source checkout." + ) + data = json.loads(path.read_text(encoding="utf-8")) + if not isinstance(data, dict): + raise ValueError(f"Expected {path} to contain a JSON object") + extensions = data.get("extensions") + if not isinstance(extensions, dict): + raise ValueError(f"Expected {path} to contain an 'extensions' object") + + rows: list[dict[str, Any]] = [] + for ext_id, ext in extensions.items(): + if not isinstance(ext, dict): + raise ValueError(f"Community extension {ext_id!r} must be a mapping") + rows.append( + { + "name": str(ext.get("name") or ext_id), + "id": str(ext.get("id") or ext_id), + "description": str(ext.get("description") or ""), + "tags": ext.get("tags") or [], + "verified": "Yes" if bool(ext.get("verified")) else "No", + "repository": str(ext.get("repository") or ""), + } + ) + + return sorted(rows, key=lambda row: (row["name"].casefold(), row["id"].casefold())) + + +def render_community_extensions_table(path: Path = COMMUNITY_CATALOG_PATH) -> str: + """Render the community extensions table from catalog.community.json.""" + rows = list_community_extensions(path=path) + if not rows: + raise ValueError("Community catalog has no extensions") + + table_rows: list[list[str]] = [] + for row in rows: + # Escape raw field values *before* composing Markdown syntax so that + # a pipe inside a name or description doesn't break a link target. + safe_name = _render_cell(row["name"]) + safe_repository = _sanitize_link_target(row["repository"]) + link = ( + f"[{safe_name}]({safe_repository})" + if safe_repository + else safe_name + ) + table_rows.append( + [ + link, + _format_inline_code(row["id"]), + _render_cell(row["description"]), + _format_tags(row["tags"]), + row["verified"], + ] + ) + + headers = ("Extension", "ID", "Description", "Tags", "Verified") + + def render_row(values: list[str]) -> str: + # Values are already escaped; do not re-apply _render_cell here. + return "| " + " | ".join(values) + " |" + + separator = "| " + " | ".join("---" for _ in headers) + " |" + lines = [render_row(list(headers)), separator] + lines.extend(render_row(row) for row in table_rows) + return "\n".join(lines) + "\n" diff --git a/src/specify_cli/extensions/__init__.py b/src/specify_cli/extensions/__init__.py index 9271a9fde6..14d5e15889 100644 --- a/src/specify_cli/extensions/__init__.py +++ b/src/specify_cli/extensions/__init__.py @@ -1284,7 +1284,7 @@ def check_compatibility( # Parse version specifier (e.g., ">=0.1.0,<2.0.0") try: specifier = SpecifierSet(required) - if current not in specifier: + if not specifier.contains(current, prereleases=True): raise CompatibilityError( f"Extension requires spec-kit {required}, " f"but {speckit_version} is installed.\n" diff --git a/src/specify_cli/presets/__init__.py b/src/specify_cli/presets/__init__.py index 8d5c044193..adba993f01 100644 --- a/src/specify_cli/presets/__init__.py +++ b/src/specify_cli/presets/__init__.py @@ -576,7 +576,7 @@ def check_compatibility( try: specifier = SpecifierSet(required) - if current not in specifier: + if not specifier.contains(current, prereleases=True): raise PresetCompatibilityError( f"Preset requires spec-kit {required}, " f"but {speckit_version} is installed.\n" diff --git a/tests/test_community_catalog_docs.py b/tests/test_community_catalog_docs.py new file mode 100644 index 0000000000..2cb9417eef --- /dev/null +++ b/tests/test_community_catalog_docs.py @@ -0,0 +1,141 @@ +from __future__ import annotations + +import json +from pathlib import Path + +import pytest +from specify_cli.community_catalog_docs import list_community_extensions, render_community_extensions_table + + +def _write_catalog(tmp_path: Path, extensions: dict) -> Path: + p = tmp_path / "catalog.community.json" + p.write_text(json.dumps({"extensions": extensions}), encoding="utf-8") + return p + + +# --------------------------------------------------------------------------- +# Happy-path tests against the real catalog +# --------------------------------------------------------------------------- + +def test_community_extensions_table_renders() -> None: + table = render_community_extensions_table() + assert "| Extension" in table + assert "| ID" in table + assert "| Description" in table + assert "| Tags" in table + assert "| Verified" in table + + +def test_community_extensions_are_sorted_by_name() -> None: + rows = list_community_extensions() + names = [row["name"] for row in rows] + assert names == sorted(names, key=str.casefold) + + +# --------------------------------------------------------------------------- +# Edge-case tests using synthetic catalogs +# --------------------------------------------------------------------------- + +def test_missing_catalog_file(tmp_path: Path) -> None: + with pytest.raises(FileNotFoundError, match="spec-kit source checkout"): + list_community_extensions(path=tmp_path / "missing.json") + + +def test_malformed_json(tmp_path: Path) -> None: + bad = tmp_path / "bad.json" + bad.write_text("not valid json", encoding="utf-8") + with pytest.raises(json.JSONDecodeError): + list_community_extensions(path=bad) + + +def test_non_dict_root(tmp_path: Path) -> None: + f = tmp_path / "catalog.json" + f.write_text(json.dumps([{"id": "foo"}]), encoding="utf-8") + with pytest.raises(ValueError, match="JSON object"): + list_community_extensions(path=f) + + +def test_missing_extensions_key(tmp_path: Path) -> None: + f = tmp_path / "catalog.json" + f.write_text(json.dumps({"other": {}}), encoding="utf-8") + with pytest.raises(ValueError, match="'extensions' object"): + list_community_extensions(path=f) + + +def test_non_dict_extension_value(tmp_path: Path) -> None: + f = _write_catalog(tmp_path, {"foo": "not-a-dict"}) + with pytest.raises(ValueError, match="must be a mapping"): + list_community_extensions(path=f) + + +def test_empty_catalog_raises(tmp_path: Path) -> None: + f = _write_catalog(tmp_path, {}) + with pytest.raises(ValueError, match="no extensions"): + render_community_extensions_table(path=f) + + +def test_extension_without_repository(tmp_path: Path) -> None: + f = _write_catalog(tmp_path, { + "foo": {"name": "Foo", "id": "foo", "description": "A foo tool", "tags": [], "verified": False, "repository": ""}, + }) + table = render_community_extensions_table(path=f) + assert "Foo" in table + assert "[Foo](" not in table # plain name, no link + + +def test_backticks_in_ids_and_tags_render_safely(tmp_path: Path) -> None: + f = _write_catalog(tmp_path, { + "foo": { + "name": "Foo", + "id": "foo`bar", + "description": "", + "tags": ["a`b"], + "verified": False, + "repository": "", + }, + }) + table = render_community_extensions_table(path=f) + assert "``foo`bar``" in table + assert "``a`b``" in table + foo_row = next(line for line in table.split("\n") if line.startswith("| ") and "Foo" in line) + assert foo_row.count("|") == 6 + + +def test_repository_values_are_sanitized_for_table_cells(tmp_path: Path) -> None: + f = _write_catalog(tmp_path, { + "foo": { + "name": "Foo", + "id": "foo", + "description": "", + "tags": [], + "verified": False, + "repository": "https://example.com/a|b\nnext", + }, + }) + table = render_community_extensions_table(path=f) + assert "https://example.com/a%7Cbnext" in table + foo_row = next(line for line in table.split("\n") if line.startswith("| ") and "Foo" in line) + assert foo_row.count("|") == 6 + + +def test_tags_containing_pipe_do_not_break_table(tmp_path: Path) -> None: + f = _write_catalog(tmp_path, { + # No "id" field — exercises ext_id fallback; tag has pipe — exercises stripping + "foo": {"name": "Foo", "description": "", "tags": ["foo|bar"], "verified": False, "repository": ""}, + }) + table = render_community_extensions_table(path=f) + # pipe stripped from tag value + assert "`foobar`" in table + # id falls back to the dict key when "id" field is absent + assert "`foo`" in table + # row is well-formed: 5-column table has exactly 6 pipe separators per row + foo_row = next(line for line in table.split("\n") if line.startswith("| ") and "Foo" in line) + assert foo_row.count("|") == 6 + + +def test_non_list_tags_renders_em_dash(tmp_path: Path) -> None: + f = _write_catalog(tmp_path, { + "foo": {"name": "Foo", "description": "", "tags": "not-a-list", "verified": False, "repository": ""}, + }) + table = render_community_extensions_table(path=f) + assert "—" in table diff --git a/tests/test_extensions.py b/tests/test_extensions.py index e8dc2b7beb..4b9ae96c12 100644 --- a/tests/test_extensions.py +++ b/tests/test_extensions.py @@ -992,6 +992,14 @@ def test_check_compatibility_valid(self, extension_dir, project_dir): result = manager.check_compatibility(manifest, "0.1.0") assert result is True + def test_check_compatibility_allows_prerelease_dev_version(self, extension_dir, project_dir): + """Test compatibility check allows source/dev prerelease versions.""" + manager = ExtensionManager(project_dir) + manifest = ExtensionManifest(extension_dir / "extension.yml") + + result = manager.check_compatibility(manifest, "0.8.15.dev0") + assert result is True + def test_check_compatibility_invalid(self, extension_dir, project_dir): """Test compatibility check with invalid version.""" manager = ExtensionManager(project_dir) diff --git a/tests/test_presets.py b/tests/test_presets.py index 0632fe3a89..a3edeec71b 100644 --- a/tests/test_presets.py +++ b/tests/test_presets.py @@ -710,6 +710,12 @@ def test_check_compatibility_valid(self, pack_dir, temp_dir): manifest = PresetManifest(pack_dir / "preset.yml") assert manager.check_compatibility(manifest, "0.1.5") is True + def test_check_compatibility_allows_prerelease_dev_version(self, pack_dir, temp_dir): + """Test compatibility check allows source/dev prerelease versions.""" + manager = PresetManager(temp_dir) + manifest = PresetManifest(pack_dir / "preset.yml") + assert manager.check_compatibility(manifest, "0.8.15.dev0") is True + def test_check_compatibility_invalid(self, pack_dir, temp_dir): """Test compatibility check with invalid specifier.""" manager = PresetManager(temp_dir) From b3ed73b8af15b3ed1b5ad3588ce2ae54032bb494 Mon Sep 17 00:00:00 2001 From: Dyan Galih Date: Fri, 26 Jun 2026 03:01:48 +0000 Subject: [PATCH 07/10] fix: address PR 2564 feedback --- src/specify_cli/extensions/_commands.py | 9 +++++---- tests/test_community_catalog_docs.py | 8 ++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/specify_cli/extensions/_commands.py b/src/specify_cli/extensions/_commands.py index 732600ffe2..50cb2076dd 100644 --- a/src/specify_cli/extensions/_commands.py +++ b/src/specify_cli/extensions/_commands.py @@ -708,8 +708,8 @@ def extension_search( False, "--markdown", help=( - "Output the full community catalog as a markdown table " - "(ignores query/tag/author/verified filters)" + "Contributor-only utility to output the full community catalog " + "as a markdown table (cannot be used with filters)" ), ), ): @@ -717,9 +717,10 @@ def extension_search( if markdown: if query or tag or author or verified: console.print( - "[yellow]Warning:[/yellow] --markdown outputs the full community catalog " - "and ignores filters (query, --tag, --author, --verified)." + "[red]Error:[/red] The --markdown flag outputs the full community catalog " + "and cannot be used with filters (query, --tag, --author, --verified)." ) + raise typer.Exit(1) from ..community_catalog_docs import render_community_extensions_table try: diff --git a/tests/test_community_catalog_docs.py b/tests/test_community_catalog_docs.py index 2cb9417eef..5782b58507 100644 --- a/tests/test_community_catalog_docs.py +++ b/tests/test_community_catalog_docs.py @@ -139,3 +139,11 @@ def test_non_list_tags_renders_em_dash(tmp_path: Path) -> None: }) table = render_community_extensions_table(path=f) assert "—" in table + +def test_community_extensions_markdown_rejects_filters() -> None: + from typer.testing import CliRunner + from specify_cli import app + runner = CliRunner() + result = runner.invoke(app, ["extension", "search", "--markdown", "--tag", "foo"]) + assert result.exit_code == 1 + assert "The --markdown flag outputs the full community catalog" in result.stdout From d6b7c07aaecc0aef4d3d37332769b44f21dbd4fc Mon Sep 17 00:00:00 2001 From: Dyan Galih Date: Fri, 26 Jun 2026 03:07:25 +0000 Subject: [PATCH 08/10] chore: add explanatory comments for prereleases=True --- src/specify_cli/extensions/__init__.py | 2 ++ src/specify_cli/presets/__init__.py | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/specify_cli/extensions/__init__.py b/src/specify_cli/extensions/__init__.py index 14d5e15889..3f98d0dc78 100644 --- a/src/specify_cli/extensions/__init__.py +++ b/src/specify_cli/extensions/__init__.py @@ -1284,6 +1284,8 @@ def check_compatibility( # Parse version specifier (e.g., ">=0.1.0,<2.0.0") try: specifier = SpecifierSet(required) + # Intentionally allow prereleases so source/dev spec-kit installs + # can satisfy extension compatibility checks. if not specifier.contains(current, prereleases=True): raise CompatibilityError( f"Extension requires spec-kit {required}, " diff --git a/src/specify_cli/presets/__init__.py b/src/specify_cli/presets/__init__.py index adba993f01..906b3fdc9a 100644 --- a/src/specify_cli/presets/__init__.py +++ b/src/specify_cli/presets/__init__.py @@ -576,6 +576,9 @@ def check_compatibility( try: specifier = SpecifierSet(required) + # Intentionally allow prereleases so source/dev spec-kit installs + # can satisfy preset compatibility checks; the same rationale + # applies to the analogous prerelease handling in extensions.py. if not specifier.contains(current, prereleases=True): raise PresetCompatibilityError( f"Preset requires spec-kit {required}, " From a8afb50d94c3c38dcc32ec5fcf16f1c896b0ab54 Mon Sep 17 00:00:00 2001 From: Dyan Galih Date: Fri, 26 Jun 2026 03:15:31 +0000 Subject: [PATCH 09/10] fix: embed community extensions table in docs and add tests --- docs/community/extensions.md | 130 +++++++++++++++++++++++++ src/specify_cli/extensions/__init__.py | 7 +- src/specify_cli/presets/__init__.py | 8 +- tests/test_community_catalog_docs.py | 18 ++++ 4 files changed, 156 insertions(+), 7 deletions(-) diff --git a/docs/community/extensions.md b/docs/community/extensions.md index 3dbdd8a7e4..ebc555ca33 100644 --- a/docs/community/extensions.md +++ b/docs/community/extensions.md @@ -10,4 +10,134 @@ The following community-contributed extensions are available in [`catalog.commun > Run `specify extension search --markdown` to regenerate this table. + +| Extension | ID | Description | Tags | Verified | +| --- | --- | --- | --- | --- | +| [.NET Framework to Modern .NET Migration](https://github.com/RogerBestMsft/spec-kit-FxToNet) | `fx-to-dotnet` | Orchestrate end-to-end .NET Framework to modern .NET migration across 7 phases, with SDD lifecycle integration. | `dotnet`, `migration`, `modernization`, `framework`, `aspnet`, `shared-artifact` | No | +| [Agent Assign](https://github.com/xymelon/spec-kit-agent-assign) | `agent-assign` | Assign specialized Claude Code agents to spec-kit tasks for targeted execution | `agent`, `automation`, `implementation`, `multi-agent`, `task-routing` | No | +| [Agent Governance](https://github.com/bigsmartben/spec-kit-agent-governance) | `agent-governance` | Generate agent-platform repository governance files from Spec Kit metadata. | `governance`, `agents`, `memory`, `context` | No | +| [AI-Driven Engineering (AIDE)](https://github.com/mnriem/spec-kit-extensions) | `aide` | A structured 7-step workflow for building new projects from scratch with AI assistants — from vision through implementation. | `workflow`, `project-management`, `ai-driven`, `new-project`, `planning`, `experimental` | No | +| [API Evolve](https://github.com/Quratulain-bilal/spec-kit-api-evolve) | `api-evolve` | Managed API contract evolution — breaking-change detection, semver enforcement, deprecation orchestration, and lifecycle gates across REST, GraphQL, and gRPC. | `api`, `contracts`, `versioning`, `openapi`, `graphql`, `grpc`, `deprecation`, `breaking-changes`, `semver`, `governance` | No | +| [Architect Impact Previewer](https://github.com/UmmeHabiba1312/spec-kit-architect-preview) | `architect-preview` | Predicts architectural impact, complexity, and risks of proposed changes before implementation. | `architecture`, `analysis`, `risk-assessment`, `planning`, `preview` | No | +| [Architecture Guard](https://github.com/DyanGalih/spec-kit-architecture-guard) | `architecture-guard` | Framework-agnostic architecture review extension for validating implementation against governance and architecture constitutions, detecting architectural drift, and generating non-blocking refactor tasks. | `architecture`, `spec-kit`, `review`, `refactor`, `workflow`, `governance`, `guardrails` | No | +| [Architecture Workflow](https://github.com/bigsmartben/spec-kit-arch) | `arch` | Generate or reverse project-level 4+1 architecture views as separate commands | `architecture`, `4plus1`, `workflow`, `design` | No | +| [Archive Extension](https://github.com/stn1slv/spec-kit-archive) | `archive` | Archive merged features into main project memory, resolving gaps and conflicts. | `archive`, `memory`, `merge`, `changelog` | No | +| [Azure DevOps Integration](https://github.com/pragya247/spec-kit-azure-devops) | `azure-devops` | Sync user stories and tasks to Azure DevOps work items using OAuth authentication. | `azure`, `devops`, `project-management`, `work-items`, `issue-tracking` | No | +| [Blueprint](https://github.com/chordpli/spec-kit-blueprint) | `blueprint` | Stay code-literate in AI-driven development: review a complete code blueprint for every task from spec artifacts before /speckit.implement runs | `blueprint`, `pre-implementation`, `review`, `scaffolding`, `code-literacy` | No | +| [Branch Convention](https://github.com/Quratulain-bilal/spec-kit-branch-convention) | `branch-convention` | Configurable branch and folder naming conventions for /specify with presets and custom patterns. | `branch`, `naming`, `convention`, `gitflow`, `workflow` | No | +| [Brownfield Bootstrap](https://github.com/Quratulain-bilal/spec-kit-brownfield) | `brownfield` | Bootstrap spec-kit for existing codebases — auto-discover architecture and adopt SDD incrementally. | `brownfield`, `bootstrap`, `existing-project`, `migration`, `onboarding` | No | +| [BrownKit — Brownfield Discovery for Spec-Kit](https://github.com/MaksimShevtsov/BrownKit) | `brownkit` | Evidence-driven capability discovery, security and QA risk assessment for existing codebases. | `brownfield`, `discovery`, `security`, `qa`, `capabilities` | No | +| [Bugfix Workflow](https://github.com/Quratulain-bilal/spec-kit-bugfix) | `bugfix` | Structured bugfix workflow — capture bugs, trace to spec artifacts, and patch specs surgically. | `bugfix`, `debugging`, `workflow`, `traceability`, `maintenance` | No | +| [Canon](https://github.com/maximiliamus/spec-kit-canon) | `canon` | Adds canon-driven (baseline-driven) workflows: spec-first, code-first, spec-drift. Requires Canon Core preset installation. | `process`, `baseline`, `canon`, `drift`, `spec-first`, `code-first`, `spec-drift`, `vibecoding` | No | +| [Catalog CI](https://github.com/Quratulain-bilal/spec-kit-catalog-ci) | `catalog-ci` | Automated validation for spec-kit community catalog entries — structure, URLs, diffs, and linting. | `ci`, `validation`, `catalog`, `quality`, `automation` | No | +| [Checkpoint Extension](https://github.com/aaronrsun/spec-kit-checkpoint) | `checkpoint` | An extension to commit the changes made during the middle of the implementation, so you don't end up with just one very large commit at the end. | `checkpoint`, `commit` | No | +| [CI Guard](https://github.com/Quratulain-bilal/spec-kit-ci-guard) | `ci-guard` | Spec compliance gates for CI/CD — verify specs exist, check drift, and block merges on gaps. | `ci-cd`, `compliance`, `governance`, `quality-gate`, `drift-detection`, `automation` | No | +| [Cleanup Extension](https://github.com/dsrednicki/spec-kit-cleanup) | `cleanup` | Post-implementation quality gate that reviews changes, fixes small issues (scout rule), creates tasks for medium issues, and generates analysis for large issues. | `quality`, `tech-debt`, `review`, `cleanup`, `scout-rule` | No | +| [Coding Standards Drift Control](https://github.com/benizzio/spec-kit-coding-standards-drift-control) | `coding-standards-drift-control` | Generate coding-standards drift reports and remediation tasks for active Spec Kit features | `analysis`, `standards`, `quality`, `maintenance` | No | +| [Conduct Extension](https://github.com/twbrandon7/spec-kit-conduct-ext) | `conduct` | Executes a single spec-kit phase via sub-agent delegation to reduce context pollution. | `conduct`, `workflow`, `automation` | No | +| [Confluence Extension](https://github.com/aaronrsun/spec-kit-confluence) | `confluence` | Create, read, and update Confluence docs for your project | `confluence` | No | +| [Cost Tracker](https://github.com/Quratulain-bilal/spec-kit-cost) | `cost` | Track real LLM dollar cost across SDD workflows — per-feature budgets, per-integration comparison, and finance-ready exports. | `cost`, `budget`, `tokens`, `visibility`, `finance` | No | +| [Data Model Diagram](https://github.com/benizzio/spec-kit-data-model-diagram) | `data-model-diagram` | Generates Mermaid ER diagrams from Spec Kit data models after planning. | `diagram`, `documentation`, `mermaid` | No | +| [DocGuard — CDD Enforcement](https://github.com/raccioly/docguard) | `docguard` | Canonical-Driven Development enforcement. Validates, scores, and traces project documentation with automated checks, AI-driven workflows, and spec-kit hooks. One pinned runtime dependency; pure Node.js otherwise. | `documentation`, `validation`, `quality`, `cdd`, `traceability`, `ai-agents`, `enforcement`, `spec-kit` | No | +| [Extensify](https://github.com/mnriem/spec-kit-extensions) | `extensify` | Create and validate extensions and extension catalogs. | `extensions`, `workflow`, `validation`, `experimental` | No | +| [Fix Findings](https://github.com/Quratulain-bilal/spec-kit-fix-findings) | `fix-findings` | Automated analyze-fix-reanalyze loop that resolves spec findings until clean. | `code`, `analysis`, `quality`, `automation`, `findings` | No | +| [FixIt Extension](https://github.com/speckit-community/spec-kit-fixit) | `fixit` | Spec-aware bug fixing: maps bugs to spec artifacts, proposes a plan, applies minimal changes. | `debugging`, `fixit`, `spec-alignment`, `post-implementation` | No | +| [Fleet Orchestrator](https://github.com/sharathsatish/spec-kit-fleet) | `fleet` | Orchestrate a full feature lifecycle with human-in-the-loop gates across all SpecKit phases. | `orchestration`, `workflow`, `human-in-the-loop`, `parallel` | No | +| [GitHub Issues Integration 1](https://github.com/Fatima367/spec-kit-github-issues) | `github-issues` | Generate spec artifacts from GitHub Issues - import issues, sync updates, and maintain bidirectional traceability | `integration`, `github`, `issues`, `import`, `sync`, `traceability` | No | +| [GitHub Issues Integration 2](https://github.com/aaronrsun/spec-kit-issue) | `issue` | Creates and syncs local specs based on an existing issue in GitHub | `issue`, `integration`, `github`, `issues`, `sync` | No | +| [Golden Demo](https://github.com/jasstt/spec-kit-golden-demo) | `golden-demo` | Extracts acceptance criteria from specs, builds test vectors, and produces a behavioral drift report — complementary to Architecture Guard and CDD. | `testing`, `drift-detection`, `behavioral-oracle`, `tdd`, `quality` | No | +| [Improve Extension](https://github.com/d0whc3r/spec-kit-improve) | `improve` | Audits any codebase as a senior advisor and writes prioritized, self-contained spec prompts under specs/ that the spec-kit lifecycle can process. | `advisor`, `audit`, `code-quality`, `code-review`, `improvement`, `performance`, `planning`, `refactoring`, `security`, `spec-kit`, `spec-kit-extension`, `specs`, `tech-debt`, `testing` | No | +| [Intake](https://github.com/bigsmartben/spec-kit-intake) | `intake` | Normalize PRD, design, and test-case evidence into SDD-ready intake artifacts. | `intake`, `sdd`, `requirements`, `validation`, `figma` | No | +| [Intelligent Agent Orchestrator](https://github.com/pragya247/spec-kit-orchestrator) | `agent-orchestrator` | Cross-catalog agent discovery and intelligent prompt-to-command routing | `orchestrator`, `routing`, `discovery`, `agent`, `ai` | No | +| [Iterate](https://github.com/imviancagrace/spec-kit-iterate) | `iterate` | Iterate on spec documents with a two-phase define-and-apply workflow — refine specs mid-implementation and go straight back to building | `iteration`, `change-management`, `spec-maintenance` | No | +| [Jira Integration](https://github.com/mbachorik/spec-kit-jira) | `jira` | Create Jira Epics, Stories, and Issues from spec-kit specifications and task breakdowns with configurable hierarchy and custom field support. | `issue-tracking`, `jira`, `atlassian`, `project-management` | No | +| [Jira Integration (Sync Engine)](https://github.com/ashbrener/spec-kit-jira-sync) | `jira-sync` | An idempotent, drift-aware, fail-closed reconcile engine that mirrors spec-kit specs into Jira (Epic per repo, Story per spec, Subtask per phase). | `issue-tracking`, `jira`, `tasks-sync`, `reconcile`, `drift-aware` | No | +| [Learning Extension](https://github.com/imviancagrace/spec-kit-learn) | `learn` | Generate educational guides from implementations and enhance clarifications with mentoring context. | `learning`, `education`, `mentoring`, `knowledge-transfer` | No | +| [Linear Integration](https://github.com/ashbrener/spec-kit-linear-sync) | `linear` | Mirror spec-kit feature directories into Linear (filesystem → Linear, reconcile-based, unidirectional). | `issue-tracking`, `linear`, `tasks-sync`, `lifecycle-mirror`, `memory`, `cross-repo` | No | +| [Loop Engineering](https://github.com/formin/spec-kit-loop) | `loop` | Engineer safe autonomous agent loops for spec-driven development: a maker/checker split, externalized loop state, and stay-the-engineer guardrails against comprehension debt and cognitive surrender | `loop-engineering`, `automation`, `verification`, `maker-checker`, `workflow` | No | +| [MAQA Azure DevOps Integration](https://github.com/GenieRobot/spec-kit-maqa-azure-devops) | `maqa-azure-devops` | Azure DevOps Boards integration for the MAQA extension. Populates work items from specs, moves User Stories across columns as features progress, real-time Task child ticking. | `azure-devops`, `project-management`, `multi-agent`, `maqa`, `kanban` | No | +| [MAQA CI/CD Gate](https://github.com/GenieRobot/spec-kit-maqa-ci) | `maqa-ci` | CI/CD pipeline gate for the MAQA extension. Auto-detects GitHub Actions, CircleCI, GitLab CI, and Bitbucket Pipelines. Blocks QA handoff until pipeline is green. | `ci-cd`, `github-actions`, `circleci`, `gitlab-ci`, `quality-gate`, `maqa` | No | +| [MAQA GitHub Projects Integration](https://github.com/GenieRobot/spec-kit-maqa-github-projects) | `maqa-github-projects` | GitHub Projects v2 integration for the MAQA extension. Populates draft issues from specs, moves items across Status columns as features progress, real-time task list ticking. | `github-projects`, `project-management`, `multi-agent`, `maqa`, `kanban` | No | +| [MAQA Jira Integration](https://github.com/GenieRobot/spec-kit-maqa-jira) | `maqa-jira` | Jira integration for the MAQA extension. Populates Stories from specs, moves issues across board columns as features progress, real-time Subtask ticking. | `jira`, `project-management`, `multi-agent`, `maqa`, `kanban` | No | +| [MAQA Linear Integration](https://github.com/GenieRobot/spec-kit-maqa-linear) | `maqa-linear` | Linear integration for the MAQA extension. Populates issues from specs, moves items across workflow states as features progress, real-time sub-issue ticking. | `linear`, `project-management`, `multi-agent`, `maqa`, `kanban` | No | +| [MAQA Trello Integration](https://github.com/GenieRobot/spec-kit-maqa-trello) | `maqa-trello` | Trello board integration for the MAQA extension. Populates board from specs, moves cards between lists as features progress, real-time checklist ticking. | `trello`, `project-management`, `multi-agent`, `maqa`, `kanban` | No | +| [MAQA — Multi-Agent & Quality Assurance](https://github.com/GenieRobot/spec-kit-maqa-ext) | `maqa` | Coordinator → feature → QA agent workflow with parallel worktree-based implementation. Language-agnostic. Auto-detects installed board plugins (Trello, Linear, GitHub Projects, Jira, Azure DevOps). Optional CI gate. | `multi-agent`, `orchestration`, `quality-assurance`, `workflow`, `parallel`, `tdd` | No | +| [MarkItDown Document Converter](https://github.com/BenBtg/spec-kit-markitdown) | `markitdown` | Convert documents (PDF, Word, PowerPoint, Excel, and more) to Markdown for use as spec reference material in Spec Kit workflows. | `markdown`, `pdf`, `document-conversion`, `reference-material`, `extraction` | No | +| [MDE](https://github.com/AI-MDE/spec-kit-mde) | `mde` | A Spec Kit extension that exposes a minimal model-driven engineering workflow with setup, next, and status commands. | `mde`, `model-driven-engineering`, `workflow`, `process` | No | +| [Memory Loader](https://github.com/KevinBrown5280/spec-kit-memory-loader) | `memory-loader` | Loads .specify/memory/ files before spec-kit lifecycle commands so LLM agents have project governance context | `context`, `memory`, `governance`, `hooks` | No | +| [Memory MD](https://github.com/DyanGalih/spec-kit-memory-hub) | `memory-md` | Spec Kit extension for repository-native Markdown memory that captures durable decisions, bugs, and project context | `memory`, `workflow`, `docs`, `copilot`, `markdown`, `ai-context` | No | +| [MemoryLint](https://github.com/RbBtSn0w/spec-kit-extensions) | `memorylint` | Evidence-driven instruction drift checker: audits agent memory files for boundary, reality, conflict, and redundancy drift. | `memory`, `governance`, `constitution`, `agents-md`, `process` | No | +| [Microsoft 365 Integration](https://github.com/BenBtg/spec-kit-m365) | `m365` | Fetch Teams messages, meeting transcripts, and SharePoint/OneDrive files as local Markdown for spec generation. | `microsoft-365`, `teams`, `transcripts`, `collaboration`, `summarization` | No | +| [Multi-Model Review](https://github.com/formin/multi-model-review) | `multi-model-review` | Cross-model Spec Kit handoffs for spec authoring, implementation routing, and review. | `review`, `workflow`, `multi-model`, `spec-driven-development`, `code` | No | +| [Multi-Sites Spec Kit](https://github.com/teeyo/spec-kit-multi-sites) | `multi-sites` | Multi-site aware specify command with per-site spec folders, auto-increment, and Drupal support | `multi-site`, `drupal`, `workflow`, `process` | No | +| [Onboard](https://github.com/dmux/spec-kit-onboard) | `onboard` | Contextual onboarding and progressive growth for developers new to spec-kit projects. Explains specs, maps dependencies, validates understanding, and guides the next step. | `onboarding`, `learning`, `mentoring`, `developer-experience`, `gamification`, `knowledge-transfer` | No | +| [Optimize Extension](https://github.com/sakitA/spec-kit-optimize) | `optimize` | Audits and optimizes AI governance for context efficiency | `constitution`, `optimization`, `token-budget`, `governance`, `audit` | No | +| [OWASP LLM Threat Model](https://github.com/NaviaSamal/spec-kit-threatmodel) | `threatmodel` | OWASP Top 10 for LLM Applications 2025 threat analysis on agent artifacts | `security`, `owasp`, `threat-model`, `llm`, `analysis` | No | +| [Plan Review Gate](https://github.com/luno/spec-kit-plan-review-gate) | `plan-review-gate` | Require spec.md and plan.md to be merged via MR/PR before allowing task generation | `review`, `quality`, `workflow`, `gate` | No | +| [PR Bridge](https://github.com/Quratulain-bilal/spec-kit-pr-bridge-) | `pr-bridge` | Auto-generate pull request descriptions, checklists, and summaries from spec artifacts. | `pull-request`, `automation`, `traceability`, `workflow`, `review` | No | +| [Presetify](https://github.com/mnriem/spec-kit-extensions) | `presetify` | Create and validate presets and preset catalogs. | `presets`, `workflow`, `templates`, `experimental` | No | +| [Product Forge](https://github.com/VaiYav/speckit-product-forge) | `product-forge` | Full product-lifecycle orchestrator for Spec Kit: research → product-spec → plan → tasks → implement → verify → test → release-readiness, across express/lite/standard/v-model modes with human-in-the-loop gates. | `process`, `lifecycle`, `testing`, `sync-verify`, `release-readiness` | No | +| [Product Spec Extension](https://github.com/d0whc3r/spec-kit-product) | `product` | Generates PRFAQ, Lean PRD, stakeholder summaries, and technical designs from engineering specs. | `design`, `documentation`, `jtbd`, `lean-prd`, `planning`, `prd`, `prfaq`, `product`, `product-management`, `requirements`, `spec`, `spec-kit`, `spec-kit-extension`, `stakeholder`, `technical-design` | No | +| [Project Health Check](https://github.com/KhawarHabibKhan/spec-kit-doctor) | `doctor` | Diagnose a Spec Kit project and report health issues across structure, agents, features, scripts, extensions, and git. | `diagnostics`, `health-check`, `validation`, `project-structure` | No | +| [Project Status](https://github.com/KhawarHabibKhan/spec-kit-status) | `status` | Show current SDD workflow progress — active feature, artifact status, task completion, workflow phase, and extensions summary. | `status`, `workflow`, `progress`, `feature-tracking`, `task-progress` | No | +| [QA Testing Extension](https://github.com/arunt14/spec-kit-qa) | `qa` | Systematic QA testing with browser-driven or CLI-based validation of acceptance criteria from spec. | `code`, `testing`, `qa` | No | +| [RAG Azure Builder](https://github.com/Sertxito/spec-kit-extension-rag-azure-builder) | `rag-azure-builder` | Spec Kit extension for onboarding and operating an Azure RAG stack with guided workflows. | `azure`, `rag`, `search`, `onboarding`, `cost-optimization` | No | +| [Ralph Loop](https://github.com/Rubiss-Projects/spec-kit-ralph) | `ralph` | Autonomous implementation loop using AI agent CLI | `implementation`, `automation`, `loop`, `copilot`, `codex` | No | +| [Reconcile Extension](https://github.com/stn1slv/spec-kit-reconcile) | `reconcile` | Reconcile implementation drift by surgically updating the feature's own spec, plan, and tasks. | `reconcile`, `drift`, `tasks`, `remediation` | No | +| [Red Team](https://github.com/ashbrener/spec-kit-red-team) | `red-team` | Adversarial review of functional specs before /speckit.plan. Parallel adversarial lens agents catch hostile actors, silent failures, and regulatory blind spots that clarify/analyze cannot. | `adversarial-review`, `quality-gate`, `spec-hardening`, `pre-plan`, `audit` | No | +| [Repository Index](https://github.com/liuyiyu/spec-kit-repoindex) | `repoindex` | Generate index of your repo for overview, architecture and module | `utility`, `brownfield`, `analysis` | No | +| [Reqnroll BDD](https://github.com/LoogacyStudio/spec-kit-reqnroll-bdd) | `reqnroll-bdd` | Adds Reqnroll BDD planning, Gherkin generation, traceability, safe task injection, handoff, and verification to Spec Kit. | `bdd`, `reqnroll`, `dotnet`, `gherkin`, `acceptance-testing` | No | +| [Research Harness](https://github.com/formin/spec-kit-harness) | `harness` | State-externalizing research harness: budgeted exploration, evidence curation, and claim verification for spec-driven development | `research`, `verification`, `evidence`, `context-management`, `workflow` | No | +| [Retro Extension](https://github.com/arunt14/spec-kit-retro) | `retro` | Sprint retrospective analysis with metrics, spec accuracy assessment, and improvement suggestions. | `process`, `retrospective`, `metrics` | No | +| [Retrospective Extension](https://github.com/emi-dm/spec-kit-retrospective) | `retrospective` | Post-implementation retrospective with spec adherence scoring, drift analysis, and human-gated spec updates. | `retrospective`, `spec-drift`, `quality`, `analysis`, `governance` | No | +| [Review Extension](https://github.com/ismaelJimenez/spec-kit-review) | `review` | Post-implementation comprehensive code review with specialized agents for code quality, comments, tests, error handling, type design, and simplification. | `code-review`, `quality`, `review`, `testing`, `error-handling`, `type-design`, `simplification` | No | +| [Ripple](https://github.com/chordpli/spec-kit-ripple) | `ripple` | Detect side effects that tests can't catch after implementation — delta-anchored analysis across 9 domain-agnostic categories with fix-induced side effect detection | `side-effects`, `post-implementation`, `analysis`, `quality`, `risk-detection` | No | +| [SDD Utilities](https://github.com/mvanhorn/speckit-utils) | `speckit-utils` | Resume interrupted workflows, validate project health, and verify spec-to-task traceability. | `resume`, `doctor`, `validate`, `workflow`, `health-check` | No | +| [Security Review](https://github.com/DyanGalih/spec-kit-security-review) | `security-review` | Full-project secure-by-design security audits plus staged, branch/PR, plan, task, follow-up, and apply reviews | `security`, `devsecops`, `audit`, `owasp`, `compliance` | No | +| [SFSpeckit — Salesforce Spec-Driven Development](https://github.com/ysumanth06/spec-kit-sf) | `sf` | Enterprise-Grade Spec-Driven Development (SDD) Framework for Salesforce. | `salesforce`, `enterprise`, `sdlc`, `apex`, `devops` | No | +| [Ship Release Extension](https://github.com/arunt14/spec-kit-ship) | `ship` | Automates release pipeline: pre-flight checks, branch sync, changelog generation, CI verification, and PR creation. | `process`, `release`, `automation` | No | +| [Spec Changelog](https://github.com/Quratulain-bilal/spec-kit-changelog) | `changelog` | Auto-generate changelogs and release notes from spec git history and requirement diffs. | `changelog`, `release-notes`, `documentation`, `git-history`, `notifications` | No | +| [Spec Critique Extension](https://github.com/arunt14/spec-kit-critique) | `critique` | Dual-lens critical review of spec and plan from product strategy and engineering risk perspectives. | `docs`, `review`, `planning` | No | +| [Spec Diagram](https://github.com/Quratulain-bilal/spec-kit-diagram-) | `diagram` | Auto-generate Mermaid diagrams of SDD workflow state, feature progress, and task dependencies. | `diagram`, `mermaid`, `visualization`, `workflow`, `dependencies` | No | +| [Spec Kit Discovery Extension](https://github.com/bigsmartben/spec-kit-discovery) | `discovery` | Run technical discovery commands for feasibility, technology selection, scenario-specific technical decisions, legacy codebase assessment, implementation understanding, and proof-of-concept validation. | `discovery`, `workflow`, `validation`, `feasibility`, `decision` | No | +| [Spec Kit Preview](https://github.com/bigsmartben/spec-kit-preview) | `preview` | Generate evidence-backed low, mid, or high fidelity previews from Spec Kit artifacts as Markdown or self-contained HTML | `preview`, `prototype`, `html`, `markdown`, `ux` | No | +| [Spec Kit Schedule — CP-SAT Agent Orchestrator](https://github.com/jfranc38/spec-kit-schedule) | `schedule` | Optimal multi-agent task scheduling via CP-SAT solver with DAG precedence, hallucination-aware caps, file-conflict avoidance, stochastic durations, replanning, and interactive HTML output | `scheduling`, `optimization`, `multi-agent`, `cp-sat`, `operations-research` | No | +| [Spec Kit TLDR](https://github.com/qurore/speckit-tldr) | `tldr` | Render a feature's spec.md / plan.md into a review-oriented TLDR (self-contained HTML dashboard + PR-native Markdown) that surfaces risks for faster PR review. | `review`, `pr-review`, `sdd`, `spec`, `visibility` | No | +| [Spec Orchestrator](https://github.com/Quratulain-bilal/spec-kit-orchestrator) | `orchestrator` | Cross-feature orchestration — track state, select tasks, and detect conflicts across parallel specs. | `orchestration`, `multi-feature`, `coordination`, `workflow`, `parallel` | No | +| [Spec Reference Loader](https://github.com/KevinBrown5280/spec-kit-spec-reference-loader) | `spec-reference-loader` | Reads the ## References section from the current feature spec and loads the listed files into context | `context`, `references`, `docs`, `hooks` | No | +| [Spec Refine](https://github.com/Quratulain-bilal/spec-kit-refine) | `refine` | Update specs in-place, propagate changes to plan and tasks, and diff impact across artifacts. | `refine`, `iterate`, `propagation`, `workflow`, `specifications` | No | +| [Spec Roadmap](https://github.com/srobroek/speckit-roadmap) | `roadmap` | Capture a durable spec roadmap after the constitution, then review specs against it before and after implementation so spec-specific decisions, outcomes, and constraints are never lost. | `roadmap`, `planning`, `governance`, `review`, `spec-alignment` | No | +| [Spec Scope](https://github.com/Quratulain-bilal/spec-kit-scope-) | `scope` | Effort estimation and scope tracking — estimate work, detect creep, and budget time per phase. | `estimation`, `scope`, `effort`, `planning`, `project-management`, `tracking` | No | +| [Spec Sync](https://github.com/bgervin/spec-kit-sync) | `sync` | Detect and resolve drift between specs and implementation. AI-assisted resolution with human approval. | `sync`, `drift`, `validation`, `bidirectional`, `backfill` | No | +| [Spec Trace](https://github.com/Quratulain-bilal/spec-kit-trace) | `trace` | Build a requirement → test traceability matrix from spec.md and the test suite — surface untested requirements and orphan tests | `traceability`, `testing`, `coverage`, `compliance`, `requirements` | No | +| [Spec Validate](https://github.com/aeltayeb/spec-kit-spec-validate) | `spec-validate` | Comprehension validation, review gating, and approval state for spec-kit artifacts — staged-reveal quizzes, peer review SLA, and a hard gate before /speckit.implement. | `validation`, `review`, `quality`, `workflow`, `process` | No | +| [Spec2Cloud](https://github.com/Azure-Samples/Spec2Cloud) | `spec2cloud` | Spec-driven workflow tuned for shipping to Azure: spec → plan → tasks → implement → deploy. | `spec2cloud`, `azure`, `cloud`, `deploy`, `workflow` | No | +| [SpecKit Companion](https://github.com/alfredoperez/speckit-companion) | `companion` | Live spec-driven progress for SpecKit Companion — lifecycle capture, status, resume, and a turbo pipeline profile. | `tracking`, `companion`, `progress`, `vscode`, `lifecycle`, `resume` | No | +| [SpecTest](https://github.com/Quratulain-bilal/spec-kit-spectest) | `spectest` | Auto-generate test scaffolds from spec criteria, map coverage, and find untested requirements. | `testing`, `test-generation`, `coverage`, `quality`, `automation`, `traceability` | No | +| [Squad Bridge](https://github.com/jwill824/spec-kit-squad) | `squad` | Bootstrap and synchronize a Squad agent team from your Speckit spec and tasks. | `multi-agent`, `agents`, `orchestration`, `process`, `integration` | No | +| [Staff Review Extension](https://github.com/arunt14/spec-kit-staff-review) | `staff-review` | Staff-engineer-level code review that validates implementation against spec, checks security, performance, and test coverage. | `code`, `review`, `quality` | No | +| [Status Report](https://github.com/Open-Agent-Tools/spec-kit-status) | `status-report` | Project status, feature progress, and next-action recommendations for spec-driven workflows. | `workflow`, `project-management`, `status` | No | +| [Superpowers Bridge](https://github.com/RbBtSn0w/spec-kit-extensions) | `superb` | Bridges selected Superpowers disciplines into Spec Kit as evidence-first trust gates for agent workflows. | `quality-gates`, `tdd`, `code-review`, `workflow`, `superpowers`, `verification`, `debugging`, `branch-management` | No | +| [Superpowers Implementation Bridge](https://github.com/lihan3238/speckit-superpowers-bridge) | `speckit-superpowers-bridge` | Thin orchestrator between Spec Kit (design) and Superpowers (implementation). Cross-agent. | `bridge`, `superpowers`, `cross-agent`, `tdd`, `workflow` | No | +| [Superspec](https://github.com/WangX0111/superspec) | `superspec` | Bridges spec-kit workflows with obra/superpowers capabilities for brainstorming, TDD, code review, and resumable execution. | `superpowers`, `brainstorming`, `tdd`, `code-review`, `subagent`, `workflow` | No | +| [Tasks to GitHub Project](https://github.com/mancioshell/spec-kit-tasks-to-project) | `tasks-to-project` | Publish and synchronize Spec Kit tasks as cards on a GitHub Project (v2) kanban board, with priority and status sync between spec.md/tasks.md and the board. | `github`, `project`, `kanban`, `automation`, `tasks` | No | +| [Team Assign](https://github.com/tarunkumarbhati/spec-kit-team-assign) | `team-assign` | Assign tasks.md items to human engineers, split into subtasks, and generate a per-engineer workboard | `team`, `assignment`, `process`, `planning`, `subtasks` | No | +| [Time Machine](https://github.com/teeyo/spec-kit-time-machine) | `time-machine` | Retroactively apply the full SDD workflow to existing codebases — analyse, spec, and ship feature-by-feature | `brownfield`, `automation`, `workflow`, `process` | No | +| [TinySpec](https://github.com/Quratulain-bilal/spec-kit-tinyspec) | `tinyspec` | Lightweight single-file workflow for small tasks — skip the heavy multi-step SDD process. | `lightweight`, `small-tasks`, `workflow`, `productivity`, `efficiency` | No | +| [Token Budget](https://github.com/tinesoft/spec-kit-token-budget) | `token-budget` | Reduces LLM token consumption in Spec Kit workflows: compact artifacts in-place, scope per-phase reading, suppress prose padding, and report token usage. | `tokens`, `budget`, `context`, `efficiency`, `cost-optimization` | No | +| [Token Consumption Analyzer](https://github.com/coderandhiker/spec-kit-token-analyzer) | `token-analyzer` | Captures, analyzes, and compares token consumption across SDD workflows | `tokens`, `measurement`, `optimization`, `analysis` | No | +| [Token Economy](https://github.com/formin/spec-kit-token-economy) | `token-economy` | Token routing, measured savings, and context audit workflows. | `tokens`, `routing`, `reporting`, `context` | No | +| [V-Model Extension Pack](https://github.com/leocamello/spec-kit-v-model) | `v-model` | Enforces V-Model paired generation of development specs and test specs with full traceability. | `v-model`, `traceability`, `testing`, `compliance`, `safety-critical` | No | +| [Verify Extension](https://github.com/ismaelJimenez/spec-kit-verify) | `verify` | Post-implementation quality gate that validates implemented code against specification artifacts. | `verification`, `quality-gate`, `implementation`, `spec-adherence`, `compliance` | No | +| [Verify Tasks Extension](https://github.com/datastone-inc/spec-kit-verify-tasks) | `verify-tasks` | Detect phantom completions: tasks marked [X] in tasks.md with no real implementation. | `verification`, `quality`, `phantom-completion`, `tasks` | No | +| [Version Guard](https://github.com/KevinBrown5280/spec-kit-version-guard) | `version-guard` | Verify tech stack versions against live registries before planning and implementation | `versioning`, `npm`, `validation`, `hooks` | No | +| [What-if Analysis](https://github.com/DevAbdullah90/spec-kit-whatif) | `whatif` | Preview the downstream impact (complexity, effort, tasks, risks) of requirement changes before committing to them. | `analysis`, `planning`, `simulation` | No | +| [Wireframe Visual Feedback Loop](https://github.com/TortoiseWolfe/spec-kit-extension-wireframe) | `wireframe` | SVG wireframe generation, review, and sign-off for spec-driven development. Approved wireframes become spec constraints honored by /speckit.plan, /speckit.tasks, and /speckit.implement. | `wireframe`, `visual`, `design`, `ui`, `mockup`, `svg`, `feedback-loop`, `sign-off` | No | +| [Work IQ](https://github.com/sakitA/spec-kit-workiq) | `workiq` | Integrate Microsoft 365 organizational knowledge into spec-driven development workflows | `microsoft-365`, `work-iq`, `context`, `integration`, `productivity` | No | +| [Worktree Isolation](https://github.com/Quratulain-bilal/spec-kit-worktree) | `worktree` | Spawn isolated git worktrees for parallel feature development without checkout switching. | `worktree`, `git`, `parallel`, `isolation`, `workflow` | No | +| [Worktrees](https://github.com/dango85/spec-kit-worktree-parallel) | `worktrees` | Default-on worktree isolation for parallel agents — sibling or nested layout | `worktree`, `git`, `parallel`, `isolation`, `agents` | No | + + + + To submit your own extension, see the [Extension Publishing Guide](https://github.com/github/spec-kit/blob/main/extensions/EXTENSION-PUBLISHING-GUIDE.md). diff --git a/src/specify_cli/extensions/__init__.py b/src/specify_cli/extensions/__init__.py index 3f98d0dc78..a7b758ad4d 100644 --- a/src/specify_cli/extensions/__init__.py +++ b/src/specify_cli/extensions/__init__.py @@ -1284,9 +1284,10 @@ def check_compatibility( # Parse version specifier (e.g., ">=0.1.0,<2.0.0") try: specifier = SpecifierSet(required) - # Intentionally allow prereleases so source/dev spec-kit installs - # can satisfy extension compatibility checks. - if not specifier.contains(current, prereleases=True): + # Intentionally allow prereleases only for source/dev spec-kit installs + # so they can satisfy extension compatibility checks, while still + # rejecting RC/beta builds per normal PEP 440 rules. + if not specifier.contains(current, prereleases=current.is_devrelease): raise CompatibilityError( f"Extension requires spec-kit {required}, " f"but {speckit_version} is installed.\n" diff --git a/src/specify_cli/presets/__init__.py b/src/specify_cli/presets/__init__.py index 906b3fdc9a..4d2febfb16 100644 --- a/src/specify_cli/presets/__init__.py +++ b/src/specify_cli/presets/__init__.py @@ -576,10 +576,10 @@ def check_compatibility( try: specifier = SpecifierSet(required) - # Intentionally allow prereleases so source/dev spec-kit installs - # can satisfy preset compatibility checks; the same rationale - # applies to the analogous prerelease handling in extensions.py. - if not specifier.contains(current, prereleases=True): + # Intentionally allow prereleases only for source/dev spec-kit installs + # so they can satisfy preset compatibility checks, while still + # rejecting RC/beta builds per normal PEP 440 rules. + if not specifier.contains(current, prereleases=current.is_devrelease): raise PresetCompatibilityError( f"Preset requires spec-kit {required}, " f"but {speckit_version} is installed.\n" diff --git a/tests/test_community_catalog_docs.py b/tests/test_community_catalog_docs.py index 5782b58507..9fe7944b22 100644 --- a/tests/test_community_catalog_docs.py +++ b/tests/test_community_catalog_docs.py @@ -147,3 +147,21 @@ def test_community_extensions_markdown_rejects_filters() -> None: result = runner.invoke(app, ["extension", "search", "--markdown", "--tag", "foo"]) assert result.exit_code == 1 assert "The --markdown flag outputs the full community catalog" in result.stdout + +def test_docs_extensions_md_is_up_to_date() -> None: + from pathlib import Path + from specify_cli.community_catalog_docs import render_community_extensions_table + + root_dir = Path(__file__).resolve().parents[1] + docs_path = root_dir / "docs" / "community" / "extensions.md" + + assert docs_path.exists(), "docs/community/extensions.md not found" + docs_content = docs_path.read_text(encoding="utf-8") + + generated_table = render_community_extensions_table() + + # Assert that the exact generated table is embedded in the markdown file + assert generated_table in docs_content, ( + "docs/community/extensions.md is out of sync with catalog.community.json. " + "Please run `specify extension search --markdown` and update the docs file." + ) From 744d0048d80737e3eac984f2d6a92d911d53db22 Mon Sep 17 00:00:00 2001 From: Dyan Galih Date: Fri, 26 Jun 2026 03:23:55 +0000 Subject: [PATCH 10/10] fix: address final PR feedback on prerelease flags and tests --- pr_body.json | 3 +++ pr_body.txt | 20 ++++++++++++++++++++ src/specify_cli/extensions/__init__.py | 4 ++-- src/specify_cli/presets/__init__.py | 4 ++-- tests/test_community_catalog_docs.py | 15 +++++++++++++-- threads.txt | 1 + 6 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 pr_body.json create mode 100644 pr_body.txt create mode 100644 threads.txt diff --git a/pr_body.json b/pr_body.json new file mode 100644 index 0000000000..abe737ab2c --- /dev/null +++ b/pr_body.json @@ -0,0 +1,3 @@ +{ + "body": "## What changed\n- Added a generator for `docs/community/extensions.md` backed by `extensions/catalog.community.json`.\n- Replaced the hand-maintained community extensions table with a generated index block.\n- Added a regression test that checks the committed page stays in sync with the generator.\n- Added `--markdown` flag to the `specify extension search` command to generate the docs.\n- **Compatibility Behavior Change:** Presets and extensions now evaluate `prereleases=True` if `current.is_devrelease` is True, allowing source/dev installations to satisfy version specifiers without accidentally accepting normal RC/beta builds.\n\n## Why\n- The community extensions page was a large manual table and was easy to drift from the catalog source of truth.\n- Moving the page to generated output keeps the community index aligned with the catalog as entries change.\n- This reduces maintainer overhead and makes the published list more trustworthy for contributors and users.\n\n## Impact\n- Contributors now update the catalog JSON instead of editing the rendered table by hand.\n- The community extensions page is more consistent and less likely to go stale.\n- CI and local tests can detect drift before it lands.\n\n## Validation\n- `specify extension search --markdown > docs/community/extensions.md` (to update the page)\n- `pytest tests/test_community_catalog_docs.py -q`\n" +} diff --git a/pr_body.txt b/pr_body.txt new file mode 100644 index 0000000000..97d5af0345 --- /dev/null +++ b/pr_body.txt @@ -0,0 +1,20 @@ +## What changed +- Added a generator for `docs/community/extensions.md` backed by `extensions/catalog.community.json`. +- Replaced the hand-maintained community extensions table with a generated index block. +- Added a regression test that checks the committed page stays in sync with the generator. +- Added `--markdown` flag to the `specify extension search` command to generate the docs. +- **Compatibility Behavior Change:** Presets and extensions now evaluate `prereleases=True` if `current.is_devrelease` is True, allowing source/dev installations to satisfy version specifiers without accidentally accepting normal RC/beta builds. + +## Why +- The community extensions page was a large manual table and was easy to drift from the catalog source of truth. +- Moving the page to generated output keeps the community index aligned with the catalog as entries change. +- This reduces maintainer overhead and makes the published list more trustworthy for contributors and users. + +## Impact +- Contributors now update the catalog JSON instead of editing the rendered table by hand. +- The community extensions page is more consistent and less likely to go stale. +- CI and local tests can detect drift before it lands. + +## Validation +- `specify extension search --markdown > docs/community/extensions.md` (to update the page) +- `pytest tests/test_community_catalog_docs.py -q` diff --git a/src/specify_cli/extensions/__init__.py b/src/specify_cli/extensions/__init__.py index a7b758ad4d..65961a21e8 100644 --- a/src/specify_cli/extensions/__init__.py +++ b/src/specify_cli/extensions/__init__.py @@ -1286,8 +1286,8 @@ def check_compatibility( specifier = SpecifierSet(required) # Intentionally allow prereleases only for source/dev spec-kit installs # so they can satisfy extension compatibility checks, while still - # rejecting RC/beta builds per normal PEP 440 rules. - if not specifier.contains(current, prereleases=current.is_devrelease): + # preserving normal PEP 440 rules for RC/beta builds. + if not specifier.contains(current, prereleases=True if current.is_devrelease else None): raise CompatibilityError( f"Extension requires spec-kit {required}, " f"but {speckit_version} is installed.\n" diff --git a/src/specify_cli/presets/__init__.py b/src/specify_cli/presets/__init__.py index 4d2febfb16..0174001c14 100644 --- a/src/specify_cli/presets/__init__.py +++ b/src/specify_cli/presets/__init__.py @@ -578,8 +578,8 @@ def check_compatibility( specifier = SpecifierSet(required) # Intentionally allow prereleases only for source/dev spec-kit installs # so they can satisfy preset compatibility checks, while still - # rejecting RC/beta builds per normal PEP 440 rules. - if not specifier.contains(current, prereleases=current.is_devrelease): + # preserving normal PEP 440 rules for RC/beta builds. + if not specifier.contains(current, prereleases=True if current.is_devrelease else None): raise PresetCompatibilityError( f"Preset requires spec-kit {required}, " f"but {speckit_version} is installed.\n" diff --git a/tests/test_community_catalog_docs.py b/tests/test_community_catalog_docs.py index 9fe7944b22..fe59359142 100644 --- a/tests/test_community_catalog_docs.py +++ b/tests/test_community_catalog_docs.py @@ -160,8 +160,19 @@ def test_docs_extensions_md_is_up_to_date() -> None: generated_table = render_community_extensions_table() - # Assert that the exact generated table is embedded in the markdown file - assert generated_table in docs_content, ( + # Extract the block between markers and compare it exactly + start_marker = "\n" + end_marker = "" + + start_idx = docs_content.find(start_marker) + end_idx = docs_content.find(end_marker) + + assert start_idx != -1, f"Missing '{start_marker.strip()}' in docs/community/extensions.md" + assert end_idx != -1, f"Missing '{end_marker}' in docs/community/extensions.md" + + actual_table = docs_content[start_idx + len(start_marker):end_idx] + + assert actual_table.strip() == generated_table.strip(), ( "docs/community/extensions.md is out of sync with catalog.community.json. " "Please run `specify extension search --markdown` and update the docs file." ) diff --git a/threads.txt b/threads.txt new file mode 100644 index 0000000000..f9a5dc70cd --- /dev/null +++ b/threads.txt @@ -0,0 +1 @@ +{"data":{"repository":{"pullRequest":{"reviewThreads":{"nodes":[{"id":"PRRT_kwDOPiFCnc6CIN4d","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CIN5d","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CIN5o","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CIN5z","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CIN59","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CIN6W","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CIN61","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CIN7O","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CIN7w","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNfSR","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNfTG","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNfTX","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNfTp","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNfTz","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNfT9","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNfUD","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNfUQ","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNfUe","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNokX","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNokp","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNoky","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNok8","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNolG","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNolS","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNolc","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNols","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNol3","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNomI","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNomQ","isResolved":true},{"id":"PRRT_kwDOPiFCnc6CNomb","isResolved":true},{"id":"PRRT_kwDOPiFCnc6E8Oyd","isResolved":true},{"id":"PRRT_kwDOPiFCnc6E8Oyt","isResolved":true},{"id":"PRRT_kwDOPiFCnc6E8Oy1","isResolved":true},{"id":"PRRT_kwDOPiFCnc6E8OzL","isResolved":true},{"id":"PRRT_kwDOPiFCnc6E8Ozb","isResolved":true},{"id":"PRRT_kwDOPiFCnc6E8Ozp","isResolved":true},{"id":"PRRT_kwDOPiFCnc6E8Ozz","isResolved":true},{"id":"PRRT_kwDOPiFCnc6E8Oz7","isResolved":true},{"id":"PRRT_kwDOPiFCnc6E8O0B","isResolved":true},{"id":"PRRT_kwDOPiFCnc6E8O0I","isResolved":true},{"id":"PRRT_kwDOPiFCnc6FGrAb","isResolved":true},{"id":"PRRT_kwDOPiFCnc6FGrBO","isResolved":true},{"id":"PRRT_kwDOPiFCnc6FGrBo","isResolved":true},{"id":"PRRT_kwDOPiFCnc6FGrB7","isResolved":true},{"id":"PRRT_kwDOPiFCnc6Fd6xX","isResolved":true},{"id":"PRRT_kwDOPiFCnc6Fd6x5","isResolved":true},{"id":"PRRT_kwDOPiFCnc6Fd6yV","isResolved":true},{"id":"PRRT_kwDOPiFCnc6Fd6yy","isResolved":true},{"id":"PRRT_kwDOPiFCnc6FeQZP","isResolved":false},{"id":"PRRT_kwDOPiFCnc6FeQZt","isResolved":true},{"id":"PRRT_kwDOPiFCnc6FeQaA","isResolved":true},{"id":"PRRT_kwDOPiFCnc6FeluI","isResolved":true},{"id":"PRRT_kwDOPiFCnc6Felum","isResolved":true},{"id":"PRRT_kwDOPiFCnc6Felu6","isResolved":true},{"id":"PRRT_kwDOPiFCnc6FelvU","isResolved":true},{"id":"PRRT_kwDOPiFCnc6MaMag","isResolved":true},{"id":"PRRT_kwDOPiFCnc6MaMan","isResolved":true},{"id":"PRRT_kwDOPiFCnc6MaMas","isResolved":true},{"id":"PRRT_kwDOPiFCnc6MaMax","isResolved":true}]}}}}}