diff --git a/docforge/cli/mkdocs_utils.py b/docforge/cli/mkdocs_utils.py index 1c135bd..dbcad85 100644 --- a/docforge/cli/mkdocs_utils.py +++ b/docforge/cli/mkdocs_utils.py @@ -32,6 +32,12 @@ def generate_sources( module_is_source, ) + renderer.generate_readme( + project, + docs_dir, + module_is_source, + ) + def generate_config(docs_dir: Path, nav_file: Path, template: Path | None, out: Path, site_name: str) -> None: """ Generate an mkdocs.yml configuration file. diff --git a/docforge/renderers/mkdocs_renderer.py b/docforge/renderers/mkdocs_renderer.py index b851812..d70c8ce 100644 --- a/docforge/renderers/mkdocs_renderer.py +++ b/docforge/renderers/mkdocs_renderer.py @@ -7,6 +7,7 @@ and mkdocstrings, ensuring: - Root index.md always exists - Parent package indexes are created automatically - Child modules are linked in parent index files +- README.md can be generated from the root package docstring """ from pathlib import Path @@ -35,9 +36,14 @@ class MkDocsRenderer: provided Project models. Args: - project: The project models to render. - out_dir: Target directory for documentation files. - module_is_source: Module is the source folder and to be treated as the root folder. + project: + The project model to render. + + out_dir: + Target directory for generated Markdown. + + module_is_source: + If True, treat the module as the root folder. """ out_dir.mkdir(parents=True, exist_ok=True) self._ensure_root_index(project, out_dir) @@ -59,9 +65,75 @@ class MkDocsRenderer: module_is_source, ) + def generate_readme( + self, + project: Project, + docs_dir: Path, + module_is_source: bool | None = None, + ) -> None: + """ + Generate README.md from the root package docstring. + + Behavior: + + - If module_is_source is True: + README.md is generated at project root (docs_dir.parent) + + - If module_is_source is False: + TODO: generate README.md inside respective module folders + """ + + # ------------------------- + # Only implement source-root mode + # ------------------------- + if not module_is_source: + # TODO: support per-module README generation + return + + readme_path = docs_dir.parent / "README.md" + + root_module = None + for module in project.get_all_modules(): + if module.path == project.name: + root_module = module + break + + if root_module is None: + return + + doc = "" + + if root_module.docstring: + doc = getattr( + root_module.docstring, + "value", + str(root_module.docstring), + ) + + content = ( + f"# {project.name}\n\n" + f"{doc.strip()}\n" + ) + + if not readme_path.exists() or readme_path.read_text(encoding="utf-8") != content: + readme_path.write_text( + content, + encoding="utf-8", + ) + # ------------------------- # Internal helpers # ------------------------- + + def _find_root_module(self, project: Project) -> Module | None: + """ + Find the root module matching the project name. + """ + for module in project.get_all_modules(): + if module.path == project.name: + return module + return None + def _write_module( self, module: Module, @@ -79,6 +151,7 @@ class MkDocsRenderer: out_dir: The base output directory. module_is_source: Module is the source folder and to be treated as the root folder. """ + parts = module.path.split(".") if module_is_source: @@ -90,12 +163,15 @@ class MkDocsRenderer: # Package → directory/index.md dir_path = out_dir.joinpath(*parts) dir_path.mkdir(parents=True, exist_ok=True) + md_path = dir_path / "index.md" link_target = f"{parts[-1]}/" if parts else None + else: # Leaf module → parent_dir/.md dir_path = out_dir.joinpath(*parts[:-1]) dir_path.mkdir(parents=True, exist_ok=True) + md_path = dir_path / f"{parts[-1]}.md" link_target = f"{parts[-1]}.md" if parts else None @@ -127,7 +203,7 @@ class MkDocsRenderer: def _ensure_root_index( self, project: Project, - out_dir: Path + out_dir: Path, ) -> None: root_index = out_dir / "index.md" @@ -147,14 +223,11 @@ class MkDocsRenderer: ) -> None: if len(parts) == 1: parent_index = out_dir / "index.md" - link = f"- [{title}]({link_target})\n" else: parent_dir = out_dir.joinpath(*parts[:-1]) parent_dir.mkdir(parents=True, exist_ok=True) parent_index = parent_dir / "index.md" - link = f"- [{title}]({link_target})\n" - if not parent_index.exists(): parent_title = parts[-2].replace("_", " ").title() parent_index.write_text( @@ -164,5 +237,6 @@ class MkDocsRenderer: content = parent_index.read_text(encoding="utf-8") + link = f"- [{title}]({link_target})\n" if link not in content: parent_index.write_text(content + link, encoding="utf-8") diff --git a/docforge/renderers/mkdocs_renderer.pyi b/docforge/renderers/mkdocs_renderer.pyi index 130e4dc..584e425 100644 --- a/docforge/renderers/mkdocs_renderer.pyi +++ b/docforge/renderers/mkdocs_renderer.pyi @@ -12,6 +12,13 @@ class MkDocsRenderer: module_is_source: bool | None = None, ) -> None: ... + def generate_readme( + self, + project: Project, + docs_dir: Path, + module_is_source: bool | None = None, + ) -> None: + def _write_module( self, module: Module, diff --git a/mcp_docs/modules/docforge.cli.commands.json b/mcp_docs/modules/docforge.cli.commands.json index 1d5d04d..d57c644 100644 --- a/mcp_docs/modules/docforge.cli.commands.json +++ b/mcp_docs/modules/docforge.cli.commands.json @@ -139,7 +139,14 @@ "kind": "function", "path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer.generate_sources", "signature": "", - "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project: The project models to render.\n out_dir: Target directory for documentation files.\n module_is_source: Module is the source folder and to be treated as the root folder." + "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project:\n The project model to render.\n\n out_dir:\n Target directory for generated Markdown.\n\n module_is_source:\n If True, treat the module as the root folder." + }, + "generate_readme": { + "name": "generate_readme", + "kind": "function", + "path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer.generate_readme", + "signature": "", + "docstring": "Generate README.md from the root package docstring.\n\nBehavior:\n\n- If module_is_source is True:\n README.md is generated at project root (docs_dir.parent)\n\n- If module_is_source is False:\n TODO: generate README.md inside respective module folders" } } }, diff --git a/mcp_docs/modules/docforge.cli.json b/mcp_docs/modules/docforge.cli.json index 51c5aad..e3f6736 100644 --- a/mcp_docs/modules/docforge.cli.json +++ b/mcp_docs/modules/docforge.cli.json @@ -169,7 +169,14 @@ "kind": "function", "path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer.generate_sources", "signature": "", - "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project: The project models to render.\n out_dir: Target directory for documentation files.\n module_is_source: Module is the source folder and to be treated as the root folder." + "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project:\n The project model to render.\n\n out_dir:\n Target directory for generated Markdown.\n\n module_is_source:\n If True, treat the module as the root folder." + }, + "generate_readme": { + "name": "generate_readme", + "kind": "function", + "path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer.generate_readme", + "signature": "", + "docstring": "Generate README.md from the root package docstring.\n\nBehavior:\n\n- If module_is_source is True:\n README.md is generated at project root (docs_dir.parent)\n\n- If module_is_source is False:\n TODO: generate README.md inside respective module folders" } } }, @@ -601,7 +608,14 @@ "kind": "function", "path": "docforge.cli.mkdocs_utils.MkDocsRenderer.generate_sources", "signature": "", - "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project: The project models to render.\n out_dir: Target directory for documentation files.\n module_is_source: Module is the source folder and to be treated as the root folder." + "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project:\n The project model to render.\n\n out_dir:\n Target directory for generated Markdown.\n\n module_is_source:\n If True, treat the module as the root folder." + }, + "generate_readme": { + "name": "generate_readme", + "kind": "function", + "path": "docforge.cli.mkdocs_utils.MkDocsRenderer.generate_readme", + "signature": "", + "docstring": "Generate README.md from the root package docstring.\n\nBehavior:\n\n- If module_is_source is True:\n README.md is generated at project root (docs_dir.parent)\n\n- If module_is_source is False:\n TODO: generate README.md inside respective module folders" } } }, @@ -639,28 +653,28 @@ "name": "generate_sources", "kind": "function", "path": "docforge.cli.mkdocs_utils.generate_sources", - "signature": "", + "signature": "", "docstring": "Generate Markdown source files for the specified module.\n\nArgs:\n module: The dotted path of the primary module to document.\n project_name: Optional override for the project name.\n docs_dir: Directory where the generated Markdown files will be written.\n module_is_source: Module is the source folder and to be treated as the root folder." }, "generate_config": { "name": "generate_config", "kind": "function", "path": "docforge.cli.mkdocs_utils.generate_config", - "signature": "", + "signature": "", "docstring": "Generate an mkdocs.yml configuration file.\n\nArgs:\n docs_dir: Path to the directory containing documentation Markdown files.\n nav_file: Path to the docforge.nav.yml specification.\n template: Optional path to an mkdocs.yml template (overrides built-in).\n out: Path where the final mkdocs.yml will be written.\n site_name: The display name for the documentation site." }, "build": { "name": "build", "kind": "function", "path": "docforge.cli.mkdocs_utils.build", - "signature": "", + "signature": "", "docstring": "Build the documentation site using MkDocs.\n\nArgs:\n mkdocs_yml: Path to the mkdocs.yml configuration file." }, "serve": { "name": "serve", "kind": "function", "path": "docforge.cli.mkdocs_utils.serve", - "signature": "", + "signature": "", "docstring": "Serve the documentation site with live-reload using MkDocs.\n\nArgs:\n mkdocs_yml: Path to the mkdocs.yml configuration file." } } diff --git a/mcp_docs/modules/docforge.cli.mkdocs_utils.json b/mcp_docs/modules/docforge.cli.mkdocs_utils.json index 92af3a4..26eb5d7 100644 --- a/mcp_docs/modules/docforge.cli.mkdocs_utils.json +++ b/mcp_docs/modules/docforge.cli.mkdocs_utils.json @@ -81,7 +81,14 @@ "kind": "function", "path": "docforge.cli.mkdocs_utils.MkDocsRenderer.generate_sources", "signature": "", - "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project: The project models to render.\n out_dir: Target directory for documentation files.\n module_is_source: Module is the source folder and to be treated as the root folder." + "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project:\n The project model to render.\n\n out_dir:\n Target directory for generated Markdown.\n\n module_is_source:\n If True, treat the module as the root folder." + }, + "generate_readme": { + "name": "generate_readme", + "kind": "function", + "path": "docforge.cli.mkdocs_utils.MkDocsRenderer.generate_readme", + "signature": "", + "docstring": "Generate README.md from the root package docstring.\n\nBehavior:\n\n- If module_is_source is True:\n README.md is generated at project root (docs_dir.parent)\n\n- If module_is_source is False:\n TODO: generate README.md inside respective module folders" } } }, @@ -119,28 +126,28 @@ "name": "generate_sources", "kind": "function", "path": "docforge.cli.mkdocs_utils.generate_sources", - "signature": "", + "signature": "", "docstring": "Generate Markdown source files for the specified module.\n\nArgs:\n module: The dotted path of the primary module to document.\n project_name: Optional override for the project name.\n docs_dir: Directory where the generated Markdown files will be written.\n module_is_source: Module is the source folder and to be treated as the root folder." }, "generate_config": { "name": "generate_config", "kind": "function", "path": "docforge.cli.mkdocs_utils.generate_config", - "signature": "", + "signature": "", "docstring": "Generate an mkdocs.yml configuration file.\n\nArgs:\n docs_dir: Path to the directory containing documentation Markdown files.\n nav_file: Path to the docforge.nav.yml specification.\n template: Optional path to an mkdocs.yml template (overrides built-in).\n out: Path where the final mkdocs.yml will be written.\n site_name: The display name for the documentation site." }, "build": { "name": "build", "kind": "function", "path": "docforge.cli.mkdocs_utils.build", - "signature": "", + "signature": "", "docstring": "Build the documentation site using MkDocs.\n\nArgs:\n mkdocs_yml: Path to the mkdocs.yml configuration file." }, "serve": { "name": "serve", "kind": "function", "path": "docforge.cli.mkdocs_utils.serve", - "signature": "", + "signature": "", "docstring": "Serve the documentation site with live-reload using MkDocs.\n\nArgs:\n mkdocs_yml: Path to the mkdocs.yml configuration file." } } diff --git a/mcp_docs/modules/docforge.json b/mcp_docs/modules/docforge.json index 17ed506..91fb247 100644 --- a/mcp_docs/modules/docforge.json +++ b/mcp_docs/modules/docforge.json @@ -2,7 +2,7 @@ "module": "docforge", "content": { "path": "docforge", - "docstring": "Renderer-agnostic Python documentation compiler that converts docstrings into\nstructured documentation for both humans (MkDocs) and machines (MCP / AI agents).\n\n`doc-forge` statically analyzes your source code, builds a semantic model of\nmodules and objects, and renders that model into documentation outputs without\nexecuting your code.\n---\n\n# Core Philosophy\n\n`doc-forge` follows a compiler architecture:\n\n1. **Front-end (Introspection)**\n Static analysis of modules, classes, functions, signatures, and docstrings.\n\n2. **Middle-end (Semantic Model)**\n Renderer-neutral structured representation of your API.\n\n3. **Back-end (Renderers)**\n\n * MkDocs → human documentation\n * MCP JSON → AI-readable documentation\n---\n\n# Docstring Writing Standard\n\nDocstrings are the single source of truth. `doc-forge` does not generate content.\nIt compiles and renders what you write.\n\nDocumentation follows the Python import hierarchy.\n---\n\n# Package docstring (`package/__init__.py`) — Full user guide\n\nThis is the landing page. A developer must be able to install and use the\npackage after reading only this docstring.\n\n## Example:\n\n '''\n Short description of what this package provides.\n\n # Installation\n\n ```bash\n pip install my-package\n ```\n\n # Quick start\n\n ```python\n from my_package.foo import Bar\n\n bar = Bar()\n result = bar.process(\"example\")\n ```\n ---\n\n # Core concepts\n\n ## Bar\n - Primary object exposed by the package.\n\n ## foo module\n - Provides core functionality.\n ---\n\n # Typical workflow\n\n 1. Import public objects\n 2. Initialize objects\n 3. Call methods\n ---\n\n # Public API\n\n foo.Bar\n foo.helper_function\n ---\n '''\n---\n\n# Submodule docstring (`package/foo/__init__.py`) — Subsystem guide\n\nExplains a specific subsystem.\n\n## Example:\n\n '''\n Provides core functionality.\n\n # Usage\n\n ```python\n from my_package.foo import Bar\n\n bar = Bar()\n bar.process(\"example\")\n ```\n ---\n '''\n---\n\n# Class docstring — Object contract\n\nDefines responsibility and behavior.\n\n## Example:\n\n```python\nclass Bar:\n '''\n Performs processing on input data.\n\n Instances may be reused across multiple calls.\n ---\n '''\n```\n\nInclude:\n\n* Responsibility\n* Lifecycle expectations\n* Thread safety (if relevant)\n* Performance characteristics (if relevant)\n---\n\n# Function and method docstrings — API specification\n\n## Example:\n\n```python\ndef process(\n self,\n value1: str,\n value2: str | None = \"default value\",\n value3: str | None = None,\n) -> str:\n '''\n Process an input value.\n ---\n\n Parameters\n ----------\n value1 : str\n required: True\n value to be processed\n Example:\n 'string'\n\n value2 : str\n required: False\n default: \"default value\"\n value to be processed\n Example:\n 'string'\n\n value3 : str\n required: False\n value to be processed\n Example:\n 'string'\n ---\n\n Returns\n -------\n processed value : str\n result after processing value\n ---\n\n Behavior\n --------\n - behaviour 1\n - behaviour 2\n ---\n '''\n```\n---\n\n# Attribute docstrings (optional)\n\n## Example:\n\n```python\nclass Class\n '''\n attribute1 : str\n required: True\n default: \"default value\"\n attribute description\n\n attribute2 : str\n required: False\n attribute description\n\n attribute2 : str\n required: False\n default: \"default value\"\n attribute description\n '''\n\n attribute1: str = \"default value\"\n attribute2: str | None = None\n attribute3: str | None = \"default value\"\n```\n---\n\n# Writing Rules\n\n**Heading hierarchy**\n\nModule docstring\n\n- Examples\n- Usage\n- Core concepts\n- Public API\n\nClass docstring\n\n- Attributes\n- Execution contract\n- Lifecycle\n- Thread safety\n- Notes\n\nMethod docstring\n\n- Parameters\n- Returns\n- Raises\n- Yields\n- Behavior\n\n**Required**\n\n* Use Markdown headings\n* Use Markdown line separator `---`\n* Line separator should be followed by a blank line\n* Provide real import examples\n* Document all public APIs\n* Keep descriptions precise and factual\n\n**Avoid**\n\n* Plain-text separators like `====`\n* Duplicate external documentation\n* Informal or conversational language\n---\n\n# How doc-forge uses these docstrings\n\n## Build MkDocs site:\n\n```bash\ndoc-forge build --mkdocs --module my_package\n```\n\n## Build MCP documentation:\n\n```bash\ndoc-forge build --mcp --module my_package\n```\n\nBoth outputs are generated directly from docstrings.\n---", + "docstring": "Renderer-agnostic Python documentation compiler that converts Python docstrings\ninto structured documentation for both humans (MkDocs) and machines (MCP / AI agents).\n\n`doc-forge` statically analyzes source code, builds a semantic model of modules,\nclasses, functions, and attributes, and renders that model into documentation\noutputs without executing user code.\n\n---\n\n## Installation\n\nInstall using pip:\n\n pip install doc-forge\n\n---\n\n## Quick start\n\nGenerate a MkDocs site from a Python package:\n\n doc-forge build --mkdocs --module my_package\n\nGenerate MCP JSON documentation:\n\n doc-forge build --mcp --module my_package\n\nServe documentation locally:\n\n doc-forge serve --mkdocs --module my_package\n\n---\n\n## Core concepts\n\n**Loader**\n\nExtracts symbols, signatures, and docstrings using static analysis.\n\n**Semantic model**\n\nStructured, renderer-agnostic representation of the API.\n\n**Renderer**\n\nConverts the semantic model into output formats such as MkDocs or MCP JSON.\n\n**Symbol**\n\nAny documentable object:\n\n - module\n - class\n - function\n - method\n - property\n - attribute\n\n---\n\n## Architecture\n\n`doc-forge` follows a compiler architecture:\n\nFront-end:\n\n Static analysis of modules, classes, functions, type hints, and docstrings.\n\nMiddle-end:\n\n Builds a semantic model describing symbols and relationships.\n\nBack-end:\n\n Renders documentation using interchangeable renderers.\n\nThis architecture ensures deterministic documentation generation.\n\n---\n\n## Rendering pipeline\n\nTypical flow:\n\n Python package\n ↓\n Loader (static analysis)\n ↓\n Semantic model\n ↓\n Renderer\n ↓\n MkDocs site or MCP JSON\n\n---\n\n## CLI usage\n\nBuild MkDocs documentation:\n\n doc-forge build --mkdocs --module my_package\n\nBuild MCP documentation:\n\n doc-forge build --mcp --module my_package\n\nServe MkDocs locally:\n\n doc-forge serve --module my_package\n\n---\n\n## Public API\n\nLoaders:\n\n GriffeLoader\n discover_module_paths\n\nRenderers:\n\n MkDocsRenderer\n MCPRenderer\n\nCLI:\n\n main\n\nModels:\n\n models\n\n---\n\n# Google-Styled Doc-Forge Convention (GSDFC)\n\nGSDFC defines how docstrings must be written so they render correctly in MkDocs and remain machine-parsable by doc-forge and AI tooling.\n\n- Docstrings are the single source of truth.\n- doc-forge compiles docstrings but does not generate documentation content.\n- Documentation follows the Python import hierarchy.\n- Every public symbol should have a complete and accurate docstring.\n\n---\n\n## General rules\n\n- Use **Markdown headings** at package and module level.\n- Use **Google-style structured sections** at class, function, and method level.\n- Indent section contents using four spaces.\n- Use type hints in signatures instead of duplicating types in prose.\n- Write summaries in imperative form.\n- Sections are separated by ```---```\n\n---\n\n## Package docstrings\n\n- Package docstrings act as the documentation home page.\n\nRecommended sections:\n\n ## Summary\n ## Installation\n ## Quick start\n ## Core concepts\n ## Architecture\n ## Rendering pipeline\n ## CLI usage\n ## Public API\n ## Examples\n ## Notes\n\nExample:\n Package Doc String:\n\n '''\n Foo-bar processing framework.\n\n Provides tools for defining Foo objects and executing Bar pipelines.\n\n ---\n\n # Installation\n\n pip install foo-bar\n\n ---\n\n # Quick start\n\n from foobar import Foo, BarEngine\n\n foo = Foo(\"example\")\n engine = BarEngine([foo])\n\n result = engine.run()\n\n ---\n\n # Public API\n\n Foo\n Bar\n BarEngine\n\n ---\n '''\n\n---\n\n## Module docstrings\n\n- Module docstrings describe a subsystem.\n\nRecommended sections:\n\n ## Summary\n ## Examples\n ## Notes\n ## Public API\n\nExample:\n Module Doc String:\n\n '''\n Foo execution subsystem.\n\n Provides utilities for executing Foo objects through Bar stages.\n\n ---\n\n Example:\n\n from foobar.engine import BarEngine\n from foobar.foo import Foo\n\n foo = Foo(\"example\")\n\n engine = BarEngine([foo])\n engine.run()\n\n ---\n '''\n\n---\n\n## Class docstrings\n\n- Class docstrings define object responsibility, lifecycle, and attributes.\n\nRecommended sections:\n\n Attributes:\n Notes:\n Example:\n Raises:\n\nExample:\n Simple Foo:\n\n class Foo:\n '''\n Represents a unit of work.\n\n Attributes:\n name (str):\n Identifier of the foo instance.\n\n value (int):\n Numeric value associated with foo.\n\n Notes:\n Guarantees:\n\n - instances are immutable after creation\n\n Lifecycle:\n\n - create instance\n - pass to processing engine\n\n Example:\n Create and inspect a Foo:\n\n foo = Foo(\"example\", value=42)\n print(foo.name)\n '''\n\n Complex Bar:\n\n class BarEngine:\n '''\n Executes Foo objects through Bar stages.\n\n Attributes:\n foos (tuple[Foo, ...]):\n Foo instances managed by the engine.\n\n Notes:\n Guarantees:\n\n - deterministic execution order\n\n Example:\n Run engine:\n\n foo1 = Foo(\"a\")\n foo2 = Foo(\"b\")\n\n engine = BarEngine([foo1, foo2])\n engine.run()\n '''\n\n---\n\n## Function and method docstrings\n\n- Function docstrings define API contracts.\n\nRecommended sections:\n\n Args:\n Returns:\n Raises:\n Yields:\n Notes:\n Example:\n\nExample:\n Simple process method:\n\n def process(foo: Foo, multiplier: int) -> int:\n '''\n Process a Foo instance.\n\n Args:\n foo (Foo):\n Foo instance to process.\n\n multiplier (int):\n Value used to scale foo.\n\n Returns:\n int:\n Processed result.\n\n Raises:\n ValueError:\n If multiplier is negative.\n\n Notes:\n Guarantees:\n\n - foo is not modified\n\n Example:\n Process foo:\n\n foo = Foo(\"example\", value=10)\n\n result = process(foo, multiplier=2)\n print(result)\n '''\n\n Multiple Examples:\n\n def combine(foo_a: Foo, foo_b: Foo) -> Foo:\n '''\n Combine two Foo instances.\n\n Args:\n foo_a (Foo):\n First foo.\n\n foo_b (Foo):\n Second foo.\n\n Returns:\n Foo:\n Combined foo.\n\n Example:\n Basic usage:\n\n foo1 = Foo(\"a\")\n foo2 = Foo(\"b\")\n\n combined = combine(foo1, foo2)\n\n Pipeline usage:\n\n engine = BarEngine([foo1, foo2])\n engine.run()\n '''\n\n---\n\n## Property docstrings\n\n- Properties must document return values.\n\nExample:\n Property Doc String:\n\n @property\n def foos(self) -> tuple[Foo, ...]:\n '''\n Return contained Foo instances.\n\n Returns:\n tuple[Foo, ...]:\n Stored foo objects.\n\n Example:\n container = FooContainer()\n\n foos = container.foos\n '''\n\n---\n\n## Attribute documentation\n\n- Document attributes in class docstrings using Attributes:.\n\nExample:\n Attribute Doc String:\n\n '''\n Represents a processing stage.\n\n Attributes:\n id (str):\n Unique identifier.\n\n enabled (bool):\n Whether the stage is active.\n '''\n\n---\n\n## Notes subsection grouping\n\n- Group related information using labeled subsections.\n\nExample:\n Notes Example:\n\n Notes:\n **Guarantees:**\n\n - deterministic behavior\n\n **Lifecycle:**\n\n - created during initialization\n - reused across executions\n\n **Thread safety:**\n\n - safe for concurrent reads\n\n---\n\n## Example formatting\n\n- Use indentation for examples.\n\nExample:\n Single example:\n\n Example:\n\n foo = Foo(\"example\")\n process(foo, multiplier=2)\n\n Multiple examples:\n\n Example:\n Create foo:\n\n foo = Foo(\"example\")\n\n Run engine:\n\n engine = BarEngine([foo])\n engine.run()\n\nAvoid fenced code blocks inside structured sections.\n\n---\n\n## Separator rules\n\nUse horizontal separators only at docstring root level to separate sections:\n\n ---\n\nAllowed locations:\n\n- package docstrings\n- module docstrings\n- major documentation sections\n\nDo not use separators inside code sections.\n\n---\n\n## Parsing guarantees\n\nGSDFC ensures doc-forge can deterministically extract:\n\n- symbol kind (module, class, function, property, attribute)\n- symbol name\n- parameters\n- return values\n- attributes\n- examples\n- structured Notes subsections\n\nThis enables:\n\n- reliable MkDocs rendering\n- deterministic MCP export\n- accurate AI semantic interpretation\n\n---\n\nNotes:\n - doc-forge never executes analyzed modules.\n - Documentation is generated entirely through static analysis.", "objects": { "GriffeLoader": { "name": "GriffeLoader", @@ -53,7 +53,14 @@ "kind": "function", "path": "docforge.MkDocsRenderer.generate_sources", "signature": "", - "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project: The project models to render.\n out_dir: Target directory for documentation files.\n module_is_source: Module is the source folder and to be treated as the root folder." + "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project:\n The project model to render.\n\n out_dir:\n Target directory for generated Markdown.\n\n module_is_source:\n If True, treat the module as the root folder." + }, + "generate_readme": { + "name": "generate_readme", + "kind": "function", + "path": "docforge.MkDocsRenderer.generate_readme", + "signature": "", + "docstring": "Generate README.md from the root package docstring.\n\nBehavior:\n\n- If module_is_source is True:\n README.md is generated at project root (docs_dir.parent)\n\n- If module_is_source is False:\n TODO: generate README.md inside respective module folders" } } }, @@ -275,7 +282,14 @@ "kind": "function", "path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer.generate_sources", "signature": "", - "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project: The project models to render.\n out_dir: Target directory for documentation files.\n module_is_source: Module is the source folder and to be treated as the root folder." + "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project:\n The project model to render.\n\n out_dir:\n Target directory for generated Markdown.\n\n module_is_source:\n If True, treat the module as the root folder." + }, + "generate_readme": { + "name": "generate_readme", + "kind": "function", + "path": "docforge.cli.commands.mkdocs_utils.MkDocsRenderer.generate_readme", + "signature": "", + "docstring": "Generate README.md from the root package docstring.\n\nBehavior:\n\n- If module_is_source is True:\n README.md is generated at project root (docs_dir.parent)\n\n- If module_is_source is False:\n TODO: generate README.md inside respective module folders" } } }, @@ -707,7 +721,14 @@ "kind": "function", "path": "docforge.cli.mkdocs_utils.MkDocsRenderer.generate_sources", "signature": "", - "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project: The project models to render.\n out_dir: Target directory for documentation files.\n module_is_source: Module is the source folder and to be treated as the root folder." + "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project:\n The project model to render.\n\n out_dir:\n Target directory for generated Markdown.\n\n module_is_source:\n If True, treat the module as the root folder." + }, + "generate_readme": { + "name": "generate_readme", + "kind": "function", + "path": "docforge.cli.mkdocs_utils.MkDocsRenderer.generate_readme", + "signature": "", + "docstring": "Generate README.md from the root package docstring.\n\nBehavior:\n\n- If module_is_source is True:\n README.md is generated at project root (docs_dir.parent)\n\n- If module_is_source is False:\n TODO: generate README.md inside respective module folders" } } }, @@ -745,28 +766,28 @@ "name": "generate_sources", "kind": "function", "path": "docforge.cli.mkdocs_utils.generate_sources", - "signature": "", + "signature": "", "docstring": "Generate Markdown source files for the specified module.\n\nArgs:\n module: The dotted path of the primary module to document.\n project_name: Optional override for the project name.\n docs_dir: Directory where the generated Markdown files will be written.\n module_is_source: Module is the source folder and to be treated as the root folder." }, "generate_config": { "name": "generate_config", "kind": "function", "path": "docforge.cli.mkdocs_utils.generate_config", - "signature": "", + "signature": "", "docstring": "Generate an mkdocs.yml configuration file.\n\nArgs:\n docs_dir: Path to the directory containing documentation Markdown files.\n nav_file: Path to the docforge.nav.yml specification.\n template: Optional path to an mkdocs.yml template (overrides built-in).\n out: Path where the final mkdocs.yml will be written.\n site_name: The display name for the documentation site." }, "build": { "name": "build", "kind": "function", "path": "docforge.cli.mkdocs_utils.build", - "signature": "", + "signature": "", "docstring": "Build the documentation site using MkDocs.\n\nArgs:\n mkdocs_yml: Path to the mkdocs.yml configuration file." }, "serve": { "name": "serve", "kind": "function", "path": "docforge.cli.mkdocs_utils.serve", - "signature": "", + "signature": "", "docstring": "Serve the documentation site with live-reload using MkDocs.\n\nArgs:\n mkdocs_yml: Path to the mkdocs.yml configuration file." } } @@ -2079,7 +2100,14 @@ "kind": "function", "path": "docforge.renderers.MkDocsRenderer.generate_sources", "signature": "", - "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project: The project models to render.\n out_dir: Target directory for documentation files.\n module_is_source: Module is the source folder and to be treated as the root folder." + "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project:\n The project model to render.\n\n out_dir:\n Target directory for generated Markdown.\n\n module_is_source:\n If True, treat the module as the root folder." + }, + "generate_readme": { + "name": "generate_readme", + "kind": "function", + "path": "docforge.renderers.MkDocsRenderer.generate_readme", + "signature": "", + "docstring": "Generate README.md from the root package docstring.\n\nBehavior:\n\n- If module_is_source is True:\n README.md is generated at project root (docs_dir.parent)\n\n- If module_is_source is False:\n TODO: generate README.md inside respective module folders" } } }, @@ -2465,7 +2493,7 @@ "kind": "module", "path": "docforge.renderers.mkdocs_renderer", "signature": null, - "docstring": "MkDocsRenderer\n\nGenerates Markdown source files compatible with MkDocs Material\nand mkdocstrings, ensuring:\n\n- Root index.md always exists\n- Parent package indexes are created automatically\n- Child modules are linked in parent index files", + "docstring": "MkDocsRenderer\n\nGenerates Markdown source files compatible with MkDocs Material\nand mkdocstrings, ensuring:\n\n- Root index.md always exists\n- Parent package indexes are created automatically\n- Child modules are linked in parent index files\n- README.md can be generated from the root package docstring", "members": { "Path": { "name": "Path", @@ -2580,7 +2608,7 @@ "name": "MkDocsRenderer", "kind": "class", "path": "docforge.renderers.mkdocs_renderer.MkDocsRenderer", - "signature": "", + "signature": "", "docstring": "Renderer that generates Markdown source files formatted for the MkDocs\n'mkdocstrings' plugin.", "members": { "name": { @@ -2594,8 +2622,15 @@ "name": "generate_sources", "kind": "function", "path": "docforge.renderers.mkdocs_renderer.MkDocsRenderer.generate_sources", - "signature": "", - "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project: The project models to render.\n out_dir: Target directory for documentation files.\n module_is_source: Module is the source folder and to be treated as the root folder." + "signature": "", + "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project:\n The project model to render.\n\n out_dir:\n Target directory for generated Markdown.\n\n module_is_source:\n If True, treat the module as the root folder." + }, + "generate_readme": { + "name": "generate_readme", + "kind": "function", + "path": "docforge.renderers.mkdocs_renderer.MkDocsRenderer.generate_readme", + "signature": "", + "docstring": "Generate README.md from the root package docstring.\n\nBehavior:\n\n- If module_is_source is True:\n README.md is generated at project root (docs_dir.parent)\n\n- If module_is_source is False:\n TODO: generate README.md inside respective module folders" } } } diff --git a/mcp_docs/modules/docforge.renderers.json b/mcp_docs/modules/docforge.renderers.json index 81a0102..137a5ec 100644 --- a/mcp_docs/modules/docforge.renderers.json +++ b/mcp_docs/modules/docforge.renderers.json @@ -23,7 +23,14 @@ "kind": "function", "path": "docforge.renderers.MkDocsRenderer.generate_sources", "signature": "", - "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project: The project models to render.\n out_dir: Target directory for documentation files.\n module_is_source: Module is the source folder and to be treated as the root folder." + "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project:\n The project model to render.\n\n out_dir:\n Target directory for generated Markdown.\n\n module_is_source:\n If True, treat the module as the root folder." + }, + "generate_readme": { + "name": "generate_readme", + "kind": "function", + "path": "docforge.renderers.MkDocsRenderer.generate_readme", + "signature": "", + "docstring": "Generate README.md from the root package docstring.\n\nBehavior:\n\n- If module_is_source is True:\n README.md is generated at project root (docs_dir.parent)\n\n- If module_is_source is False:\n TODO: generate README.md inside respective module folders" } } }, @@ -409,7 +416,7 @@ "kind": "module", "path": "docforge.renderers.mkdocs_renderer", "signature": null, - "docstring": "MkDocsRenderer\n\nGenerates Markdown source files compatible with MkDocs Material\nand mkdocstrings, ensuring:\n\n- Root index.md always exists\n- Parent package indexes are created automatically\n- Child modules are linked in parent index files", + "docstring": "MkDocsRenderer\n\nGenerates Markdown source files compatible with MkDocs Material\nand mkdocstrings, ensuring:\n\n- Root index.md always exists\n- Parent package indexes are created automatically\n- Child modules are linked in parent index files\n- README.md can be generated from the root package docstring", "members": { "Path": { "name": "Path", @@ -524,7 +531,7 @@ "name": "MkDocsRenderer", "kind": "class", "path": "docforge.renderers.mkdocs_renderer.MkDocsRenderer", - "signature": "", + "signature": "", "docstring": "Renderer that generates Markdown source files formatted for the MkDocs\n'mkdocstrings' plugin.", "members": { "name": { @@ -538,8 +545,15 @@ "name": "generate_sources", "kind": "function", "path": "docforge.renderers.mkdocs_renderer.MkDocsRenderer.generate_sources", - "signature": "", - "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project: The project models to render.\n out_dir: Target directory for documentation files.\n module_is_source: Module is the source folder and to be treated as the root folder." + "signature": "", + "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project:\n The project model to render.\n\n out_dir:\n Target directory for generated Markdown.\n\n module_is_source:\n If True, treat the module as the root folder." + }, + "generate_readme": { + "name": "generate_readme", + "kind": "function", + "path": "docforge.renderers.mkdocs_renderer.MkDocsRenderer.generate_readme", + "signature": "", + "docstring": "Generate README.md from the root package docstring.\n\nBehavior:\n\n- If module_is_source is True:\n README.md is generated at project root (docs_dir.parent)\n\n- If module_is_source is False:\n TODO: generate README.md inside respective module folders" } } } diff --git a/mcp_docs/modules/docforge.renderers.mkdocs_renderer.json b/mcp_docs/modules/docforge.renderers.mkdocs_renderer.json index 73ce76c..a6368bf 100644 --- a/mcp_docs/modules/docforge.renderers.mkdocs_renderer.json +++ b/mcp_docs/modules/docforge.renderers.mkdocs_renderer.json @@ -2,7 +2,7 @@ "module": "docforge.renderers.mkdocs_renderer", "content": { "path": "docforge.renderers.mkdocs_renderer", - "docstring": "MkDocsRenderer\n\nGenerates Markdown source files compatible with MkDocs Material\nand mkdocstrings, ensuring:\n\n- Root index.md always exists\n- Parent package indexes are created automatically\n- Child modules are linked in parent index files", + "docstring": "MkDocsRenderer\n\nGenerates Markdown source files compatible with MkDocs Material\nand mkdocstrings, ensuring:\n\n- Root index.md always exists\n- Parent package indexes are created automatically\n- Child modules are linked in parent index files\n- README.md can be generated from the root package docstring", "objects": { "Path": { "name": "Path", @@ -117,7 +117,7 @@ "name": "MkDocsRenderer", "kind": "class", "path": "docforge.renderers.mkdocs_renderer.MkDocsRenderer", - "signature": "", + "signature": "", "docstring": "Renderer that generates Markdown source files formatted for the MkDocs\n'mkdocstrings' plugin.", "members": { "name": { @@ -131,8 +131,15 @@ "name": "generate_sources", "kind": "function", "path": "docforge.renderers.mkdocs_renderer.MkDocsRenderer.generate_sources", - "signature": "", - "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project: The project models to render.\n out_dir: Target directory for documentation files.\n module_is_source: Module is the source folder and to be treated as the root folder." + "signature": "", + "docstring": "Produce a set of Markdown files in the output directory based on the\nprovided Project models.\n\nArgs:\n project:\n The project model to render.\n\n out_dir:\n Target directory for generated Markdown.\n\n module_is_source:\n If True, treat the module as the root folder." + }, + "generate_readme": { + "name": "generate_readme", + "kind": "function", + "path": "docforge.renderers.mkdocs_renderer.MkDocsRenderer.generate_readme", + "signature": "", + "docstring": "Generate README.md from the root package docstring.\n\nBehavior:\n\n- If module_is_source is True:\n README.md is generated at project root (docs_dir.parent)\n\n- If module_is_source is False:\n TODO: generate README.md inside respective module folders" } } }