diff --git a/docs/README.skills.md b/docs/README.skills.md
index 6b38622ce..88b15d07b 100644
--- a/docs/README.skills.md
+++ b/docs/README.skills.md
@@ -192,6 +192,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-skills) for guidelines on how to
| [github-copilot-starter](../skills/github-copilot-starter/SKILL.md)
`gh skills install github/awesome-copilot github-copilot-starter` | Set up complete GitHub Copilot configuration for a new project based on technology stack | None |
| [github-issues](../skills/github-issues/SKILL.md)
`gh skills install github/awesome-copilot github-issues` | Create, update, and manage GitHub issues using MCP tools. Use this skill when users want to create bug reports, feature requests, or task issues, update existing issues, add labels/assignees/milestones, set issue fields (dates, priority, custom fields), set issue types, manage issue workflows, link issues, add dependencies, or track blocked-by/blocking relationships. Triggers on requests like "create an issue", "file a bug", "request a feature", "update issue X", "set the priority", "set the start date", "link issues", "add dependency", "blocked by", "blocking", or any GitHub issue management task. | `references/dependencies.md`
`references/images.md`
`references/issue-fields.md`
`references/issue-types.md`
`references/projects.md`
`references/search.md`
`references/sub-issues.md`
`references/templates.md` |
| [github-release](../skills/github-release/SKILL.md)
`gh skills install github/awesome-copilot github-release` | Guides IA through releasing a new version of a GitHub library end-to-end. Handles SemVer versioning and Keep a Changelog formatting automatically. | `references/commit-classification.md`
`references/semver-rules.md` |
+| [github-repo-publisher](../skills/github-repo-publisher/SKILL.md)
`gh skills install github/awesome-copilot github-repo-publisher` | Guide agents through GitHub repository publishing-surface preparation, audits, and safe publishing workflows. Use when preparing a repository for first public release, reviewing an already public GitHub repo, or updating README files, translated READMEs, About description, topics, homepage, social preview, badges, license and attribution notices, community health files, package metadata, changelog or release copy, issues, PR text, branch or security settings, and other public-facing GitHub copy; also use for git, gh, GitHub API, or connector operations that must preserve repo facts and user changes. | `references/github-operations.md`
`references/publishing-copy.md`
`references/readme-metadata.md`
`references/safety-quality.md`
`scripts/collect-repo-facts.mjs`
`scripts/collect-repo-facts.ps1` |
| [go-mcp-server-generator](../skills/go-mcp-server-generator/SKILL.md)
`gh skills install github/awesome-copilot go-mcp-server-generator` | Generate a complete Go MCP server project with proper structure, dependencies, and implementation using the official github.com/modelcontextprotocol/go-sdk. | None |
| [gsap-framer-scroll-animation](../skills/gsap-framer-scroll-animation/SKILL.md)
`gh skills install github/awesome-copilot gsap-framer-scroll-animation` | Use this skill whenever the user wants to build scroll animations, scroll effects, parallax, scroll-triggered reveals, pinned sections, horizontal scroll, text animations, or any motion tied to scroll position — in vanilla JS, React, or Next.js. Covers GSAP ScrollTrigger (pinning, scrubbing, snapping, timelines, horizontal scroll, ScrollSmoother, matchMedia) and Framer Motion / Motion v12 (useScroll, useTransform, useSpring, whileInView, variants). Use this skill even if the user just says "animate on scroll", "fade in as I scroll", "make it scroll like Apple", "parallax effect", "sticky section", "scroll progress bar", or "entrance animation". Also triggers for Copilot prompt patterns for GSAP or Framer Motion code generation. Pairs with the premium-frontend-ui skill for creative philosophy and design-level polish. | `references/framer.md`
`references/gsap.md` |
| [gtm-0-to-1-launch](../skills/gtm-0-to-1-launch/SKILL.md)
`gh skills install github/awesome-copilot gtm-0-to-1-launch` | Launch new products from idea to first customers. Use when launching products, finding early adopters, building launch week playbooks, diagnosing why adoption stalls, or learning that press coverage does not equal growth. Includes the three-layer diagnosis, the 2-week experiment cycle, and the launch that got 50K impressions and 12 signups. | None |
diff --git a/skills/github-repo-publisher/SKILL.md b/skills/github-repo-publisher/SKILL.md
new file mode 100644
index 000000000..e30420afe
--- /dev/null
+++ b/skills/github-repo-publisher/SKILL.md
@@ -0,0 +1,64 @@
+---
+name: github-repo-publisher
+description: 'Guide agents through GitHub repository publishing-surface preparation, audits, and safe publishing workflows. Use when preparing a repository for first public release, reviewing an already public GitHub repo, or updating README files, translated READMEs, About description, topics, homepage, social preview, badges, license and attribution notices, community health files, package metadata, changelog or release copy, issues, PR text, branch or security settings, and other public-facing GitHub copy; also use for git, gh, GitHub API, or connector operations that must preserve repo facts and user changes.'
+---
+
+# GitHub Repo Publisher
+
+Use this skill to make GitHub-facing work factual, consistent, and safe. Treat README, About metadata, topics, releases, PRs, issues, and discussions as one publishing surface, not separate scraps of copy.
+
+## Core Workflow
+
+1. Resolve context.
+ - Identify the local repository, target GitHub remote, default branch, current branch, and whether the task is read-only or write-capable.
+ - Read local `AGENTS.md` or equivalent repo instructions before using network commands, `gh`, git writes, or packaging/release commands.
+ - Review Git tracking state with `git status`, `git ls-files`, and ignored/untracked files before treating local-vs-remote differences as publishing problems.
+ - Prefer GitHub connector tools for structured repo, issue, and PR data when available. Use `gh` or git when local branch state, Actions logs, commits, pushes, or fields unsupported by the connector matter.
+
+2. Collect facts before writing.
+ - Inspect source files, package manifests, docs, CI config, license, examples, screenshots, releases, and existing GitHub metadata.
+ - For local repos, prefer `node scripts/collect-repo-facts.mjs --repo ` for a quick cross-platform fact map.
+ - If Node.js is unavailable, use `pwsh -NoProfile -File scripts/collect-repo-facts.ps1 -RepoPath ` when PowerShell 7 is available, or collect the same facts manually.
+ - Classify local files as tracked repository content, ignored local context, or untracked candidates. Do not call ignored/untracked local assistant instructions "missing from GitHub" unless the user explicitly intends to publish them.
+ - Report likely tracking mistakes: local assistant instructions that are tracked and need public-intent review, and public-facing docs/assets/manifests that are untracked and may have been forgotten.
+ - Before changing README, About, topics, or homepage, check package manifest metadata, README raw line structure, available screenshot/image assets, license files, and attribution clues.
+ - If the project has i18n config, `_locales`, locale directories, translation resources, or existing translated READMEs, evaluate whether README languages match the user-facing project-supported locales.
+ - Do not invent features, badges, benchmarks, compatibility claims, sponsorship claims, security posture, or installation commands.
+
+3. Classify project scale before making recommendations.
+ - Read `references/safety-quality.md` and classify the repository as `Tiny / Personal / Experiment`, `Small Public / Low-Risk`, `Usable / Public Utility`, or `Serious / Community / Product`.
+ - Then classify the right-sizing dimensions: `Collaboration posture`, `Security exposure`, `Distribution surface`, `User impact`, `Documentation complexity`, and `README language coverage`.
+ - Fit recommendations to the project scale, audience, and right-sizing dimensions. Do not prescribe community governance, security automation, release process, docs architecture, or multilingual documentation unless the context justifies it or the user asks.
+ - Treat Dependabot, code scanning, dependency review, secret scanning, push protection, branch protection, and vulnerability reporting as audit recommendations by default. Do not create configs, workflows, or change GitHub settings for them unless the user explicitly asks for that specific action.
+
+4. Choose the publishing track.
+ - README/About/Topics/Homepage/Social preview/multilingual docs: read `references/readme-metadata.md`.
+ - PR, issue, discussion, release, and changelog copy: read `references/publishing-copy.md`.
+ - GitHub operations, commits, pushes, PR creation, or API writes: read `references/github-operations.md`.
+ - Risk checks, write confirmations, and quality gates: read `references/safety-quality.md`.
+
+5. Draft or edit with traceability.
+ - Tie each public claim to observed repository facts.
+ - Keep copy audience-aware: first-time evaluator, potential contributor, package user, maintainer, or reviewer.
+ - If facts are missing, add a clear placeholder note, ask a focused question, or omit the claim.
+
+6. Validate before delivery.
+ - Re-read changed files for broken headings, links, image paths, tables, fenced code blocks, and stale badges.
+ - For README audits, report whether raw Markdown line structure was checked. Prefer `lineCount` and `maxLineLength` from `scripts/collect-repo-facts.mjs` when available.
+ - Run relevant tests or lint/docs checks when the repo provides them.
+ - For GitHub writes, summarize target repo, branch, files/metadata, and exact action before applying unless the user already explicitly requested that write.
+
+## Operating Rules
+
+- Preserve user work. Do not reset, checkout away, delete, or overwrite unrelated changes.
+- Keep local edits and remote writes separate. A polished README draft is not permission to push it.
+- Use explicit paths when staging mixed worktrees. Avoid broad `git add -A` unless every change belongs to the task.
+- Treat ignored or untracked local assistant instructions such as `AGENTS.md`, `CLAUDE.md`, or editor/agent rule folders as operational context, not GitHub publishing-surface gaps. If they are tracked, review whether they are intentional public repo content before recommending changes.
+- For security automation, report `Required for this context` or `Optional for this context` recommendations first. Do not add `.github/dependabot.yml`, security workflows, branch rules, or repository security settings unless the user explicitly authorizes that exact change.
+- Prefer draft PRs unless the user asks for ready review.
+- For `gh` or HTTPS failures, check auth first, then repo instructions for proxy requirements. If a local instruction requires proxy environment variables, apply them to the command invocation.
+- If a requested GitHub field is not available through the current tool, state the limitation and provide an exact fallback command or manual update text.
+
+## Output Shape
+
+For audits, include `Scale classification`, `Right-sizing dimensions`, concrete findings, and right-sized proposed edits. Mark every recommendation as `Required for this context` or `Optional for this context`, and name the dimension that triggers it. For creation/update tasks, provide the changed files plus concise notes on what GitHub metadata should be set to. For write operations, include what succeeded, what was verified, and anything still requiring the user's GitHub permissions.
diff --git a/skills/github-repo-publisher/references/github-operations.md b/skills/github-repo-publisher/references/github-operations.md
new file mode 100644
index 000000000..009bbe915
--- /dev/null
+++ b/skills/github-repo-publisher/references/github-operations.md
@@ -0,0 +1,104 @@
+# GitHub Operations
+
+Use this reference when a task touches git state, GitHub APIs, `gh`, PRs, issues, releases, or repository metadata writes.
+
+## Tool Preference
+
+- Use GitHub connector tools for structured repo, issue, PR, comment, label, and reaction operations when available.
+- Use local `git` for branch, diff, status, staging, commit, and push.
+- Use `gh` for current-branch PR discovery, GitHub Actions checks/logs, repository metadata fields not exposed elsewhere, releases, and API fallbacks.
+- Use the browser only when an action depends on the user's existing logged-in web session or when the user explicitly asks for browser operation.
+
+## Before Write Operations
+
+Check:
+
+- `git status --short --branch`
+- `git ls-files`
+- Ignored and untracked files, for example with `git ls-files --others --exclude-standard` and `git ls-files --others --ignored --exclude-standard`
+- `git remote -v`
+- Current branch and upstream.
+- Whether the worktree contains unrelated user changes.
+- Local instructions such as `AGENTS.md`, especially proxy, packaging, release, branch, or commit conventions.
+- Auth with `gh auth status` when using `gh`.
+- Branch protection, rulesets, required reviews, required status checks, signed commit rules, and release permissions when a write targets GitHub.
+- For security automation writes, confirm the target repository, exact file or setting, schedule or trigger, affected branches/ecosystems, and expected notification or permission impact. This includes `.github/dependabot.yml`, `.github/workflows/*security*`, code scanning, dependency review, branch protection, Dependabot settings, secret scanning, push protection, and private vulnerability reporting.
+
+If GitHub HTTPS access requires a proxy, apply repo-local instructions. Example for shells that support environment variables:
+
+```bash
+HTTPS_PROXY= HTTP_PROXY= gh repo view
+```
+
+In PowerShell:
+
+```powershell
+$env:HTTPS_PROXY=''; $env:HTTP_PROXY=''; gh repo view
+```
+
+## Git Tracking Review
+
+Before reporting that a local file is missing from GitHub, classify it by Git tracking state.
+
+Common local assistant instruction files include `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `CODEX.md`, `.cursor/rules`, `.cursorrules`, `.windsurfrules`, `.clinerules`, `.claude`, and `.codex`.
+
+- Treat ignored or untracked files in this family as local operational context, not GitHub publishing-surface gaps.
+- Treat tracked files in this family as valid repository content, but review whether publishing them is intentional, useful, and free of sensitive local instructions.
+- Flag untracked files that look public-facing as possible forgotten tracking, especially README assets, docs, license files, manifests, examples, screenshots, social previews, and CI/config files meant for the repository.
+- Do not stage, untrack, delete, or push tracking-review findings unless the user explicitly asks for that action.
+
+## Safe Git Flow
+
+1. Inspect current state.
+2. Create or switch to a task branch when appropriate. Use the repo's preferred agent branch prefix, or `agent/` when no convention exists.
+3. Edit only relevant files.
+4. Run focused validation.
+5. Stage explicit paths in mixed worktrees.
+6. Commit with a concise message.
+7. Push the branch.
+8. Open a draft PR unless the user requests ready review.
+
+Do not use destructive commands such as hard resets or checkout-based reverts unless the user clearly asks for them.
+
+Do not bypass branch protection, rulesets, required review, signed commit, or required status check policies. For regular collaborators, prefer a branch PR workflow. Use fork PRs primarily for external contributors or when repository permissions require them.
+
+Do not add Dependabot, code scanning, dependency review, secret scanning, or other security automation as a side effect of a repository audit. Draft or report the recommendation first, then apply only the exact security change the user explicitly requested.
+
+## Release Operations
+
+- Confirm the release tag, target commit, version, changelog source, generated notes source, and release assets before creating or updating a release.
+- Treat draft releases as the default when the user has not explicitly asked to publish immediately.
+- Do not upload binaries, installers, archives, screenshots, or GIFs unless the user requested release assets and the files are verified.
+
+## Metadata Updates
+
+Repository About metadata commonly includes:
+
+- `description`
+- `homepage`
+- `topics`
+
+Prefer drafting exact values first. Apply through connector/API/`gh repo edit` only after the target repo and values are confirmed or the user explicitly requested the update.
+
+Example fallback:
+
+```bash
+gh repo edit OWNER/REPO --description "..." --homepage "https://..."
+gh repo edit OWNER/REPO --add-topic agents --add-topic github
+```
+
+## Actions and CI
+
+For failing GitHub Actions:
+
+- Use `gh pr checks --json name,state,bucket,link,workflow`.
+- Fetch logs with `gh run view --log-failed` when available.
+- Report external checks as external unless the user asks for a separate provider investigation.
+
+Never claim a check passed unless the command or connector result shows it.
+
+## Large Files and Assets
+
+- Avoid adding large screenshots, GIFs, videos, archives, installers, datasets, or generated binaries directly to the repository.
+- Prefer optimized images for README assets, GitHub release assets for downloadable artifacts, and Git LFS for large files that truly must live in the repository.
+- Before adding binary assets, check existing repo conventions and whether the project already uses Git LFS or release artifacts.
diff --git a/skills/github-repo-publisher/references/publishing-copy.md b/skills/github-repo-publisher/references/publishing-copy.md
new file mode 100644
index 000000000..769d503f4
--- /dev/null
+++ b/skills/github-repo-publisher/references/publishing-copy.md
@@ -0,0 +1,94 @@
+# Publishing Copy
+
+Use this reference for PR titles and bodies, release notes, changelogs, GitHub Discussions, and issue announcements.
+
+## PR Titles
+
+Prefer:
+
+- `Add `
+- `Fix `
+- `Update documentation`
+- `Refactor to ` only when behavior is intentionally unchanged.
+
+For agent-authored PRs, use the repository's preferred agent prefix, such as `[agent] `, only when the repo or user prefers that convention. Keep titles under about 72 characters when practical.
+
+## PR Bodies
+
+Include:
+
+- Summary of what changed.
+- Why it changed or root cause for fixes.
+- Validation performed, including commands and important results.
+- Screenshots or before/after notes for UI/docs where useful.
+- Risks, migrations, or follow-ups.
+
+Avoid:
+
+- Long implementation diary.
+- Test claims for commands that were not run.
+- Hiding uncertainty. Say "Not run" with the reason.
+
+Template:
+
+```markdown
+## Summary
+-
+
+## Validation
+-
+
+## Notes
+-
+```
+
+## Release Notes
+
+Release notes are tied to GitHub releases and tags. Confirm the tag, target commit, version, assets, and changelog source before drafting or publishing.
+
+Group by user impact:
+
+- Added
+- Changed
+- Fixed
+- Removed
+- Security
+
+Write for users, not only maintainers. Mention upgrade steps, breaking changes, deprecations, and migration commands when real. Do not include internal refactors unless they affect users or contributors.
+
+GitHub automatically generated release notes can be used as a starting point, but edit them for user impact, breaking changes, upgrade notes, and missing context before publishing.
+
+Prefer Semantic Versioning when the project already follows or can reasonably adopt `MAJOR.MINOR.PATCH`. Do not invent version numbers, dates, tags, or compatibility guarantees.
+
+## Issues and Discussions
+
+Use issues for actionable work with reproduction steps, expected behavior, actual behavior, environment, and proposed fix. Use discussions for announcements, design options, questions, or community feedback.
+
+When drafting:
+
+- State the context in the first paragraph.
+- List exact acceptance criteria for implementation work.
+- Include links or file references when available.
+- Label uncertainty as open questions.
+
+## Issue and PR Templates
+
+- Audit for bug report, feature request, and pull request templates when assessing public repository readiness.
+- Recommend issue forms or templates when issues need structured environment, reproduction, expected behavior, and actual behavior fields.
+- Recommend a PR template when reviewers need consistent summary, validation, screenshots, risks, or migration notes.
+- Do not create or rewrite templates unless the user explicitly asks for that artifact.
+
+## Changelog Entries
+
+Prefer concise entries that map to real commits or PRs. Do not fabricate version numbers, dates, contributors, or links.
+
+Use Keep a Changelog-style categories when practical:
+
+- Added
+- Changed
+- Deprecated
+- Removed
+- Fixed
+- Security
+
+Do not use raw git logs as user-facing changelogs. Conventional Commits can inform grouping and automation, but do not force the convention onto a repository that does not use it.
diff --git a/skills/github-repo-publisher/references/readme-metadata.md b/skills/github-repo-publisher/references/readme-metadata.md
new file mode 100644
index 000000000..c8a99909c
--- /dev/null
+++ b/skills/github-repo-publisher/references/readme-metadata.md
@@ -0,0 +1,156 @@
+# README and GitHub Metadata
+
+Use this reference for README files, repository About descriptions, topics, homepage URLs, social preview guidance, and profile README work.
+
+## Fact-First Inputs
+
+Inspect these before drafting:
+
+- Existing `README*`, docs, examples, screenshots, `CHANGELOG*`, `LICENSE*`, `CONTRIBUTING*`, `SECURITY*`, and `CODE_OF_CONDUCT*`.
+- Manifests such as `package.json`, `pyproject.toml`, `Cargo.toml`, `.csproj`, `go.mod`, `composer.json`, `Gemfile`, Docker files, extension manifests, app manifests, and CI files.
+- Public GitHub metadata when accessible: description, homepage, topics, license, latest release, default branch, open issues/PRs, and Actions status.
+- Real usage paths from tests, examples, CLI entry points, exported APIs, routes, screenshots, or demo links.
+
+## README Structure
+
+Prefer this order unless the repo already has a strong convention:
+
+1. Title and one-sentence positioning.
+2. Fast proof: screenshot, demo GIF, CLI output, or minimal example if the project benefits from visual or behavioral proof.
+3. What it does and who it is for.
+4. Feature bullets grounded in repo facts.
+5. Installation or setup.
+6. Quick start with the shortest working path.
+7. Configuration, usage, API, or workflows as needed.
+8. Development, testing, and contribution notes.
+9. License, security, support, or roadmap when present.
+
+Keep the first screen useful: a visitor should understand the project, value, and first action without scrolling far. Do not bury install or usage behind marketing copy.
+
+GitHub README display details:
+
+- README should answer what the project does, why it is useful, how to get started, where to get help, and who maintains it.
+- When multiple README files exist, GitHub shows the first matching file it finds in `.github`, then the repository root, then `docs`.
+- GitHub may truncate README rendering after about `500 KiB`; move long manuals, API references, and tutorials into `docs/`, a wiki, or a documentation site.
+- Prefer relative links and relative image paths for files inside the same repository so links continue to work across branches, forks, and GitHub rendering contexts.
+
+## README Quality Rules
+
+- Prefer concrete verbs and nouns over vague claims such as "powerful", "modern", "seamless", "blazing fast", or "production ready" unless the repository proves them.
+- Keep badges factual and maintainable. Only add badges backed by existing CI, package registries, license files, or public services.
+- Include commands only after verifying package manager, scripts, paths, and prerequisites.
+- Make code examples copy-pasteable, fenced with language tags, and aligned with exported names or CLI flags.
+- If the project is visual, include actual screenshots or asset paths when available. Do not invent images.
+- If the project is a library, show the smallest real import/use example. If it is an app, show run/deploy steps. If it is a plugin/extension, show install/build/package steps.
+- Avoid overpromising support matrix, security guarantees, or roadmap unless documented.
+
+## Markdown Source Maintainability
+
+- README must work as rendered GitHub content and as raw Markdown that is readable in source, diffs, reviews, and translation workflows.
+- Do not compress whole sections, multiple headings, lists, tables, Mermaid diagrams, or HTML blocks into a few extremely long physical lines.
+- Keep normal prose in natural Markdown paragraphs, with lists, tables, fenced code blocks, HTML, and Mermaid diagrams structured across multiple lines.
+- Long URLs, badge links, image links, and unavoidable table cells may stay on one line, but they should not make the whole document a long-line blob.
+- When auditing a README, treat unusually low line counts plus very long lines as a `Recommended improvements` item. Escalate it as a maintainability issue when it makes translation, review, or GitHub diffs hard to trust.
+
+## Repository Lifecycle
+
+- Identify lifecycle status from repository facts: recent commits, releases, open maintenance notes, archived state, deprecation notices, issue activity, and README wording.
+- Reflect status honestly in README, About, topics, and release notes when relevant: `experimental`, `WIP`, `maintained`, `deprecated`, `archived`, or `looking for maintainers`.
+- Put deprecation, archival, or replacement-project notices near the top of the README before installation instructions.
+- Do not present dormant, archived, experimental, or deprecated projects as actively maintained or production ready.
+- Do not archive repositories, close issues, change topics, or alter settings solely because lifecycle language suggests it.
+
+## Badge Policy
+
+- Prefer 3-6 useful badges, ordered roughly as CI/build, package or version, license, coverage, and security.
+- Each badge must reflect a real service, workflow, package registry, license file, or security signal and link to the relevant page.
+- Avoid vanity, decorative, stale, unverifiable, or duplicated badges.
+- Do not add badges for CI, coverage, downloads, package versions, funding, security, or license unless the underlying source exists.
+- Keep badges below the title and language switcher, before the short description.
+
+## Docs Architecture
+
+- Keep README focused on orientation, quick start, core usage, screenshots or proof, and links to deeper documentation.
+- Move long tutorials, API references, FAQ, troubleshooting, architecture notes, and advanced configuration into `docs/`, a wiki, or a documentation site.
+- Link from README to deeper docs with relative links when the docs live in the repository.
+- Do not duplicate large docs sections across README and `docs/`; pick one canonical location and link to it.
+
+## About Description
+
+Write the repository About description as a compact phrase, usually 50-160 characters.
+
+Good pattern:
+
+`Action-oriented project type for audience/context, with key differentiator.`
+
+Examples:
+
+- `Agent skill for auditing GitHub repos and producing factual README, About, PR, and release copy.`
+- `Chrome extension that captures page notes and syncs them to local Markdown files.`
+
+Avoid:
+
+- Keyword stuffing.
+- Ending with a period when the text reads like a label.
+- Claims not visible in the README or code.
+
+## Topics
+
+Recommend 5-12 lowercase GitHub topics:
+
+- Include ecosystem, language/framework, project type, and domain.
+- Prefer common searchable terms over clever branding.
+- Do not include private company names, unsupported platforms, or aspirational tech.
+- For agent skills, include `agents`, the target agent runtime when accurate, and the task domain when appropriate.
+
+## Homepage and Social Preview
+
+- Homepage should be a working demo, docs site, package page, or product page. Leave blank if no stable URL exists.
+- Social preview should show the actual product, CLI result, UI, or concise branded title. Avoid generic gradients.
+- If no image exists, suggest dimensions and content instead of pretending one exists.
+
+## Accessibility
+
+- Give every meaningful image, screenshot, and badge useful alt text. Use empty alt text only for purely decorative images.
+- Keep heading levels in order; do not jump from `##` to `####` for visual sizing.
+- Use descriptive link text. Avoid `click here`, `more`, or bare URLs when a human-readable label is possible.
+- Keep tables readable in raw Markdown and on narrow screens. Prefer lists when table cells become long paragraphs.
+- Do not rely on color alone in screenshots, diagrams, badges, or status explanations.
+
+## Package Metadata Alignment
+
+- Compare README, About description, topics, and homepage against package manifests before changing public copy.
+- Align with manifest fields when present: `description`, `keywords`, `homepage`, `repository`, `license`, package name, binary names, exported entry points, and supported runtime versions.
+- If manifests disagree with the README or GitHub metadata, report the conflict before rewriting both surfaces.
+- Do not add package keywords, compatibility claims, or install commands that are absent from manifests or examples.
+- When improving metadata, prefer one consistent positioning sentence reused across README, package description, and GitHub About with only length-specific edits.
+
+## README Language Coverage
+
+- Default README language follows the repository's existing primary language.
+- Prefer `README.md` for the primary/default language.
+- GitHub does not automatically choose a README by browser language; the repository page displays `README.md`, so multilingual projects need explicit language links.
+- Treat README language coverage as a right-sizing dimension. It controls whether multilingual README work is required, optional, partial, or unnecessary for the current repository context.
+- Respect the user-specified language scope. If the user does not specify one, align README translations with project-supported locales that are visible to users.
+- Determine project-supported locales from explicit i18n configuration, locale directories, translation resource files, manifest or package configuration, existing README locale files, and project documentation, in that order.
+- Do not count programming languages, dependency languages, generated locale test fixtures, or incidental foreign-language text as user-facing supported locales.
+- If no user-facing locale support is observed and the user did not request multilingual docs, report `No project-supported locales observed` and do not recommend new translations by default.
+- If many project-supported locales exist, do not generate every README translation by default. Recommend a locale matrix and prioritize the primary language, English when useful for discoverability, and the project's main user locales; mark the rest as shipped, partial, planned, or deferred.
+- If a locale exists only in code but no maintainer can review it, do not advertise that README locale as fully supported.
+- Use `README..md` for translations, with BCP-47/IETF-style locale codes such as `README.zh-CN.md`, `README.zh-TW.md`, `README.ja.md`, and `README.pt-BR.md`.
+- Add a language switcher near the top of every shipped README translation, between the title and badges. If the title area is strongly branded, put the switcher on the line immediately below the title.
+- Prefer a compact switcher such as `**Languages:** English | [简体中文](README.zh-CN.md)` and localize its label in translated files when helpful.
+- Keep language links symmetric across shipped translations and do not link missing translation files.
+- Optionally add hidden tracking comments at the top of translated files, such as `` and ``.
+- Translate prose, headings, descriptions, alt text, and link text.
+- Do not translate code snippets, shell commands, flags, package names, file paths, URLs, GitHub usernames, repository names, API names, config keys, or brand names.
+- Keep translations in the same diff-friendly Markdown style as the primary README so translation updates do not create huge, hard-to-review diffs.
+- When changing user-facing docs, update corresponding translations in the same PR/commit, or clearly mark translations as pending, outdated, or partial to prevent translation drift.
+- Maintain a locale matrix when supporting more than two languages: shipped, partial, planned, and deferred.
+- Only advertise a locale as supported if someone can maintain or review it.
+- For many locales or frequently changing README content, suggest a single-source README generator or CI drift check instead of manual translation maintenance.
+- Prefer English for GitHub About descriptions and topics for discoverability unless the project is intentionally local-language focused.
+
+## Profile README Notes
+
+For profile README work, optimize for identity, current work, credible proof, and contact paths. Do not add fake contribution stats, fake trophies, or unrelated badges.
diff --git a/skills/github-repo-publisher/references/safety-quality.md b/skills/github-repo-publisher/references/safety-quality.md
new file mode 100644
index 000000000..079779d0b
--- /dev/null
+++ b/skills/github-repo-publisher/references/safety-quality.md
@@ -0,0 +1,145 @@
+# Safety and Quality Gates
+
+Use this reference before delivering drafts or performing GitHub write operations.
+
+## Claim Safety
+
+Reject or rewrite claims that are:
+
+- Not supported by code, docs, tests, releases, or GitHub metadata.
+- Based only on package names or folder names.
+- Aspirational, such as future platform support or planned integrations.
+- Security-sensitive, such as "secure", "encrypted", "private", or "compliant", without direct evidence.
+- Performance-sensitive, such as "fastest" or "blazing fast", without benchmarks.
+
+Use factual alternatives:
+
+- `Includes a GitHub Actions workflow for tests` instead of `battle-tested CI`.
+- `Provides read-only fact collection scripts` instead of `fully automated`.
+- `Designed for agent skill workflows` instead of `works with every agent`.
+
+## Attribution and License
+
+- Use `fork` only when the repository was actually forked from another repository or intentionally preserves upstream history.
+- Use `derived from` when code, templates, scripts, assets, or substantial text were copied and adapted from an upstream project.
+- Use `inspired by`, `references`, or `acknowledgements` when only ideas, structure, or general patterns informed a new implementation.
+- Preserve upstream copyright notices, license files, and required notices when copying licensed material.
+- Do not copy large prose blocks, images, logos, or generated assets from another repository unless the license permits it and attribution is added.
+- For MIT, Apache, BSD, and similar licenses, keep the required license notice with copied material. For GPL/AGPL or unclear licensing, flag compatibility risk before reuse.
+
+## Secrets and Privacy
+
+- Before publishing, scan drafts and changed docs for API keys, tokens, private URLs, internal hostnames, private repository names, emails, phone numbers, addresses, stack traces, log dumps, and local absolute paths.
+- Treat `.env`, credentials, screenshots, terminal captures, CI logs, and issue templates as high-risk sources.
+- Replace sensitive examples with placeholders such as `` or `` only when the placeholder is useful to readers.
+- Do not send private or sensitive content to GitHub metadata, issues, discussions, PRs, releases, or README files without explicit user authorization.
+- If sensitive content appears necessary for reproduction, summarize it minimally and ask before publishing exact values.
+
+## Community Health
+
+- Audit common community files when reviewing repository readiness: `LICENSE`, `CONTRIBUTING.md`, `SECURITY.md`, `CODE_OF_CONDUCT.md`, `.github/ISSUE_TEMPLATE`, and `.github/PULL_REQUEST_TEMPLATE.md`.
+- Before recommending `CONTRIBUTING.md`, issue templates, PR templates, or `CODE_OF_CONDUCT.md`, classify the repository's `Collaboration posture`.
+- For solo-maintained, personal, tiny, or low-risk public projects with no active external issues or PRs, do not push full community governance files by default. Prefer a short README contribution note only when useful.
+- Report missing files as recommendations unless the user explicitly asks to create them.
+- Do not claim contribution, security, support, or code of conduct policies exist unless the corresponding file or documented process exists.
+- Keep security reporting guidance factual. Do not invent contact emails, vulnerability programs, or SLA promises.
+
+## Security Automation
+
+- Audit whether the repository should enable Dependabot alerts, Dependabot version updates, secret scanning, push protection, code scanning, dependency review, `SECURITY.md`, and private vulnerability reporting.
+- Before recommending `SECURITY.md`, private vulnerability reporting, or security automation, classify the repository's `Security exposure`.
+- For low-exposure projects that do not network, process credentials or personal data, ship binaries, or alter user systems, avoid presenting `SECURITY.md` as required. Prefer factual README safety boundaries when useful.
+- Treat security automation and repository settings as recommendations unless the user explicitly asks to change the specific file, workflow, ruleset, or setting.
+- Do not create or modify `.github/dependabot.yml` by default. Recommend Dependabot as `Optional for this context` for tiny, personal, experimental, small public, or low-risk projects unless the user asks for Dependabot or concrete repository risk makes it required.
+- Do not add code scanning, dependency review, secret scanning, or other security workflows by default. Explain the risk and recommendation first, then wait for explicit authorization before creating workflow files.
+- Do not modify GitHub security settings such as Dependabot alerts, secret scanning, push protection, branch protection, rulesets, or private vulnerability reporting unless the user explicitly authorizes that exact remote setting change.
+- Even for `Moderate`, `High`, or `Critical` security exposure, separate the recommendation from execution: state the evidence, mark the item as `Required for this context` or `Optional for this context`, and ask or wait before applying configuration.
+- Do not imply security features are active unless GitHub metadata, workflow files, or repository settings prove they are active.
+- For public-facing security claims, prefer factual wording such as `Uses GitHub code scanning workflow` over broad claims like `secure by default`.
+
+## Repository Scale and Fit-to-Scope
+
+Classify repository scale before recommending GitHub governance, docs, security, release, or multilingual work. If the user explicitly states the project goal, audience, or desired maturity, prefer that over inferred scale.
+
+- `Tiny / Personal / Experiment`: personal scripts, demos, learning projects, prototypes, one-off tools, or private experiments. Recommend only the essentials by default: clear README purpose, quick run command, limitations, About description, 3-5 topics, and license only if public reuse is intended. Do not push `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, issue forms, PR templates, release process, Dependabot, code scanning, or multilingual README unless requested or risk requires it. If Dependabot is mentioned for this scale, mark it as optional unless the user explicitly asked for it.
+- `Small Public / Low-Risk`: low-risk public projects that others can view or download but have an expected small audience, do not network, do not process credentials or personal data, do not publish packages or installers, and are not multi-maintainer community projects. Recommend clear README, run instructions, limitations, About description, topics, and license. Treat 1-3 real badges, a simple screenshot or social preview, a simple changelog, and Dependabot suggestions as optional. Do not push `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, issue forms, PR templates, branch protection, Dependabot, code scanning, multilingual README, or formal release process by default.
+- `Usable / Public Utility`: public tools, plugins, libraries, templates, or apps that others may install, depend on, use regularly, or report issues against, or that already have a clear user group. Recommend practical docs and light operations: install, quick start, configuration, troubleshooting, license, basic badges, issue guidance, simple release/changelog convention, and security/contact notes if the project touches data, network, credentials, or binaries.
+- `Serious / Community / Product`: team, company, community, production, high-usage, security-sensitive, or multi-contributor projects. Recommend fuller governance: docs architecture, `CONTRIBUTING.md`, `SECURITY.md`, code of conduct when community-facing, issue/PR templates, release/versioning policy, branch protection, security automation, social preview, and multilingual strategy when the project supports locales.
+
+Escalate from `Small Public / Low-Risk` to `Usable / Public Utility` or higher when risk or audience grows: networking, credentials, personal data, browser extensions, installers, package publishing, automation that changes user systems, production deployment, visible user adoption, or multiple maintainers. Project scale changes recommendation strength, not truthfulness, privacy, security, or license requirements.
+
+## Right-Sizing Dimensions
+
+After classifying scale, classify these dimensions before recommending governance, security, release, docs, or multilingual work. Use direct evidence when available, and write `not observed` or `not assessed` when evidence is missing.
+
+- `Collaboration posture`: external collaboration expectation. Use `Solo / No External Collaboration` for personal or solo projects with no active external issues or PRs; `Casual Contributions Welcome` when simple issue/PR help is acceptable; `Active External Contributions` when external issues or PRs already exist or are explicitly desired; `Community / Multi-Maintainer` for multi-maintainer, team, or community projects. This controls `CONTRIBUTING.md`, issue/PR templates, and `CODE_OF_CONDUCT.md`.
+- `Security exposure`: safety risk surface. Use `Low` when the project does not network, process credentials or personal data, ship binaries, or alter user systems; `Moderate` for scripts, CLIs, browser extensions, GitHub API workflows, local file processing, or release assets; `High` for tokens, cookies, accounts, personal data, installers, package distribution, or automation that changes user systems; `Critical` for production, enterprise, supply-chain, or sensitive-data projects. This controls `SECURITY.md`, vulnerability reporting, Dependabot, secret scanning, push protection, and code scanning.
+- `Distribution surface`: how users receive or run the project. Use `Source-only`, `Release assets`, `Package registry`, `App/extension store`, `Installer/binary`, or `Hosted service`. This controls release notes, changelog, SemVer, package metadata alignment, install instructions, binary asset handling, and Git LFS guidance.
+- `User impact`: expected audience and consequence of mistakes. Use `Private/author only`, `Expected small audience`, `Installable by others`, `Dependency or workflow component`, or `Production/user-facing`. This controls README depth, support wording, troubleshooting, compatibility notes, screenshots, and social preview priority.
+- `Documentation complexity`: documentation shape needed. Use `Single README enough`, `README plus docs folder`, `API/reference docs needed`, or `Docs site/wiki needed`. This controls whether to recommend `docs/`, FAQ, troubleshooting, API reference, advanced guides, or docs-site work.
+- `README language coverage`: README translation need. Use `No project-supported locales observed`, `User-specified language scope`, `Matches project-supported locales`, `Partial/outdated coverage`, or `Many locales need matrix`. This controls multilingual README recommendations and should be based on user-facing locale evidence, not programming languages.
+
+## Write Confirmation Rules
+
+Proceed without extra confirmation only when the user's instruction already authorizes the exact write, such as "commit and push these changes" or "update the repo About to this text".
+
+Confirm first when:
+
+- Publishing to GitHub, creating a release, or editing repo metadata.
+- Sending private or sensitive content to a remote service.
+- Creating or modifying security automation configuration, including `.github/dependabot.yml`, security workflows, branch protection, rulesets, Dependabot settings, secret scanning, push protection, code scanning, dependency review, or private vulnerability reporting.
+- Deleting branches, closing issues, resolving review threads, or changing labels at scale.
+- The worktree contains unrelated changes and staging scope is ambiguous.
+
+## Verification Commands
+
+- README install, run, test, build, package, and release commands must come from manifests, scripts, docs, examples, or commands actually run during the task.
+- Prefer running cheap verification commands when the repo provides them and the user asked for publish-ready docs.
+- If a command was not run, say it is unverified instead of implying it works.
+- Do not invent successful output, screenshots, passing tests, package names, CLI flags, or environment requirements.
+- When commands are platform-specific, label the platform or shell explicitly.
+
+## Audit Output Format
+
+For repository audits, use these headings unless the user requests another format:
+
+- `Scale classification`: tiny/personal/experiment, small public/low-risk, usable/public utility, or serious/community/product, with the evidence and any risk-based escalation. Explicitly say when the low-risk public category applies.
+- `Right-sizing dimensions`: collaboration posture, security exposure, distribution surface, user impact, documentation complexity, and README language coverage, with brief evidence for each.
+- `Critical blockers`: broken links, false claims, missing license for copied material, secrets, unsafe publish actions, or commands likely to fail.
+- `Recommended improvements`: useful but non-blocking README, metadata, docs, security, or community health changes, with each item marked `Required for this context` or `Optional for this context` and tied to the dimension that triggers it.
+- `Suggested metadata`: exact About description, topics, homepage, social preview, badges, or lifecycle wording.
+- `Safe-to-apply edits`: local file edits that can be made without remote writes or policy changes.
+- `Validation status`: commands run, commands not run, whether raw Markdown line structure was checked, license/attribution risk as `not observed` or `not assessed` when no issue is reported, and remaining unknowns.
+
+## README Review Checklist
+
+- Title, description, and About text agree.
+- Installation commands match actual manifests and scripts.
+- Quick start can plausibly run from a fresh clone.
+- Links are relative when linking inside the repo and absolute when linking outside it.
+- Images and badges resolve or are clearly marked as suggestions.
+- Screenshot and social preview recommendations are based on real checked image assets, explicitly unverified assets, or clearly labeled generated/new image suggestions.
+- License section matches the actual license file.
+- Contribution and security sections reflect files that exist.
+- Attribution and acknowledgements match the actual reuse relationship.
+- Raw README source is diff-friendly: not compressed into a few very long physical lines, dense paragraphs, or hard-to-review Markdown blobs.
+- Content contains no secrets, private URLs, internal-only identifiers, or unnecessary personal data.
+- Security automation, Dependabot, secret scanning, push protection, and code scanning claims are backed by repo settings or files.
+- No generated boilerplate remains.
+
+## GitHub Metadata Checklist
+
+- Description is concise and searchable.
+- Topics are lowercase and relevant.
+- Homepage is stable and working when supplied.
+- Social preview recommendation is specific and not generic decoration.
+- README first screen communicates purpose, proof, and first action.
+
+## Delivery Checklist
+
+Report:
+
+- Files changed or exact metadata values drafted.
+- Validation performed and commands run.
+- GitHub writes performed, if any.
+- Open questions, missing facts, or manual steps that remain.
diff --git a/skills/github-repo-publisher/scripts/collect-repo-facts.mjs b/skills/github-repo-publisher/scripts/collect-repo-facts.mjs
new file mode 100644
index 000000000..e7db7db2e
--- /dev/null
+++ b/skills/github-repo-publisher/scripts/collect-repo-facts.mjs
@@ -0,0 +1,363 @@
+#!/usr/bin/env node
+import { execFileSync } from "node:child_process";
+import fs from "node:fs";
+import path from "node:path";
+
+function parseArgs(argv) {
+ let repoPath = ".";
+ for (let i = 0; i < argv.length; i += 1) {
+ if ((argv[i] === "--repo" || argv[i] === "-r" || argv[i] === "--repo-path") && argv[i + 1]) {
+ repoPath = argv[i + 1];
+ i += 1;
+ } else if (argv[i] === "--help" || argv[i] === "-h") {
+ console.log("Usage: node scripts/collect-repo-facts.mjs --repo ");
+ process.exit(0);
+ }
+ }
+ return { repoPath };
+}
+
+function gitLines(root, args) {
+ try {
+ const output = execFileSync("git", args, {
+ cwd: root,
+ encoding: "utf8",
+ stdio: ["ignore", "pipe", "ignore"],
+ });
+ return output.split(/\r?\n/).filter((line) => line.length > 0);
+ } catch {
+ return [];
+ }
+}
+
+function pathExists(target) {
+ try {
+ fs.accessSync(target);
+ return true;
+ } catch {
+ return false;
+ }
+}
+
+function rel(root, target) {
+ return path.relative(root, target).split(path.sep).join("/");
+}
+
+function normalizeGitPath(file) {
+ return file.split("\\").join("/").replace(/^\.\//, "");
+}
+
+function uniqueSorted(files) {
+ return [...new Set(files.map(normalizeGitPath).filter(Boolean))].sort((a, b) => a.localeCompare(b));
+}
+
+function isInstructionFile(file) {
+ const normalized = normalizeGitPath(file);
+ const lower = normalized.toLowerCase();
+ const basename = path.posix.basename(lower);
+ const instructionNames = new Set(["agents.md", "claude.md", "gemini.md", "codex.md"]);
+
+ return instructionNames.has(basename) ||
+ lower === ".cursorrules" ||
+ lower === ".windsurfrules" ||
+ lower === ".clinerules" ||
+ lower === ".cursor/rules" ||
+ lower.startsWith(".cursor/rules/") ||
+ lower === ".claude" ||
+ lower.startsWith(".claude/") ||
+ lower === ".codex" ||
+ lower.startsWith(".codex/");
+}
+
+function looksPublicFacing(file) {
+ const normalized = normalizeGitPath(file);
+ const lower = normalized.toLowerCase();
+ const basename = path.posix.basename(lower);
+
+ if (isInstructionFile(normalized)) {
+ return false;
+ }
+
+ if (/^readme(\.|$)/i.test(basename) ||
+ /^(license|copying|notice|changelog|contributing|security)(\.|$)/i.test(basename)) {
+ return true;
+ }
+
+ const publicDirs = [
+ "docs/",
+ "doc/",
+ "examples/",
+ "example/",
+ "samples/",
+ "sample/",
+ "assets/",
+ "images/",
+ "screenshots/",
+ "public/",
+ "media/",
+ ".github/workflows/",
+ ];
+ if (publicDirs.some((dir) => lower.startsWith(dir))) {
+ return true;
+ }
+
+ const manifestNames = new Set([
+ "package.json",
+ "pyproject.toml",
+ "cargo.toml",
+ "go.mod",
+ "composer.json",
+ "gemfile",
+ "dockerfile",
+ "manifest.json",
+ "extension.json",
+ ]);
+ if (manifestNames.has(basename)) {
+ return true;
+ }
+
+ const ext = path.posix.extname(lower);
+ const publicAssetExtensions = new Set([".png", ".jpg", ".jpeg", ".gif", ".webp", ".avif", ".svg"]);
+ const publicAssetPattern = /(readme|screenshot|preview|social|demo|hero|cover|banner|logo)/i;
+ return publicAssetExtensions.has(ext) && publicAssetPattern.test(normalized);
+}
+
+function shouldIgnore(root, target, ignoredDirs) {
+ const parts = rel(root, target).split("/").filter(Boolean);
+ return parts.some((part) => ignoredDirs.has(part));
+}
+
+function readLinesUtf8(file) {
+ const content = fs.readFileSync(file, "utf8");
+ if (content.length === 0) {
+ return [];
+ }
+ const lines = content.split(/\r\n|\n|\r/);
+ if (/\r\n|\n|\r/.test(content.slice(-2))) {
+ lines.pop();
+ }
+ return lines;
+}
+
+function walkDirs(root, maxDepth, ignoredDirs) {
+ const results = [];
+
+ function visit(dir, depth) {
+ if (depth > maxDepth) {
+ return;
+ }
+
+ let entries = [];
+ try {
+ entries = fs.readdirSync(dir, { withFileTypes: true });
+ } catch {
+ return;
+ }
+
+ for (const entry of entries) {
+ if (!entry.isDirectory()) {
+ continue;
+ }
+ const fullPath = path.join(dir, entry.name);
+ if (shouldIgnore(root, fullPath, ignoredDirs)) {
+ continue;
+ }
+ results.push(fullPath);
+ visit(fullPath, depth + 1);
+ }
+ }
+
+ visit(root, 1);
+ return results;
+}
+
+function walkFiles(root, maxDepth, ignoredDirs) {
+ const results = [];
+
+ function visit(dir, depth) {
+ if (depth > maxDepth) {
+ return;
+ }
+
+ let entries = [];
+ try {
+ entries = fs.readdirSync(dir, { withFileTypes: true });
+ } catch {
+ return;
+ }
+
+ for (const entry of entries) {
+ const fullPath = path.join(dir, entry.name);
+ if (shouldIgnore(root, fullPath, ignoredDirs)) {
+ continue;
+ }
+ if (entry.isDirectory()) {
+ visit(fullPath, depth + 1);
+ } else if (entry.isFile()) {
+ results.push(fullPath);
+ }
+ }
+ }
+
+ visit(root, 1);
+ return results;
+}
+
+const { repoPath } = parseArgs(process.argv.slice(2));
+const root = path.resolve(repoPath);
+
+const facts = {
+ root,
+ git: {},
+ files: {},
+ manifests: [],
+ scripts: {},
+ localeSignals: [],
+ imageAssets: [],
+};
+
+if (pathExists(path.join(root, ".git"))) {
+ facts.git.branch = gitLines(root, ["branch", "--show-current"])[0] ?? null;
+ facts.git.status = gitLines(root, ["status", "--short", "--branch"]);
+ facts.git.remotes = gitLines(root, ["remote", "-v"]);
+ facts.git.defaultBranchGuess = gitLines(root, ["symbolic-ref", "refs/remotes/origin/HEAD"])[0] ?? null;
+ facts.git.trackedFiles = uniqueSorted(gitLines(root, ["ls-files"]));
+ facts.git.untrackedFiles = uniqueSorted(gitLines(root, ["ls-files", "--others", "--exclude-standard"]));
+ facts.git.ignoredFiles = uniqueSorted(gitLines(root, ["ls-files", "--others", "--ignored", "--exclude-standard"]));
+
+ const trackedInstructions = facts.git.trackedFiles.filter(isInstructionFile);
+ const untrackedInstructions = facts.git.untrackedFiles.filter(isInstructionFile);
+ const ignoredInstructions = facts.git.ignoredFiles.filter(isInstructionFile);
+ facts.git.instructionFiles = {
+ tracked: trackedInstructions,
+ untracked: untrackedInstructions,
+ ignored: ignoredInstructions,
+ localOnly: uniqueSorted([...untrackedInstructions, ...ignoredInstructions]),
+ };
+ facts.git.trackingReview = {
+ localOnlyInstructionFiles: facts.git.instructionFiles.localOnly,
+ possiblyMistakenlyTrackedInstructionFiles: trackedInstructions,
+ possiblyForgottenPublicFiles: facts.git.untrackedFiles.filter(looksPublicFacing),
+ };
+}
+
+const interesting = [
+ "README.md",
+ "README.mdx",
+ "README.txt",
+ "LICENSE",
+ "LICENSE.md",
+ "CONTRIBUTING.md",
+ "SECURITY.md",
+ "CHANGELOG.md",
+ "package.json",
+ "pyproject.toml",
+ "Cargo.toml",
+ "go.mod",
+ "composer.json",
+ "Gemfile",
+ "Dockerfile",
+ "manifest.json",
+ "extension.json",
+];
+
+const manifestNames = new Set([
+ "package.json",
+ "pyproject.toml",
+ "Cargo.toml",
+ "go.mod",
+ "composer.json",
+ "Gemfile",
+ "manifest.json",
+ "extension.json",
+]);
+
+for (const file of interesting) {
+ const fullPath = path.join(root, file);
+ if (!pathExists(fullPath)) {
+ continue;
+ }
+ const stat = fs.statSync(fullPath);
+ facts.files[file] = {
+ size: stat.size,
+ modified: stat.mtime.toISOString(),
+ };
+ if (manifestNames.has(file)) {
+ facts.manifests.push(file);
+ }
+}
+
+for (const entry of fs.readdirSync(root, { withFileTypes: true })) {
+ if (!entry.isFile() || !entry.name.startsWith("README")) {
+ continue;
+ }
+
+ const fullPath = path.join(root, entry.name);
+ const stat = fs.statSync(fullPath);
+ if (!facts.files[entry.name]) {
+ facts.files[entry.name] = {
+ size: stat.size,
+ modified: stat.mtime.toISOString(),
+ };
+ }
+
+ try {
+ const lines = readLinesUtf8(fullPath);
+ facts.files[entry.name].lineCount = lines.length;
+ facts.files[entry.name].maxLineLength = lines.length
+ ? Math.max(...lines.map((line) => line.length))
+ : 0;
+ } catch (error) {
+ facts.files[entry.name].lineStatsError = error.message;
+ }
+}
+
+const packageJsonPath = path.join(root, "package.json");
+if (pathExists(packageJsonPath)) {
+ try {
+ const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
+ facts.package = {
+ name: pkg.name,
+ version: pkg.version,
+ description: pkg.description,
+ scripts: pkg.scripts,
+ };
+ } catch (error) {
+ facts.packageParseError = error.message;
+ }
+}
+
+const ignoredDirs = new Set([".git", "node_modules", "dist", "build", "out", "target", ".next", ".cache", "vendor"]);
+const localeDirNames = new Set(["_locales", "locales", "locale", "i18n", "translations", "translation", "lang", "langs"]);
+facts.localeSignals = walkDirs(root, 4, ignoredDirs)
+ .filter((dir) => localeDirNames.has(path.basename(dir).toLowerCase()))
+ .slice(0, 40)
+ .map((dir) => rel(root, dir));
+
+const imageExtensions = new Set([".png", ".jpg", ".jpeg", ".gif", ".webp", ".avif", ".svg"]);
+const imageNamePattern = /(screenshot|preview|social|demo|hero|readme|cover|banner|logo)/i;
+const imageDirPattern = /(docs|assets|images|screenshots|public|media)/i;
+facts.imageAssets = walkFiles(root, 5, ignoredDirs)
+ .filter((file) => {
+ const ext = path.extname(file).toLowerCase();
+ const dirname = path.dirname(file);
+ return imageExtensions.has(ext) && (
+ imageNamePattern.test(path.basename(file)) ||
+ imageNamePattern.test(dirname) ||
+ imageDirPattern.test(dirname)
+ );
+ })
+ .slice(0, 80)
+ .map((file) => rel(root, file));
+
+const workflowsDir = path.join(root, ".github", "workflows");
+facts.ci = pathExists(workflowsDir)
+ ? walkFiles(workflowsDir, 3, ignoredDirs).map((file) => rel(root, file))
+ : [];
+
+facts.topLevel = fs.readdirSync(root, { withFileTypes: true })
+ .filter((entry) => entry.name !== ".git")
+ .slice(0, 80)
+ .map((entry) => entry.name);
+
+console.log(JSON.stringify(facts, null, 2));
diff --git a/skills/github-repo-publisher/scripts/collect-repo-facts.ps1 b/skills/github-repo-publisher/scripts/collect-repo-facts.ps1
new file mode 100644
index 000000000..c80951001
--- /dev/null
+++ b/skills/github-repo-publisher/scripts/collect-repo-facts.ps1
@@ -0,0 +1,234 @@
+param(
+ [string]$RepoPath = "."
+)
+
+$ErrorActionPreference = "Stop"
+$root = (Resolve-Path -LiteralPath $RepoPath).Path
+
+function Invoke-GitLines {
+ param([string[]]$GitArgs)
+ $previousErrorActionPreference = $ErrorActionPreference
+ try {
+ $ErrorActionPreference = "Continue"
+ $output = & git @GitArgs 2>$null
+ if ($LASTEXITCODE -ne 0) {
+ return @()
+ }
+ return @($output)
+ } finally {
+ $ErrorActionPreference = $previousErrorActionPreference
+ }
+}
+
+function Normalize-GitPath {
+ param([string]$File)
+ return (($File -replace "\\", "/") -replace "^\./", "")
+}
+
+function Get-UniqueSorted {
+ param([string[]]$Files)
+ return @($Files | ForEach-Object { Normalize-GitPath $_ } | Where-Object { $_ } | Sort-Object -Unique)
+}
+
+function Test-InstructionFile {
+ param([string]$File)
+ $normalized = Normalize-GitPath $File
+ $lower = $normalized.ToLowerInvariant()
+ $basename = @($lower -split "/")[-1]
+ $instructionNames = @("agents.md","claude.md","gemini.md","codex.md")
+
+ return ($instructionNames -contains $basename) -or
+ $lower -eq ".cursorrules" -or
+ $lower -eq ".windsurfrules" -or
+ $lower -eq ".clinerules" -or
+ $lower -eq ".cursor/rules" -or
+ $lower.StartsWith(".cursor/rules/") -or
+ $lower -eq ".claude" -or
+ $lower.StartsWith(".claude/") -or
+ $lower -eq ".codex" -or
+ $lower.StartsWith(".codex/")
+}
+
+function Test-PublicFacingFile {
+ param([string]$File)
+ $normalized = Normalize-GitPath $File
+ $lower = $normalized.ToLowerInvariant()
+ $basename = @($lower -split "/")[-1]
+
+ if (Test-InstructionFile $normalized) {
+ return $false
+ }
+
+ if ($basename -match "^(readme)(\.|$)" -or
+ $basename -match "^(license|copying|notice|changelog|contributing|security)(\.|$)") {
+ return $true
+ }
+
+ $publicDirs = @(
+ "docs/",
+ "doc/",
+ "examples/",
+ "example/",
+ "samples/",
+ "sample/",
+ "assets/",
+ "images/",
+ "screenshots/",
+ "public/",
+ "media/",
+ ".github/workflows/"
+ )
+ foreach ($dir in $publicDirs) {
+ if ($lower.StartsWith($dir)) {
+ return $true
+ }
+ }
+
+ $manifestNames = @(
+ "package.json",
+ "pyproject.toml",
+ "cargo.toml",
+ "go.mod",
+ "composer.json",
+ "gemfile",
+ "dockerfile",
+ "manifest.json",
+ "extension.json"
+ )
+ if ($manifestNames -contains $basename) {
+ return $true
+ }
+
+ $publicAssetExtensions = @(".png",".jpg",".jpeg",".gif",".webp",".avif",".svg")
+ $extension = [IO.Path]::GetExtension($lower)
+ return ($publicAssetExtensions -contains $extension) -and ($normalized -match "(?i)(readme|screenshot|preview|social|demo|hero|cover|banner|logo)")
+}
+
+Push-Location $root
+try {
+ $facts = [ordered]@{
+ root = $root
+ git = [ordered]@{}
+ files = [ordered]@{}
+ manifests = @()
+ scripts = [ordered]@{}
+ localeSignals = @()
+ imageAssets = @()
+ }
+
+ if (Test-Path -LiteralPath ".git") {
+ $facts.git.branch = (Invoke-GitLines @("branch", "--show-current") | Select-Object -First 1)
+ $facts.git.status = @(Invoke-GitLines @("status", "--short", "--branch"))
+ $facts.git.remotes = @(Invoke-GitLines @("remote", "-v"))
+ $facts.git.defaultBranchGuess = (Invoke-GitLines @("symbolic-ref", "refs/remotes/origin/HEAD") | Select-Object -First 1)
+ $facts.git.trackedFiles = @(Get-UniqueSorted @(Invoke-GitLines @("ls-files")))
+ $facts.git.untrackedFiles = @(Get-UniqueSorted @(Invoke-GitLines @("ls-files", "--others", "--exclude-standard")))
+ $facts.git.ignoredFiles = @(Get-UniqueSorted @(Invoke-GitLines @("ls-files", "--others", "--ignored", "--exclude-standard")))
+
+ $trackedInstructions = @($facts.git.trackedFiles | Where-Object { Test-InstructionFile $_ })
+ $untrackedInstructions = @($facts.git.untrackedFiles | Where-Object { Test-InstructionFile $_ })
+ $ignoredInstructions = @($facts.git.ignoredFiles | Where-Object { Test-InstructionFile $_ })
+ $localOnlyInstructions = @(Get-UniqueSorted @($untrackedInstructions + $ignoredInstructions))
+ $facts.git.instructionFiles = [ordered]@{
+ tracked = $trackedInstructions
+ untracked = $untrackedInstructions
+ ignored = $ignoredInstructions
+ localOnly = $localOnlyInstructions
+ }
+ $facts.git.trackingReview = [ordered]@{
+ localOnlyInstructionFiles = $localOnlyInstructions
+ possiblyMistakenlyTrackedInstructionFiles = $trackedInstructions
+ possiblyForgottenPublicFiles = @($facts.git.untrackedFiles | Where-Object { Test-PublicFacingFile $_ })
+ }
+ }
+
+ $interesting = @(
+ "README.md","README.mdx","README.txt",
+ "LICENSE","LICENSE.md",
+ "CONTRIBUTING.md","SECURITY.md","CHANGELOG.md",
+ "package.json","pyproject.toml","Cargo.toml","go.mod",
+ "composer.json","Gemfile","Dockerfile",
+ "manifest.json","extension.json"
+ )
+
+ foreach ($file in $interesting) {
+ if (Test-Path -LiteralPath $file) {
+ $item = Get-Item -LiteralPath $file
+ $facts.files[$file] = [ordered]@{
+ size = $item.Length
+ modified = $item.LastWriteTimeUtc.ToString("o")
+ }
+ if ($file -match "^(package\.json|pyproject\.toml|Cargo\.toml|go\.mod|composer\.json|Gemfile|manifest\.json|extension\.json)$") {
+ $facts.manifests += $file
+ }
+ }
+ }
+
+ foreach ($item in @(Get-ChildItem -File -Filter "README*" -ErrorAction SilentlyContinue)) {
+ $name = $item.Name
+ if (-not $facts.files.Contains($name)) {
+ $facts.files[$name] = [ordered]@{
+ size = $item.Length
+ modified = $item.LastWriteTimeUtc.ToString("o")
+ }
+ }
+
+ try {
+ $lines = @(Get-Content -LiteralPath $item.FullName -Encoding UTF8)
+ $facts.files[$name]["lineCount"] = $lines.Count
+ if ($lines.Count -gt 0) {
+ $facts.files[$name]["maxLineLength"] = ($lines | ForEach-Object { $_.Length } | Measure-Object -Maximum).Maximum
+ } else {
+ $facts.files[$name]["maxLineLength"] = 0
+ }
+ } catch {
+ $facts.files[$name]["lineStatsError"] = $_.Exception.Message
+ }
+ }
+
+ if (Test-Path -LiteralPath "package.json") {
+ try {
+ $pkg = Get-Content -Raw -Encoding UTF8 -LiteralPath "package.json" | ConvertFrom-Json
+ $facts.package = [ordered]@{
+ name = $pkg.name
+ version = $pkg.version
+ description = $pkg.description
+ scripts = $pkg.scripts
+ }
+ } catch {
+ $facts.packageParseError = $_.Exception.Message
+ }
+ }
+
+ $ignoredDirs = @(".git","node_modules","dist","build","out","target",".next",".cache","vendor")
+ $localeDirNames = @("_locales","locales","locale","i18n","translations","translation","lang","langs")
+ $scanDirs = @(Get-ChildItem -Directory -Recurse -Depth 4 -Force -ErrorAction SilentlyContinue | Where-Object {
+ $parts = $_.FullName.Substring($root.Length).Split([IO.Path]::DirectorySeparatorChar, [StringSplitOptions]::RemoveEmptyEntries)
+ -not ($parts | Where-Object { $ignoredDirs -contains $_ })
+ })
+
+ $facts.localeSignals = @($scanDirs | Where-Object {
+ $localeDirNames -contains $_.Name.ToLowerInvariant()
+ } | Select-Object -First 40 | ForEach-Object {
+ $_.FullName.Substring($root.Length + 1)
+ })
+
+ $imageExtensions = @(".png",".jpg",".jpeg",".gif",".webp",".avif",".svg")
+ $imageNamePattern = "(?i)(screenshot|preview|social|demo|hero|readme|cover|banner|logo)"
+ $facts.imageAssets = @(Get-ChildItem -File -Recurse -Depth 5 -Force -ErrorAction SilentlyContinue | Where-Object {
+ $parts = $_.FullName.Substring($root.Length).Split([IO.Path]::DirectorySeparatorChar, [StringSplitOptions]::RemoveEmptyEntries)
+ -not ($parts | Where-Object { $ignoredDirs -contains $_ }) -and
+ ($imageExtensions -contains $_.Extension.ToLowerInvariant()) -and
+ ($_.Name -match $imageNamePattern -or $_.DirectoryName -match $imageNamePattern -or $_.DirectoryName -match "(?i)(docs|assets|images|screenshots|public|media)")
+ } | Select-Object -First 80 | ForEach-Object {
+ $_.FullName.Substring($root.Length + 1)
+ })
+
+ $workflowsPath = Join-Path ".github" "workflows"
+ $facts.ci = @(Get-ChildItem -File -Recurse -Depth 3 -Path $workflowsPath -ErrorAction SilentlyContinue | ForEach-Object { $_.FullName.Substring($root.Length + 1) })
+ $facts.topLevel = @(Get-ChildItem -Force | Where-Object { $_.Name -ne ".git" } | Select-Object -First 80 -ExpandProperty Name)
+
+ $facts | ConvertTo-Json -Depth 8
+} finally {
+ Pop-Location
+}