diff --git a/.copilot/skills/pr-lifecycle/SKILL.md b/.copilot/skills/pr-lifecycle/SKILL.md index 50456644e..0aa6cceae 100644 --- a/.copilot/skills/pr-lifecycle/SKILL.md +++ b/.copilot/skills/pr-lifecycle/SKILL.md @@ -138,7 +138,7 @@ For advanced scenarios (worktrees, multi-repo coordination), see `.copilot/skill 2. **Create PR targeting dev:** ```bash - gh pr create --repo bradygaster/squad --base dev \ + gh pr create --repo github/squad --base dev \ --title "fix: brief description (#issue-number)" \ --body "Closes #{issue-number} @@ -351,7 +351,7 @@ Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>" # Push and PR git push -u origin squad/610-fix-broken-link -gh pr create --repo bradygaster/squad --base dev \ +gh pr create --repo github/squad --base dev \ --title "docs: fix broken link (#610)" \ --body "Closes #610" ``` @@ -386,7 +386,7 @@ Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>" # Push and PR git push -u origin squad/42-add-profile-api -gh pr create --repo bradygaster/squad --base dev \ +gh pr create --repo github/squad --base dev \ --title "feat: add profile API (#42)" \ --body "Closes #42 diff --git a/.github/workflows/squad-ci.yml b/.github/workflows/squad-ci.yml index 09e07c7f4..9fb1a7b34 100644 --- a/.github/workflows/squad-ci.yml +++ b/.github/workflows/squad-ci.yml @@ -68,6 +68,10 @@ jobs: with: node-version: '22.23.4' cache: 'npm' + # Docs-only pull requests skip the `test` job, so the docs site location guard runs here + # as well. The suite uses Node built-ins only, so it needs no npm install. + - name: Docs feature and site location tests + run: node --test docs/tests/astro-features.test.mjs - name: Install docs tools run: | success=false diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 53ebc9ea5..e94b69ef0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -62,7 +62,7 @@ Each package has independent versioning via changesets. A change to squad-sdk ma **Step 1: Fork the repo on GitHub** -Go to https://github.com/bradygaster/squad and click "Fork" to create your own copy. +Go to https://github.com/github/squad and click "Fork" to create your own copy. **Step 2: Clone your fork** @@ -74,7 +74,7 @@ cd squad **Step 3: Add upstream remote** ```bash -git remote add upstream git@github.com:bradygaster/squad.git +git remote add upstream git@github.com:github/squad.git ``` **Step 4: Fetch the dev branch** @@ -187,7 +187,7 @@ The Co-authored-by trailer is **required** for all commits (added by Copilot CLI 1. Add a changeset: `npx changeset add` (required before PR — see Changesets section) 2. Push your branch: `git push origin {yourusername}/217-readme-help-update` -3. Create a PR **as a draft**: `gh pr create --draft --base dev --repo bradygaster/squad --head {yourusername}:your-branch` +3. Create a PR **as a draft**: `gh pr create --draft --base dev --repo github/squad --head {yourusername}:your-branch` 4. Link the issue: Add `Closes #217` to PR description 5. Work on your changes until CI passes and you're satisfied 6. **Mark as "Ready for review"** — this is the handoff signal to the core team (see below) @@ -390,7 +390,7 @@ CI watches for drift: `scripts/check-changeset-drift.mjs` warns on PRs and fails - **main** — Stable, published releases. All merges include changesets. - **preview** — Staging branch for release candidates (promote: dev → preview → main). -- **bradygaster/dev** — Integration branch. **All PRs from forks must target this branch**, not `main`. +- **dev** — Integration branch on `github/squad`. **All PRs from forks must target this branch**, not `main`. - **user/issue-slug** — Feature branches from users or agents. > **Note:** The `insider` npm tag (`@bradygaster/squad-cli@insider`) publishes from `dev` via manual workflow dispatch. There is no separate insider branch. diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index f5ec910dc..0882cb927 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -19,13 +19,13 @@ The Insider Program gives you access to cutting-edge features before they ship. ### How to Join -Install from the insider branch using the honor system: +Install the insider build from npm using the honor system: ```bash -npx github:bradygaster/squad#insider +npm install -g @bradygaster/squad-cli@insider ``` -That's it. You're now on insider builds. +That's it. You're now on insider builds. For Homebrew and WinGet, see the [Insider Program guide](https://github.github.com/squad/docs/insider-program/). ### What to Expect @@ -36,7 +36,7 @@ That's it. You're now on insider builds. ### Report Issues -Found a bug in an insider build? Please [open a GitHub issue](https://github.com/bradygaster/squad/issues) with: +Found a bug in an insider build? Please [open a GitHub issue](https://github.com/github/squad/issues) with: - **Version** — The full version string from your `squad.agent.md` - **What happened** — Clear description of the bug or unexpected behavior @@ -130,4 +130,4 @@ These community members shaped Squad through issues, discussions, and feedback. Contributing code? See [CONTRIBUTING.md](CONTRIBUTING.md) for the full guide. -Questions? [GitHub Discussions](https://github.com/bradygaster/squad/discussions). +Questions? [GitHub Discussions](https://github.com/github/squad/discussions). diff --git a/README.md b/README.md index de91c387b..2f6999313 100644 --- a/README.md +++ b/README.md @@ -42,14 +42,14 @@ Choose the install method for your platform: | npm (all platforms, Node.js 22.5+) | `npm install -g @bradygaster/squad-cli` | | Homebrew (macOS) | `brew install --cask bradygaster/squad/squad` | | WinGet (Windows) | `winget install --id bradygaster.Squad --exact` | -| Install script (macOS/Linux, no npm) | See [Standalone Install](https://bradygaster.github.io/squad/docs/features/standalone-install/) | +| Install script (macOS/Linux, no npm) | See [Standalone Install](https://github.github.com/squad/docs/features/standalone-install/) | Preview and insider builds are available as `squad-preview` and `squad-insider` Homebrew casks, or as `bradygaster.Squad.Preview` and `bradygaster.Squad.Insider` WinGet packages. Direct archives for macOS, Linux, and Windows are also available from -[GitHub Releases](https://github.com/bradygaster/squad/releases/latest). +[GitHub Releases](https://github.com/github/squad/releases/latest). ```bash squad init @@ -57,7 +57,7 @@ squad init All methods install the same CLI. Standalone installs vendor Node.js, so they do not require Node.js or access to the npm registry. See the -[complete installation guide](https://bradygaster.github.io/squad/docs/get-started/installation/) +[complete installation guide](https://github.github.com/squad/docs/get-started/installation/) for prerequisites and platform details. > **⚡ Want to be up and running in under a second?** Use `squad init --preset default` to start with a fully-configured squad — complete with members, charters, and routing rules — ready to go immediately. The default `squad init` (without the flag) walks you through setup step by step, ideal if you prefer to build and customize your squad deliberately. @@ -112,8 +112,8 @@ Use the same channel you installed from: | npm | `npm install -g @bradygaster/squad-cli@latest` | | Homebrew | `brew upgrade --cask squad` | | WinGet | `winget upgrade --id bradygaster.Squad --exact` | -| Install script | Re-run the [install script](https://bradygaster.github.io/squad/docs/features/standalone-install/#macos-and-linux) | -| Direct archive | Download the newer archive from [GitHub Releases](https://github.com/bradygaster/squad/releases/latest) | +| Install script | Re-run the [install script](https://github.github.com/squad/docs/features/standalone-install/#macos-and-linux) | +| Direct archive | Download the newer archive from [GitHub Releases](https://github.com/github/squad/releases/latest) | **Step 2: Update Squad-owned files in your project** @@ -144,7 +144,7 @@ To install and run Squad from source for development: ```bash # Clone the repository -git clone https://github.com/bradygaster/squad.git +git clone https://github.com/github/squad.git cd squad # Install dependencies (npm workspaces) @@ -442,7 +442,7 @@ When agents finish, the coordinator records follow-up work and leaves a breadcru **And it's all in git.** Anyone who clones your repo gets the team — with all their accumulated knowledge. -**Each agent gets the right model.** Squad picks models quality-first by default: premium for architecture, research and review, standard for code and docs, fast for mechanical work. Opt in to the `balanced` or `economy` profile, or to the `hydrafusion` research preview with `"modelProfile": "hydrafusion"` in `.squad/config.json`. Per-agent selection works in the Copilot CLI and app; VS Code runs every agent on the one session model. See [Model Selection](https://bradygaster.github.io/squad/docs/features/model-selection/). +**Each agent gets the right model.** Squad picks models quality-first by default: premium for architecture, research and review, standard for code and docs, fast for mechanical work. Opt in to the `balanced` or `economy` profile, or to the `hydrafusion` research preview with `"modelProfile": "hydrafusion"` in `.squad/config.json`. Per-agent selection works in the Copilot CLI and app; VS Code runs every agent on the one session model. See [Model Selection](https://github.github.com/squad/docs/features/model-selection/). --- @@ -654,7 +654,7 @@ durable human handoff after exhaustion. Both workers produce drafts only; open, merged and closed-unmerged linked PRs suppress automatic duplicates. Human review and merge are always required. -See [the gh-aw guide](https://bradygaster.github.io/squad/docs/guide/gh-aw/#retrospective-auto-implementation-opt-in) for the full authority model. +See [the gh-aw guide](https://github.github.com/squad/docs/guide/gh-aw/#retrospective-auto-implementation-opt-in) for the full authority model. ### Slash commands @@ -675,7 +675,7 @@ See [the gh-aw guide](https://bradygaster.github.io/squad/docs/guide/gh-aw/#retr Write a detailed team description in the issue body, then comment `/squad cast` — the issue becomes your casting brief. The more context you give, the better Squad tailors your team. -📖 See [GitHub Agentic Workflows guide](https://bradygaster.github.io/squad/docs/guide/gh-aw/) for the complete setup, configuration, and usage reference. +📖 See [GitHub Agentic Workflows guide](https://github.github.com/squad/docs/guide/gh-aw/) for the complete setup, configuration, and usage reference. --- diff --git a/README.zh.md b/README.zh.md index b0f163116..37d302a62 100644 --- a/README.zh.md +++ b/README.zh.md @@ -40,13 +40,13 @@ git init | npm(所有平台,需要 Node.js 22.5+) | `npm install -g @bradygaster/squad-cli` | | Homebrew(macOS) | `brew install --cask bradygaster/squad/squad` | | WinGet(Windows) | `winget install --id bradygaster.Squad --exact` | -| 安装脚本(macOS/Linux,无需 npm) | 查看[独立安装指南](https://bradygaster.github.io/squad/docs/features/standalone-install/) | +| 安装脚本(macOS/Linux,无需 npm) | 查看[独立安装指南](https://github.github.com/squad/docs/features/standalone-install/) | 预览版和 Insider 版也可通过 Homebrew 的 `squad-preview`、 `squad-insider` cask,或 WinGet 的 `bradygaster.Squad.Preview`、 `bradygaster.Squad.Insider` 软件包安装。 -你也可以从 [GitHub Releases](https://github.com/bradygaster/squad/releases/latest) +你也可以从 [GitHub Releases](https://github.com/github/squad/releases/latest) 直接下载 macOS、Linux 或 Windows 压缩包。 ```bash @@ -55,7 +55,7 @@ squad init 所有方式安装的都是同一个 CLI。独立安装包自带 Node.js,无需安装 Node.js,也无需访问 npm registry。完整要求和平台说明请参阅 -[安装指南](https://bradygaster.github.io/squad/docs/get-started/installation/)。 +[安装指南](https://github.github.com/squad/docs/get-started/installation/)。 **✓ 验证:** 检查项目中是否创建了 `.squad/team.md`。 @@ -103,8 +103,8 @@ Squad 会提议一个团队 — 每个成员的名字都来自一个持久化的 | npm | `npm install -g @bradygaster/squad-cli@latest` | | Homebrew | `brew upgrade --cask squad` | | WinGet | `winget upgrade --id bradygaster.Squad --exact` | -| 安装脚本 | 重新运行[安装脚本](https://bradygaster.github.io/squad/docs/features/standalone-install/#macos-and-linux) | -| 直接下载 | 从 [GitHub Releases](https://github.com/bradygaster/squad/releases/latest) 下载新版本 | +| 安装脚本 | 重新运行[安装脚本](https://github.github.com/squad/docs/features/standalone-install/#macos-and-linux) | +| 直接下载 | 从 [GitHub Releases](https://github.com/github/squad/releases/latest) 下载新版本 | **第二步:更新项目中 Squad 管理的文件** diff --git a/SUPPORT.md b/SUPPORT.md index 0316949a8..f2d7c523d 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -4,7 +4,7 @@ This project uses GitHub Issues to track bugs and feature requests. Please search the existing issues before filing new issues to avoid duplicates. For new issues, file your bug or feature request as a new issue. -For help or questions about using Squad, please use [GitHub Discussions](https://github.com/bradygaster/squad/discussions) on this repository. +For help or questions about using Squad, please use [GitHub Discussions](https://github.com/github/squad/discussions) on this repository. **Squad** is under active development and maintained by GitHub staff and the community. We will do our best to respond to support, feature requests, and community questions in a timely manner. diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 5c4de456e..b57a56339 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -8,7 +8,7 @@ import { createRequire } from 'module'; const require = createRequire(import.meta.url); export default defineConfig({ - site: 'https://bradygaster.github.io', + site: 'https://github.github.com', base: '/squad/', integrations: [sitemap()], vite: { diff --git a/docs/demo-agentic-sdlc-walkthrough.md b/docs/demo-agentic-sdlc-walkthrough.md index 815c8f944..e42c9ea56 100644 --- a/docs/demo-agentic-sdlc-walkthrough.md +++ b/docs/demo-agentic-sdlc-walkthrough.md @@ -519,4 +519,4 @@ Accept: "Reply /squad plan activate..." --- -*Demo created for the Squad project — [github.com/bradygaster/squad](https://github.com/bradygaster/squad)* +*Demo created for the Squad project — [github.com/github/squad](https://github.com/github/squad)* diff --git a/docs/public/robots.txt b/docs/public/robots.txt index ae9d9c74b..c76763b2c 100644 --- a/docs/public/robots.txt +++ b/docs/public/robots.txt @@ -1,4 +1,4 @@ User-agent: * Allow: / -Sitemap: https://squad.dev/sitemap-index.xml +Sitemap: https://github.github.com/squad/sitemap-index.xml diff --git a/docs/research/jsdoc-api-reference-research.md b/docs/research/jsdoc-api-reference-research.md index 50908d37c..4b84d9dc8 100644 --- a/docs/research/jsdoc-api-reference-research.md +++ b/docs/research/jsdoc-api-reference-research.md @@ -116,10 +116,10 @@ docs/src/content/docs/reference/ ### URL Structure \\\ -https://bradygaster.github.io/squad/reference/api-reference/ (overview page) -https://bradygaster.github.io/squad/reference/api/ (index) -https://bradygaster.github.io/squad/reference/api/classes/squad-coordinator/ -https://bradygaster.github.io/squad/reference/api/interfaces/agent/ +https://github.github.com/squad/reference/api-reference/ (overview page) +https://github.github.com/squad/reference/api/ (index) +https://github.github.com/squad/reference/api/classes/squad-coordinator/ +https://github.github.com/squad/reference/api/interfaces/agent/ \\\ ### Build Workflow diff --git a/docs/src/components/Footer.astro b/docs/src/components/Footer.astro index 39e68714d..edd1bd556 100644 --- a/docs/src/components/Footer.astro +++ b/docs/src/components/Footer.astro @@ -30,8 +30,8 @@ const base = import.meta.env.BASE_URL;

Community

