@@ -11199,9 +11199,8 @@ def _inject_version_selector(self, quarto_yml: Path) -> None:
1119911199 """
1120011200 Inject the version selector widget into the Quarto config.
1120111201
11202- Adds the version-selector.js script and a `<meta name="gd-version-map">`
11203- tag containing the serialized `_version_map.json` data so the widget
11204- can resolve versions client-side.
11202+ Adds the version-selector.js script and a `<meta name="gd-version-map">` tag containing the
11203+ serialized `_version_map.json` data so the widget can resolve versions client-side.
1120511204 """
1120611205 import html as html_mod
1120711206
@@ -11721,15 +11720,16 @@ def _generate_skill_md(self) -> None:
1172111720 """
1172211721 Generate a SKILL.md file conforming to the Agent Skills specification.
1172311722
11724- Creates a skill file that gives AI coding agents structured context about the
11725- documented package — its capabilities, API decision table, gotchas, and links
11726- to comprehensive documentation.
11723+ Creates a skill file that gives AI coding agents structured context about the documented
11724+ package: its capabilities, API decision table, gotchas, and links to comprehensive
11725+ documentation.
1172711726
11728- If the user has provided a hand-written SKILL.md via `skill.file` in
11729- `great-docs.yml`, that file is copied verbatim instead of generating one.
11727+ If the user has provided a hand-written SKILL.md via `skill.file` in `great-docs.yml`, that
11728+ file is copied verbatim instead of generating one.
1173011729
11731- The generated file is written to `<docs>/skill.md` and optionally copied to
11732- `<docs>/.well-known/skills/default/SKILL.md` for auto-discovery.
11730+ The generated file is written to `<docs>/skill.md` and optionally published at
11731+ `<docs>/.well-known/agent-skills/<name>/SKILL.md` with a discovery manifest at
11732+ `<docs>/.well-known/agent-skills/index.json` for `npx skills add` auto-discovery.
1173311733 """
1173411734 import shutil
1173511735
@@ -11939,25 +11939,24 @@ def _generate_skill_md(self) -> None:
1193911939
1194011940 def _generate_skills_page(self, skill_path: "Path", *, skill_dir: "Path | None" = None) -> None:
1194111941 """
11942- Generate a `skills.qmd` page that renders the raw SKILL.md content in a
11943- styled, human-readable format.
11942+ Generate a `skills.qmd` page that renders the raw SKILL.md content in a styled,
11943+ human-readable format.
1194411944
11945- The page displays the skill's YAML frontmatter as a highlighted block and
11946- the Markdown body with color-coded headings and monospaced font — a halfway
11947- point between raw Markdown and fully rendered HTML.
11945+ The page displays the skill's YAML frontmatter as a highlighted block and the Markdown body
11946+ with color-coded headings and monospaced font: a halfway point between raw Markdown and
11947+ fully rendered HTML.
1194811948
11949- When *skill_dir* points to a curated skill directory that contains companion
11950- subdirectories (`references/`, `scripts/`, `assets/`), a directory
11951- tree is rendered before the SKILL.md and each `.md` / `.sh` file is
11952- displayed in its own text area with anchor links.
11949+ When *skill_dir* points to a curated skill directory that contains companion subdirectories
11950+ (`references/`, `scripts/`, `assets/`), a directory tree is rendered before the SKILL.md and
11951+ each `.md` / `.sh` file is displayed in its own text area with anchor links.
1195311952
1195411953 Parameters
1195511954 ----------
1195611955 skill_path
1195711956 Path to the skill.md file to render.
1195811957 skill_dir
11959- Optional path to the curated skill directory containing SKILL.md and
11960- its companion subdirectories.
11958+ Optional path to the curated skill directory containing SKILL.md and its companion
11959+ subdirectories.
1196111960 """
1196211961 import re
1196311962
@@ -12257,7 +12256,13 @@ def _t(key: str, fallback: str) -> str:
1225712256
1225812257 def _place_well_known_skill(self, skill_path: "Path") -> None:
1225912258 """
12260- Copy the SKILL.md to .well-known/skills/default/ for auto-discovery.
12259+ Copy the SKILL.md to .well-known/ directories for auto-discovery.
12260+
12261+ Places the skill at two well-known locations:
12262+
12263+ 1. `.well-known/agent-skills/{name}/SKILL.md` with an `index.json` discovery manifest: the
12264+ preferred path used by `npx skills add`.
12265+ 2. `.well-known/skills/default/SKILL.md`: legacy fallback.
1226112266
1226212267 Parameters
1226312268 ----------
@@ -12269,11 +12274,37 @@ def _place_well_known_skill(self, skill_path: "Path") -> None:
1226912274 if not self._config.skill_well_known:
1227012275 return
1227112276
12277+ # Parse frontmatter to extract skill name and description
12278+ content = skill_path.read_text(encoding="utf-8")
12279+ fm, _ = self._split_frontmatter(content)
12280+ skill_name = fm.get("name", "default")
12281+ skill_description = fm.get("description", "")
12282+ if isinstance(skill_description, str):
12283+ skill_description = skill_description.strip()
12284+
12285+ # --- Preferred: .well-known/agent-skills/{name}/SKILL.md + index.json ---
12286+ agent_skills_dir = self.project_path / ".well-known" / "agent-skills" / skill_name
12287+ agent_skills_dir.mkdir(parents=True, exist_ok=True)
12288+ shutil.copy2(skill_path, agent_skills_dir / "SKILL.md")
12289+
12290+ index_data = {
12291+ "skills": [
12292+ {
12293+ "name": skill_name,
12294+ "description": skill_description,
12295+ "files": ["SKILL.md"],
12296+ }
12297+ ]
12298+ }
12299+ index_path = self.project_path / ".well-known" / "agent-skills" / "index.json"
12300+ with open(index_path, "w", encoding="utf-8") as f:
12301+ json.dump(index_data, f, indent=2)
12302+ f.write("\n")
12303+
12304+ # --- Legacy: .well-known/skills/default/SKILL.md ---
1227212305 well_known_dir = self.project_path / ".well-known" / "skills" / "default"
1227312306 well_known_dir.mkdir(parents=True, exist_ok=True)
12274-
12275- dest = well_known_dir / "SKILL.md"
12276- shutil.copy2(skill_path, dest)
12307+ shutil.copy2(skill_path, well_known_dir / "SKILL.md")
1227712308
1227812309 # ══════════════════════════════════════════════════════════════════════════
1227912310 # SEO GENERATION METHODS
@@ -12337,8 +12368,8 @@ def _generate_sitemap_xml(self) -> None:
1233712368 """
1233812369 Generate a sitemap.xml file for search engine indexing.
1233912370
12340- Creates an XML sitemap at _site/sitemap.xml with proper priorities
12341- and change frequencies based on page type.
12371+ Creates an XML sitemap at _site/sitemap.xml with proper priorities and change frequencies
12372+ based on page type.
1234212373 """
1234312374 if not self._config.sitemap_enabled:
1234412375 return # pragma: no cover
@@ -12476,9 +12507,9 @@ def _resolve_social_card_image_url(self) -> str | None:
1247612507 """
1247712508 Resolve the social card image to an absolute URL.
1247812509
12479- If the configured image is a local file path, copies it to the build
12480- directory and returns the site-relative path. If it's already a URL,
12481- returns it as-is. If no image is configured, returns None.
12510+ If the configured image is a local file path, copies it to the build directory and returns
12511+ the site-relative path. If it's already a URL, returns it as-is. If no image is configured ,
12512+ returns ` None` .
1248212513
1248312514 Returns
1248412515 -------
@@ -12617,9 +12648,7 @@ def _annotate(pages: list[dict[str, object]]) -> list[dict[str, object]]:
1261712648 total_seconds += ver_total
1261812649 versions_payload[tag] = {
1261912650 "seconds": ver_total,
12620- "pages": sorted(
12621- _annotate(timings), key=lambda t: t["seconds"], reverse=True
12622- ),
12651+ "pages": sorted(_annotate(timings), key=lambda t: t["seconds"], reverse=True),
1262312652 }
1262412653 payload["total_seconds"] = round(total_seconds, 3)
1262512654 payload["versions"] = versions_payload
@@ -12696,8 +12725,8 @@ def _get_user_guide_text_for_llms(self) -> str:
1269612725 """
1269712726 Get User Guide content formatted for llms-full.txt.
1269812727
12699- Reads all user guide .qmd files in order and extracts their content,
12700- stripping YAML frontmatter but preserving the document structure.
12728+ Reads all user guide .qmd files in order and extracts their content, stripping YAML
12729+ frontmatter but preserving the document structure.
1270112730
1270212731 Returns
1270312732 -------
@@ -13501,8 +13530,7 @@ class Result:
1350113530 mock_modified = _expand_mock_cells(self.project_path)
1350213531 if mock_modified:
1350313532 log.detail(
13504- f"Expanded {len(mock_modified)} mock-code cell(s): "
13505- + ", ".join(mock_modified)
13533+ f"Expanded {len(mock_modified)} mock-code cell(s): " + ", ".join(mock_modified)
1350613534 )
1350713535
1350813536 # Get environment with QUARTO_PYTHON set
0 commit comments