@@ -42,7 +42,7 @@ const base = import.meta.env.BASE_URL;
diff --git a/docs/src/components/Header.astro b/docs/src/components/Header.astro index a50e168a9..29251700f 100644 --- a/docs/src/components/Header.astro +++ b/docs/src/components/Header.astro @@ -49,7 +49,7 @@ const mobileNavBase = "block px-3 py-2 rounded-md text-base transition-colors"; @@ -57,7 +57,7 @@ const mobileNavBase = "block px-3 py-2 rounded-md text-base transition-colors"; Docs Blog - GitHub + GitHub diff --git a/docs/src/content/blog/028-new-docs-site.md b/docs/src/content/blog/028-new-docs-site.md index 07035b798..0a76a3208 100644 --- a/docs/src/content/blog/028-new-docs-site.md +++ b/docs/src/content/blog/028-new-docs-site.md @@ -61,7 +61,7 @@ Both contributors are now credited in [CONTRIBUTORS.md](https://github.com/brady --- ## Try It -Visit the docs at [bradygaster.github.io/squad](https://bradygaster.github.io/squad/) or run them locally: +Visit the docs at [bradygaster.github.io/squad](https://github.github.com/squad/) or run them locally: ```bash cd docs npm install diff --git a/docs/src/content/blog/033-swe-bench-lite-results.md b/docs/src/content/blog/033-swe-bench-lite-results.md index e4c2adb18..861f8c88d 100644 --- a/docs/src/content/blog/033-swe-bench-lite-results.md +++ b/docs/src/content/blog/033-swe-bench-lite-results.md @@ -278,7 +278,7 @@ benchmarks/swe-bench/ Squad is a multi-agent orchestration framework that turns AI coding assistants into coordinated engineering teams. Each agent has a persistent identity, charter, and memory — enabling the kind of specialization and institutional knowledge that makes human teams effective. -Learn more at [bradygaster.github.io/squad](https://bradygaster.github.io/squad/). +Learn more at [bradygaster.github.io/squad](https://github.github.com/squad/). --- diff --git a/docs/src/content/docs/community.md b/docs/src/content/docs/community.md index d30e5cb8d..b9e1d87eb 100644 --- a/docs/src/content/docs/community.md +++ b/docs/src/content/docs/community.md @@ -4,10 +4,10 @@ Squad is built by contributors who believe in democratizing multi-agent developm ## Project Metrics -[![GitHub stars](https://img.shields.io/github/stars/bradygaster/squad?style=flat-square&logo=github)](https://github.com/bradygaster/squad/stargazers) -[![GitHub forks](https://img.shields.io/github/forks/bradygaster/squad?style=flat-square&logo=github)](https://github.com/bradygaster/squad/network/members) -[![GitHub issues](https://img.shields.io/github/issues/bradygaster/squad?style=flat-square&logo=github)](https://github.com/bradygaster/squad/issues) -[![GitHub pull requests](https://img.shields.io/github/issues-pr/bradygaster/squad?style=flat-square&logo=github)](https://github.com/bradygaster/squad/pulls) +[![GitHub stars](https://img.shields.io/github/stars/github/squad?style=flat-square&logo=github)](https://github.com/github/squad/stargazers) +[![GitHub forks](https://img.shields.io/github/forks/github/squad?style=flat-square&logo=github)](https://github.com/github/squad/network/members) +[![GitHub issues](https://img.shields.io/github/issues/github/squad?style=flat-square&logo=github)](https://github.com/github/squad/issues) +[![GitHub pull requests](https://img.shields.io/github/issues-pr/github/squad?style=flat-square&logo=github)](https://github.com/github/squad/pulls) ## How to Contribute @@ -16,13 +16,13 @@ We welcome contributions in all forms: **For detailed contribution guidelines, including branch rules and PR process, see the [Contributing Guide](./guide/contributing.html).** ### Report Issues -Found a bug, have a feature request, or want to discuss an idea? [Open an issue](https://github.com/bradygaster/squad/issues). +Found a bug, have a feature request, or want to discuss an idea? [Open an issue](https://github.com/github/squad/issues). ### Submit a Pull Request -Ready to contribute code? [Check out the open issues](https://github.com/bradygaster/squad/issues) and submit a PR. See the [Contributing Guide](./guide/contributing.html) for branch protection rules and the branch model. +Ready to contribute code? [Check out the open issues](https://github.com/github/squad/issues) and submit a PR. See the [Contributing Guide](./guide/contributing.html) for branch protection rules and the branch model. ### Join the Discussion -Have questions, want to share how you're using Squad, or discuss the roadmap? [Start a discussion](https://github.com/bradygaster/squad/discussions). +Have questions, want to share how you're using Squad, or discuss the roadmap? [Start a discussion](https://github.com/github/squad/discussions). ### External Deployments & Case Studies Deploy Squad on your project and share your experience. These real-world deployments inform our roadmap and help the community learn from each other. @@ -72,6 +72,6 @@ If you're using Squad, consider: ## Contact & Support -- **Issues & Feature Requests:** [GitHub Issues](https://github.com/bradygaster/squad/issues) -- **Discussion & Questions:** [GitHub Discussions](https://github.com/bradygaster/squad/discussions) +- **Issues & Feature Requests:** [GitHub Issues](https://github.com/github/squad/issues) +- **Discussion & Questions:** [GitHub Discussions](https://github.com/github/squad/discussions) - **Security Issues:** Report privately via GitHub Security Advisory diff --git a/docs/src/content/docs/concepts/github-workflow.md b/docs/src/content/docs/concepts/github-workflow.md index 2a5c9b269..ad7a55a53 100644 --- a/docs/src/content/docs/concepts/github-workflow.md +++ b/docs/src/content/docs/concepts/github-workflow.md @@ -173,7 +173,7 @@ See the [Notifications Guide](../features/notifications.md) for [platform setup] --- ## Sample Prompts ``` -connect to bradygaster/squad and show me the backlog +connect to github/squad and show me the backlog ``` Links Squad to a GitHub repo and displays all open issues. ``` diff --git a/docs/src/content/docs/concepts/your-team.md b/docs/src/content/docs/concepts/your-team.md index 87765148f..1939761e5 100644 --- a/docs/src/content/docs/concepts/your-team.md +++ b/docs/src/content/docs/concepts/your-team.md @@ -212,7 +212,7 @@ and optional `## Model`, before any `## X-` extensions. Use it for representativ requests and expected behavior as quick checks. Structured charter edits preserve Examples, but Squad does not run them or treat them as permissions or proof of a passing evaluation. They are prompt-visible guidance, not hidden evaluation cases. -See the [Charter Profile](https://github.com/bradygaster/squad/blob/dev/docs/specification/charter-v0.1.md#71-optional-examples) +See the [Charter Profile](https://github.com/github/squad/blob/dev/docs/specification/charter-v0.1.md#71-optional-examples) for the format and a YAML example. **@copilot** (🤖) appears on the roster and works via GitHub issue assignment. It reads `.github/copilot-instructions.md` instead of a charter. diff --git a/docs/src/content/docs/features/github-issues.md b/docs/src/content/docs/features/github-issues.md index 8afb5cb8b..9eed8f2fb 100644 --- a/docs/src/content/docs/features/github-issues.md +++ b/docs/src/content/docs/features/github-issues.md @@ -130,7 +130,7 @@ Squad refreshes the backlog and shows remaining open issues. ## Sample Prompts ``` -connect to bradygaster/squad +connect to github/squad ``` Links Squad to a GitHub repository for issue-driven development. diff --git a/docs/src/content/docs/features/gitlab-issues.md b/docs/src/content/docs/features/gitlab-issues.md index 2021f1886..2ac6a085e 100644 --- a/docs/src/content/docs/features/gitlab-issues.md +++ b/docs/src/content/docs/features/gitlab-issues.md @@ -1,6 +1,6 @@ # GitLab Issues Mode -> **🗺️ Planned, not shipped.** Squad 2.0 has no GitLab platform adapter: `PlatformType` is `github | azure-devops | planner`, `squad triage` / `squad watch` have no `glab` path, and neither the canonical coordinator nor the per-host digest contains a GitLab section. What follows describes the intended experience; today it only works if you ask the coordinator to use `glab` ad hoc and it improvises the flow described here. Track progress and vote in [issues](https://github.com/bradygaster/squad/issues). +> **🗺️ Planned, not shipped.** Squad 2.0 has no GitLab platform adapter: `PlatformType` is `github | azure-devops | planner`, `squad triage` / `squad watch` have no `glab` path, and neither the canonical coordinator nor the per-host digest contains a GitLab section. What follows describes the intended experience; today it only works if you ask the coordinator to use `glab` ad hoc and it improvises the flow described here. Track progress and vote in [issues](https://github.com/github/squad/issues). **Try this to connect to your backlog:** ``` diff --git a/docs/src/content/docs/features/issue-templates.md b/docs/src/content/docs/features/issue-templates.md index d54350c5e..666796915 100644 --- a/docs/src/content/docs/features/issue-templates.md +++ b/docs/src/content/docs/features/issue-templates.md @@ -274,10 +274,10 @@ GitHub supports multiple templates. Create a config file to customize the issue blank_issues_enabled: false contact_links: - name: Squad Community Discussions - url: https://github.com/bradygaster/squad/discussions + url: https://github.com/github/squad/discussions about: Ask questions or share ideas in Discussions - name: Squad Documentation - url: https://squad.dev + url: https://github.github.com/squad/ about: Read the full Squad documentation ``` diff --git a/docs/src/content/docs/features/mcp-frontmatter.md b/docs/src/content/docs/features/mcp-frontmatter.md index e1cdab37d..08ba66e6d 100644 --- a/docs/src/content/docs/features/mcp-frontmatter.md +++ b/docs/src/content/docs/features/mcp-frontmatter.md @@ -12,7 +12,7 @@ squad init --mcp-frontmatter By default, `squad init` writes MCP server configuration to two places: - `.copilot/mcp-config.json` (workspace-level for Copilot CLI) -- `~/.copilot/mcp-config.json` (user-level, ensures `copilot -p` non-interactive mode also sees the MCP — see [#1247](https://github.com/bradygaster/squad/issues/1247)) +- `~/.copilot/mcp-config.json` (user-level, ensures `copilot -p` non-interactive mode also sees the MCP — see [#1247](https://github.com/github/squad/issues/1247)) The `--mcp-frontmatter` flag changes this: instead of writing JSON config files, MCP server declarations go directly into the YAML frontmatter of `.github/agents/squad.agent.md` (or `.github/agents/squad.md` if you've exported with [Coordinator-as-Agent Export](/squad/docs/features/coordinator-as-agent-export/)). @@ -88,7 +88,7 @@ To switch modes after init, re-run `squad init --mcp-frontmatter` (or run `squad ## Limitations -- **Less robust for `copilot -p` non-interactive mode.** Standard mode pins MCP at user level too, which solves the workspace-only loading gap (PR [#1251](https://github.com/bradygaster/squad/pull/1251)). Frontmatter mode skips that user-level write — so `copilot -p` may not see the squad MCP unless the harness reads frontmatter directly. +- **Less robust for `copilot -p` non-interactive mode.** Standard mode pins MCP at user level too, which solves the workspace-only loading gap (PR [#1251](https://github.com/github/squad/pull/1251)). Frontmatter mode skips that user-level write — so `copilot -p` may not see the squad MCP unless the harness reads frontmatter directly. - **No second-layer fallback.** If the harness that reads frontmatter MCP fails to load it correctly, there's no `.copilot/mcp-config.json` to fall back to. Test in your specific harness before adopting. - **Schema is harness-specific.** The frontmatter `mcpServers` key follows the Copilot CLI convention, but other harnesses may expect different key names (`mcp_servers`, `mcp.servers`, etc.). Check your harness's spec. diff --git a/docs/src/content/docs/features/plugins.md b/docs/src/content/docs/features/plugins.md index a80d34793..2bfc616a4 100644 --- a/docs/src/content/docs/features/plugins.md +++ b/docs/src/content/docs/features/plugins.md @@ -231,7 +231,7 @@ The product goal is simple pluggability: install, enable, refresh, and give agen See [Plugin security model](../reference/plugin-security.md) for the threat model and the negative checks that gate this feature. -The follow-up roadmap tracks remote marketplace distribution, broader built-in providers, and the trusted executable-provider RFC in [#1102](https://github.com/bradygaster/squad/issues/1102), [#1103](https://github.com/bradygaster/squad/issues/1103), [#1104](https://github.com/bradygaster/squad/issues/1104), and [#1105](https://github.com/bradygaster/squad/issues/1105). +The follow-up roadmap tracks remote marketplace distribution, broader built-in providers, and the trusted executable-provider RFC in [#1102](https://github.com/github/squad/issues/1102), [#1103](https://github.com/github/squad/issues/1103), [#1104](https://github.com/github/squad/issues/1104), and [#1105](https://github.com/github/squad/issues/1105). --- diff --git a/docs/src/content/docs/features/security-hardening.md b/docs/src/content/docs/features/security-hardening.md index 66e91d892..8f077331b 100644 --- a/docs/src/content/docs/features/security-hardening.md +++ b/docs/src/content/docs/features/security-hardening.md @@ -14,7 +14,7 @@ This page is the operational security reference for teams running Squad in produ | This page | Operational threat model — runtime risks, mitigations, and production posture | | [Plugin Security](/squad/docs/reference/plugin-security/) | Plugin install sandbox — manifest validation and static-file restrictions | | [Skill Security Scanner](/squad/docs/features/skill-security-scanner/) | CI-time credential and privilege-escalation scanning for skill files | -| [#1427](https://github.com/bradygaster/squad/issues/1427) | Corporate security policy page (in progress — separate scope) | +| [#1427](https://github.com/github/squad/issues/1427) | Corporate security policy page (in progress — separate scope) | --- @@ -22,7 +22,7 @@ This page is the operational security reference for teams running Squad in produ Before reading the mitigations below, be aware of what Squad does **not** yet provide: -- **No HTTP health or readiness endpoints.** Squad exposes no `/healthz` or `/readyz` endpoint. Container restart policy is the current liveness mechanism. HTTP readiness is planned in [#1577](https://github.com/bradygaster/squad/issues/1577). +- **No HTTP health or readiness endpoints.** Squad exposes no `/healthz` or `/readyz` endpoint. Container restart policy is the current liveness mechanism. HTTP readiness is planned in [#1577](https://github.com/github/squad/issues/1577). - **No built-in network egress filtering.** Squad does not sandbox agent network access beyond what the host OS or container runtime provides. - **No formal CVE/vulnerability disclosure process.** This page describes risks and recommended mitigations, not incident history. - **`PermissionHandler.ApproveAll` is not a production-safe default.** See [Least-Privilege Permission Handlers](#least-privilege-permission-handlers--approveall-warning) below. @@ -156,7 +156,7 @@ GITHUB_TOKEN=ghp_realtoken1234567890abcdef GITHUB_TOKEN= ``` -Cross-reference: [closed #267](https://github.com/bradygaster/squad/issues/267). +Cross-reference: [closed #267](https://github.com/github/squad/issues/267). Add `.env` and `.env.*` to `.gitignore`. The skill security scanner ([Skill Security Scanner](/squad/docs/features/skill-security-scanner/)) catches credential patterns in skill files; extend this discipline to all generated code. @@ -301,7 +301,7 @@ const pipeline = new HookPipeline({ allowedWritePaths: ['.squad/**'] }); pipeline.addPreToolHook(writeGuardHook); ``` -> **Source:** `PreToolUseContext` properties (`toolName`, `arguments`, `agentName`, `sessionId`) and `addPreToolHook` method are verified against [`packages/squad-sdk/src/hooks/index.ts`](https://github.com/bradygaster/squad/blob/dev/packages/squad-sdk/src/hooks/index.ts). +> **Source:** `PreToolUseContext` properties (`toolName`, `arguments`, `agentName`, `sessionId`) and `addPreToolHook` method are verified against [`packages/squad-sdk/src/hooks/index.ts`](https://github.com/github/squad/blob/dev/packages/squad-sdk/src/hooks/index.ts). See [Custom Tools & Hooks](/squad/docs/reference/tools-and-hooks/) for the full `HookPipeline` API. @@ -321,7 +321,7 @@ Squad-generated GitHub Actions workflows should pin every `uses:` reference to a - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 ``` -[#1462](https://github.com/bradygaster/squad/issues/1462) tracks completing SHA pinning for the `squad-insider-release.yml` template. All other Squad workflow templates use SHA pinning with weekly Dependabot updates. +[#1462](https://github.com/github/squad/issues/1462) tracks completing SHA pinning for the `squad-insider-release.yml` template. All other Squad workflow templates use SHA pinning with weekly Dependabot updates. When you extend Squad-generated workflows, maintain this pattern. If you add a new `uses:` step, resolve its current SHA immediately: @@ -472,7 +472,7 @@ Use this checklist before moving a Squad deployment to production. - [ ] Shared state files are periodically inspected for unexpected entries ### Supply chain -- [ ] All GitHub Actions `uses:` references are SHA-pinned (see [#1462](https://github.com/bradygaster/squad/issues/1462)) +- [ ] All GitHub Actions `uses:` references are SHA-pinned (see [#1462](https://github.com/github/squad/issues/1462)) - [ ] Container image is pinned to digest in production manifests - [ ] MCP servers in `.mcp.json` are version-pinned and sourced from trusted organizations - [ ] Skill files pass the [Skill Security Scanner](/squad/docs/features/skill-security-scanner/) on every PR @@ -481,7 +481,7 @@ Use this checklist before moving a Squad deployment to production. - [ ] OTEL telemetry is routing to Azure Monitor or equivalent - [ ] Token revocation and rotation procedure is documented - [ ] Incident response runbook covers shared-state compromise -- [ ] HTTP health probes: note that readiness endpoints are not yet available ([#1577](https://github.com/bradygaster/squad/issues/1577)); container restart policy is the current liveness mechanism +- [ ] HTTP health probes: note that readiness endpoints are not yet available ([#1577](https://github.com/github/squad/issues/1577)); container restart policy is the current liveness mechanism --- diff --git a/docs/src/content/docs/features/skills.md b/docs/src/content/docs/features/skills.md index d7b649a51..9f882d783 100644 --- a/docs/src/content/docs/features/skills.md +++ b/docs/src/content/docs/features/skills.md @@ -56,7 +56,7 @@ Legacy term for built-in skills. Previously called "starter skills" and prefixed ### Session Recovery -The `session-recovery` skill teaches agents to find and resume interrupted Copilot CLI sessions. When a session is interrupted (terminal crash, network drop, machine restart), in-progress work may be left incomplete. This skill uses `session_store` SQL queries to detect abandoned sessions, inspect checkpoint progress, and resume work. See [`.copilot/skills/session-recovery/SKILL.md`](https://github.com/bradygaster/squad/blob/dev/.copilot/skills/session-recovery/SKILL.md) for query patterns and examples. +The `session-recovery` skill teaches agents to find and resume interrupted Copilot CLI sessions. When a session is interrupted (terminal crash, network drop, machine restart), in-progress work may be left incomplete. This skill uses `session_store` SQL queries to detect abandoned sessions, inspect checkpoint progress, and resume work. See [`.squad-templates/skills/session-recovery/SKILL.md`](https://github.com/github/squad/blob/dev/.squad-templates/skills/session-recovery/SKILL.md) for query patterns and examples. ### Earned skills diff --git a/docs/src/content/docs/features/squad-rc.md b/docs/src/content/docs/features/squad-rc.md index 3b1b73087..7be6dfee7 100644 --- a/docs/src/content/docs/features/squad-rc.md +++ b/docs/src/content/docs/features/squad-rc.md @@ -473,6 +473,6 @@ squad rc --port 8080 # Specific port - squad start — PTY mirror mode for terminal streaming - [CLI Reference](../reference/cli.md) — All squad commands -- [Remote Control Protocol](https://github.com/bradygaster/squad/blob/main/packages/squad-sdk/src/remote/protocol.ts) — Wire protocol types -- [RemoteBridge SDK](https://github.com/bradygaster/squad/blob/main/packages/squad-sdk/src/remote/bridge.ts) — Server implementation +- [Remote Control Protocol](https://github.com/github/squad/blob/main/packages/squad-sdk/src/remote/protocol.ts) — Wire protocol types +- [RemoteBridge SDK](https://github.com/github/squad/blob/main/packages/squad-sdk/src/remote/bridge.ts) — Server implementation - [devtunnel documentation](https://aka.ms/devtunnels) — Tunnel setup and auth diff --git a/docs/src/content/docs/features/standalone-install.md b/docs/src/content/docs/features/standalone-install.md index 6edea7a5f..ece2d1cda 100644 --- a/docs/src/content/docs/features/standalone-install.md +++ b/docs/src/content/docs/features/standalone-install.md @@ -18,7 +18,7 @@ your environment can reach the npm registry. ### macOS and Linux ```sh -curl -fsSL https://raw.githubusercontent.com/bradygaster/squad/main/scripts/install.sh | sh +curl -fsSL https://raw.githubusercontent.com/github/squad/main/scripts/install.sh | sh ``` The installer picks the right bundle for your platform, verifies it against the @@ -29,11 +29,11 @@ release `SHA256SUMS.txt`, unpacks it into `$PREFIX/lib/squad`, and symlinks |----------|---------|---------| | `VERSION` | latest release | Install a specific version | | `PREFIX` | `/usr/local` as root, else `$HOME/.local` | Install location | -| `REPO` | `bradygaster/squad` | Source repository or internal mirror | +| `REPO` | `github/squad` | Source repository or internal mirror | ```sh # pin a version and install somewhere specific -curl -fsSL https://raw.githubusercontent.com/bradygaster/squad/main/scripts/install.sh \ +curl -fsSL https://raw.githubusercontent.com/github/squad/main/scripts/install.sh \ | VERSION="v0.13.1" PREFIX="$HOME/tools" sh ``` @@ -46,7 +46,7 @@ winget install bradygaster.Squad ``` Or download `squad-win32-x64.zip` (or `squad-win32-arm64.zip`) from the -[releases page](https://github.com/bradygaster/squad/releases), unpack it, and +[releases page](https://github.com/github/squad/releases), unpack it, and add the folder to your `PATH`. ### macOS @@ -146,7 +146,7 @@ Point `repository:` at an internal mirror if your runners cannot reach env: SQUAD_VERSION: v0.13.1 run: | - curl -fsSL https://raw.githubusercontent.com/bradygaster/squad/main/scripts/install.sh \ + curl -fsSL https://raw.githubusercontent.com/github/squad/main/scripts/install.sh \ | VERSION="${SQUAD_VERSION}" PREFIX="${HOME}/.local" sh echo "${HOME}/.local/bin" >> "${GITHUB_PATH}" diff --git a/docs/src/content/docs/features/tiered-memory.md b/docs/src/content/docs/features/tiered-memory.md index 5cfed9760..097e588a0 100644 --- a/docs/src/content/docs/features/tiered-memory.md +++ b/docs/src/content/docs/features/tiered-memory.md @@ -85,7 +85,7 @@ The exact savings depend on what fraction of each agent's history is task-releva - **The tier split is currently advisory** — the skill defines hot/cold/wiki semantics, but the spawn template doesn't yet enforce `--include-cold` / `--include-wiki` flags as part of the runtime contract. Adoption is per-team via spawn-template edits. - **Wiki has no UI** — there's no `squad wiki list` command yet. Entries live as files in `.squad/wiki/` (when teams create that directory) and the coordinator references them by path. -- **Issue [#1268](https://github.com/bradygaster/squad/issues/1268) and [#1269](https://github.com/bradygaster/squad/issues/1269)** propose making Scribe enforce these tiers via the governed memory pipeline. Until those land, tier maintenance is best-effort. +- **Issue [#1268](https://github.com/github/squad/issues/1268) and [#1269](https://github.com/github/squad/issues/1269)** propose making Scribe enforce these tiers via the governed memory pipeline. Until those land, tier maintenance is best-effort. --- diff --git a/docs/src/content/docs/get-started/installation.md b/docs/src/content/docs/get-started/installation.md index 4939f17bc..1cd5eb496 100644 --- a/docs/src/content/docs/get-started/installation.md +++ b/docs/src/content/docs/get-started/installation.md @@ -41,7 +41,7 @@ The verified install script selects the correct archive, checks its SHA-256, and installs it under `/usr/local` or `$HOME/.local`: ```bash -curl -fsSL https://raw.githubusercontent.com/bradygaster/squad/main/scripts/install.sh | sh +curl -fsSL https://raw.githubusercontent.com/github/squad/main/scripts/install.sh | sh ``` ### Homebrew on macOS @@ -82,7 +82,7 @@ Homebrew cask or WinGet package before switching channels. ### Direct download Download the archive for your operating system and CPU from -[GitHub Releases](https://github.com/bradygaster/squad/releases/latest): +[GitHub Releases](https://github.com/github/squad/releases/latest): ```text squad-linux-x64.tar.gz squad-darwin-x64.tar.gz squad-win32-x64.zip diff --git a/docs/src/content/docs/get-started/migration.md b/docs/src/content/docs/get-started/migration.md index 5147f7797..2e2cf1d4a 100644 --- a/docs/src/content/docs/get-started/migration.md +++ b/docs/src/content/docs/get-started/migration.md @@ -387,7 +387,7 @@ You may be using the old package name. Use the correct name: npm install -g @bradygaster/squad-cli ``` -If the package genuinely isn't published yet, check [the npm page](https://www.npmjs.com/package/@bradygaster/squad-cli) or the [GitHub repo](https://github.com/bradygaster/squad) for release status. +If the package genuinely isn't published yet, check [the npm page](https://www.npmjs.com/package/@bradygaster/squad-cli) or the [GitHub repo](https://github.com/github/squad) for release status. ### Permission denied during install @@ -529,8 +529,8 @@ Key improvements since the migration from v0.5.4 beta: - **Casting system:** Universe-based agent naming with persistent registries (v0.8.25+). - **Stable v1 packages:** The CLI and SDK graduated from prerelease status in v1.0.0. -For the full list of changes, see the [CHANGELOG](https://github.com/bradygaster/squad/blob/main/CHANGELOG.md). +For the full list of changes, see the [CHANGELOG](https://github.com/github/squad/blob/main/CHANGELOG.md). --- -*Questions or issues? Open an issue at [github.com/bradygaster/squad](https://github.com/bradygaster/squad/issues).* +*Questions or issues? Open an issue at [github.com/github/squad](https://github.com/github/squad/issues).* diff --git a/docs/src/content/docs/guide/agent-framework-integration.md b/docs/src/content/docs/guide/agent-framework-integration.md index 5782d2d29..195d2bb6d 100644 --- a/docs/src/content/docs/guide/agent-framework-integration.md +++ b/docs/src/content/docs/guide/agent-framework-integration.md @@ -3,7 +3,7 @@ title: "Microsoft Agent Framework integration" description: "Expose any Squad team as a MAF AIAgent for durable .NET workflows, Aspire dashboard observability, and multi-model composition." --- -`Squad.Agents.AI` **1.0.0** is the stable package version for .NET 8, 9, and 10. Source versioning is separate from publication; until 1.0.0 is available on NuGet, follow the [local package instructions](https://github.com/bradygaster/squad/blob/dev/src/Squad.Agents.AI/README.md#install). +`Squad.Agents.AI` **1.0.0** is the stable package version for .NET 8, 9, and 10. Source versioning is separate from publication; until 1.0.0 is available on NuGet, follow the [local package instructions](https://github.com/github/squad/blob/dev/src/Squad.Agents.AI/README.md#install). `Squad.Agents.AI` exposes any Squad team as a Microsoft Agent Framework (MAF) `AIAgent`. Once registered, a `SquadAgent` participates in durable workflows alongside Azure OpenAI, Anthropic, and every other MAF provider — with DTS checkpointing, Aspire dashboard observability, and streaming out of the box. @@ -170,7 +170,7 @@ builder.Services.AddSquadAgent(o => }); ``` -Cross-reference: open issue [#1144](https://github.com/bradygaster/squad/issues/1144) tracks additional telemetry from embedded hosts. +Cross-reference: open issue [#1144](https://github.com/github/squad/issues/1144) tracks additional telemetry from embedded hosts. --- @@ -243,7 +243,7 @@ The Copilot CLI runs as a subprocess. It must be present in the deployment envir | 10-minute tutorial gist (Tamir Dresher) | [gist.github.com/tamirdresher/d0e38cbadd962de18e8373706eccad97](https://gist.github.com/tamirdresher/d0e38cbadd962de18e8373706eccad97) | | Squad + MAF demo repo | [github.com/tamirdresher/squad-agent-framework-demo](https://github.com/tamirdresher/squad-agent-framework-demo) | | Microsoft devblogs post | [devblogs.microsoft.com/agent-framework/building-agent-teams-with-agent-framework-github-copilot-cli-and-squad/](https://devblogs.microsoft.com/agent-framework/building-agent-teams-with-agent-framework-github-copilot-cli-and-squad/) | -| `Squad.Agents.AI` package source | [`src/Squad.Agents.AI/`](https://github.com/bradygaster/squad/tree/main/src/Squad.Agents.AI) | +| `Squad.Agents.AI` package source | [`src/Squad.Agents.AI/`](https://github.com/github/squad/tree/main/src/Squad.Agents.AI) | | `microsoft/agent-framework#6457` | [Upstream `buildTransitive` fix (merged 2026-06-10; not yet in NuGet preview)](https://github.com/microsoft/agent-framework/issues/6457) | > **Credit:** The integration pattern and companion demo were co-authored with [Tamir Dresher](https://www.tamirdresher.com). The tutorial gist and blog post are the original source of record for this guide. diff --git a/docs/src/content/docs/guide/build-autonomous-agent.md b/docs/src/content/docs/guide/build-autonomous-agent.md index c2e98d2e8..39e9b031d 100644 --- a/docs/src/content/docs/guide/build-autonomous-agent.md +++ b/docs/src/content/docs/guide/build-autonomous-agent.md @@ -2,7 +2,7 @@ Build a CLI-wrapped autonomous agent pipeline that picks up tasks, coordinates work across teammates, and runs unattended. -**Try this:** Clone the [autonomous-pipeline sample](https://github.com/bradygaster/squad/tree/dev/samples/autonomous-pipeline) and run `npm run dev` to see the pattern in action. +**Try this:** Clone the [autonomous-pipeline sample](https://github.com/github/squad/tree/dev/samples/autonomous-pipeline) and run `npm run dev` to see the pattern in action. This guide walks you through the pattern used by production autonomous agents — like a docs agent that monitors a repo for changes and generates documentation without human intervention. @@ -531,7 +531,7 @@ streaming.clear(); ## Next steps -- Run the [autonomous-pipeline sample](https://github.com/bradygaster/squad/tree/dev/samples/autonomous-pipeline) to see the full pattern with OTel, cost dashboards, and skill matching +- Run the [autonomous-pipeline sample](https://github.com/github/squad/tree/dev/samples/autonomous-pipeline) to see the full pattern with OTel, cost dashboards, and skill matching - Read the [SDK reference](/reference/sdk/) for the complete API surface - See the [extensibility guide](/guide/extensibility/) for where your agent fits in the Squad ecosystem - Check the [Aspire dashboard scenario](/scenarios/aspire-dashboard/) for observability setup diff --git a/docs/src/content/docs/guide/building-extensions.md b/docs/src/content/docs/guide/building-extensions.md index fc47512b0..5c2a2477c 100644 --- a/docs/src/content/docs/guide/building-extensions.md +++ b/docs/src/content/docs/guide/building-extensions.md @@ -178,7 +178,7 @@ squad plugin marketplace add github/my-org/my-team-plugins ## Real examples -- **Client-delivery workflow** ([RFC #328](https://github.com/bradygaster/squad/issues/328)) — discovery, research, multi-round review with evidence gates +- **Client-delivery workflow** ([RFC #328](https://github.com/github/squad/issues/328)) — discovery, research, multi-round review with evidence gates - **Azure infrastructure patterns** — VM provisioning, Cosmos DB design, monitoring rules - **Knowledge libraries** — document structured analysis, reference synthesis - **External integration samples** — see `samples/plugin-knowledge-graphify` for the real Graphify knowledge graph tool, `samples/plugin-knowledge-index-server` for the real Index Server instruction/knowledge MCP server, and `samples/plugin-memory-mempalace` for the real MemPalace memory CLI/MCP system @@ -194,4 +194,4 @@ squad plugin marketplace add github/my-org/my-team-plugins --- -**Ready to share?** [Open a discussion](https://github.com/bradygaster/squad/discussions) in the Squad community. +**Ready to share?** [Open a discussion](https://github.com/github/squad/discussions) in the Squad community. diff --git a/docs/src/content/docs/guide/building-resilient-agents.md b/docs/src/content/docs/guide/building-resilient-agents.md index 9306d08a5..2ae2e0abd 100644 --- a/docs/src/content/docs/guide/building-resilient-agents.md +++ b/docs/src/content/docs/guide/building-resilient-agents.md @@ -121,5 +121,5 @@ Log state transitions and include the circuit state in agent status or dashboard ## See also -- [PR #552](https://github.com/bradygaster/squad/pull/552) — Circuit breaker implementation +- [PR #552](https://github.com/github/squad/pull/552) — Circuit breaker implementation - [Failure handling](../reference/tools-and-hooks) — Error boundaries and fallbacks diff --git a/docs/src/content/docs/guide/contributing.md b/docs/src/content/docs/guide/contributing.md index b0df1587f..acb50b7b3 100644 --- a/docs/src/content/docs/guide/contributing.md +++ b/docs/src/content/docs/guide/contributing.md @@ -43,7 +43,7 @@ them together. **Step 1: Fork the repo on GitHub** -Go to [github.com/bradygaster/squad](https://github.com/bradygaster/squad) and click "Fork" to create your own copy. +Go to [github.com/github/squad](https://github.com/github/squad) and click "Fork" to create your own copy. **Step 2: Clone your fork** @@ -55,7 +55,7 @@ cd squad **Step 3: Add upstream remote** ```bash -git remote add upstream git@github.com:bradygaster/squad.git +git remote add upstream git@github.com:github/squad.git ``` **Step 4: Fetch the dev branch** @@ -154,7 +154,7 @@ The Co-authored-by trailer is **required** for all commits (added by Copilot CLI 1. Add a changeset: `npx changeset add` (required before PR — see Changesets section) 2. Push your branch: `git push origin {yourusername}/217-readme-help-update` -3. Create a PR with explicit base and head: `gh pr create --base dev --repo bradygaster/squad --head {yourusername}:your-branch` +3. Create a PR with explicit base and head: `gh pr create --base dev --repo github/squad --head {yourusername}:your-branch` 4. Link the issue: Add `Closes #217` to PR description 5. Wait for CI checks to pass 6. Request review from the team (agents will respond via comments) diff --git a/docs/src/content/docs/guide/extensibility.md b/docs/src/content/docs/guide/extensibility.md index 6acae0769..a3fea5cff 100644 --- a/docs/src/content/docs/guide/extensibility.md +++ b/docs/src/content/docs/guide/extensibility.md @@ -44,7 +44,7 @@ Where does your change idea belong? Squad core, marketplace plugin, or team conf ## Worked example: Client-delivery RFC -[RFC #328](https://github.com/bradygaster/squad/issues/328) proposed a sophisticated client-delivery workflow: discovery interviews, research sprints, multi-round review with `SHIP`/`NEEDS_WORK`/`BLOCKED` verdicts, evidence bundles. +[RFC #328](https://github.com/github/squad/issues/328) proposed a sophisticated client-delivery workflow: discovery interviews, research sprints, multi-round review with `SHIP`/`NEEDS_WORK`/`BLOCKED` verdicts, evidence bundles. **The realization:** It maps entirely to existing Squad primitives. No core changes needed. @@ -131,8 +131,8 @@ Install records lock data and leaves the plugin disabled. Enable activates the r - [Ceremonies](../features/ceremonies.md) — How to define team meetings and gates - [Routing](../features/routing.md) — How to configure work assignment rules - [Building extensions](./building-extensions.md) — Step-by-step guide to building and sharing extensions -- [Contributing](https://github.com/bradygaster/squad/blob/main/CONTRIBUTING.md) — How to propose changes to Squad core +- [Contributing](https://github.com/github/squad/blob/main/CONTRIBUTING.md) — How to propose changes to Squad core --- -**Questions?** [Open an issue](https://github.com/bradygaster/squad/issues/new) or join the discussion in the Squad community. +**Questions?** [Open an issue](https://github.com/github/squad/issues/new) or join the discussion in the Squad community. diff --git a/docs/src/content/docs/guide/faq.md b/docs/src/content/docs/guide/faq.md index cad859857..43a690dd0 100644 --- a/docs/src/content/docs/guide/faq.md +++ b/docs/src/content/docs/guide/faq.md @@ -1,6 +1,6 @@ # Frequently asked questions -Common questions, troubleshooting tips, and clarifications based on community feedback. Can't find your answer? [Open an issue](https://github.com/bradygaster/squad/issues/new). +Common questions, troubleshooting tips, and clarifications based on community feedback. Can't find your answer? [Open an issue](https://github.com/github/squad/issues/new). --- @@ -268,9 +268,9 @@ See [Disaster Recovery](../scenarios/disaster-recovery.md) for more recovery pat ## Where should I report bugs or request features? -[Open an issue on GitHub](https://github.com/bradygaster/squad/issues/new) with: +[Open an issue on GitHub](https://github.com/github/squad/issues/new) with: - **Environment:** OS, Node.js version, Squad version (`squad --version`) - **Reproduction steps:** What you ran, what happened, what you expected - **Output:** Copy the full terminal output, including any errors -For questions or discussions, use [GitHub Discussions](https://github.com/bradygaster/squad/discussions). +For questions or discussions, use [GitHub Discussions](https://github.com/github/squad/discussions). diff --git a/docs/src/content/docs/guide/gh-aw.md b/docs/src/content/docs/guide/gh-aw.md index b7b2443ae..0ce64aa73 100644 --- a/docs/src/content/docs/guide/gh-aw.md +++ b/docs/src/content/docs/guide/gh-aw.md @@ -1614,7 +1614,7 @@ comment, ignore a missing proof, or dispatch partial bindings. #### Run the existing executable example The repository's -[activation finalization integration fixture](https://github.com/bradygaster/squad/blob/dev/test/gh-aw-activation-finalization.test.ts) +[activation finalization integration fixture](https://github.com/github/squad/blob/dev/test/gh-aw-activation-finalization.test.ts) is the executable producer/consumer example. In `continues after a later-phase pending-source recovery and validates the complete transitive reader chain`, it obtains proofs through the real workflow `verifyReconciliationRequest`, @@ -1623,7 +1623,7 @@ both the SDK selector and canonical checker. These helpers belong to `workflows/shared/squad-activation.mjs`; they are **not** public `/casting` verifier exports. The `trusted synchronous publication completion (source and strict-compiled jobs)` group also executes emitted job scripts and the pinned issue-creation API adapter. -The companion [selector contract tests](https://github.com/bradygaster/squad/blob/dev/test/agent-provenance.test.ts) +The companion [selector contract tests](https://github.com/github/squad/blob/dev/test/agent-provenance.test.ts) cover selection, no-record results and rejection cases; their hand-built evidence is test data, not production authorization. @@ -2610,7 +2610,7 @@ other refs. ## See also -- [Squad README](https://github.com/bradygaster/squad#readme) — project overview and local CLI usage -- [Workflow definition](https://github.com/bradygaster/squad/blob/dev/workflows/squad.md) — full slash command specification -- [Implementation worker](https://github.com/bradygaster/squad/blob/dev/workflows/squad-implement-worker.md) — isolated issue implementation workflow -- [Bootstrap component](https://github.com/bradygaster/squad/blob/dev/workflows/shared/squad.md) — activation and artifact lifecycle +- [Squad README](https://github.com/github/squad#readme) — project overview and local CLI usage +- [Workflow definition](https://github.com/github/squad/blob/dev/workflows/squad.md) — full slash command specification +- [Implementation worker](https://github.com/github/squad/blob/dev/workflows/squad-implement-worker.md) — isolated issue implementation workflow +- [Bootstrap component](https://github.com/github/squad/blob/dev/workflows/shared/squad.md) — activation and artifact lifecycle diff --git a/docs/src/content/docs/insider-program.md b/docs/src/content/docs/insider-program.md index 4522e33e6..fa9cac00c 100644 --- a/docs/src/content/docs/insider-program.md +++ b/docs/src/content/docs/insider-program.md @@ -153,7 +153,7 @@ squad upgrade # Apply stable version Homebrew and WinGet users should uninstall the insider package, install the stable package, and then run `squad upgrade`. -Then [report the issue](https://github.com/bradygaster/squad/issues). +Then [report the issue](https://github.com/github/squad/issues). --- @@ -161,4 +161,4 @@ Then [report the issue](https://github.com/bradygaster/squad/issues). Insiders help us ship better software. Your bug reports, feature requests, and feedback make Squad stronger. Thank you for being part of the journey. -Have questions? [Start a discussion](https://github.com/bradygaster/squad/discussions). +Have questions? [Start a discussion](https://github.com/github/squad/discussions). diff --git a/docs/src/content/docs/reference/container-image.md b/docs/src/content/docs/reference/container-image.md index 7dfdd5504..af2f93cb5 100644 --- a/docs/src/content/docs/reference/container-image.md +++ b/docs/src/content/docs/reference/container-image.md @@ -73,9 +73,9 @@ volumeMounts: mountPath: /app/.squad ``` -The config is injected at runtime from a ConfigMap or Azure Files share. Supports live config updates without rebuilding the image. Note that FSStorageProvider may resolve state paths relative to the process working directory rather than the volume mount when `rootDir` is not set in `config.json` — see [#1555](https://github.com/bradygaster/squad/issues/1555). +The config is injected at runtime from a ConfigMap or Azure Files share. Supports live config updates without rebuilding the image. Note that FSStorageProvider may resolve state paths relative to the process working directory rather than the volume mount when `rootDir` is not set in `config.json` — see [#1555](https://github.com/github/squad/issues/1555). -> ⚠️ **Multi-replica state warning:** The `local` state backend (files on disk) is **not safe for concurrent writes** from multiple pod replicas. If you scale beyond one replica, use the `orphan` or `two-layer` state backend, or persist state to an external store. See [State Backends](/squad/docs/features/state-backends/) and [#1402](https://github.com/bradygaster/squad/issues/1402). +> ⚠️ **Multi-replica state warning:** The `local` state backend (files on disk) is **not safe for concurrent writes** from multiple pod replicas. If you scale beyond one replica, use the `orphan` or `two-layer` state backend, or persist state to an external store. See [State Backends](/squad/docs/features/state-backends/) and [#1402](https://github.com/github/squad/issues/1402). --- @@ -127,14 +127,14 @@ CMD ["squad", "watch", "--execute"] ## Process Lifecycle and Health -Squad does not expose an HTTP health server or liveness/readiness endpoints. There is no `SQUAD_HEALTH_PORT`, `/healthz`, or `/readyz` — these are planned features tracked in [#1577](https://github.com/bradygaster/squad/issues/1577). +Squad does not expose an HTTP health server or liveness/readiness endpoints. There is no `SQUAD_HEALTH_PORT`, `/healthz`, or `/readyz` — these are planned features tracked in [#1577](https://github.com/github/squad/issues/1577). **Current container health behavior:** - The container is healthy as long as the `squad watch --execute` process is running. - If `squad` exits for any reason, the container exits. Kubernetes and ACA restart exited containers automatically via the container restart policy — this is sufficient for the current release. - Do **not** configure HTTP liveness or readiness probes — there is no listener and probes will always fail, crash-looping your pod. -If your cluster policy requires an exec probe, use Node.js (already present in the image) to check that PID 1 is still running. This is a **shallow** check — it only confirms the process table entry for PID 1 exists; it does not verify GitHub API connectivity or queue health. An HTTP readiness endpoint is the tracked solution in [#1577](https://github.com/bradygaster/squad/issues/1577). +If your cluster policy requires an exec probe, use Node.js (already present in the image) to check that PID 1 is still running. This is a **shallow** check — it only confirms the process table entry for PID 1 exists; it does not verify GitHub API connectivity or queue health. An HTTP readiness endpoint is the tracked solution in [#1577](https://github.com/github/squad/issues/1577). ```yaml # Shallow PID-1 existence check (no procps / pgrep required) @@ -152,7 +152,7 @@ livenessProbe: failureThreshold: 3 ``` -> **Tracking:** An explicit HTTP health/readiness contract is planned. See [#1577](https://github.com/bradygaster/squad/issues/1577) for status. +> **Tracking:** An explicit HTTP health/readiness contract is planned. See [#1577](https://github.com/github/squad/issues/1577) for status. --- @@ -233,10 +233,10 @@ Azure Container Apps supports [Key Vault secret references](https://learn.micros | Limitation | Status | Workaround | |---|---|---| -| FSStorageProvider may resolve state paths relative to process working directory instead of volume mount when `rootDir` is not explicit in `config.json` | Open — [#1555](https://github.com/bradygaster/squad/issues/1555) | Set `rootDir` explicitly in `.squad/config.json` to the absolute volume mount path; no env var override exists yet | -| No HTTP health/readiness endpoints | Planned — [#1577](https://github.com/bradygaster/squad/issues/1577) | Use process-check exec probe; Kubernetes restarts exited containers automatically | -| `local` state backend not safe for concurrent multi-replica writes | Design gap — [#1402](https://github.com/bradygaster/squad/issues/1402) | Use `orphan` or `two-layer` backend, or scale to one replica | -| Remote dispatch (`--remote` flag) | RFC in progress — [#1189](https://github.com/bradygaster/squad/issues/1189) | Use KEDA queue-based scaling as a near-term alternative | +| FSStorageProvider may resolve state paths relative to process working directory instead of volume mount when `rootDir` is not explicit in `config.json` | Open — [#1555](https://github.com/github/squad/issues/1555) | Set `rootDir` explicitly in `.squad/config.json` to the absolute volume mount path; no env var override exists yet | +| No HTTP health/readiness endpoints | Planned — [#1577](https://github.com/github/squad/issues/1577) | Use process-check exec probe; Kubernetes restarts exited containers automatically | +| `local` state backend not safe for concurrent multi-replica writes | Design gap — [#1402](https://github.com/github/squad/issues/1402) | Use `orphan` or `two-layer` backend, or scale to one replica | +| Remote dispatch (`--remote` flag) | RFC in progress — [#1189](https://github.com/github/squad/issues/1189) | Use KEDA queue-based scaling as a near-term alternative | --- @@ -286,4 +286,4 @@ az aks update \ - [State Backends](/squad/docs/features/state-backends/) — choosing a backend safe for multi-replica deployments - [Azure Container Apps deployment](../scenarios/azure-container-apps) — end-to-end ACA scenario - [AKS deployment runbook](../scenarios/aks-deployment) — Kubernetes scenario with workload identity and KEDA -- [#1577](https://github.com/bradygaster/squad/issues/1577) — health/readiness endpoint product gap +- [#1577](https://github.com/github/squad/issues/1577) — health/readiness endpoint product gap diff --git a/docs/src/content/docs/reference/plugin-security.md b/docs/src/content/docs/reference/plugin-security.md index 5fe4b45be..b3b78cdaa 100644 --- a/docs/src/content/docs/reference/plugin-security.md +++ b/docs/src/content/docs/reference/plugin-security.md @@ -49,10 +49,10 @@ Runtime artifact generation commands (`refresh`, `run-lifecycle`) add a new capa The next executable-provider roadmap is tracked in: -- [Epic #1102](https://github.com/bradygaster/squad/issues/1102) -- [Phase 1 marketplace distribution #1103](https://github.com/bradygaster/squad/issues/1103) -- [Phase 2 built-in providers #1104](https://github.com/bradygaster/squad/issues/1104) -- [Phase 3 executable runtime RFC #1105](https://github.com/bradygaster/squad/issues/1105) +- [Epic #1102](https://github.com/github/squad/issues/1102) +- [Phase 1 marketplace distribution #1103](https://github.com/github/squad/issues/1103) +- [Phase 2 built-in providers #1104](https://github.com/github/squad/issues/1104) +- [Phase 3 executable runtime RFC #1105](https://github.com/github/squad/issues/1105) --- diff --git a/docs/src/content/docs/reference/state-backend-selection.md b/docs/src/content/docs/reference/state-backend-selection.md index 88877cc03..a49b2e009 100644 --- a/docs/src/content/docs/reference/state-backend-selection.md +++ b/docs/src/content/docs/reference/state-backend-selection.md @@ -6,7 +6,7 @@ order: 15 # State Backend Selection -> 🔗 **Full backend documentation:** [State Backends](/squad/docs/features/state-backends/) · [Container Image — Env Var Contract](/squad/docs/reference/container-image/) · [#1402](https://github.com/bradygaster/squad/issues/1402) (external state gaps — tracked separately) +> 🔗 **Full backend documentation:** [State Backends](/squad/docs/features/state-backends/) · [Container Image — Env Var Contract](/squad/docs/reference/container-image/) · [#1402](https://github.com/github/squad/issues/1402) (external state gaps — tracked separately) --- @@ -31,7 +31,7 @@ Choose a backend based on your deployment shape: > - **`local`:** Files on disk. Two pods writing to the same PVC simultaneously will corrupt state — no locking, no merge. This is data loss, not a merge conflict. > - **`orphan` / `two-layer`:** Branch-based. The second pod to push `squad-state` gets a non-fast-forward rejection. The losing pod's state changes are silently discarded unless the operator manually resolves the conflict. Under high concurrency this causes regular state loss. > -> **If you run more than one Squad replica at a time, you must use an external state store.** The external state backend ([#1402](https://github.com/bradygaster/squad/issues/1402)) is not yet GA — see [External State](/squad/docs/features/external-state/) for current status and workarounds. +> **If you run more than one Squad replica at a time, you must use an external state store.** The external state backend ([#1402](https://github.com/github/squad/issues/1402)) is not yet GA — see [External State](/squad/docs/features/external-state/) for current status and workarounds. > > The `squad-per-pod` deployment mode (via `SQUAD_DEPLOYMENT_MODE=squad-per-pod`) assigns each pod a stable identity and partition of the issue queue — but it does not eliminate shared-state write conflicts. It reduces them by partitioning work, but does not make any built-in backend safe for concurrent writers. @@ -118,17 +118,17 @@ git fetch origin squad-state:squad-state ## Known bug: FSStorageProvider `rootDir` (#1555) -> ⚠️ **Open bug [#1555](https://github.com/bradygaster/squad/issues/1555):** `FSStorageProvider` is constructed without a `rootDir` argument in `resolveSquadState()`. All relative state keys resolve against the Node.js process working directory (the repo root) rather than `.squad/`, silently creating a shadow state tree that diverges from the authoritative `.squad/` copy agents actually read. +> ⚠️ **Open bug [#1555](https://github.com/github/squad/issues/1555):** `FSStorageProvider` is constructed without a `rootDir` argument in `resolveSquadState()`. All relative state keys resolve against the Node.js process working directory (the repo root) rather than `.squad/`, silently creating a shadow state tree that diverges from the authoritative `.squad/` copy agents actually read. > -> **There is no configuration-level workaround.** Because `FSStorageProvider` is constructed with zero arguments regardless of any user configuration, setting `rootDir` in `config.json` has no effect — the constructor call ignores it. This must be fixed in the SDK itself ([#1555](https://github.com/bradygaster/squad/issues/1555)). +> **There is no configuration-level workaround.** Because `FSStorageProvider` is constructed with zero arguments regardless of any user configuration, setting `rootDir` in `config.json` has no effect — the constructor call ignores it. This must be fixed in the SDK itself ([#1555](https://github.com/github/squad/issues/1555)). > -> **Until #1555 is resolved:** Run only a single Squad replica. Avoid deployment paths where the MCP server process `cwd` differs from the volume mount path. Track [#1555](https://github.com/bradygaster/squad/issues/1555) for the fix. +> **Until #1555 is resolved:** Run only a single Squad replica. Avoid deployment paths where the MCP server process `cwd` differs from the volume mount path. Track [#1555](https://github.com/github/squad/issues/1555) for the fix. --- ## Multi-pod: external state (future) -The external state backend — designed to be safe for concurrent writers via a centralized, transactional store — is tracked in [#1402](https://github.com/bradygaster/squad/issues/1402). It is not yet available as a GA backend. +The external state backend — designed to be safe for concurrent writers via a centralized, transactional store — is tracked in [#1402](https://github.com/github/squad/issues/1402). It is not yet available as a GA backend. Until #1402 lands, the recommended mitigation for multi-pod deployments is: diff --git a/docs/src/content/docs/reference/vscode-troubleshooting.md b/docs/src/content/docs/reference/vscode-troubleshooting.md index a3a4cf598..1f4aa8289 100644 --- a/docs/src/content/docs/reference/vscode-troubleshooting.md +++ b/docs/src/content/docs/reference/vscode-troubleshooting.md @@ -6,7 +6,7 @@ This page covers known issues and mitigations when running Squad inside VS Code' ## Symptom: VS Code closes unexpectedly during Squad execution -**Reported in:** [Issue #259](https://github.com/bradygaster/squad/issues/259), [Discussion #174](https://github.com/bradygaster/squad/discussions/174) +**Reported in:** [Issue #259](https://github.com/github/squad/issues/259), [Discussion #174](https://github.com/github/squad/discussions/174) VS Code (especially Insiders/Nightly builds) may close without a crash dialog while Squad tasks are executing. This is most often caused by resource pressure — not a bug in Squad itself — but Squad's runtime patterns can contribute to the problem. @@ -80,7 +80,7 @@ Squad uses the Ink framework for rendering, which batches React state updates. D 5. **Close unused terminals** in VS Code before starting a Squad session. Each terminal consumes renderer memory. -6. **Disable terminal GPU acceleration** if you see flickering (related: [#254](https://github.com/bradygaster/squad/issues/254)): +6. **Disable terminal GPU acceleration** if you see flickering (related: [#254](https://github.com/github/squad/issues/254)): ```json { "terminal.integrated.gpuAcceleration": "off" @@ -100,6 +100,6 @@ Squad uses the Ink framework for rendering, which batches React state updates. D | Issue | Description | Status | |-------|-------------|--------| -| [#259](https://github.com/bradygaster/squad/issues/259) | VS Code crash during Squad execution | This investigation | -| [#254](https://github.com/bradygaster/squad/issues/254) | Terminal flicker in VS Code | Open | -| [Discussion #174](https://github.com/bradygaster/squad/discussions/174) | Original crash report by @diberry | Open | +| [#259](https://github.com/github/squad/issues/259) | VS Code crash during Squad execution | This investigation | +| [#254](https://github.com/github/squad/issues/254) | Terminal flicker in VS Code | Open | +| [Discussion #174](https://github.com/github/squad/discussions/174) | Original crash report by @diberry | Open | diff --git a/docs/src/content/docs/scenarios/aks-deployment.md b/docs/src/content/docs/scenarios/aks-deployment.md index 88c89ccd2..e692279e8 100644 --- a/docs/src/content/docs/scenarios/aks-deployment.md +++ b/docs/src/content/docs/scenarios/aks-deployment.md @@ -455,7 +455,7 @@ Add to `squad-deployment.yaml` volumes and volumeMounts: mountPath: /app/.squad/state ``` -> ⚠️ **Multi-replica write safety:** `ReadWriteOnce` (Azure Disk) only supports one writer pod at a time. For multiple replicas, use `ReadWriteMany` with an Azure Files storage class, **and** switch to the orphan or two-layer state backend. See [#1402](https://github.com/bradygaster/squad/issues/1402). +> ⚠️ **Multi-replica write safety:** `ReadWriteOnce` (Azure Disk) only supports one writer pod at a time. For multiple replicas, use `ReadWriteMany` with an Azure Files storage class, **and** switch to the orphan or two-layer state backend. See [#1402](https://github.com/github/squad/issues/1402). --- @@ -561,7 +561,7 @@ kubectl exec -it --namespace $NAMESPACE -- \ cat /app/.squad/config.json | grep stateBackend ``` -**Fix:** Switch to the `orphan` or `two-layer` state backend, which uses Git-native structures safe for concurrent access. See [State Backends](/squad/docs/features/state-backends/) and open issue [#1402](https://github.com/bradygaster/squad/issues/1402). +**Fix:** Switch to the `orphan` or `two-layer` state backend, which uses Git-native structures safe for concurrent access. See [State Backends](/squad/docs/features/state-backends/) and open issue [#1402](https://github.com/github/squad/issues/1402). The `local` (file-based) backend is **not safe** for multi-replica deployments. @@ -586,7 +586,7 @@ Common causes: > ⚠️ The `local` state backend (default) is **not safe for concurrent writes** from multiple Squad pods. The orphan-branch state backend uses a dedicated Git branch (`squad-state`) that is safe for multi-replica deployments because commits serialize writes. The two-layer backend further separates immutable assets from mutable state for better concurrency. Use one of these backends when scaling beyond a single replica. > -> See [State Backends](/squad/docs/features/state-backends/) and [#1402](https://github.com/bradygaster/squad/issues/1402) for details and planned improvements. +> See [State Backends](/squad/docs/features/state-backends/) and [#1402](https://github.com/github/squad/issues/1402) for details and planned improvements. --- @@ -594,10 +594,10 @@ Common causes: | Feature | Status | |---|---| -| Remote dispatch (`--remote` flag for webhook-triggered runs) | RFC — [#1189](https://github.com/bradygaster/squad/issues/1189) | -| External state backend safety for multi-replica writes | Design — [#1402](https://github.com/bradygaster/squad/issues/1402) | -| FSStorageProvider rootDir bug (no env-var override; set `rootDir` explicitly in `config.json`) | Open — [#1555](https://github.com/bradygaster/squad/issues/1555) | -| HTTP health/readiness endpoints | Planned — [#1577](https://github.com/bradygaster/squad/issues/1577) | +| Remote dispatch (`--remote` flag for webhook-triggered runs) | RFC — [#1189](https://github.com/github/squad/issues/1189) | +| External state backend safety for multi-replica writes | Design — [#1402](https://github.com/github/squad/issues/1402) | +| FSStorageProvider rootDir bug (no env-var override; set `rootDir` explicitly in `config.json`) | Open — [#1555](https://github.com/github/squad/issues/1555) | +| HTTP health/readiness endpoints | Planned — [#1577](https://github.com/github/squad/issues/1577) | | Helm chart for Squad (community request) | Not planned in this issue — contributions welcome | --- diff --git a/docs/src/content/docs/scenarios/azure-container-apps.md b/docs/src/content/docs/scenarios/azure-container-apps.md index 584d906ed..971ef34cc 100644 --- a/docs/src/content/docs/scenarios/azure-container-apps.md +++ b/docs/src/content/docs/scenarios/azure-container-apps.md @@ -197,7 +197,7 @@ Azure Container Apps has [built-in KEDA support](https://learn.microsoft.com/azu ### Option A — ACA built-in HTTP scaler -For HTTP-triggered workflows (webhook dispatch, future `--remote` mode — see [#1189](https://github.com/bradygaster/squad/issues/1189)): +For HTTP-triggered workflows (webhook dispatch, future `--remote` mode — see [#1189](https://github.com/github/squad/issues/1189)): ```bash az containerapp update \ @@ -289,7 +289,7 @@ az containerapp job start \ --resource-group $RESOURCE_GROUP ``` -> **Future:** Remote dispatch (`squad --remote`) is being designed in [#1189](https://github.com/bradygaster/squad/issues/1189). Once available, ACA Jobs will be the recommended execution backend for remote dispatch. +> **Future:** Remote dispatch (`squad --remote`) is being designed in [#1189](https://github.com/github/squad/issues/1189). Once available, ACA Jobs will be the recommended execution backend for remote dispatch. --- @@ -303,7 +303,7 @@ For durable state: 2. **Azure Files volume mount**: Mount an Azure Files share to `/app/.squad/` for shared file-system persistence across replicas. 3. **Single replica**: If scaling to one replica (min=max=1), ephemeral state survives in-memory but not across restarts. -> ⚠️ **Multi-replica safety:** The `local` state backend is **not safe for concurrent writes** from multiple replicas. Use the orphan or two-layer backend, or constrain to one replica. See [State Backends](/squad/docs/features/state-backends/) and [#1402](https://github.com/bradygaster/squad/issues/1402). +> ⚠️ **Multi-replica safety:** The `local` state backend is **not safe for concurrent writes** from multiple replicas. Use the orphan or two-layer backend, or constrain to one replica. See [State Backends](/squad/docs/features/state-backends/) and [#1402](https://github.com/github/squad/issues/1402). --- @@ -348,7 +348,7 @@ az containerapp identity show \ **Symptom:** First issue pickup after scale-from-zero is slow (15–45 s typical). -- This is expected behavior — Squad has no readiness endpoint yet (see [#1577](https://github.com/bradygaster/squad/issues/1577)). ACA restarts exited containers automatically; no HTTP probe is needed. +- This is expected behavior — Squad has no readiness endpoint yet (see [#1577](https://github.com/github/squad/issues/1577)). ACA restarts exited containers automatically; no HTTP probe is needed. - Set `--min-replicas 1` to keep one warm replica if latency matters. - Use `node:22-alpine` base image (not `node:22`) for a smaller, faster startup. @@ -366,11 +366,11 @@ az containerapp identity show \ | Feature | Status | |---|---| -| `--remote` dispatch (webhook-triggered issue execution) | RFC — [#1189](https://github.com/bradygaster/squad/issues/1189) | -| External state gap for multi-replica deployments | Design — [#1402](https://github.com/bradygaster/squad/issues/1402) | -| FSStorageProvider rootDir bug (no env-var override; set `rootDir` in `config.json`) | Open — [#1555](https://github.com/bradygaster/squad/issues/1555) | -| HTTP health/readiness endpoints | Planned — [#1577](https://github.com/bradygaster/squad/issues/1577) | -| ACA Dynamic Sessions / Sandbox execution | Planned — [#1564](https://github.com/bradygaster/squad/issues/1564) | +| `--remote` dispatch (webhook-triggered issue execution) | RFC — [#1189](https://github.com/github/squad/issues/1189) | +| External state gap for multi-replica deployments | Design — [#1402](https://github.com/github/squad/issues/1402) | +| FSStorageProvider rootDir bug (no env-var override; set `rootDir` in `config.json`) | Open — [#1555](https://github.com/github/squad/issues/1555) | +| HTTP health/readiness endpoints | Planned — [#1577](https://github.com/github/squad/issues/1577) | +| ACA Dynamic Sessions / Sandbox execution | Planned — [#1564](https://github.com/github/squad/issues/1564) | --- diff --git a/docs/src/content/docs/scenarios/multi-machine-watch.md b/docs/src/content/docs/scenarios/multi-machine-watch.md index 323976c3f..bc9f86c39 100644 --- a/docs/src/content/docs/scenarios/multi-machine-watch.md +++ b/docs/src/content/docs/scenarios/multi-machine-watch.md @@ -11,7 +11,7 @@ description: Run squad watch --execute on several machines or pods without two o Work claims are opt-in and off by default. The design and its guarantees are recorded in -[ADR-002: Work Claims and External Work Queues](https://github.com/bradygaster/squad/blob/dev/docs/specification/adr-002-work-claims-and-external-queues.md). +[ADR-002: Work Claims and External Work Queues](https://github.com/github/squad/blob/dev/docs/specification/adr-002-work-claims-and-external-queues.md). ## Why: double-pick @@ -347,7 +347,7 @@ and a local `squad watch` process cannot be one. Work claims don't depend on gh-aw and work the same with or without it. Integration with the gh-aw work queue is deferred until the gates in -[ADR-002](https://github.com/bradygaster/squad/blob/dev/docs/specification/adr-002-work-claims-and-external-queues.md#gh-aw-adapter-gates) +[ADR-002](https://github.com/github/squad/blob/dev/docs/specification/adr-002-work-claims-and-external-queues.md#gh-aw-adapter-gates) pass, including a stable queue protocol and daily use of `git-ref` claims on at least two machines. diff --git a/docs/src/content/docs/scenarios/open-source.md b/docs/src/content/docs/scenarios/open-source.md index ad577c2ac..d9bba103a 100644 --- a/docs/src/content/docs/scenarios/open-source.md +++ b/docs/src/content/docs/scenarios/open-source.md @@ -255,7 +255,7 @@ Add a badge to your README: ```markdown ## Contributing -This project uses [Squad](https://github.com/bradygaster/squad) for AI-assisted development. +This project uses [Squad](https://github.com/github/squad) for AI-assisted development. - **Triaging:** Issues are auto-labeled by Squad's Ralph agent - **Patterns:** See `.ai-team/skills/` for coding conventions diff --git a/docs/src/content/docs/scenarios/production-observability.md b/docs/src/content/docs/scenarios/production-observability.md index ea53c7acb..997bbb118 100644 --- a/docs/src/content/docs/scenarios/production-observability.md +++ b/docs/src/content/docs/scenarios/production-observability.md @@ -6,7 +6,7 @@ order: 26 # Production Observability -> 🔗 **Related:** [Aspire Dashboard](./aspire-dashboard) (local dev telemetry) · [Production Troubleshooting Runbook](./production-troubleshooting) · [Container Image — Env Var Contract](/squad/docs/reference/container-image/) · [#1144](https://github.com/bradygaster/squad/issues/1144) (embedded-host telemetry — tracked separately) +> 🔗 **Related:** [Aspire Dashboard](./aspire-dashboard) (local dev telemetry) · [Production Troubleshooting Runbook](./production-troubleshooting) · [Container Image — Env Var Contract](/squad/docs/reference/container-image/) · [#1144](https://github.com/github/squad/issues/1144) (embedded-host telemetry — tracked separately) --- @@ -228,7 +228,7 @@ When filing a support issue or escalating an incident: 2. Collect events: `kubectl get events -n squad --sort-by=.lastTimestamp > squad-events.txt` 3. Export a 30-minute trace sample from Application Insights or Grafana Tempo 4. Attach `kubectl describe pod -n squad ` output -5. Open an issue at [bradygaster/squad](https://github.com/bradygaster/squad/issues) with the above artifacts, redacting any PII from log excerpts +5. Open an issue at [github/squad](https://github.com/github/squad/issues) with the above artifacts, redacting any PII from log excerpts --- @@ -236,8 +236,8 @@ When filing a support issue or escalating an incident: | Issue | Status | Impact | |---|---|---| -| [#1144](https://github.com/bradygaster/squad/issues/1144) | Open — embedded host telemetry | Squad running via `@github/copilot-sdk` does not yet expose OTLP. Production telemetry requires Squad CLI container mode. | -| [#1577](https://github.com/bradygaster/squad/issues/1577) | Open — HTTP health endpoints | No `/healthz` or `/readyz` endpoint exists. Readiness cannot be confirmed via HTTP; Kubernetes relies on process restart policy only. | +| [#1144](https://github.com/github/squad/issues/1144) | Open — embedded host telemetry | Squad running via `@github/copilot-sdk` does not yet expose OTLP. Production telemetry requires Squad CLI container mode. | +| [#1577](https://github.com/github/squad/issues/1577) | Open — HTTP health endpoints | No `/healthz` or `/readyz` endpoint exists. Readiness cannot be confirmed via HTTP; Kubernetes relies on process restart policy only. | --- diff --git a/docs/src/content/docs/scenarios/production-troubleshooting.md b/docs/src/content/docs/scenarios/production-troubleshooting.md index 3123bbdba..10f42f0dd 100644 --- a/docs/src/content/docs/scenarios/production-troubleshooting.md +++ b/docs/src/content/docs/scenarios/production-troubleshooting.md @@ -153,11 +153,11 @@ If the PVC mount is missing, the pod is writing state to the container's ephemer ### FSStorageProvider rootDir bug (#1555) -If Squad logs show state files at the repo root (e.g., `agents/`, `log/`, `decisions.md` appearing at `/app/` rather than `/app/.squad/`), this is [#1555](https://github.com/bradygaster/squad/issues/1555): `FSStorageProvider` is constructed without a `rootDir` argument, so all state keys resolve against the process `cwd` (the repo root) instead of `.squad/`. +If Squad logs show state files at the repo root (e.g., `agents/`, `log/`, `decisions.md` appearing at `/app/` rather than `/app/.squad/`), this is [#1555](https://github.com/github/squad/issues/1555): `FSStorageProvider` is constructed without a `rootDir` argument, so all state keys resolve against the process `cwd` (the repo root) instead of `.squad/`. > ⚠️ **There is no configuration-level workaround for #1555.** Setting `rootDir` in `config.json` has no effect — `FSStorageProvider` ignores constructor arguments in the affected code path. This must be fixed in the SDK itself. > -> **Mitigation until #1555 is resolved:** Run only a single Squad replica. Avoid deployment shapes where the MCP server process `cwd` differs from the intended state path. Track [#1555](https://github.com/bradygaster/squad/issues/1555) for status. +> **Mitigation until #1555 is resolved:** Run only a single Squad replica. Avoid deployment shapes where the MCP server process `cwd` differs from the intended state path. Track [#1555](https://github.com/github/squad/issues/1555) for status. See [State Backend Selection — Known bug #1555](/squad/docs/reference/state-backend-selection/#known-bug-fsstorageprovider-rootdir-1555) for background. @@ -167,7 +167,7 @@ See [State Backend Selection — Known bug #1555](/squad/docs/reference/state-ba kubectl logs -n squad | grep "non-fast-forward\|push rejected" ``` -If you see push rejections, two pods wrote to `squad-state` concurrently. One pod's state changes were discarded. For multi-pod deployments, do not use branch-based backends — see [State Backend Selection](/squad/docs/reference/state-backend-selection/) and track [#1402](https://github.com/bradygaster/squad/issues/1402). +If you see push rejections, two pods wrote to `squad-state` concurrently. One pod's state changes were discarded. For multi-pod deployments, do not use branch-based backends — see [State Backend Selection](/squad/docs/reference/state-backend-selection/) and track [#1402](https://github.com/github/squad/issues/1402). --- @@ -274,7 +274,7 @@ kubectl top pod -n squad # requires metrics-server > > **Workaround:** Alert on GitHub 401 errors in structured logs (Log Analytics KQL or Grafana log panel). Treat repeated 401s as a readiness failure requiring manual intervention. > -> Track [#1577](https://github.com/bradygaster/squad/issues/1577) for HTTP health endpoint implementation. +> Track [#1577](https://github.com/github/squad/issues/1577) for HTTP health endpoint implementation. --- @@ -300,7 +300,7 @@ kubectl describe scaledobject -n squad squad-agents > squad-scaledobject.txt kubectl exec -n squad -- cat /app/.squad/config.json 2>/dev/null ``` -Open an issue at [bradygaster/squad](https://github.com/bradygaster/squad/issues) and attach the above files. Redact any GitHub tokens, connection strings, or personal data from log excerpts before attaching. +Open an issue at [github/squad](https://github.com/github/squad/issues) and attach the above files. Redact any GitHub tokens, connection strings, or personal data from log excerpts before attaching. --- @@ -308,7 +308,7 @@ Open an issue at [bradygaster/squad](https://github.com/bradygaster/squad/issues | Issue | This runbook covers | |---|---| -| [#1144](https://github.com/bradygaster/squad/issues/1144) | Embedded host (copilot-sdk) telemetry not available in production — agents must use Squad CLI container mode | -| [#1402](https://github.com/bradygaster/squad/issues/1402) | External state backend for multi-pod deployments — not yet GA | -| [#1555](https://github.com/bradygaster/squad/issues/1555) | FSStorageProvider `rootDir` bug — no configuration-level workaround; run single replica and track issue for fix | -| [#1577](https://github.com/bradygaster/squad/issues/1577) | HTTP health/readiness endpoints — not yet implemented | +| [#1144](https://github.com/github/squad/issues/1144) | Embedded host (copilot-sdk) telemetry not available in production — agents must use Squad CLI container mode | +| [#1402](https://github.com/github/squad/issues/1402) | External state backend for multi-pod deployments — not yet GA | +| [#1555](https://github.com/github/squad/issues/1555) | FSStorageProvider `rootDir` bug — no configuration-level workaround; run single replica and track issue for fix | +| [#1577](https://github.com/github/squad/issues/1577) | HTTP health/readiness endpoints — not yet implemented | diff --git a/docs/src/content/docs/scenarios/scaling-workstreams.md b/docs/src/content/docs/scenarios/scaling-workstreams.md index 3730533a7..5210c234f 100644 --- a/docs/src/content/docs/scenarios/scaling-workstreams.md +++ b/docs/src/content/docs/scenarios/scaling-workstreams.md @@ -164,5 +164,5 @@ Configured SubSquads ## See Also - [Multi-Codespace Setup](multi-codespace.md) — Walkthrough of the Tetris experiment -- [SubSquads PRD](https://github.com/bradygaster/squad/blob/main/docs/_internal/specs/streams-prd.md) — Full specification +- [SubSquads PRD](https://github.com/github/squad/blob/main/docs/_internal/specs/streams-prd.md) — Full specification - [SubSquads Feature Guide](../features/streams.md) — API reference diff --git a/docs/src/layouts/DocsLayout.astro b/docs/src/layouts/DocsLayout.astro index 1e892b430..033c2ee24 100644 --- a/docs/src/layouts/DocsLayout.astro +++ b/docs/src/layouts/DocsLayout.astro @@ -23,7 +23,7 @@ const navSection = NAV_SECTIONS.find(s => s.dir === sectionDir); const section = navSection?.title || 'Docs'; const editUrl = currentSlug - ? `https://github.com/bradygaster/squad/edit/dev/docs/src/content/docs/${currentSlug}.md` + ? `https://github.com/github/squad/edit/dev/docs/src/content/docs/${currentSlug}.md` : null; --- diff --git a/docs/src/pages/index.astro b/docs/src/pages/index.astro index 40a0bbe80..20a115fde 100644 --- a/docs/src/pages/index.astro +++ b/docs/src/pages/index.astro @@ -50,7 +50,7 @@ const base = import.meta.env.BASE_URL; ({ title: post.data.title ?? post.id, pubDate: new Date(post.data.date), diff --git a/docs/src/plugins/remark-rewrite-links.mjs b/docs/src/plugins/remark-rewrite-links.mjs index a649c1490..f3a32633b 100644 --- a/docs/src/plugins/remark-rewrite-links.mjs +++ b/docs/src/plugins/remark-rewrite-links.mjs @@ -12,7 +12,7 @@ import { visit } from 'unist-util-visit'; * Links that escape the content directory (../../README.md) go to GitHub. */ -const GITHUB_REPO = 'https://github.com/bradygaster/squad'; +const GITHUB_REPO = 'https://github.com/github/squad'; // Map old section paths to new locations const SECTION_REDIRECTS = { diff --git a/docs/tests/astro-features.test.mjs b/docs/tests/astro-features.test.mjs index e0907e444..911073485 100644 --- a/docs/tests/astro-features.test.mjs +++ b/docs/tests/astro-features.test.mjs @@ -7,6 +7,15 @@ import { describe, it } from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import path from 'node:path'; +import { + RETIRED_SITE_LINK, + SCANNED_PATHS, + SITE_SETTINGS, + findLinks, + readScannedFiles, + readSetting, + scanOldRepoLinks, +} from '../../scripts/docs-site-location.mjs'; const DOCS_ROOT = path.resolve(import.meta.dirname, '..'); const SRC = path.join(DOCS_ROOT, 'src'); @@ -52,7 +61,7 @@ describe('"Edit this page" link', () => { it('DocsLayout.astro contains edit-this-page link', () => { const layout = fs.readFileSync(path.join(SRC, 'layouts', 'DocsLayout.astro'), 'utf-8'); assert.ok(layout.includes('edit-this-page') || layout.includes('Edit this page'), 'DocsLayout should include Edit this page link'); - assert.ok(layout.includes('github.com/bradygaster/squad/edit'), 'Edit link should point to GitHub edit URL'); + assert.ok(layout.includes('github.com/github/squad/edit'), 'Edit link should point to the github/squad edit URL'); }); }); @@ -137,3 +146,35 @@ describe('View Transitions', () => { assert.ok(layout.includes('') || layout.includes(''), 'BaseLayout should render '); }); }); + +// 11. site location: the repo moved to github/squad, and GitHub Pages does not redirect the +// retired bradygaster.github.io site to github.github.com/squad/. The contract lives in +// scripts/docs-site-location.mjs, shared with test/docs-site-location.test.ts (CI), which also +// pins its patterns and allowlist with examples. +describe('docs site location', () => { + let scanned; + const scannedFiles = () => (scanned ??= readScannedFiles()); + + for (const setting of SITE_SETTINGS) { + it(`${setting.name} in ${setting.file} is ${setting.expected}`, () => { + const { value, at } = readSetting(setting); + assert.equal(value, setting.expected, `${at}: ${setting.name} is ${value}`); + }); + } + + it('scans the tracked docs, samples, READMEs and contributor guides', () => { + const paths = scannedFiles().map((file) => file.path); + const emptyRoots = SCANNED_PATHS.filter((root) => !paths.some((file) => file === root || file.startsWith(`${root}/`))); + assert.deepEqual(emptyRoots, [], `scanned paths with no tracked text files: ${emptyRoots.join(', ')}`); + }); + + it('nothing scanned links to the retired bradygaster.github.io site', () => { + const offenders = findLinks(scannedFiles(), RETIRED_SITE_LINK); + assert.deepEqual(offenders, [], `Links to the retired docs site (use https://github.github.com/squad/...):\n${offenders.join('\n')}`); + }); + + it('everything scanned links to github/squad, apart from the historical records in HISTORICAL_REPO_LINKS', () => { + const { offenders } = scanOldRepoLinks(scannedFiles()); + assert.deepEqual(offenders, [], `Links to the old bradygaster/squad repository (use https://github.com/github/squad):\n${offenders.join('\n')}`); + }); +}); diff --git a/packages/squad-cli/README.md b/packages/squad-cli/README.md index 5afb2f2bd..1e0d834fb 100644 --- a/packages/squad-cli/README.md +++ b/packages/squad-cli/README.md @@ -2,7 +2,7 @@ The programmable multi-agent CLI for GitHub Copilot. Build an AI team, assign roles, and let them work your repo—automating issue triage, code review, documentation, and more through orchestrated AI agents. -Breaking changes are documented in [CHANGELOG.md](https://github.com/bradygaster/squad/blob/main/CHANGELOG.md). +Breaking changes are documented in [CHANGELOG.md](https://github.com/github/squad/blob/main/CHANGELOG.md). ## Installation @@ -61,12 +61,12 @@ cask or package before switching channels. **macOS or Linux with the verified install script:** ```bash -curl -fsSL https://raw.githubusercontent.com/bradygaster/squad/main/scripts/install.sh | sh +curl -fsSL https://raw.githubusercontent.com/github/squad/main/scripts/install.sh | sh ``` You can also download the archive for your platform directly from -[GitHub Releases](https://github.com/bradygaster/squad/releases/latest). -See [Standalone Install](https://bradygaster.github.io/squad/docs/features/standalone-install/) +[GitHub Releases](https://github.com/github/squad/releases/latest). +See [Standalone Install](https://github.github.com/squad/docs/features/standalone-install/) for checksums, custom install locations, and CI usage. ### Verify Installation @@ -399,9 +399,9 @@ ensure your Node.js version is 22.5 or later. - **Documentation:** [docs.squad.ai](https://docs.squad.ai) - **CLI Reference:** [docs.squad.ai/reference/cli](https://docs.squad.ai/reference/cli) — detailed command docs - **SDK:** [@bradygaster/squad-sdk](https://www.npmjs.com/package/@bradygaster/squad-sdk) — programmatic API -- **GitHub:** [github.com/bradygaster/squad](https://github.com/bradygaster/squad) -- **Issues:** [github.com/bradygaster/squad/issues](https://github.com/bradygaster/squad/issues) +- **GitHub:** [github.com/github/squad](https://github.com/github/squad) +- **Issues:** [github.com/github/squad/issues](https://github.com/github/squad/issues) ## License -MIT. See [LICENSE](https://github.com/bradygaster/squad/blob/main/LICENSE) in the repository root. +MIT. See [LICENSE](https://github.com/github/squad/blob/main/LICENSE) in the repository root. diff --git a/packages/squad-sdk/README.md b/packages/squad-sdk/README.md index 232f972b4..fd45c64f8 100644 --- a/packages/squad-sdk/README.md +++ b/packages/squad-sdk/README.md @@ -144,7 +144,7 @@ await tool.handler({ Agents learn as they work. Next session, Frontend reads this and knows immediately. No context hunting, no re-explaining. -> Two more tools — `squad_status` (query the session pool) and `squad_skill` (read/write compressed learnings) — round out the coordination layer. See the [full docs](https://github.com/bradygaster/squad#the-custom-tools) for details. +> Two more tools — `squad_status` (query the session pool) and `squad_skill` (read/write compressed learnings) — round out the coordination layer. See the [full docs](https://github.com/github/squad#the-custom-tools) for details. --- @@ -354,9 +354,9 @@ When agents complete work, record decisions, or hit errors — Ralph knows. If a ## Links -- **Repository:** [github.com/bradygaster/squad](https://github.com/bradygaster/squad) +- **Repository:** [github.com/github/squad](https://github.com/github/squad) - **CLI package:** [@bradygaster/squad-cli](https://www.npmjs.com/package/@bradygaster/squad-cli) -- **Issues:** [github.com/bradygaster/squad/issues](https://github.com/bradygaster/squad/issues) +- **Issues:** [github.com/github/squad/issues](https://github.com/github/squad/issues) --- diff --git a/samples/autonomous-pipeline/index.ts b/samples/autonomous-pipeline/index.ts index 73727fcc6..edfc1307e 100644 --- a/samples/autonomous-pipeline/index.ts +++ b/samples/autonomous-pipeline/index.ts @@ -455,7 +455,7 @@ function printFinalReport( } console.log(); - console.log(chalk.dim(` Squad SDK v${VERSION} · github.com/bradygaster/squad-pr`)); + console.log(chalk.dim(` Squad SDK v${VERSION} · github.com/github/squad`)); console.log(); } diff --git a/scripts/docs-site-location.mjs b/scripts/docs-site-location.mjs new file mode 100644 index 000000000..3da52fdf5 --- /dev/null +++ b/scripts/docs-site-location.mjs @@ -0,0 +1,248 @@ +/** + * Docs site location contract. + * + * The repository moved from bradygaster/squad to github/squad. GitHub Pages does not redirect + * after a transfer, so the old project site returns 404 and the docs are served from + * https://github.github.com/squad/. GitHub does redirect the old repository URLs, but current + * docs, samples, READMEs and contributor guides name github/squad. Only the historical records + * in HISTORICAL_REPO_LINKS keep their old repository links as written. + * + * This module is the single source of truth for both guards: test/docs-site-location.test.ts + * (root vitest, runs in CI) and the "docs site location" suite in + * docs/tests/astro-features.test.mjs (`node --test` in docs/). It uses Node built-ins only. + */ + +import { execFileSync } from 'node:child_process'; +import { readFileSync, statSync } from 'node:fs'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +export const REPO_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..'); + +export const SITE = 'https://github.github.com'; +export const BASE = '/squad/'; +export const REPO_URL = 'https://github.com/github/squad'; + +/** Settings that place the site. Each `pattern` captures the value and has the `d` flag for line numbers. */ +export const SITE_SETTINGS = [ + { + name: 'Astro site', + file: 'docs/astro.config.mjs', + pattern: /^[ \t]*site:[ \t]*['"`]([^'"`]*)['"`]/dm, + expected: SITE, + }, + { + name: 'Astro base', + file: 'docs/astro.config.mjs', + pattern: /^[ \t]*base:[ \t]*['"`]([^'"`]*)['"`]/dm, + expected: BASE, + }, + { + name: 'RSS site fallback', + file: 'docs/src/pages/rss.xml.js', + pattern: /context\.site\s*\?\?\s*['"`]([^'"`]*)['"`]/d, + expected: `${SITE}${BASE}`, + }, + { + name: 'robots.txt Sitemap', + file: 'docs/public/robots.txt', + pattern: /^Sitemap:[ \t]*(\S+)/dm, + expected: `${SITE}${BASE}sitemap-index.xml`, + }, + { + name: '"Edit this page" URL', + file: 'docs/src/layouts/DocsLayout.astro', + pattern: /const editUrl\s*=\s*currentSlug\s*\?\s*`([^`]*)`/d, + expected: `${REPO_URL}/edit/dev/docs/src/content/docs/\${currentSlug}.md`, + }, +]; + +/** + * A link to the retired project site: `//bradygaster.github.io/squad`, with or without a scheme, + * in any case. `/squad` must end at a path boundary, so `/squadcaster/` is another site. The + * implementation-provenance schema ID (`/squad/schemas/implementation-provenance/v1`) is an + * identifier, not a link, so it is exempt, but only where the version ends the URL. That means + * the version is followed by the end of the line, whitespace, one of ) " ' ` < > ], or a `#` + * fragment, which points into the same schema. A `.` counts only as a sentence end, followed by + * whitespace or the end of the line. Paths below the ID, dotted suffixes such as `v1.json` and + * queries such as `v1?format=json` are links. + */ +export const RETIRED_SITE_LINK = + /(?:https?:)?\/\/bradygaster\.github\.io\/squad(?![\w-])(?!\/schemas\/implementation-provenance\/v\d+(?:[\s)"'`<>\]#]|\.(?:\s|$)|$))[^\s)"'`<>\]]*/gi; + +/** + * A reference to the old repository location, in any case. This covers web and raw file URLs + * (`github.com/bradygaster/squad`, `raw.githubusercontent.com/bradygaster/squad`), the SSH remote + * (`git@github.com:bradygaster/squad`), REST paths (`repos/bradygaster/squad`) and the gh + * `--repo` flag. The name must end at a boundary, so other repositories such as + * `bradygaster/squad-cli` do not match. The `@bradygaster/` npm scope and `bradygaster/squad#NNN` + * work references are not repository locations. + */ +export const OLD_REPO_LINK = + /(?:(?\]]*/gi; + +/** The files the migration covers: docs, samples, READMEs, contributor guides and the PR skill. */ +export const SCANNED_PATHS = [ + 'docs', + 'samples', + 'README.md', + 'README.zh.md', + 'CONTRIBUTING.md', + 'CONTRIBUTORS.md', + 'SUPPORT.md', + 'packages/squad-cli/README.md', + 'packages/squad-sdk/README.md', + '.copilot/skills/pr-lifecycle/SKILL.md', +]; + +/** A numbered pull request, issue or discussion, or a commit: a record of where something happened. */ +const PERMALINK = /^github\.com\/bradygaster\/squad\/(?:(?:pull|issues|discussions)\/\d+|commit\/[0-9a-f]{7,40})(?![\w-])/i; + +/** + * Historical records that keep their old repository links as written. Everything else in the + * scanned files must name github/squad. A `path` ending in `/` covers a directory. An entry can + * narrow what it keeps: + * - `links`: only links matching this (non-global) pattern are history; + * - `section`: only the lines from the `from` marker through the `to` marker (or the end of the + * file) are history. If a marker is missing, nothing in the file is exempt. + * Add an entry only for a record of the past, never for a current instruction or link. + */ +export const HISTORICAL_REPO_LINKS = [ + { + path: 'docs/src/content/blog/', + reason: 'Blog posts are dated narrative and stay as published.', + }, + { + path: 'docs/src/content/docs/whatsnew.md', + reason: 'Release notes for v1.1.0 and earlier are release history; the current 2.0 notes are documentation.', + section: { from: /^## v1\.1\.0\b/ }, + }, + { + path: 'docs/src/content/docs/guide/contributors.md', + reason: 'Contributor credits cite the pull requests, issues and discussions where the work happened.', + links: PERMALINK, + }, + { + path: 'docs/specification/', + reason: 'Working-draft provenance cites the pull requests, issue and commit each draft came from; the Charter text is pinned by SHA-256.', + links: PERMALINK, + }, + { + path: 'docs/src/content/docs/scenarios/upgrading.md', + reason: 'The generated upgrade matrix records the CI runs and GitHub Releases behind its results (rendered from test-fixtures/spec/suite-v0.2/upgrade-matrix.json).', + section: { from: /^/, to: /^/ }, + }, + { + path: 'docs/_internal/launch/migration-announcement.md', + reason: 'Launch announcement from when Squad first went public.', + }, + { + path: 'docs/_internal/prd-cli-polish.md', + reason: 'Product requirements that quote the CLI banner text as it was proposed.', + }, + { + path: 'docs/_internal/proposals/fixed-input-box-design.md', + reason: 'Design proposal with a mock-up of the CLI banner as it was proposed.', + }, +]; + +/** Tracked files under SCANNED_PATHS, repo-relative with `/`, except Astro's generated `.astro/` types. */ +export function scannedFiles(root = REPO_ROOT) { + let listed; + try { + listed = execFileSync('git', ['ls-files', '-z', '--', ...SCANNED_PATHS], { + cwd: root, + encoding: 'utf8', + maxBuffer: 64 * 1024 * 1024, + stdio: ['ignore', 'pipe', 'pipe'], + }); + } catch (error) { + throw new Error(`The docs site location guard lists tracked files with git; run it in a git checkout. ${error.message}`); + } + return listed + .split('\0') + .filter((path) => path && !path.split('/').includes('.astro')) + .sort(); +} + +/** The scanned files as text, without binaries and tracked files missing from the working tree. */ +export function readScannedFiles(root = REPO_ROOT) { + const files = []; + for (const path of scannedFiles(root)) { + const absolute = join(root, path); + let bytes; + try { + if (!statSync(absolute).isFile()) continue; + bytes = readFileSync(absolute); + } catch (error) { + if (error.code === 'ENOENT') continue; + throw error; + } + if (bytes.includes(0)) continue; + files.push({ path, text: bytes.toString('utf8') }); + } + return files; +} + +function lineAt(text, index) { + return text.slice(0, index).split('\n').length; +} + +/** The value `setting.pattern` captures in `setting.file`, and the `file:line` it was read from. */ +export function readSetting(setting, root = REPO_ROOT) { + const text = readFileSync(join(root, setting.file), 'utf8'); + const match = setting.pattern.exec(text); + if (!match) return { value: undefined, at: `${setting.file} (setting not found)` }; + const start = match.indices?.[1]?.[0] ?? match.index; + return { value: match[1], at: `${setting.file}:${lineAt(text, start)}` }; +} + +/** `path:line: link` for every match of the global `pattern` in `files` ({ path, text }[]). */ +export function findLinks(files, pattern) { + const found = []; + for (const { path, text } of files) { + text.split('\n').forEach((line, index) => { + for (const match of line.matchAll(pattern)) found.push(`${path}:${index + 1}: ${match[0]}`); + }); + } + return found; +} + +function covers(entry, path) { + return entry.path.endsWith('/') ? path.startsWith(entry.path) : path === entry.path; +} + +/** The 0-based [first, last] lines `entry` treats as history, or undefined if a marker is missing. */ +function historyLines(entry, lines) { + if (!entry.section) return [0, lines.length - 1]; + const first = lines.findIndex((line) => entry.section.from.test(line)); + if (first === -1) return undefined; + if (!entry.section.to) return [first, lines.length - 1]; + const last = lines.findIndex((line, index) => index > first && entry.section.to.test(line)); + return last === -1 ? undefined : [first, last]; +} + +/** + * Old repository links in `files`, split into `offenders` (`path:line: link`) and `kept`, the + * links each `historical` entry keeps as history. + */ +export function scanOldRepoLinks(files, historical = HISTORICAL_REPO_LINKS) { + const offenders = []; + const kept = new Map(historical.map((entry) => [entry, []])); + for (const { path, text } of files) { + const lines = text.split('\n'); + const history = historical + .filter((entry) => covers(entry, path)) + .map((entry) => ({ entry, range: historyLines(entry, lines) })); + lines.forEach((line, index) => { + for (const [link] of line.matchAll(OLD_REPO_LINK)) { + const at = `${path}:${index + 1}: ${link}`; + const keeper = history.find(({ entry, range }) => + range !== undefined && index >= range[0] && index <= range[1] && (!entry.links || entry.links.test(link))); + if (keeper) kept.get(keeper.entry).push(at); + else offenders.push(at); + } + }); + } + return { offenders, kept }; +} diff --git a/test/ci/docs-quality.test.ts b/test/ci/docs-quality.test.ts new file mode 100644 index 000000000..1d7a5a55f --- /dev/null +++ b/test/ci/docs-quality.test.ts @@ -0,0 +1,62 @@ +/** + * Where CI runs the docs site location guard. + * + * squad-ci.yml routes each pull request by the paths it changes. The `test` job runs `npm test`, + * which includes test/docs-site-location.test.ts, but it is skipped when only docs paths change. + * So `docs-quality` runs the guard's `node --test` suite itself. These tests fail if that step + * goes away, if the suite it runs stops importing the guard, or if docs-quality stops running for + * docs-only pull requests. + */ + +import { readFileSync } from 'node:fs'; +import path, { dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { runInNewContext } from 'node:vm'; +import { parse } from 'yaml'; +import { describe, expect, it } from 'vitest'; + +type Step = { name?: string; uses?: string; run?: string }; +type Job = { if?: string; steps?: Step[] }; +type Workflow = { jobs: Record }; + +const ROOT = path.resolve(dirname(fileURLToPath(import.meta.url)), '..', '..'); +const GUARD_SUITE = 'docs/tests/astro-features.test.mjs'; +const GUARD_COMMAND = `node --test ${GUARD_SUITE}`; +const workflow = parse(readFileSync(path.join(ROOT, '.github', 'workflows', 'squad-ci.yml'), 'utf8')) as Workflow; +const docsQuality = workflow.jobs['docs-quality']; + +/** Evaluates docs-quality's job-level `if:` the way the runner would for this event. */ +function docsQualityRuns(eventName: string, outputs: Record): boolean { + return Boolean(runInNewContext(docsQuality?.if ?? 'true', { + github: { event_name: eventName }, + needs: { changes: { result: 'success', outputs } }, + always: () => true, + cancelled: () => false, + success: () => true, + failure: () => false, + })); +} + +describe('docs-quality runs the docs site location guard', () => { + it(`runs ${GUARD_COMMAND}`, () => { + const commands = (docsQuality?.steps ?? []).map((step) => step.run?.trim() ?? `uses: ${step.uses}`); + + expect(commands, `docs-quality steps in .github/workflows/squad-ci.yml:\n${commands.join('\n')}`).toContain(GUARD_COMMAND); + }); + + it(`${GUARD_SUITE} imports the guard from scripts/docs-site-location.mjs`, () => { + const suite = readFileSync(path.join(ROOT, GUARD_SUITE), 'utf8'); + const imported = suite.match(/import\s*\{([^}]*)\}\s*from\s*'\.\.\/\.\.\/scripts\/docs-site-location\.mjs'/)?.[1] ?? ''; + const names = imported.split(',').map((name) => name.trim()).filter(Boolean); + const guard = ['SITE_SETTINGS', 'readSetting', 'readScannedFiles', 'RETIRED_SITE_LINK', 'findLinks', 'scanOldRepoLinks']; + + expect(guard.filter((name) => !names.includes(name)), `${GUARD_SUITE} imports [${names.join(', ')}]`).toEqual([]); + }); + + it('runs for docs-only pull requests and on push', () => { + const docsOnly = { docs: 'true', code: 'false', workflows: 'false' }; + + expect(docsQualityRuns('pull_request', docsOnly), `docs-quality if: ${docsQuality?.if}`).toBe(true); + expect(docsQualityRuns('push', { docs: 'false', code: 'true', workflows: 'false' }), `docs-quality if: ${docsQuality?.if}`).toBe(true); + }); +}); diff --git a/test/docs-site-location.test.ts b/test/docs-site-location.test.ts new file mode 100644 index 000000000..93bb711f2 --- /dev/null +++ b/test/docs-site-location.test.ts @@ -0,0 +1,268 @@ +/** + * Docs site location guard. + * + * The repository moved from bradygaster/squad to github/squad. GitHub Pages does not redirect + * after a transfer, so https://bradygaster.github.io/squad/ returns 404 and the docs site is + * served from https://github.github.com/squad/. The contract lives in + * scripts/docs-site-location.mjs: the site settings, the retired-site and old-repository link + * patterns, the scanned files and the historical allowlist. docs/tests/astro-features.test.mjs + * enforces the same module under `node --test`. + * + * This file runs the contract in CI and pins it. The expected settings, the pattern examples and + * the allowlist behavior are written out here, so a change to the shared module cannot quietly + * loosen the guard. + */ + +import { describe, it, expect } from 'vitest'; +import { + BASE, + HISTORICAL_REPO_LINKS, + OLD_REPO_LINK, + REPO_URL, + RETIRED_SITE_LINK, + SCANNED_PATHS, + SITE, + SITE_SETTINGS, + findLinks, + readScannedFiles, + readSetting, + scanOldRepoLinks, +} from '../scripts/docs-site-location.mjs'; + +interface ScannedFile { + path: string; + text: string; +} + +let scanned: ScannedFile[] | undefined; +const scannedFiles = (): ScannedFile[] => (scanned ??= readScannedFiles()); + +const matches = (pattern: RegExp, text: string): string[] => [...text.matchAll(pattern)].map((match) => match[0]); + +/** Asserts what `pattern` finds in `text`; a failure names the input and what was found. */ +function expectMatches(pattern: RegExp, text: string, expected: string[]): void { + const found = matches(pattern, text); + expect(found, `${JSON.stringify(text)} -> ${JSON.stringify(found)}, expected ${JSON.stringify(expected)}`).toEqual(expected); +} + +/** Asserts a list of `path:line: link` results; a failure lists what was found and expected. */ +function expectLines(found: string[], expected: string[]): void { + expect(found, `found:\n${found.join('\n')}\nexpected:\n${expected.join('\n')}\n`).toEqual(expected); +} + +/** Current entry points: always scanned, never history. */ +const CURRENT_FILES = [ + 'README.md', + 'README.zh.md', + 'CONTRIBUTING.md', + 'CONTRIBUTORS.md', + 'SUPPORT.md', + 'packages/squad-cli/README.md', + 'packages/squad-sdk/README.md', + '.copilot/skills/pr-lifecycle/SKILL.md', + 'samples/autonomous-pipeline/index.ts', + 'docs/astro.config.mjs', + 'docs/src/components/Header.astro', + 'docs/src/components/Footer.astro', + 'docs/src/pages/index.astro', + 'docs/src/layouts/DocsLayout.astro', + 'docs/src/plugins/remark-rewrite-links.mjs', + 'docs/src/content/docs/community.md', + 'docs/src/content/docs/get-started/installation.md', + 'docs/src/content/docs/guide/contributing.md', +]; + +describe('docs site location (https://github.github.com/squad/)', () => { + it('the shared contract places the site at https://github.github.com/squad/ and the repository at github/squad', () => { + const constants = { SITE, BASE, REPO_URL }; + expect(constants, JSON.stringify(constants)).toEqual({ + SITE: 'https://github.github.com', + BASE: '/squad/', + REPO_URL: 'https://github.com/github/squad', + }); + const settings = Object.fromEntries(SITE_SETTINGS.map((setting) => [setting.name, `${setting.file} = ${setting.expected}`])); + expect(settings, JSON.stringify(settings, null, 2)).toEqual({ + 'Astro site': 'docs/astro.config.mjs = https://github.github.com', + 'Astro base': 'docs/astro.config.mjs = /squad/', + 'RSS site fallback': 'docs/src/pages/rss.xml.js = https://github.github.com/squad/', + 'robots.txt Sitemap': 'docs/public/robots.txt = https://github.github.com/squad/sitemap-index.xml', + '"Edit this page" URL': 'docs/src/layouts/DocsLayout.astro = https://github.com/github/squad/edit/dev/docs/src/content/docs/${currentSlug}.md', + }); + }); + + it.each(SITE_SETTINGS)('$name in $file', (setting) => { + const { value, at } = readSetting(setting); + + expect(value, `${at}: ${setting.name} is ${value}`).toBe(setting.expected); + }); + + it('scans the tracked docs, samples, READMEs and contributor guides', () => { + const paths = scannedFiles().map((file) => file.path); + + const emptyRoots = SCANNED_PATHS.filter((root: string) => !paths.some((path) => path === root || path.startsWith(`${root}/`))); + expect(emptyRoots, `scanned paths with no tracked text files: ${emptyRoots.join(', ')}`).toEqual([]); + const unreached = CURRENT_FILES.filter((path) => !paths.includes(path)); + expect(unreached, `files the scan should have reached: ${unreached.join(', ')}`).toEqual([]); + }); + + it('nothing scanned links to the retired bradygaster.github.io/squad site', () => { + const offenders = findLinks(scannedFiles(), RETIRED_SITE_LINK); + + expect(offenders, `Links to the retired docs site; use https://github.github.com/squad/...:\n${offenders.join('\n')}`) + .toEqual([]); + }); + + it('everything scanned links to github/squad, apart from the historical records in HISTORICAL_REPO_LINKS', () => { + const { offenders } = scanOldRepoLinks(scannedFiles()); + + expect(offenders, [ + 'Links to the old bradygaster/squad repository; use https://github.com/github/squad.', + 'Only records of the past belong in HISTORICAL_REPO_LINKS (scripts/docs-site-location.mjs):', + ...offenders, + ].join('\n')).toEqual([]); + }); + + it('every historical exemption still keeps an old link', () => { + const { kept } = scanOldRepoLinks(scannedFiles()); + const unused = [...kept].filter(([, links]) => links.length === 0).map(([entry]) => entry.path); + + expect(unused, `HISTORICAL_REPO_LINKS entries that keep no old links; remove them: ${unused.join(', ')}`).toEqual([]); + }); + + it('every historical exemption gives its reason', () => { + const unexplained = HISTORICAL_REPO_LINKS.filter((entry: { reason?: string }) => !entry.reason?.trim()).map((entry: { path: string }) => entry.path); + + expect(unexplained, `HISTORICAL_REPO_LINKS entries without a reason: ${unexplained.join(', ')}`).toEqual([]); + }); + + it('no historical exemption covers a current file', () => { + // A permalink is the narrowest form of history, so any entry covering these files would keep it. + const planted = CURRENT_FILES.map((path) => ({ path, text: 'Credit: https://github.com/bradygaster/squad/pull/1\n' })); + const flagged = scanOldRepoLinks(planted).offenders; + const exempted = CURRENT_FILES.filter((path) => !flagged.includes(`${path}:1: github.com/bradygaster/squad/pull/1`)); + + expect(exempted, `current files that HISTORICAL_REPO_LINKS treats as history: ${exempted.join(', ')}`).toEqual([]); + }); +}); + +describe('retired-site pattern', () => { + it.each([ + ['a page link', '[Model Selection](https://bradygaster.github.io/squad/docs/features/model-selection/)', ['https://bradygaster.github.io/squad/docs/features/model-selection/']], + ['a protocol-relative link', 'Docs', ['//bradygaster.github.io/squad/']], + ['the site root in any case, at the end of a line', 'Docs: HTTP://BradyGaster.GitHub.io/Squad', ['HTTP://BradyGaster.GitHub.io/Squad']], + ['a bracketed URL, without the bracket', '[https://bradygaster.github.io/squad/guide/]', ['https://bradygaster.github.io/squad/guide/']], + ['a path under the schema directory', 'https://bradygaster.github.io/squad/schemas/implementation-provenance/', ['https://bradygaster.github.io/squad/schemas/implementation-provenance/']], + ['an unversioned schema path', 'https://bradygaster.github.io/squad/schemas/implementation-provenance/latest', ['https://bradygaster.github.io/squad/schemas/implementation-provenance/latest']], + ['a path below the versioned schema ID', 'https://bradygaster.github.io/squad/schemas/implementation-provenance/v1/../../docs/', ['https://bradygaster.github.io/squad/schemas/implementation-provenance/v1/../../docs/']], + ['a suffixed schema version', 'https://bradygaster.github.io/squad/schemas/implementation-provenance/v1-draft', ['https://bradygaster.github.io/squad/schemas/implementation-provenance/v1-draft']], + ['a .json suffix on the schema version', '[schema](https://bradygaster.github.io/squad/schemas/implementation-provenance/v1.json)', ['https://bradygaster.github.io/squad/schemas/implementation-provenance/v1.json']], + ['a .html suffix on the schema version', 'https://bradygaster.github.io/squad/schemas/implementation-provenance/v1.html', ['https://bradygaster.github.io/squad/schemas/implementation-provenance/v1.html']], + ['a dot after the schema version that does not end a sentence', '[schema](https://bradygaster.github.io/squad/schemas/implementation-provenance/v1.)', ['https://bradygaster.github.io/squad/schemas/implementation-provenance/v1.']], + ['a query on the schema ID', 'https://bradygaster.github.io/squad/schemas/implementation-provenance/v1?format=json', ['https://bradygaster.github.io/squad/schemas/implementation-provenance/v1?format=json']], + ])('matches %s', (_case, text, expected) => { + expectMatches(RETIRED_SITE_LINK, text, expected); + }); + + it.each([ + ['another site whose path starts with squad', 'Another project: https://bradygaster.github.io/squadcaster/'], + ['a hyphenated sibling path', 'https://bradygaster.github.io/squad-legacy/'], + ['the versioned schema ID in prose', 'Schema: `https://bradygaster.github.io/squad/schemas/implementation-provenance/v1`.'], + ['the versioned schema ID in JSON', '"$id": "https://bradygaster.github.io/squad/schemas/implementation-provenance/v12",'], + ['the versioned schema ID at the end of a line', 'schema: https://bradygaster.github.io/squad/schemas/implementation-provenance/v1'], + ['the versioned schema ID ending a sentence', 'The schema ID is https://bradygaster.github.io/squad/schemas/implementation-provenance/v1. It is not a page.'], + ['the versioned schema ID in an autolink', ''], + ['a fragment of the versioned schema ID', '"$ref": "https://bradygaster.github.io/squad/schemas/implementation-provenance/v1#/$defs/goal"'], + ['old-host link text with a new-host target', 'Visit the docs at [bradygaster.github.io/squad](https://github.github.com/squad/).'], + ['the new site', 'https://github.github.com/squad/docs/'], + ])('does not match %s', (_case, text) => { + expectMatches(RETIRED_SITE_LINK, text, []); + }); + + it('names the file and line of each retired-site link', () => { + const text = [ + 'intro', + 'See [Model Selection](https://bradygaster.github.io/squad/docs/features/model-selection/).', + 'Another project: https://bradygaster.github.io/squadcaster/', + 'Docs', + 'Schema: `https://bradygaster.github.io/squad/schemas/implementation-provenance/v1`.', + 'Download the [schema](https://bradygaster.github.io/squad/schemas/implementation-provenance/v1.json).', + ].join('\r\n'); + + expectLines(findLinks([{ path: 'docs/example.md', text }], RETIRED_SITE_LINK), [ + 'docs/example.md:2: https://bradygaster.github.io/squad/docs/features/model-selection/', + 'docs/example.md:4: //bradygaster.github.io/squad/', + 'docs/example.md:6: https://bradygaster.github.io/squad/schemas/implementation-provenance/v1.json', + ]); + }); +}); + +describe('old-repository pattern', () => { + it.each([ + ['a web link', '[Fork](https://github.com/bradygaster/squad)', ['github.com/bradygaster/squad']], + ['a web link in any case', 'https://GitHub.com/BradyGaster/Squad/issues/new', ['GitHub.com/BradyGaster/Squad/issues/new']], + ['a raw file URL', 'curl -fsSL https://raw.githubusercontent.com/bradygaster/squad/main/scripts/install.sh | sh', ['raw.githubusercontent.com/bradygaster/squad/main/scripts/install.sh']], + ['the SSH remote', 'git remote add upstream git@github.com:bradygaster/squad.git', ['github.com:bradygaster/squad.git']], + ['a REST path', 'curl https://api.github.com/repos/bradygaster/squad/releases', ['repos/bradygaster/squad/releases']], + ['the gh --repo flag', 'gh pr create --base dev --repo bradygaster/squad --head me:branch', ['--repo bradygaster/squad']], + ['the gh --repo= flag', 'gh issue list --repo=bradygaster/squad', ['--repo=bradygaster/squad']], + ])('matches %s', (_case, text, expected) => { + expectMatches(OLD_REPO_LINK, text, expected); + }); + + it.each([ + ['the npm scope', 'npm install -g @bradygaster/squad-cli@insider'], + ['another repository whose name starts with squad', 'https://github.com/bradygaster/squadron'], + ['a work reference', 'Ported from bradygaster/squad#131'], + ['a look-alike host', 'https://mygithub.com/bradygaster/squad'], + ['the new repository', 'git remote add upstream git@github.com:github/squad.git && gh pr create --repo github/squad'], + ])('does not match %s', (_case, text) => { + expectMatches(OLD_REPO_LINK, text, []); + }); + + it('keeps only documented history, and names the file and line of everything else', () => { + const old = 'https://github.com/bradygaster/squad'; + const files = [ + { path: 'docs/src/content/blog/021-the-migration.md', text: `Old home: ${old}/blob/main/README.md` }, + { path: 'docs/src/content/docs/community.md', text: `intro\nStar us: ${old}` }, + { path: 'docs/src/content/docs/guide/contributors.md', text: `- [#298](${old}/pull/298)\nSee ${old}/blob/main/CONTRIBUTING.md` }, + { path: 'docs/specification/core-v0.1.md', text: `Provenance: [PR #2074](${old}/pull/2074)\nReference implementation: ${old}` }, + { path: 'docs/src/content/docs/whatsnew.md', text: `## v2.0.0\nFixed (${old}/pull/2279)\n## v1.1.0 — Stable Release\nPorted ([PR #131](${old}/pull/131))` }, + { + path: 'docs/src/content/docs/scenarios/upgrading.md', + text: `Report at ${old}/issues\n\n| [run](${old}/actions/runs/1) |\n\nAfter: ${old}/releases`, + }, + ]; + + const { offenders, kept } = scanOldRepoLinks(files); + + expectLines(offenders, [ + 'docs/src/content/docs/community.md:2: github.com/bradygaster/squad', + 'docs/src/content/docs/guide/contributors.md:2: github.com/bradygaster/squad/blob/main/CONTRIBUTING.md', + 'docs/specification/core-v0.1.md:2: github.com/bradygaster/squad', + 'docs/src/content/docs/whatsnew.md:2: github.com/bradygaster/squad/pull/2279', + 'docs/src/content/docs/scenarios/upgrading.md:1: github.com/bradygaster/squad/issues', + 'docs/src/content/docs/scenarios/upgrading.md:5: github.com/bradygaster/squad/releases', + ]); + const keptByEntry = Object.fromEntries([...kept].filter(([, links]) => links.length > 0).map(([entry, links]) => [entry.path, links])); + expect(keptByEntry, `kept:\n${JSON.stringify(keptByEntry, null, 2)}`).toEqual({ + 'docs/src/content/blog/': ['docs/src/content/blog/021-the-migration.md:1: github.com/bradygaster/squad/blob/main/README.md'], + 'docs/specification/': ['docs/specification/core-v0.1.md:1: github.com/bradygaster/squad/pull/2074'], + 'docs/src/content/docs/guide/contributors.md': ['docs/src/content/docs/guide/contributors.md:1: github.com/bradygaster/squad/pull/298'], + 'docs/src/content/docs/whatsnew.md': ['docs/src/content/docs/whatsnew.md:4: github.com/bradygaster/squad/pull/131'], + 'docs/src/content/docs/scenarios/upgrading.md': ['docs/src/content/docs/scenarios/upgrading.md:3: github.com/bradygaster/squad/actions/runs/1'], + }); + }); + + it('exempts nothing in a file whose history marker is missing', () => { + const old = 'https://github.com/bradygaster/squad'; + const files = [ + { path: 'docs/src/content/docs/whatsnew.md', text: `## v2.0.0\nPorted ([PR #131](${old}/pull/131))` }, + { path: 'docs/src/content/docs/scenarios/upgrading.md', text: `\n| [run](${old}/actions/runs/1) |` }, + ]; + + expectLines(scanOldRepoLinks(files).offenders, [ + 'docs/src/content/docs/whatsnew.md:2: github.com/bradygaster/squad/pull/131', + 'docs/src/content/docs/scenarios/upgrading.md:2: github.com/bradygaster/squad/actions/runs/1', + ]); + }); +});