diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 531be004..07d98297 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -22,7 +22,7 @@ A clear and concise description of what you expected to happen. **Environment (please complete the following information):** - OS: [e.g. macOS, Linux, Windows] - Python Version: [e.g. 3.12.0] - - APM-CLI Version: [e.g. 0.1.0] + - APM Version: [e.g. 0.1.0] - VSCode Version (if relevant): [e.g. 1.80.0] **Logs** diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index b45f9a08..73a1139b 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -4,10 +4,10 @@ For better guidance, consider using our specialized templates: -- **πŸš€ New Feature**: [Create Feature PR](https://github.com/danielmeppiel/apm/compare/main...HEAD?template=feature.md) -- **πŸ› Bug Fix**: [Create Bug Fix PR](https://github.com/danielmeppiel/apm/compare/main...HEAD?template=bugfix.md) -- **πŸ“– Documentation**: [Create Docs PR](https://github.com/danielmeppiel/apm/compare/main...HEAD?template=documentation.md) -- **πŸ”§ Maintenance**: [Create Maintenance PR](https://github.com/danielmeppiel/apm/compare/main...HEAD?template=maintenance.md) +- **πŸš€ New Feature**: [Create Feature PR](https://github.com/microsoft/apm/compare/main...HEAD?template=feature.md) +- **πŸ› Bug Fix**: [Create Bug Fix PR](https://github.com/microsoft/apm/compare/main...HEAD?template=bugfix.md) +- **πŸ“– Documentation**: [Create Docs PR](https://github.com/microsoft/apm/compare/main...HEAD?template=documentation.md) +- **πŸ”§ Maintenance**: [Create Maintenance PR](https://github.com/microsoft/apm/compare/main...HEAD?template=maintenance.md) ## Description diff --git a/.github/release.yml b/.github/release.yml index f9d65bce..ffaadb31 100644 --- a/.github/release.yml +++ b/.github/release.yml @@ -1,4 +1,4 @@ -# .danielmeppiel/release.yml +# .microsoft/release.yml changelog: exclude: labels: diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index 35f4a02a..b243e3c3 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -517,7 +517,7 @@ jobs: uses: peter-evans/repository-dispatch@v3 with: token: ${{ secrets.GH_PKG_PAT }} - repository: danielmeppiel/homebrew-apm + repository: microsoft/homebrew-apm event-type: formula-update client-payload: | { diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6fcb9f0e..2b1f6433 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ -# Contributing to apm-cli +# Contributing to APM -Thank you for considering contributing to apm-cli! This document outlines the process for contributing to the project. +Thank you for considering contributing to APM! This document outlines the process for contributing to the project. ## Code of Conduct @@ -12,7 +12,7 @@ By participating in this project, you agree to abide by our [Code of Conduct](CO Before submitting a bug report: -1. Check the [GitHub Issues](https://github.com/username/apm-cli/issues) to see if the bug has already been reported. +1. Check the [GitHub Issues](https://github.com/microsoft/apm/issues) to see if the bug has already been reported. 2. Update your copy of the code to the latest version to ensure the issue hasn't been fixed. When submitting a bug report: diff --git a/README.md b/README.md index a8b40bfa..242d89cb 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # APM – Agent Package Manager [![PyPI version](https://badge.fury.io/py/apm-cli.svg)](https://badge.fury.io/py/apm-cli) -[![CI/CD Pipeline](https://github.com/danielmeppiel/apm/actions/workflows/build-release.yml/badge.svg)](https://github.com/danielmeppiel/apm/actions/workflows/build-release.yml) +[![CI/CD Pipeline](https://github.com/microsoft/apm/actions/workflows/build-release.yml/badge.svg)](https://github.com/microsoft/apm/actions/workflows/build-release.yml) [![Downloads](https://img.shields.io/pypi/dm/apm-cli.svg)](https://pypi.org/project/apm-cli/) -[![GitHub stars](https://img.shields.io/github/stars/danielmeppiel/apm.svg?style=social&label=Star)](https://github.com/danielmeppiel/apm/stargazers) +[![GitHub stars](https://img.shields.io/github/stars/microsoft/apm.svg?style=social&label=Star)](https://github.com/microsoft/apm/stargazers) **An open-source, community-driven dependency manager for AI agents.** `apm.yml` declares the skills, prompts, instructions, and tools your project needs β€” so every developer gets the same agent setup. Packages can depend on packages, and APM resolves the full tree. @@ -21,25 +21,30 @@ AI coding agents need context to be useful: what standards to follow, what promp ```yaml # apm.yml β€” ships with your project, like package.json -name: corporate-website +name: your project dependencies: apm: - - danielmeppiel/form-builder # Skills: React Hook Form + Zod - - danielmeppiel/compliance-rules # Guardrails: GDPR, security audits - - danielmeppiel/design-guidelines # Standards: UI consistency, a11y + # Skills from any repository + - anthropics/skills/skills/frontend-design + - microsoft/GitHub-Copilot-for-Azure/plugin/skills/azure-compliance + # A full APM package with rules, skills, prompts... + - microsoft/apm-sample-package + # Specific agent primitives from any repository + - github/awesome-copilot/skills/review-and-refactor + - github/awesome-copilot/agents/api-architect.agent.md ``` New developer joins the team: ```bash -git clone your-org/corporate-website -cd corporate-website -apm install && apm compile +git clone +cd +apm install ``` -**That's it.** Copilot, Claude, Cursor β€” every agent is configured with the right skills, prompts, and coding standards. No wiki. No "ask Sarah which skills to install." It just works. +**That's it.** Copilot, Claude, Cursor β€” every agent is configured with the right skills, prompts, and coding standards. -β†’ [View the full example project](https://github.com/danielmeppiel/corporate-website) +β†’ [View the full example project](https://github.com/microsoft/apm-project-sample) ## Not Just Skills @@ -63,42 +68,41 @@ All declared in one manifest. All installed with one command β€” including trans **1. Install APM** ```bash -curl -sSL https://raw.githubusercontent.com/danielmeppiel/apm/main/install.sh | sh +curl -sSL https://raw.githubusercontent.com/microsoft/apm/main/install.sh | sh ```
Homebrew or pip ```bash -brew tap danielmeppiel/apm-cli && brew install apm-cli +brew install microsoft/apm/apm # or pip install apm-cli ```
-**2. Add packages to your project** +**2. Add APM packages to your project** ```bash -apm install danielmeppiel/compliance-rules +apm install microsoft/apm-sample-package +apm install anthropics/skills/skills/frontend-design +apm install github/awesome-copilot/agents/api-architect.agent.md ``` -> No `apm.yml` yet? APM creates one automatically on first install. - -**3. Compile your instructions** - -```bash -apm compile -``` - -**Done.** Your instructions are compiled into AGENTS.md and CLAUDE.md β€” open your project in VS Code or Claude and your agents are ready. +**Done.** Open your project in VS Code or Claude and your AI tools are ready. ## Install From Anywhere ```bash -apm install owner/repo # GitHub -apm install github/awesome-copilot/prompts/code-review.prompt.md # Single file -apm install ghe.company.com/owner/repo # GitHub Enterprise -apm install dev.azure.com/org/project/repo # Azure DevOps +# GitHub Repo or Path +apm install owner/repo +apm install owner/repo/path +# Single file +apm install github/awesome-copilot/skills/review-and-refactor +# GitHub Enterprise Server +apm install ghe.company.com/owner/repo +# Azure DevOps +apm install dev.azure.com/org/project/repo ``` ## Create & Share Packages @@ -113,6 +117,7 @@ my-standards/ └── .apm/ β”œβ”€β”€ instructions/ # Guardrails (.instructions.md) β”œβ”€β”€ prompts/ # Slash commands (.prompt.md) + β”œβ”€β”€ skills/ # Agent Skills (SKILL.md) └── agents/ # Personas (.agent.md) ``` @@ -158,18 +163,16 @@ For private repos or Azure DevOps, set a token: --- -## Community Packages +## APM Packages APM installs from any GitHub or Azure DevOps repo β€” no special packaging required. Point at a prompt file, a skill, or a full package. These are some curated packages to get you started: | Package | What you get | |---------|-------------| -| [danielmeppiel/compliance-rules](https://github.com/danielmeppiel/compliance-rules) | `/gdpr-assessment`, `/security-audit` + compliance guardrails | -| [danielmeppiel/design-guidelines](https://github.com/danielmeppiel/design-guidelines) | `/accessibility-audit`, `/design-review` + UI standards | -| [DevExpGbb/platform-mode](https://github.com/DevExpGbb/platform-mode) | Platform engineering prompts & agents | -| [github/awesome-copilot](https://github.com/github/awesome-copilot) | Community prompts, agents & instructions for Copilot | -| [anthropics/courses](https://github.com/anthropics/courses) | Anthropic's official skills & prompt library | -| [Add yours β†’](https://github.com/danielmeppiel/apm/discussions/new) | | +| [github/awesome-copilot](https://github.com/github/awesome-copilot) | Community prompts, agents & instructions for GitHub Copilot | +| [anthropics/courses](https://github.com/anthropics/courses) | Anthropic's official prompt engineering courses | +| [microsoft/GitHub-Copilot-for-Azure](https://github.com/microsoft/GitHub-Copilot-for-Azure/tree/main/plugin/skills) | Azure Skills | +| [Add yours β†’](https://github.com/microsoft/apm/discussions/new) | | --- diff --git a/docs/DEMO.md b/docs/DEMO.md deleted file mode 100644 index a3171970..00000000 --- a/docs/DEMO.md +++ /dev/null @@ -1,199 +0,0 @@ -# APM 0.7.0 Demo Script: "Skills + Guardrails in 90 Seconds" - ---- - -## Opening Hook (5 seconds) - -> "What if you could give any AI coding agent new superpowers β€” AND keep it compliant β€” with one command?" - ---- - -## Act 1: The Problem (15 seconds) - -**Scene:** Empty project folder, terminal open. - -> "You've got a corporate website to build. You want your AI agent to know how to build forms β€” BUT also follow GDPR rules. Today that means copy-pasting examples, configuring each tool separately, hoping the agent doesn't cut corners on compliance..." - -**Visual:** Show scattered files, manual copy-paste, inconsistent outputs. - ---- - -## Act 2: One Command, Native Skills (30 seconds) - -**Scene:** Terminal in fresh project. - -```bash -# Start fresh -mkdir corporate-website && cd corporate-website -apm init demo - -# Install a skill β€” give your agent form-building powers -apm install danielmeppiel/form-builder -``` - -**Narration:** -> "APM 0.7.0 brings native Agent Skills support. One command. The skill installs to `.github/skills/` β€” the standard location that works with Copilot, Claude, Cursor, and more." - -**Key Visual:** Show terminal output: -``` -βœ“ danielmeppiel/form-builder - └─ Skill integrated β†’ .github/skills/ -``` - -**Then show the folder structure:** -```bash -tree .github/skills/ -``` -``` -.github/skills/ -└── form-builder/ - β”œβ”€β”€ SKILL.md - β”œβ”€β”€ .apm/instructions/ - └── examples/ -``` - -> "No transformation. No config. Native agentskills.io format with React Hook Form and Zod validation patterns." - ---- - -## Act 3: Layer Guardrails on Top (25 seconds) - -**Scene:** Same project. - -```bash -# Now add corporate guardrails -apm install danielmeppiel/compliance-rules - -# Compile everything -apm compile -``` - -**Narration:** -> "But skills alone aren't enough. Your agent also needs guardrails β€” GDPR compliance, data minimization, audit trails. APM compiles these into AGENTS.md, the open standard for agent instructions." - -**Key Visual:** Show the compile output: -``` -Generated 1 AGENTS.md file -β”œβ”€ Context efficiency: 85% -└─ Sources: form-builder, compliance-rules -``` - -**Then show AGENTS.md:** -```bash -head -30 AGENTS.md -``` - -> "Skills give agents capabilities. Guardrails give agents boundaries. APM gives you both." - ---- - -## Act 4: The Magic Moment (15 seconds) - -**Scene:** VSCode/Copilot Chat open. - -**Prompt:** "Build a contact form" - -**Narration:** -> "Watch this. I ask for a contact form. The agent uses form-builder patterns β€” React Hook Form, Zod validation, accessible markup. But it ALSO adds the GDPR consent checkbox. Because compliance-rules require it." - -**Visual:** Show generated code with both form patterns AND consent checkbox. - -> "The skill gave it the power. The guardrail kept it compliant. One package manager. Native formats." - ---- - -## Closing: The Standards Stack (10 seconds) - -**Scene:** Terminal with the full apm.yml visible. - -```yaml -# apm.yml -dependencies: - apm: - - danielmeppiel/form-builder # Skill: what agents CAN DO - - danielmeppiel/compliance-rules # Guardrail: what agents MUST FOLLOW -``` - -> "APM 0.7.0 β€” built on open standards: AGENTS.md for instructions, agentskills.io for skills. Install once, use everywhere." - ---- - -## Commands to Reproduce - -```bash -# 1. Fresh start -cd /tmp && rm -rf demo-project -mkdir demo-project && cd demo-project - -# 2. Initialize APM project -apm init demo - -# 3. Install a skill (capability) -apm install danielmeppiel/form-builder - -# 4. Show skill structure -tree .github/skills/ -cat .github/skills/form-builder/SKILL.md | head -40 - -# 5. Install guardrails -apm install danielmeppiel/compliance-rules - -# 6. Compile to AGENTS.md -apm compile - -# 7. Show the tension in action -cat AGENTS.md | grep -A5 "GDPR\|consent\|form" -``` - ---- - -## Key Narrative Beats - -| Moment | Message | Emotion | -|--------|---------|---------| -| Hook | "Superpowers AND compliance" | Curiosity | -| Problem | "Forms that cut corners on GDPR" | Pain recognition | -| Skill Install | "React Hook Form + Zod, native format" | Relief | -| Guardrails | "Capabilities + Boundaries" | Aha moment | -| Magic | "Consent checkbox appeared automatically" | Delight | -| Close | "Skills + Guardrails = Real AI governance" | Trust | - ---- - -## The "Tension" Visual - -``` -User: "Build a contact form" - -β”Œβ”€ form-builder (Skill) ───────────────────────┐ -β”‚ βœ“ React Hook Form for controlled inputs β”‚ -β”‚ βœ“ Zod schema for validation β”‚ -β”‚ βœ“ Loading states, error handling β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - ↓ constrained by ↓ -β”Œβ”€ compliance-rules (Guardrail) ───────────────┐ -β”‚ βœ“ GDPR consent checkbox required β”‚ -β”‚ βœ“ Data minimization (only needed fields) β”‚ -β”‚ βœ“ Audit logging for submissions β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - -Result: Production-ready, GDPR-compliant form -``` - ---- - -## Alternate Packages to Demo - -| Audience | Skill | Guardrail | -|----------|-------|-----------| -| Web developers | `danielmeppiel/form-builder` | `danielmeppiel/compliance-rules` | -| Enterprise buyers | `danielmeppiel/form-builder` | `danielmeppiel/design-guidelines` | -| Full stack | Both compliance + design | Multiple guardrails stacking | - ---- - -## Live Demo Repository - -Point viewers to: **[github.com/danielmeppiel/corporate-website](https://github.com/danielmeppiel/corporate-website)** - -> "This is a real project using APM with form-builder skill and compliance guardrails. Clone it, run `apm install && apm compile`, see it work." diff --git a/docs/apm-demo.gif b/docs/apm-demo.gif deleted file mode 100644 index 1c166688..00000000 Binary files a/docs/apm-demo.gif and /dev/null differ diff --git a/docs/cli-reference.md b/docs/cli-reference.md index 3f7d31c4..c124c291 100644 --- a/docs/cli-reference.md +++ b/docs/cli-reference.md @@ -10,7 +10,7 @@ export GITHUB_APM_PAT=your_fine_grained_token_here # Optional: export GITHUB_TOKEN=your_models_token # For Codex CLI with GitHub Models # 2. Install APM CLI (GitHub org members) -curl -sSL https://raw.githubusercontent.com/danielmeppiel/apm/main/install.sh | sh +curl -sSL https://raw.githubusercontent.com/microsoft/apm/main/install.sh | sh # 3. Setup runtime apm runtime setup copilot @@ -26,26 +26,26 @@ apm compile && apm run start --param name="" ### Quick Install (Recommended) ```bash -curl -sSL https://raw.githubusercontent.com/danielmeppiel/apm/main/install.sh | sh +curl -sSL https://raw.githubusercontent.com/microsoft/apm/main/install.sh | sh ``` ### Manual Download -Download from [GitHub Releases](https://github.com/danielmeppiel/apm/releases/latest): +Download from [GitHub Releases](https://github.com/microsoft/apm/releases/latest): ```bash # Linux x86_64 -curl -L https://github.com/danielmeppiel/apm/releases/latest/download/apm-linux-x86_64 -o apm && chmod +x apm +curl -L https://github.com/microsoft/apm/releases/latest/download/apm-linux-x86_64 -o apm && chmod +x apm # macOS Intel -curl -L https://github.com/danielmeppiel/apm/releases/latest/download/apm-darwin-x86_64 -o apm && chmod +x apm +curl -L https://github.com/microsoft/apm/releases/latest/download/apm-darwin-x86_64 -o apm && chmod +x apm # macOS Apple Silicon -curl -L https://github.com/danielmeppiel/apm/releases/latest/download/apm-darwin-arm64 -o apm && chmod +x apm +curl -L https://github.com/microsoft/apm/releases/latest/download/apm-darwin-arm64 -o apm && chmod +x apm ``` ### From Source (Developers) ```bash -git clone https://github.com/danielmeppiel/apm-cli.git -cd apm-cli && pip install -e . +git clone https://github.com/microsoft/apm.git +cd apm && pip install -e . ``` ## Global Options @@ -133,7 +133,7 @@ apm install [PACKAGES...] [OPTIONS] apm install # Install ONLY this package (not others in apm.yml) -apm install danielmeppiel/design-guidelines +apm install microsoft/apm-sample-package # Add multiple packages and install apm install org/pkg1 org/pkg2 @@ -171,7 +171,7 @@ apm install --exclude codex - **Virtual Packages**: Single files or collections installed directly from URLs - Single `.prompt.md` or `.agent.md` files from any GitHub repository - Collections from curated sources (e.g., `github/awesome-copilot`) - - Example: `apm install github/awesome-copilot/prompts/code-review.prompt.md` + - Example: `apm install github/awesome-copilot/skills/review-and-refactor` - **MCP Dependencies**: Model Context Protocol servers for runtime integration **Working Example with Dependencies:** @@ -181,8 +181,8 @@ name: my-compliance-project version: 1.0.0 dependencies: apm: - - danielmeppiel/compliance-rules # GDPR, legal review workflows - - danielmeppiel/design-guidelines # Accessibility, UI standards + - microsoft/apm-sample-package # Design standards, prompts + - github/awesome-copilot/skills/review-and-refactor # Code review skill mcp: - github/github-mcp-server ``` @@ -233,7 +233,7 @@ Skills are copied directly to target directories: **Example Integration Output**: ``` -βœ“ danielmeppiel/design-guidelines +βœ“ microsoft/apm-sample-package β”œβ”€ 3 prompts integrated β†’ .github/prompts/ └─ 3 commands integrated β†’ .claude/commands/ ``` @@ -258,10 +258,10 @@ apm uninstall PACKAGE [OPTIONS] **Examples:** ```bash # Uninstall a package -apm uninstall danielmeppiel/design-guidelines +apm uninstall microsoft/apm-sample-package # Preview what would be removed -apm uninstall danielmeppiel/design-guidelines --dry-run +apm uninstall microsoft/apm-sample-package --dry-run ``` **What Gets Removed:** @@ -323,7 +323,7 @@ This check is non-blocking and cached to avoid slowing down the CLI. **Manual Update:** If the automatic update fails, you can always update manually: ```bash -curl -sSL https://raw.githubusercontent.com/danielmeppiel/apm/main/install.sh | sh +curl -sSL https://raw.githubusercontent.com/microsoft/apm/main/install.sh | sh ``` ### `apm deps` - πŸ”— Manage APM package dependencies diff --git a/docs/dependencies.md b/docs/dependencies.md index 9141156e..070780c8 100644 --- a/docs/dependencies.md +++ b/docs/dependencies.md @@ -17,10 +17,10 @@ APM supports multiple dependency types: | Type | Detection | Example | |------|-----------|---------| -| **APM Package** | Has `apm.yml` | `danielmeppiel/compliance-rules` | +| **APM Package** | Has `apm.yml` | `microsoft/apm-sample-package` | | **Claude Skill** | Has `SKILL.md` (no `apm.yml`) | `ComposioHQ/awesome-claude-skills/brand-guidelines` | | **Virtual Subdirectory Package** | Folder path in monorepo | `ComposioHQ/awesome-claude-skills/mcp-builder` | -| **Virtual File Package** | Single file path | `github/awesome-copilot/prompts/code-review.prompt.md` | +| **Virtual Subdirectory Package** | Folder path in repo | `github/awesome-copilot/skills/review-and-refactor` | | **ADO Package** | Azure DevOps repo | `dev.azure.com/org/project/_git/repo` | **Virtual Subdirectory Packages** are skill folders from monorepos - they download an entire folder and may contain a SKILL.md plus resources. @@ -57,7 +57,7 @@ Skill folders use the **source folder name directly** (not flattened paths): .github/skills/ β”œβ”€β”€ brand-guidelines/ # From ComposioHQ/awesome-claude-skills/brand-guidelines β”œβ”€β”€ mcp-builder/ # From ComposioHQ/awesome-claude-skills/mcp-builder -└── compliance-rules/ # From danielmeppiel/compliance-rules +└── apm-sample-package/ # From microsoft/apm-sample-package ``` β†’ See [Skills Guide](skills.md) for complete documentation. @@ -73,8 +73,8 @@ name: my-project version: 1.0.0 dependencies: apm: - - danielmeppiel/compliance-rules # GDPR, legal review workflows - - danielmeppiel/design-guidelines # Accessibility, UI standards + - microsoft/apm-sample-package # Design standards, prompts + - github/awesome-copilot/skills/review-and-refactor # Code review skill mcp: - io.github.github/github-mcp-server ``` @@ -102,7 +102,7 @@ apm deps list apm deps tree # Get package details -apm deps info compliance-rules +apm deps info apm-sample-package ``` ### 4. Use Dependencies in Compilation @@ -152,55 +152,46 @@ If authentication fails, you'll see an error with guidance on token setup. ## Real-World Example: Corporate Website Project -This example shows how APM dependencies enable powerful layered functionality by combining multiple specialized packages. The company website project uses both [danielmeppiel/compliance-rules](https://github.com/danielmeppiel/compliance-rules) and [danielmeppiel/design-guidelines](https://github.com/danielmeppiel/design-guidelines) to supercharge development workflows: +This example shows how APM dependencies enable powerful layered functionality by combining multiple specialized packages. The company website project uses [microsoft/apm-sample-package](https://github.com/microsoft/apm-sample-package) as a full APM package and individual prompts from [github/awesome-copilot](https://github.com/github/awesome-copilot) to supercharge development workflows: ```yaml # company-website/apm.yml name: company-website version: 1.0.0 -description: Corporate website with compliance and design standards +description: Corporate website with design standards and code review dependencies: apm: - - danielmeppiel/compliance-rules - - danielmeppiel/design-guidelines + - microsoft/apm-sample-package + - github/awesome-copilot/skills/review-and-refactor mcp: - io.github.github/github-mcp-server scripts: - # Compliance workflows - audit: "codex --skip-git-repo-check compliance-audit.prompt.md" - gdpr-check: "codex --skip-git-repo-check gdpr-assessment.prompt.md" - legal-review: "codex --skip-git-repo-check legal-review.prompt.md" - # Design workflows design-review: "codex --skip-git-repo-check design-review.prompt.md" accessibility: "codex --skip-git-repo-check accessibility-audit.prompt.md" - style-check: "codex --skip-git-repo-check style-guide-check.prompt.md" ``` ### Package Contributions The combined packages provide comprehensive coverage: -**[compliance-rules](https://github.com/danielmeppiel/compliance-rules) contributes:** -- **Agent Workflows**: `compliance-audit.prompt.md`, `gdpr-assessment.prompt.md`, `legal-review.prompt.md` -- **Context Files**: `.apm/context/legal-compliance.context.md` - Legal compliance framework and requirements -- **Instructions**: `.apm/instructions/compliance.instructions.md` - Compliance checking guidelines -- **Chat Modes**: `.apm/chatmodes/legal-compliance.chatmode.md` - Interactive legal consultation mode +**[apm-sample-package](https://github.com/microsoft/apm-sample-package) contributes:** +- **Agent Workflows**: `.apm/prompts/design-review.prompt.md`, `.apm/prompts/accessibility-audit.prompt.md` +- **Instructions**: `.apm/instructions/design-standards.instructions.md` - Design guidelines +- **Agents**: `.apm/agents/design-reviewer.agent.md` - Design review persona +- **Skills**: `.apm/skills/style-checker/SKILL.md` - Style checking capability -**[design-guidelines](https://github.com/danielmeppiel/design-guidelines) contributes:** -- **Agent Workflows**: `design-review.prompt.md`, `accessibility-audit.prompt.md`, `style-guide-check.prompt.md` -- **Context Files**: `.apm/context/design-system.context.md` - Design system specifications and standards -- **Instructions**: `.apm/instructions/design-standards.instructions.md` - UI/UX design guidelines and best practices +**[github/awesome-copilot](https://github.com/github/awesome-copilot) virtual packages contribute:** +- **Prompts**: Individual prompt files installed via virtual package references ### Compounding Benefits When both packages are installed, your project gains: -- **Legal compliance** validation for all code changes - **Accessibility audit** capabilities for web components - **Design system enforcement** with automated style checking -- **GDPR assessment** workflows for data handling -- **Rich context** about legal requirements AND design standards +- **Code review** workflows from community prompts +- **Rich context** about design standards ## Dependency Resolution @@ -243,34 +234,31 @@ Based on the actual structure of our real-world examples: ``` my-project/ β”œβ”€β”€ apm_modules/ # Dependency installation directory -β”‚ β”œβ”€β”€ compliance-rules/ # From danielmeppiel/compliance-rules -β”‚ β”‚ β”œβ”€β”€ .apm/ -β”‚ β”‚ β”‚ β”œβ”€β”€ instructions/ -β”‚ β”‚ β”‚ β”‚ └── compliance.instructions.md -β”‚ β”‚ β”‚ β”œβ”€β”€ context/ -β”‚ β”‚ β”‚ β”‚ └── legal-compliance.context.md -β”‚ β”‚ β”‚ └── chatmodes/ -β”‚ β”‚ β”‚ └── legal-compliance.chatmode.md -β”‚ β”‚ β”œβ”€β”€ compliance-audit.prompt.md # Agent workflows in root -β”‚ β”‚ β”œβ”€β”€ gdpr-assessment.prompt.md -β”‚ β”‚ β”œβ”€β”€ legal-review.prompt.md -β”‚ β”‚ └── apm.yml -β”‚ └── design-guidelines/ # From danielmeppiel/design-guidelines -β”‚ β”œβ”€β”€ .apm/ -β”‚ β”‚ β”œβ”€β”€ instructions/ -β”‚ β”‚ β”‚ └── design-standards.instructions.md -β”‚ β”‚ └── context/ -β”‚ β”‚ └── design-system.context.md -β”‚ β”œβ”€β”€ accessibility-audit.prompt.md # Agent workflows in root -β”‚ β”œβ”€β”€ design-review.prompt.md -β”‚ β”œβ”€β”€ style-guide-check.prompt.md -β”‚ └── apm.yml +β”‚ β”œβ”€β”€ microsoft/ +β”‚ β”‚ └── apm-sample-package/ # From microsoft/apm-sample-package +β”‚ β”‚ β”œβ”€β”€ .apm/ +β”‚ β”‚ β”‚ β”œβ”€β”€ instructions/ +β”‚ β”‚ β”‚ β”‚ └── design-standards.instructions.md +β”‚ β”‚ β”‚ β”œβ”€β”€ prompts/ +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ design-review.prompt.md +β”‚ β”‚ β”‚ β”‚ └── accessibility-audit.prompt.md +β”‚ β”‚ β”‚ β”œβ”€β”€ agents/ +β”‚ β”‚ β”‚ β”‚ └── design-reviewer.agent.md +β”‚ β”‚ β”‚ └── skills/ +β”‚ β”‚ β”‚ └── style-checker/SKILL.md +β”‚ β”‚ └── apm.yml +β”‚ └── github/ +β”‚ └── awesome-copilot/ # Virtual subdirectory from github/awesome-copilot +β”‚ └── skills/ +β”‚ └── review-and-refactor/ +β”‚ β”œβ”€β”€ SKILL.md +β”‚ └── apm.yml β”œβ”€β”€ .apm/ # Local context (highest priority) β”œβ”€β”€ apm.yml # Project configuration └── .gitignore # Manually add apm_modules/ to ignore ``` -**Note**: These repositories store agent workflows (`.prompt.md` files) in the root directory, while context files, instructions, and chat modes are organized under `.apm/` subdirectories. +**Note**: Full APM packages store primitives under `.apm/` subdirectories. Virtual file packages extract individual files from monorepos like `github/awesome-copilot`. ## Advanced Scenarios @@ -281,8 +269,8 @@ Specify specific branches, tags, or commits for dependency versions: ```yaml dependencies: apm: - - danielmeppiel/compliance-rules#v2.1.0 # Specific tag - - danielmeppiel/design-guidelines#main # Specific branch + - github/awesome-copilot/skills/review-and-refactor#v2.1.0 # Specific tag + - microsoft/apm-sample-package#main # Specific branch - company/internal-standards#abc123 # Specific commit ``` @@ -293,7 +281,7 @@ dependencies: apm deps update # Update specific dependency -apm deps update compliance-rules +apm deps update apm-sample-package # Install with updates (equivalent to update) apm install --update @@ -312,19 +300,19 @@ lockfile_version: "1.0" generated_at: "2026-01-22T10:30:00Z" apm_version: "0.8.0" dependencies: - danielmeppiel/compliance-rules: - repo_url: "https://github.com/danielmeppiel/compliance-rules" + microsoft/apm-sample-package: + repo_url: "https://github.com/microsoft/apm-sample-package" resolved_commit: "abc123def456" resolved_ref: "main" version: "1.0.0" depth: 1 - danielmeppiel/validation-patterns: - repo_url: "https://github.com/danielmeppiel/validation-patterns" + acme/validation-patterns: + repo_url: "https://github.com/acme/validation-patterns" resolved_commit: "789xyz012" resolved_ref: "main" version: "1.2.0" depth: 2 - resolved_by: "danielmeppiel/compliance-rules" + resolved_by: "microsoft/apm-sample-package" ``` ### How It Works @@ -358,7 +346,7 @@ apm install --update APM fully resolves transitive dependencies. If package A depends on B, and B depends on C: ``` -apm install danielmeppiel/package-a +apm install acme/package-a ``` Result: diff --git a/docs/getting-started.md b/docs/getting-started.md index 1139cd70..4951b2cb 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -64,7 +64,7 @@ export GITHUB_HOST=github.company.com #### Scenario 1: Public Modules Only (Most Users) ```bash # No tokens needed - just works! -apm install danielmeppiel/compliance-rules +apm install microsoft/apm-sample-package apm compile ``` @@ -99,10 +99,10 @@ APM installs packages from multiple sources. Use the format that matches your re | Source | Format | Example | |--------|--------|---------| -| GitHub.com | `owner/repo` | `apm install danielmeppiel/compliance-rules` | +| GitHub.com | `owner/repo` | `apm install microsoft/apm-sample-package` | | GitHub Enterprise | `ghe.company.com/owner/repo` | `apm install ghe.myco.com/team/standards` | | Azure DevOps | `dev.azure.com/org/project/repo` | `apm install dev.azure.com/myorg/proj/rules` | -| Virtual Package | `owner/repo/path/file.prompt.md` | `apm install github/awesome-copilot/prompts/code-review.prompt.md` | +| Virtual Package | `owner/repo/path/to/skill` | `apm install github/awesome-copilot/skills/review-and-refactor` | ### GitHub Enterprise Support @@ -179,7 +179,7 @@ For authentication, see [Token Configuration](#token-configuration-all-optional) The fastest way to get APM running: ```bash -curl -sSL https://raw.githubusercontent.com/danielmeppiel/apm/main/install.sh | sh +curl -sSL https://raw.githubusercontent.com/microsoft/apm/main/install.sh | sh ``` This script automatically: @@ -200,11 +200,11 @@ pip install apm-cli ### Manual Installation -Download the binary for your platform from [GitHub Releases](https://github.com/danielmeppiel/apm/releases/latest): +Download the binary for your platform from [GitHub Releases](https://github.com/microsoft/apm/releases/latest): #### macOS Apple Silicon ```bash -curl -L https://github.com/danielmeppiel/apm/releases/latest/download/apm-darwin-arm64.tar.gz | tar -xz +curl -L https://github.com/microsoft/apm/releases/latest/download/apm-darwin-arm64.tar.gz | tar -xz sudo mkdir -p /usr/local/lib/apm sudo cp -r apm-darwin-arm64/* /usr/local/lib/apm/ sudo ln -sf /usr/local/lib/apm/apm /usr/local/bin/apm @@ -212,7 +212,7 @@ sudo ln -sf /usr/local/lib/apm/apm /usr/local/bin/apm #### macOS Intel ```bash -curl -L https://github.com/danielmeppiel/apm/releases/latest/download/apm-darwin-x86_64.tar.gz | tar -xz +curl -L https://github.com/microsoft/apm/releases/latest/download/apm-darwin-x86_64.tar.gz | tar -xz sudo mkdir -p /usr/local/lib/apm sudo cp -r apm-darwin-x86_64/* /usr/local/lib/apm/ sudo ln -sf /usr/local/lib/apm/apm /usr/local/bin/apm @@ -220,7 +220,7 @@ sudo ln -sf /usr/local/lib/apm/apm /usr/local/bin/apm #### Linux x86_64 ```bash -curl -L https://github.com/danielmeppiel/apm/releases/latest/download/apm-linux-x86_64.tar.gz | tar -xz +curl -L https://github.com/microsoft/apm/releases/latest/download/apm-linux-x86_64.tar.gz | tar -xz sudo mkdir -p /usr/local/lib/apm sudo cp -r apm-linux-x86_64/* /usr/local/lib/apm/ sudo ln -sf /usr/local/lib/apm/apm /usr/local/bin/apm @@ -231,8 +231,8 @@ sudo ln -sf /usr/local/lib/apm/apm /usr/local/bin/apm For development or customization: ```bash -git clone https://github.com/danielmeppiel/apm-cli.git -cd apm-cli +git clone https://github.com/microsoft/apm.git +cd apm # Install uv (if not already installed) curl -LsSf https://astral.sh/uv/install.sh | sh @@ -252,8 +252,8 @@ To build a platform-specific binary using PyInstaller: ```bash # Clone and setup (if not already done) -git clone https://github.com/danielmeppiel/apm-cli.git -cd apm-cli +git clone https://github.com/microsoft/apm.git +cd apm # Install uv and dependencies curl -LsSf https://astral.sh/uv/install.sh | sh @@ -404,8 +404,8 @@ For reusable context from other projects, add APM dependencies: # Add to apm.yml dependencies: apm: - - danielmeppiel/compliance-rules # GDPR, legal workflows - - danielmeppiel/design-guidelines # UI/UX standards + - microsoft/apm-sample-package # Design standards, prompts + - github/awesome-copilot/skills/review-and-refactor # Code review skill mcp: - io.github.github/github-mcp-server ``` @@ -426,7 +426,7 @@ apm deps tree APM supports **virtual packages** - installing individual files directly from any repository without requiring a full APM package structure. This is perfect for reusing individual workflow files or configuration from existing projects. > πŸ’‘ **Explore ready-to-use prompts and agents!** -> Browse [github/awesome-copilot](https://github.com/github/awesome-copilot) for a curated collection of community-contributed prompts, instructions, and agents across all major languages and frameworks. Install any file directly with APM. Also works with Awesome Copilot's collections. +> Browse [github/awesome-copilot](https://github.com/github/awesome-copilot) for a curated collection of community-contributed skills, instructions, and agents across all major languages and frameworks. Install any subdirectory directly with APM. Also works with Awesome Copilot's plugins. **What are Virtual Packages?** @@ -434,7 +434,7 @@ Instead of installing an entire package (`owner/repo`), you can install specific ```bash # Install individual files directly -apm install github/awesome-copilot/prompts/architecture-blueprint-generator.prompt.md +apm install github/awesome-copilot/skills/architecture-blueprint-generator apm install myorg/standards/instructions/code-review.instructions.md apm install company/templates/chatmodes/qa-assistant.chatmode.md ``` @@ -459,18 +459,18 @@ apm install company/templates/chatmodes/qa-assistant.chatmode.md Files install to `apm_modules/{owner}/{sanitized-package-name}/`: ```bash -apm install github/awesome-copilot/prompts/code-review.prompt.md +apm install github/awesome-copilot/skills/review-and-refactor ``` Creates: ``` apm_modules/ └── github/ - └── awesome-copilot-code-review/ - β”œβ”€β”€ apm.yml - └── .apm/ - └── prompts/ - └── code-review.prompt.md + └── awesome-copilot/ + └── skills/ + └── review-and-refactor/ + β”œβ”€β”€ apm.yml + └── SKILL.md ``` **Adding to apm.yml:** @@ -481,10 +481,10 @@ Virtual packages work in `apm.yml` just like regular packages: dependencies: apm: # Regular packages - - danielmeppiel/compliance-rules + - microsoft/apm-sample-package # Virtual packages - individual files - - github/awesome-copilot/prompts/architecture-blueprint-generator.prompt.md + - github/awesome-copilot/skills/architecture-blueprint-generator - myorg/engineering/instructions/testing-standards.instructions.md ``` @@ -494,7 +494,7 @@ Use `@ref` syntax for specific versions: ```bash # Install from specific branch -apm install github/awesome-copilot/prompts/code-review.prompt.md@develop +apm install github/awesome-copilot/skills/review-and-refactor@develop # Install from tag apm install myorg/templates/chatmodes/assistant.chatmode.md@v2.1.0 @@ -539,7 +539,7 @@ Starting with v0.5.0, installed prompts are **immediately runnable** without man ```bash # Install a prompt -apm install github/awesome-copilot/prompts/architecture-blueprint-generator.prompt.md +apm install github/awesome-copilot/skills/architecture-blueprint-generator # Run immediately - APM auto-discovers it! apm run architecture-blueprint-generator --param project_name="my-app" diff --git a/docs/index.md b/docs/index.md index 2638e047..ab701808 100644 --- a/docs/index.md +++ b/docs/index.md @@ -34,7 +34,7 @@ New to APM? Follow this learning path for the fastest way to get productive: ### Community Resources - **[APM Manifesto](../MANIFESTO.md)** - Our principles and philosophy for AI-Native Development -- **[GitHub Issues](https://github.com/danielmeppiel/apm/issues)** - Bug reports and feature requests +- **[GitHub Issues](https://github.com/microsoft/apm/issues)** - Bug reports and feature requests - **[AI-Native Development Guide](https://danielmeppiel.github.io/awesome-ai-native/)** - Complete framework documentation ## Architecture & Advanced Topics diff --git a/docs/integrations.md b/docs/integrations.md index 5f10342a..e26e81fc 100644 --- a/docs/integrations.md +++ b/docs/integrations.md @@ -145,7 +145,7 @@ APM automatically integrates prompts and agents from installed packages into VSC ```bash # Install APM packages - integration happens automatically when .github/ exists -apm install danielmeppiel/design-guidelines +apm install microsoft/apm-sample-package # Prompts are automatically integrated to: # .github/prompts/*-apm.prompt.md (verbatim copy with -apm suffix) @@ -180,7 +180,7 @@ The `-apm` suffix pattern enables natural autocomplete in VSCode: **Example**: ```bash # Install package with auto-integration -apm install danielmeppiel/design-guidelines +apm install microsoft/apm-sample-package # Result in VSCode: # Prompts: @@ -232,7 +232,7 @@ APM automatically converts `.prompt.md` files from installed packages into Claud ```bash # Install a package with prompts -apm install danielmeppiel/design-guidelines +apm install microsoft/apm-sample-package # Result: # .claude/commands/accessibility-audit-apm.md β†’ /accessibility-audit @@ -292,7 +292,7 @@ apm compile --target vscode Generated commands follow Claude's native structure: ```markdown - + # Design Review Review the current design for accessibility and UI standards. @@ -305,8 +305,8 @@ Review the current design for accessibility and UI standards. ```bash # 1. Install packages (integrates commands and skills automatically) -apm install danielmeppiel/compliance-rules -apm install github/awesome-copilot/prompts/code-review.prompt.md +apm install microsoft/apm-sample-package +apm install github/awesome-copilot/skills/review-and-refactor # 2. Compile instructions for Claude apm compile --target claude @@ -330,7 +330,7 @@ APM maintains synchronization between packages and Claude commands: - **Install**: Adds commands for new packages - **Uninstall**: Removes only that package's commands - **Update**: Refreshes commands when package version changes -- **Virtual Packages**: Individual files (e.g., `github/awesome-copilot/prompts/code-review.prompt.md`) are tracked and removed correctly +- **Virtual Packages**: Individual files and skills (e.g., `github/awesome-copilot/skills/review-and-refactor`) are tracked and removed correctly ## Development Tool Integrations @@ -375,7 +375,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Setup APM - run: curl -sSL https://raw.githubusercontent.com/danielmeppiel/apm/main/install.sh | sh + run: curl -sSL https://raw.githubusercontent.com/microsoft/apm/main/install.sh | sh - name: Code Review run: | apm compile @@ -395,7 +395,7 @@ Containerize APM workflows for consistent environments: FROM python:3.12-slim # Install APM -RUN curl -sSL https://raw.githubusercontent.com/danielmeppiel/apm/main/install.sh | sh +RUN curl -sSL https://raw.githubusercontent.com/microsoft/apm/main/install.sh | sh # Install runtimes RUN apm runtime setup copilot @@ -412,7 +412,7 @@ ENTRYPOINT ["apm"] ```bash # Use in CI/CD -docker run --rm -v $(pwd):/workspace apm-cli run code-review +docker run --rm -v $(pwd):/workspace apm run code-review ``` ### IDE Integration @@ -425,7 +425,7 @@ Any IDE with GitHub Copilot support (JetBrains, Visual Studio, etc.) works with ```bash # Install APM packages -apm install danielmeppiel/design-guidelines +apm install microsoft/apm-sample-package # GitHub Copilot automatically picks up: # .github/prompts/*-apm.prompt.md (integrated prompts) diff --git a/docs/prompt-integration-analysis.md b/docs/prompt-integration-analysis.md deleted file mode 100644 index 2e768808..00000000 --- a/docs/prompt-integration-analysis.md +++ /dev/null @@ -1,702 +0,0 @@ -# APM Prompt Integration Analysis - -**Date:** November 16, 2025 -**Component:** VSCode/GitHub Prompt Integration -**Status:** Partial Implementation with Critical Gaps - -## Overview - -APM implements automatic integration of `.prompt.md` files from installed packages into the `.github/prompts/` directory for VSCode compatibility. This analysis identifies implementation gaps and potential issues in the current integration workflow. - -## Architecture - -### Core Components - -1. **`PromptIntegrator`** (`src/apm_cli/integration/prompt_integrator.py`) - - Handles copying prompts from `apm_modules/` to `.github/prompts/` - - Adds metadata headers to track source, version, and commit - - Implements smart update logic based on version/commit changes - -2. **Integration Trigger** (`src/apm_cli/cli.py`, lines 947-1069) - - Called during `apm install` workflow - - Conditional based on `.github/` directory existence and `auto_integrate` config - -3. **Configuration** (`src/apm_cli/config.py`, lines 57-70) - - `get_auto_integrate()` - Returns integration setting (default: `True`) - - `set_auto_integrate()` - Allows users to enable/disable feature - -### File Naming Convention - -- **Source:** `design-review.prompt.md` -- **Integrated:** `design-review-apm.prompt.md` -- **Pattern:** Insert `-apm` suffix before `.prompt.md` extension - -### Metadata Header Format - -```markdown - -``` - -## Architect's Verdict: 🚨 COMPLEXITY CREEP DETECTED - -### Analysis from World-Class Tool Design Perspective - -Looking at this through the lens of npm, yarn, pip, cargoβ€”tools used by millionsβ€”the current plan introduces **unnecessary complexity**: - -**Problems:** -- ❌ New `apm integrate` command (users shouldn't need this) -- ❌ New `auto_integrate` config (99% want it enabled) -- ❌ Manual intervention required (should "just work") -- ❌ Exposing implementation details (silent failures) - -**Philosophy:** npm doesn't have `npm integrate` or `npm config set auto_node_modules`. It just works. - ---- - -## Issues Analysis - -### Issue 1: Missing Cleanup on Uninstall ❌ CRITICAL - -**Status:** NOT IMPLEMENTED -**Impact:** HIGH - Leaves orphaned files -**Priority:** HIGH (Keep this fix) - -#### Current Behavior - -**File:** `src/apm_cli/cli.py`, lines 760-900 - -The `apm uninstall` command currently: -1. βœ… Removes package from `apm.yml` dependencies -2. βœ… Deletes package directory from `apm_modules/{org}/{repo}/` -3. ❌ **Does NOT** clean up integrated prompts from `.github/prompts/` - -```python -# Current uninstall logic (simplified) -for package in packages_to_remove: - package_name = package.split("/")[-1] - package_path = apm_modules_dir / package_name - - if package_path.exists(): - shutil.rmtree(package_path) # Only removes from apm_modules - # Missing: cleanup of .github/prompts/*-apm.prompt.md files -``` - -#### Consequence - -After running `apm uninstall danielmeppiel/design-guidelines`: -- ❌ `apm_modules/danielmeppiel/design-guidelines/` β†’ Deleted -- ❌ `apm.yml` β†’ Package removed from dependencies -- ⚠️ `.github/prompts/design-review-apm.prompt.md` β†’ **Still exists** (orphaned) - -Users see stale prompts in VSCode that reference uninstalled packages. - -#### Simplified Fix (Idempotent Sync) - -**Location:** `src/apm_cli/cli.py`, `uninstall()` function - -```python -# After uninstalling, re-sync integration (removes orphans automatically) -if Path(".github/prompts").exists(): - try: - apm_package = APMPackage.from_apm_yml(Path("apm.yml")) - integrator = PromptIntegrator() - integrator.sync_integration(apm_package, Path(".")) - except Exception: - pass # Silent cleanup failure OK -``` - -**New Method:** `PromptIntegrator.sync_integration()` - Simpler & Idempotent - -```python -def sync_integration(self, apm_package, project_root: Path): - """Sync .github/prompts/ with currently installed packages. - - - Removes prompts from uninstalled packages (orphans) - - Updates prompts from updated packages - - Adds prompts from new packages - - Idempotent: safe to call anytime. Reuses existing smart update logic. - """ - prompts_dir = project_root / ".github" / "prompts" - if not prompts_dir.exists(): - return - - # Get currently installed package names - installed = {dep.repo_url for dep in apm_package.get_apm_dependencies()} - - # Remove orphaned prompts (from uninstalled packages) - for prompt_file in prompts_dir.glob("*-apm.prompt.md"): - metadata = self._parse_header_metadata(prompt_file) - source = metadata.get('Source', '') - - # Check if source package is still installed - package_match = any(pkg in source for pkg in installed) - - if not package_match: - prompt_file.unlink() # Orphaned - remove it -``` - ---- - -### Issue 2: Version Change Updates βœ… WORKING - -**Status:** FULLY IMPLEMENTED -**Impact:** None - Working as designed -**Priority:** N/A - -#### Current Behavior - -**File:** `src/apm_cli/integration/prompt_integrator.py`, lines 204-276 - -The integration system correctly handles version/commit changes: - -1. **Parse existing file metadata** (lines 70-105) - ```python - def _parse_header_metadata(self, file_path: Path) -> dict: - """Extract Version and Commit from header comment.""" - # Parses - ``` - -2. **Compare versions** (lines 108-131) - ```python - def _should_update_prompt(self, existing_header: dict, package_info) -> bool: - """Return True if version or commit changed.""" - new_version = package_info.package.version - new_commit = package_info.resolved_reference.resolved_commit - - existing_version = existing_header.get('Version', '') - existing_commit = existing_header.get('Commit', '') - - return (existing_version != new_version or existing_commit != new_commit) - ``` - -3. **Smart update logic** (lines 244-259) - ```python - if target_path.exists(): - existing_header = self._parse_header_metadata(target_path) - - if self._should_update_prompt(existing_header, package_info): - # Version changed - update the file - self.copy_prompt_with_header(source_file, target_path, header) - files_updated += 1 - else: - # No change - skip to preserve timestamp - files_skipped += 1 - ``` - -#### Test Coverage - -**File:** `tests/unit/integration/test_prompt_integrator.py` - -- βœ… Version change detection tested -- βœ… Update vs skip logic tested -- βœ… Header parsing tested - -#### Result Tracking - -```python -@dataclass -class IntegrationResult: - files_integrated: int # New files added - files_updated: int # Files updated due to version change - files_skipped: int # Unchanged files (same version/commit) - target_paths: List[Path] - gitignore_updated: bool -``` - -**No action required** - this functionality works correctly. - ---- - -### Issue 3: Late `.github/` Directory Creation ❌ REMOVE THIS - -**Status:** REJECT - Over-engineered solution -**Impact:** Creates unnecessary complexity -**Priority:** REPLACE WITH AUTO-CREATE - -#### Current Problem - -Integration requires `.github/` to exist before running `apm install`. - -#### Wrong Solution (Current Plan) - -Add `apm integrate` command + helpful messages β†’ More commands to learn - -#### Right Solution (Zero-Config) - -**Location:** `src/apm_cli/integration/prompt_integrator.py`, lines 30-43 - -**Change this:** -```python -def should_integrate(self, project_root: Path) -> bool: - """Check if prompt integration should be performed.""" - github_dir = project_root / ".github" - return github_dir.exists() and get_auto_integrate() # ❌ Too conservative -``` - -**To this:** -```python -def should_integrate(self, project_root: Path) -> bool: - """Check if prompt integration should be performed.""" - return True # βœ… Always integrate (creates dirs as needed) -``` - -**Why:** The `integrate_package_prompts()` method already creates `.github/prompts/` with `mkdir(parents=True, exist_ok=True)`. The check is redundant and causes the problem. - -**Result:** Zero manual intervention, no new commands, just works. - ---- - -### Issue 4: Auto-Integrate Config ❌ REMOVE THIS - -**Status:** REJECT - Unnecessary configuration -**Impact:** Decision fatigue for 1% edge case -**Priority:** DELETE - -#### Current Problem - -Users might not want VSCode integration? - -#### Wrong Solution (Current Plan) - -Add `apm config set auto_integrate true/false` β†’ More knobs to turn - -#### Right Solution (Convention over Configuration) - -**DELETE:** The entire `auto_integrate` config option - -**Reasoning:** -- npm doesn't have `npm config set auto_node_modules false` -- cargo doesn't have `cargo config set auto_target false` -- 99% of users want prompts integrated for VSCode -- The 1% who don't can simply: `echo ".github/prompts/" >> .gitignore` - -**Action:** Remove all references to `get_auto_integrate()` and `set_auto_integrate()` - ---- - -## Implementation Priority - -### High Priority (Must Fix) - -1. **Issue 1: Cleanup on Uninstall** - - **Impact:** Leaves orphaned files that confuse users - - **Effort:** Medium (1-2 days) - - **Files:** - - `src/apm_cli/cli.py` - Add cleanup call in `uninstall()` - - `src/apm_cli/integration/prompt_integrator.py` - Add `cleanup_package_prompts()` - - `tests/unit/integration/test_prompt_integrator.py` - Add cleanup tests - -### Medium Priority (Should Fix) - -2. **Issue 3: Add `apm integrate` Command** - - **Impact:** Better UX for late `.github/` creation - - **Effort:** Medium (2-3 days) - - **Files:** - - `src/apm_cli/cli.py` - Add new `integrate` command - - `src/apm_cli/integration/prompt_integrator.py` - Add `force_update` parameter - - `tests/integration/test_integration_command.py` - New test file - -### Low Priority (Nice to Have) - -3. **Issue 4: Add Helpful Messages** - - **Impact:** Minor UX improvement - - **Effort:** Low (1 hour) - - **Files:** - - `src/apm_cli/cli.py` - Add informational messages - ---- - -## Testing Requirements (Simplified) - -### Unit Tests - -**File:** `tests/unit/integration/test_prompt_integrator.py` - -#### New Tests Required - -```python -def test_sync_integration_removes_orphaned_prompts(): - """Test that sync removes prompts from uninstalled packages.""" - # Setup: Create integrated prompts from package1, package2 - # Uninstall: Remove package1 from apm.yml - # Action: sync_integration() - # Assert: Only package1 prompts removed, package2 remains - -def test_sync_integration_preserves_installed_prompts(): - """Test sync doesn't remove prompts from installed packages.""" - -def test_sync_integration_handles_missing_prompts_dir(): - """Test sync gracefully handles missing .github/prompts/.""" - -def test_should_integrate_always_returns_true(): - """Test integration always enabled (no config check).""" - assert integrator.should_integrate(Path(".")) == True -``` - -### Integration Tests - -**File:** `tests/integration/test_uninstall_cleanup.py` (new file) - -```python -def test_uninstall_removes_integrated_prompts(): - """End-to-end: apm install β†’ apm uninstall β†’ verify cleanup.""" - -def test_uninstall_preserves_other_package_prompts(): - """Verify uninstalling one package doesn't affect others.""" - -def test_install_creates_github_directory_automatically(): - """Test that apm install creates .github/prompts/ automatically.""" -``` - ---- - -## Configuration - -### Auto-Integration Setting - -**File:** `src/apm_cli/config.py`, lines 57-70 - -Users can disable auto-integration globally: -## Configuration - -### ❌ REMOVED: Auto-Integration Setting - -**Previous approach:** `apm config set auto_integrate true/false` - -**Why removed:** -- Adds complexity for 1% edge case -- Goes against "convention over configuration" principle -- npm, cargo, pip don't have similar configs -- Users who don't want it can use `.gitignore` - -**Migration:** If users had `auto_integrate=false`, they should add `.github/prompts/` to `.gitignore` instead. -- `src/apm_cli/integration/__init__.py` - Exports `PromptIntegrator` -- `src/apm_cli/cli.py` - Command definitions and install workflow -- `src/apm_cli/config.py` - Configuration management - -### Tests -- `tests/unit/integration/test_prompt_integrator.py` - Unit tests for integrator -- `tests/integration/test_auto_integration.py` - Integration tests - -### Models -- `src/apm_cli/models/apm_package.py` - `PackageInfo` data structure - ---- - -## Recommendations (Simplified Approach) - -### Immediate Actions - -1. βœ… **Implement idempotent sync on uninstall** (High Priority) - - Add `sync_integration()` method (simpler than cleanup) - - Call from `uninstall()` command - - Add comprehensive tests - -2. βœ… **Remove `.github/` existence check** (Medium Priority) - - Change `should_integrate()` to always return `True` - - Let existing `mkdir(parents=True)` handle directory creation - - Zero user intervention required - -3. βœ… **Remove `auto_integrate` config** (Low Priority) - - Delete `get_auto_integrate()` and `set_auto_integrate()` - - Remove from all integration checks - - Update tests - -### ❌ Rejected Actions (Over-Engineering) - -- ~~Add `apm integrate` command~~ β†’ Not needed -- ~~Add helpful messages~~ β†’ Not needed -- ~~Add `--force` flag~~ β†’ Already idempotent -- ~~Add VSCode tips~~ β†’ Just works automatically - -### Long-Term Improvements - -- **Documentation:** Actually becomes simpler (nothing to explain) -- **CI/CD:** Add integration tests for auto-create and sync -- **User feedback:** Monitor for any edge cases -## Revised Implementation Priority (Simplified) - -### High Priority (Critical Fix) - -1. **Issue 1: Cleanup on Uninstall** - - **Impact:** Leaves orphaned files - - **Effort:** Low (4 hours) - Use idempotent sync approach - - **Files:** - - `src/apm_cli/cli.py` - Add sync call in `uninstall()` - - `src/apm_cli/integration/prompt_integrator.py` - Add `sync_integration()` - - `tests/unit/integration/test_prompt_integrator.py` - Add sync tests - -### Medium Priority (Simplification) - -2. **Issue 3: Auto-Create `.github/` Directory** - - **Impact:** Eliminates manual intervention - - **Effort:** Trivial (15 minutes) - Remove unnecessary check - - **Files:** - - `src/apm_cli/integration/prompt_integrator.py` - Change `should_integrate()` to always return `True` - -### Low Priority (Cleanup) - -3. **Issue 4: Remove `auto_integrate` Config** - - **Impact:** Reduces complexity - - **Effort:** Low (1 hour) - Remove config, update tests - - **Files:** - - `src/apm_cli/config.py` - Remove `get/set_auto_integrate()` - - `src/apm_cli/integration/prompt_integrator.py` - Remove config checks - - `tests/` - Remove config-related tests - -### ❌ Rejected (Complexity Bloat) - -- ~~Add `apm integrate` command~~ - Not needed with auto-create -- ~~Add helpful messages~~ - Not needed with zero-config -- ~~Add `--force` flag~~ - `apm install` is already idempotent -# OR -apm integrate # Manually integrate existing packages -``` - -Integrated prompts appear as `*-apm.prompt.md` in `.github/prompts/`. -``` - -**Effort:** 12 lines added - ---- - -#### 2. `docs/commands.md` - Add New Commands (if file exists) - -**Location:** Commands reference section - -**Add:** -```markdown -### `apm integrate` - -Integrate prompts from installed packages into `.github/prompts/`. - -**Usage:** -```bash -apm integrate # Integrate missing prompts -apm integrate --force # Re-integrate all prompts -``` - -**When to use:** -- Created `.github/` after installing packages -- Want to refresh integrated prompts -- Manually deleted integrated prompts - ---- - -### `apm uninstall` - -**Enhancement:** Now automatically removes integrated prompts from `.github/prompts/`. - -**Usage:** -```bash -apm uninstall org/package # Removes package + integrated prompts -``` -``` - -**Effort:** 25 lines added - ---- - -#### 3. `CHANGELOG.md` - Document Changes - -**Location:** Under `## [Unreleased]` or next version - -**Add:** -```markdown -### Added -- `apm integrate` command for manual prompt integration -- `apm integrate --force` flag to re-integrate all prompts -- Auto-cleanup of `.github/prompts/*-apm.prompt.md` on `apm uninstall` -- Helpful messages when `.github/` directory missing - -### Fixed -- Integrated prompts now properly removed when uninstalling packages -- Better UX for late `.github/` directory creation workflow -``` - -**Effort:** 8 lines added - ---- - -#### 4. Create `docs/integration.md` - Detailed Guide (Optional) - -**Note:** Only if users request more details. Keep it short. - -**Content:** -```markdown -# Prompt Integration Guide - -## How It Works - -APM copies `.prompt.md` files to `.github/prompts/` with: -- Metadata header (source, version, commit) -- `-apm` suffix (e.g., `design-review-apm.prompt.md`) -- Auto-update on version changes - -## Commands - -### Enable Integration -```bash -mkdir -p .github -apm install -``` - -### Manual Integration -```bash -apm integrate # Smart: only new/changed -apm integrate --force # Force: re-integrate all -``` - -### Disable Integration -```bash -apm config set auto_integrate false -``` - -## File Structure - -``` -.github/prompts/ -β”œβ”€β”€ design-review-apm.prompt.md # From design-guidelines -β”œβ”€β”€ accessibility-audit-apm.prompt.md # From design-guidelines -└── compliance-audit-apm.prompt.md # From compliance-rules - -apm_modules/ -β”œβ”€β”€ danielmeppiel/ -β”‚ β”œβ”€β”€ design-guidelines/ -β”‚ β”‚ └── design-review.prompt.md # Original -β”‚ └── compliance-rules/ -β”‚ └── compliance-audit.prompt.md # Original -``` - -## Metadata Header - -Each integrated prompt includes tracking metadata: - -```markdown - -``` - -## Troubleshooting - -**Prompts not integrating?** -- Check `.github/` exists: `ls -la .github` -- Check config: `apm config get auto_integrate` - -**Stale prompts after uninstall?** -- Run: `apm integrate` (re-syncs all) -- Or manually: `rm .github/prompts/*-apm.prompt.md` - -**Want to disable?** -```bash -apm config set auto_integrate false -rm .github/prompts/*-apm.prompt.md -``` - -**Effort:** 60 lines (only if needed) - ---- - -### Documentation Summary - -| File | Change Type | Lines Added | Priority | -|------|-------------|-------------|----------| -| `docs/getting-started.md` | Add tip | 12 | Required | -| `docs/commands.md` | Add commands | 25 | Required | -| `CHANGELOG.md` | Document changes | 8 | Required | -| `docs/integration.md` | New guide | 60 | Optional | - -**Total Required Changes:** 45 lines across 3 files -**Estimated Time:** 20 minutes - -### Writing Guidelines - -1. **Be concise** - No walls of text -2. **Show, don't tell** - Use code examples -3. **Practical first** - Common use cases only -4. **Progressive disclosure** - Basic info in README, details in separate docs -5. **Troubleshooting** - Only include if users ask - ---- - -## Impact Analysis: Before vs After - -### Before (Original Plan) - -| Metric | Value | Assessment | -|--------|-------|------------| -| New commands | 1 (`apm integrate`) | ❌ Adds complexity | -| New config options | 1 (`auto_integrate`) | ❌ Decision fatigue | -| User-facing concepts | 3 (install, integrate, config) | ❌ Too many | -| Lines of docs | 45 | ❌ Needs explanation | -| Manual steps | 2-3 | ❌ Error-prone | -| "Just works" factor | 60% | ❌ Conditional | - -### After (Simplified Plan) - -| Metric | Value | Assessment | -|--------|-------|------------| -| New commands | 0 | βœ… No learning curve | -| New config options | 0 | βœ… Zero config | -| User-facing concepts | 1 (install/uninstall) | βœ… Familiar | -| Lines of docs | 4 (changelog only) | βœ… Nothing to explain | -| Manual steps | 0 | βœ… Automatic | -| "Just works" factor | 95% | βœ… Invisible | - -### Code Changes Comparison - -**Original Plan:** -- Add `cleanup_package_prompts()` method (~40 lines) -- Add `apm integrate` command (~80 lines) -- Add helpful messages (~20 lines) -- Add integration tests (~60 lines) -- **Total: ~200 lines added** - -**Simplified Plan:** -- Add `sync_integration()` method (~20 lines) -- Change `should_integrate()` to return `True` (1 line change) -- Remove `auto_integrate` config checks (~10 lines removed) -- Add sync tests (~30 lines) -- **Total: ~40 lines added, 10 removed** - -**Effort saved:** 60% less code, 90% less documentation - ---- - -## Conclusion - -**Verdict:** The original plan suffered from **complexity creep** and exposed implementation details to users. - -**Key realizations:** -1. **Cleanup lifecycle** - Solved with idempotent sync (simpler than targeted cleanup) -2. **Late creation workflow** - Non-issue when `.github/` is auto-created -3. **User awareness** - Not needed when feature is invisible - -**Revised approach:** -- βœ… **Auto-create directories** - Remove artificial barriers -- βœ… **Idempotent sync** - Self-healing, no manual intervention -- βœ… **Zero configuration** - Convention over configuration -- βœ… **Invisible integration** - Works without user knowledge - -**Philosophy shift:** -- FROM: "Give users control" β†’ TO: "Make it just work" -- FROM: "Provide commands for every scenario" β†’ TO: "One command does everything" -- FROM: "Document all features" β†’ TO: "Features don't need docs" - -This is how npm, yarn, cargo, and pip handle similar problems. APM should too. - -**Implementation effort:** Same or less than original plan -**User experience:** Vastly superior -**Maintenance burden:** Significantly lower diff --git a/docs/prompts.md b/docs/prompts.md index d4640396..3bf83da4 100644 --- a/docs/prompts.md +++ b/docs/prompts.md @@ -234,10 +234,10 @@ Starting with v0.5.0, APM can automatically discover and run prompts without man ```bash # Install a prompt from any repository -apm install github/awesome-copilot/prompts/code-review.prompt.md +apm install github/awesome-copilot/skills/review-and-refactor # Run it immediately - no apm.yml configuration needed! -apm run code-review +apm run review-and-refactor ``` **How it works:** @@ -262,7 +262,7 @@ If you have multiple prompts with the same name from different sources: # Collision detected - APM shows all matches with guidance apm run code-review # Error: Multiple prompts found for 'code-review': -# - github/awesome-copilot (apm_modules/github/awesome-copilot-code-review/...) +# - owner/test-repo (apm_modules/owner/test-repo-code-review/...) # - acme/standards (apm_modules/acme/standards/...) # # Use qualified path: diff --git a/docs/runtime-integration.md b/docs/runtime-integration.md index e9de2c72..9e4e061b 100644 --- a/docs/runtime-integration.md +++ b/docs/runtime-integration.md @@ -17,7 +17,7 @@ APM acts as a runtime package manager, downloading and configuring LLM runtimes ### Install APM and Setup Runtime ```bash # 1. Install APM -curl -sSL https://raw.githubusercontent.com/danielmeppiel/apm/main/install.sh | sh +curl -sSL https://raw.githubusercontent.com/microsoft/apm/main/install.sh | sh # 2. Setup AI runtime (downloads and configures automatically) apm runtime setup copilot diff --git a/docs/skills.md b/docs/skills.md index 186546b2..d2ecb90c 100644 --- a/docs/skills.md +++ b/docs/skills.md @@ -61,8 +61,7 @@ Skill names are validated per the [agentskills.io](https://agentskills.io/) spec ``` .github/skills/ β”œβ”€β”€ mcp-builder/ # From ComposioHQ/awesome-claude-skills/mcp-builder -β”œβ”€β”€ design-guidelines/ # From danielmeppiel/design-guidelines -└── compliance-rules/ # From danielmeppiel/compliance-rules +└── apm-sample-package/ # From microsoft/apm-sample-package ``` ### Step 3: Primitive Integration diff --git a/install.sh b/install.sh index fbc33038..94823c8c 100755 --- a/install.sh +++ b/install.sh @@ -2,10 +2,10 @@ set -e # APM CLI Installer Script -# Usage: curl -sSL https://raw.githubusercontent.com/danielmeppiel/apm/main/install.sh | sh +# Usage: curl -sSL https://raw.githubusercontent.com/microsoft/apm/main/install.sh | sh # For private repositories, use with authentication: # curl -sSL -H "Authorization: token $GITHUB_APM_PAT" \ -# https://raw.githubusercontent.com/danielmeppiel/apm/main/install.sh | \ +# https://raw.githubusercontent.com/microsoft/apm/main/install.sh | \ # GITHUB_APM_PAT=$GITHUB_APM_PAT sh # Colors for output @@ -16,15 +16,15 @@ YELLOW='\033[1;33m' NC='\033[0m' # No Color # Configuration -REPO="danielmeppiel/apm" +REPO="microsoft/apm" INSTALL_DIR="/usr/local/bin" BINARY_NAME="apm" # Banner echo -e "${BLUE}" echo "╔══════════════════════════════════════════════════════════════╗" -echo "β•‘ APM CLI Installer β•‘" -echo "β•‘ The NPM for AI-Native Development β•‘" +echo "β•‘ APM Installer β•‘" +echo "β•‘ The NPM for AI-Native Development β•‘" echo "β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•" echo -e "${NC}" @@ -114,7 +114,7 @@ try_pip_installation() { # Try to install if $PIP_CMD install --user apm-cli; then - echo -e "${GREEN}βœ“ APM CLI installed successfully via pip!${NC}" + echo -e "${GREEN}βœ“ APM installed successfully via pip!${NC}" # Check if apm is now available if command -v apm >/dev/null 2>&1; then @@ -172,7 +172,7 @@ if [ "$PLATFORM" = "linux" ]; then echo "To install APM, you need either:" echo " 1. Python 3.9+ and pip: pip install --user apm-cli" echo " 2. A system with glibc 2.35+ to use the prebuilt binary" - echo " 3. Build from source: git clone https://github.com/$REPO.git && cd apm-cli && uv sync && uv run pip install -e ." + echo " 3. Build from source: git clone https://github.com/$REPO.git && cd apm && uv sync && uv run pip install -e ." echo "" echo "To install Python 3.9+:" echo " Ubuntu/Debian: sudo apt-get update && sudo apt-get install python3 python3-pip" @@ -222,7 +222,7 @@ if [ $CURL_EXIT_CODE -ne 0 ] || [ -z "$LATEST_RELEASE" ] || echo "$LATEST_RELEAS echo "Please set GITHUB_APM_PAT or GITHUB_TOKEN environment variable:" echo " export GITHUB_APM_PAT=your_token_here" echo " curl -sSL -H \"Authorization: token \$GITHUB_APM_PAT\" \\" - echo " https://raw.githubusercontent.com/danielmeppiel/apm/main/install.sh | \\" + echo " https://raw.githubusercontent.com/microsoft/apm/main/install.sh | \\" echo " GITHUB_APM_PAT=\$GITHUB_APM_PAT sh" exit 1 fi @@ -279,7 +279,7 @@ TMP_DIR=$(mktemp -d) trap "rm -rf $TMP_DIR" EXIT # Download binary -echo -e "${YELLOW}Downloading APM CLI...${NC}" +echo -e "${YELLOW}Downloading APM...${NC}" # Try downloading without authentication first (for public repos) if curl -L --fail --silent --show-error "$DOWNLOAD_URL" -o "$TMP_DIR/$DOWNLOAD_BINARY"; then @@ -314,7 +314,7 @@ else echo "For private repositories, ensure your token has the required permissions." echo "You can try installing from source instead:" echo " git clone https://github.com/$REPO.git" - echo " cd apm-cli && uv sync && uv run pip install -e ." + echo " cd apm && uv sync && uv run pip install -e ." exit 1 fi fi @@ -334,12 +334,12 @@ else echo "For private repositories, ensure your token has the required permissions." echo "You can try installing from source instead:" echo " git clone https://github.com/$REPO.git" - echo " cd apm-cli && uv sync && uv run pip install -e ." + echo " cd apm && uv sync && uv run pip install -e ." exit 1 fi fi else - echo -e "${RED}Error: Failed to download APM CLI${NC}" + echo -e "${RED}Error: Failed to download APM${NC}" echo "URL: $DOWNLOAD_URL" echo "This might mean:" echo " 1. No binary available for your platform ($PLATFORM-$ARCH)" @@ -350,12 +350,12 @@ else echo "For private repositories, set GITHUB_APM_PAT environment variable:" echo " export GITHUB_APM_PAT=your_token_here" echo " curl -sSL -H \"Authorization: token \$GITHUB_APM_PAT\" \\" - echo " https://raw.githubusercontent.com/danielmeppiel/apm/main/install.sh | \\" + echo " https://raw.githubusercontent.com/microsoft/apm/main/install.sh | \\" echo " GITHUB_APM_PAT=\$GITHUB_APM_PAT sh" echo "" echo "You can also try installing from source:" echo " git clone https://github.com/$REPO.git" - echo " cd apm-cli && uv sync && uv run pip install -e ." + echo " cd apm && uv sync && uv run pip install -e ." exit 1 fi fi @@ -427,11 +427,11 @@ else echo "" fi - echo "2. Homebrew (macOS/Linux): brew install danielmeppiel/apm-cli" + echo "2. Homebrew (macOS/Linux): brew install microsoft/apm/apm" echo "" echo "3. From source:" echo " git clone https://github.com/$REPO.git" - echo " cd apm-cli && uv sync && uv run pip install -e ." + echo " cd apm && uv sync && uv run pip install -e ." echo "" if [ "$PLATFORM" = "linux" ]; then @@ -478,11 +478,11 @@ fi # Verify installation if command -v apm >/dev/null 2>&1; then INSTALLED_VERSION=$(apm --version 2>/dev/null || echo "unknown") - echo -e "${GREEN}βœ“ APM CLI installed successfully!${NC}" + echo -e "${GREEN}βœ“ APM installed successfully!${NC}" echo -e "${BLUE}Version: $INSTALLED_VERSION${NC}" echo -e "${BLUE}Location: $INSTALL_DIR/$BINARY_NAME -> $APM_INSTALL_DIR/$BINARY_NAME${NC}" else - echo -e "${YELLOW}⚠ APM CLI installed but not found in PATH${NC}" + echo -e "${YELLOW}⚠ APM installed but not found in PATH${NC}" echo "You may need to add $INSTALL_DIR to your PATH environment variable." echo "Add this line to your shell profile (.bashrc, .zshrc, etc.):" echo " export PATH=\"$INSTALL_DIR:\$PATH\"" diff --git a/scripts/install.sh b/scripts/install.sh index 50d3fc89..93c81c2b 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -1,7 +1,7 @@ #!/bin/bash set -e -echo "Installing APM-CLI..." +echo "Installing APM..." # Detect package managers has_brew=$(command -v brew >/dev/null 2>&1 && echo "yes" || echo "no") @@ -11,8 +11,7 @@ has_pip=$(command -v pip >/dev/null 2>&1 && echo "yes" || echo "no") # Try to install with the best available package manager if [ "$has_brew" = "yes" ]; then echo "Installing with Homebrew..." - brew tap danielmeppiel/apm-cli - brew install apm-cli + brew install microsoft/apm/apm elif [ "$has_uv" = "yes" ]; then echo "Installing with uv..." uv pip install apm-cli @@ -28,4 +27,4 @@ else exit 1 fi -echo "APM-CLI installed successfully!" +echo "APM installed successfully!" diff --git a/scripts/test-dependency-integration.sh b/scripts/test-dependency-integration.sh index e936658b..5a26bb1f 100755 --- a/scripts/test-dependency-integration.sh +++ b/scripts/test-dependency-integration.sh @@ -33,7 +33,7 @@ test_real_dependency_installation() { local test_dir="$1" local apm_binary="$2" - log_test "Testing real dependency installation with danielmeppiel/compliance-rules" + log_test "Testing real dependency installation with microsoft/apm-sample-package" cd "$test_dir" @@ -46,10 +46,10 @@ author: CI Test dependencies: apm: - - danielmeppiel/compliance-rules + - microsoft/apm-sample-package scripts: - start: "echo 'Project with compliance rules dependency loaded'" + start: "echo 'Project with apm-sample-package dependency loaded'" EOF # Test apm deps list (should show no dependencies initially) @@ -75,25 +75,25 @@ EOF fi # Verify installation - if [[ ! -d "apm_modules/danielmeppiel/compliance-rules" ]]; then - log_error "Dependency not installed: apm_modules/danielmeppiel/compliance-rules not found" + if [[ ! -d "apm_modules/microsoft/apm-sample-package" ]]; then + log_error "Dependency not installed: apm_modules/microsoft/apm-sample-package not found" return 1 fi # Verify dependency structure - if [[ ! -f "apm_modules/danielmeppiel/compliance-rules/apm.yml" ]]; then + if [[ ! -f "apm_modules/microsoft/apm-sample-package/apm.yml" ]]; then log_error "Dependency missing apm.yml" return 1 fi - if [[ ! -d "apm_modules/danielmeppiel/compliance-rules/.apm" ]]; then + if [[ ! -d "apm_modules/microsoft/apm-sample-package/.apm" ]]; then log_error "Dependency missing .apm directory" return 1 fi - # Check for expected workflow files - if [[ ! -f "apm_modules/danielmeppiel/compliance-rules/compliance-audit.prompt.md" ]]; then - log_error "Dependency missing expected workflow file: compliance-audit.prompt.md" + # Check for expected prompt files + if [[ ! -f "apm_modules/microsoft/apm-sample-package/.apm/prompts/design-review.prompt.md" ]]; then + log_error "Dependency missing expected prompt file: .apm/prompts/design-review.prompt.md" return 1 fi @@ -101,7 +101,7 @@ EOF # Test apm deps list (should now show installed dependency) log_info "Testing 'apm deps list' with installed dependency" - if "$apm_binary" deps list | grep -q "compliance-rules"; then + if "$apm_binary" deps list | grep -q "apm-sample-package"; then log_success "Correctly shows installed dependency" else log_error "Expected to see installed dependency in list" @@ -110,7 +110,7 @@ EOF # Test apm deps tree log_info "Testing 'apm deps tree'" - if "$apm_binary" deps tree | grep -q "compliance-rules"; then + if "$apm_binary" deps tree | grep -q "apm-sample-package"; then log_success "Dependency tree shows installed dependency" else log_error "Expected to see dependency in tree output" @@ -118,8 +118,8 @@ EOF fi # Test apm deps info - log_info "Testing 'apm deps info compliance-rules'" - if "$apm_binary" deps info compliance-rules | grep -q "compliance-rules"; then + log_info "Testing 'apm deps info apm-sample-package'" + if "$apm_binary" deps info apm-sample-package | grep -q "apm-sample-package"; then log_success "Dependency info command works" else log_error "Expected dependency info to show package details" @@ -147,8 +147,8 @@ author: CI Test dependencies: apm: - - danielmeppiel/compliance-rules - - danielmeppiel/design-guidelines + - microsoft/apm-sample-package + - github/awesome-copilot/skills/review-and-refactor scripts: start: "echo 'Project with multiple dependencies loaded'" @@ -165,24 +165,24 @@ EOF fi # Verify both dependencies installed - if [[ ! -d "apm_modules/danielmeppiel/compliance-rules" ]]; then - log_error "First dependency not installed: compliance-rules" + if [[ ! -d "apm_modules/microsoft/apm-sample-package" ]]; then + log_error "First dependency not installed: apm-sample-package" return 1 fi - if [[ ! -d "apm_modules/danielmeppiel/design-guidelines" ]]; then - log_error "Second dependency not installed: design-guidelines" + if [[ ! -d "apm_modules/github/awesome-copilot/skills/review-and-refactor" ]]; then + log_error "Second dependency not installed: github/awesome-copilot/skills/review-and-refactor" return 1 fi # Test deps list shows both local deps_output=$("$apm_binary" deps list) - if ! echo "$deps_output" | grep -q "compliance-rules"; then - log_error "Multi-dependency list missing compliance-rules" + if ! echo "$deps_output" | grep -q "apm-sample-package"; then + log_error "Multi-dependency list missing apm-sample-package" return 1 fi - if ! echo "$deps_output" | grep -q "design-guidelines"; then + if ! echo "$deps_output" | grep -q "design-guidelines\|apm-sample-package"; then log_error "Multi-dependency list missing design-guidelines" return 1 fi @@ -213,8 +213,8 @@ test_dependency_update() { fi # Test update specific dependency - log_info "Testing 'apm deps update compliance-rules'" - if ! "$apm_binary" deps update compliance-rules; then + log_info "Testing 'apm deps update apm-sample-package'" + if ! "$apm_binary" deps update apm-sample-package; then log_error "Failed to update specific dependency" return 1 fi @@ -268,8 +268,8 @@ test_dependency_integration() { log_info "=== APM Dependencies Integration Testing ===" log_info "Testing with real GitHub repositories:" - log_info " - danielmeppiel/compliance-rules" - log_info " - danielmeppiel/design-guidelines" + log_info " - microsoft/apm-sample-package" + log_info " - github/awesome-copilot/skills/review-and-refactor" # Create isolated test directory local test_dir=$(mktemp -d) diff --git a/scripts/test-release-validation.sh b/scripts/test-release-validation.sh index 2ed9678a..5a71a207 100755 --- a/scripts/test-release-validation.sh +++ b/scripts/test-release-validation.sh @@ -177,9 +177,9 @@ test_hero_zero_config() { # Runtime setup is already done in test_runtime_setup() # Just test the virtual package run - echo "Running: $BINARY_PATH run github/awesome-copilot/prompts/architecture-blueprint-generator (with 15s timeout)" + echo "Running: $BINARY_PATH run github/awesome-copilot/skills/architecture-blueprint-generator (with 15s timeout)" echo "--- Command Output Start ---" - run_with_timeout 15 "$BINARY_PATH run github/awesome-copilot/prompts/architecture-blueprint-generator" + run_with_timeout 15 "$BINARY_PATH run github/awesome-copilot/skills/architecture-blueprint-generator" local exit_code=$? echo "--- Command Output End ---" echo "Exit code: $exit_code" @@ -197,7 +197,7 @@ test_hero_zero_config() { fi # Verify package was actually installed - if [[ ! -d "apm_modules/github/awesome-copilot-architecture-blueprint-generator" ]]; then + if [[ ! -d "apm_modules/github/awesome-copilot/skills/architecture-blueprint-generator" ]]; then log_error "Package was not installed by auto-install" cd .. return 1 @@ -207,7 +207,7 @@ test_hero_zero_config() { # Test second run (should use cached package, no re-download) echo "Testing second run (should use cache)..." - run_with_timeout 10 "$BINARY_PATH run github/awesome-copilot/prompts/architecture-blueprint-generator" | head -20 + run_with_timeout 10 "$BINARY_PATH run github/awesome-copilot/skills/architecture-blueprint-generator" | head -20 local second_exit_code=${PIPESTATUS[0]} if [[ $second_exit_code -eq 124 || $second_exit_code -eq 0 ]]; then @@ -245,37 +245,37 @@ test_hero_guardrailing() { cd my-project - # Step 2: apm install danielmeppiel/design-guidelines - echo "Running: $BINARY_PATH install danielmeppiel/design-guidelines" + # Step 2: apm install microsoft/apm-sample-package + echo "Running: $BINARY_PATH install microsoft/apm-sample-package" echo "--- Command Output Start ---" - APM_E2E_TESTS="${APM_E2E_TESTS:-}" "$BINARY_PATH" install danielmeppiel/design-guidelines 2>&1 + APM_E2E_TESTS="${APM_E2E_TESTS:-}" "$BINARY_PATH" install microsoft/apm-sample-package 2>&1 exit_code=$? echo "--- Command Output End ---" echo "Exit code: $exit_code" if [[ $exit_code -ne 0 ]]; then - log_error "apm install danielmeppiel/design-guidelines failed" + log_error "apm install microsoft/apm-sample-package failed" cd .. return 1 fi log_success "design-guidelines installed" - # Step 3: apm install danielmeppiel/compliance-rules - echo "Running: $BINARY_PATH install danielmeppiel/compliance-rules" + # Step 3: apm install github/awesome-copilot/skills/review-and-refactor + echo "Running: $BINARY_PATH install github/awesome-copilot/skills/review-and-refactor" echo "--- Command Output Start ---" - APM_E2E_TESTS="${APM_E2E_TESTS:-}" "$BINARY_PATH" install danielmeppiel/compliance-rules 2>&1 + APM_E2E_TESTS="${APM_E2E_TESTS:-}" "$BINARY_PATH" install github/awesome-copilot/skills/review-and-refactor 2>&1 exit_code=$? echo "--- Command Output End ---" echo "Exit code: $exit_code" if [[ $exit_code -ne 0 ]]; then - log_error "apm install danielmeppiel/compliance-rules failed" + log_error "apm install github/awesome-copilot/skills/review-and-refactor failed" cd .. return 1 fi - log_success "compliance-rules installed" + log_success "virtual package installed" # Step 4: apm compile echo "Running: $BINARY_PATH compile" diff --git a/src/apm_cli/__init__.py b/src/apm_cli/__init__.py index 111d4239..9d1a56b6 100644 --- a/src/apm_cli/__init__.py +++ b/src/apm_cli/__init__.py @@ -1,4 +1,4 @@ -"""APM-CLI package.""" +"""APM package.""" from .version import get_version diff --git a/src/apm_cli/cli.py b/src/apm_cli/cli.py index e81e85dc..5f5fbc35 100644 --- a/src/apm_cli/cli.py +++ b/src/apm_cli/cli.py @@ -933,7 +933,7 @@ def update(check): import requests install_script_url = ( - "https://raw.githubusercontent.com/danielmeppiel/apm/main/install.sh" + "https://raw.githubusercontent.com/microsoft/apm/main/install.sh" ) response = requests.get(install_script_url, timeout=10) response.raise_for_status() @@ -979,14 +979,14 @@ def update(check): _rich_error("'requests' library not available") _rich_info("Please update manually using:") click.echo( - " curl -sSL https://raw.githubusercontent.com/danielmeppiel/apm/main/install.sh | sh" + " curl -sSL https://raw.githubusercontent.com/microsoft/apm/main/install.sh | sh" ) sys.exit(1) except Exception as e: _rich_error(f"Update failed: {e}") _rich_info("Please update manually using:") click.echo( - " curl -sSL https://raw.githubusercontent.com/danielmeppiel/apm/main/install.sh | sh" + " curl -sSL https://raw.githubusercontent.com/microsoft/apm/main/install.sh | sh" ) sys.exit(1) @@ -1008,9 +1008,9 @@ def uninstall(ctx, packages, dry_run): and the apm_modules/ directory. It's the opposite of 'apm install '. Examples: - apm uninstall danielmeppiel/design-guidelines # Remove one package - apm uninstall org/pkg1 org/pkg2 # Remove multiple packages - apm uninstall danielmeppiel/pkg --dry-run # Show what would be removed + apm uninstall acme/my-package # Remove one package + apm uninstall org/pkg1 org/pkg2 # Remove multiple packages + apm uninstall acme/my-package --dry-run # Show what would be removed """ try: # Check if apm.yml exists @@ -1482,8 +1482,8 @@ def matches_filter(dep): ) as progress: for dep_ref in deps_to_install: # Determine installation directory using namespaced structure - # e.g., danielmeppiel/design-guidelines -> apm_modules/danielmeppiel/design-guidelines/ - # For virtual packages: github/awesome-copilot/prompts/file.prompt.md -> apm_modules/github/awesome-copilot-file/ + # e.g., microsoft/apm-sample-package -> apm_modules/microsoft/apm-sample-package/ + # For virtual packages: owner/repo/prompts/file.prompt.md -> apm_modules/owner/repo-file/ # For subdirectory packages: owner/repo/subdir -> apm_modules/owner/repo/subdir/ if dep_ref.alias: # If alias is provided, use it directly (assume user handles namespacing) @@ -2837,7 +2837,7 @@ def _recompile(self, changed_file): _rich_error("Watch mode requires the 'watchdog' library") _rich_info("Install it with: uv pip install watchdog") _rich_info( - "Or reinstall APM CLI: uv pip install -e . (from the apm-cli directory)" + "Or reinstall APM: uv pip install -e . (from the apm directory)" ) sys.exit(1) except Exception as e: diff --git a/src/apm_cli/config.py b/src/apm_cli/config.py index 9a6ef411..d957571f 100644 --- a/src/apm_cli/config.py +++ b/src/apm_cli/config.py @@ -1,10 +1,10 @@ -"""Configuration management for APM-CLI.""" +"""Configuration management for APM.""" import os import json -CONFIG_DIR = os.path.expanduser("~/.apm-cli") +CONFIG_DIR = os.path.expanduser("~/.apm") CONFIG_FILE = os.path.join(CONFIG_DIR, "config.json") diff --git a/src/apm_cli/core/operations.py b/src/apm_cli/core/operations.py index 91c81359..0b432482 100644 --- a/src/apm_cli/core/operations.py +++ b/src/apm_cli/core/operations.py @@ -1,4 +1,4 @@ -"""Core operations for APM-CLI.""" +"""Core operations for APM.""" from ..factory import ClientFactory, PackageManagerFactory from .safe_installer import SafeMCPInstaller diff --git a/src/apm_cli/core/script_runner.py b/src/apm_cli/core/script_runner.py index 76edae24..2b350d0e 100644 --- a/src/apm_cli/core/script_runner.py +++ b/src/apm_cli/core/script_runner.py @@ -974,7 +974,7 @@ def _resolve_prompt_file(self, prompt_file: str) -> Path: apm_modules_dir = Path("apm_modules") if apm_modules_dir.exists(): # Search all dependency directories for the prompt file - # Handle org/repo directory structure (e.g., apm_modules/danielmeppiel/compliance-rules/) + # Handle org/repo directory structure (e.g., apm_modules/microsoft/apm-sample-package/) for org_dir in apm_modules_dir.iterdir(): if org_dir.is_dir() and not org_dir.name.startswith("."): # Iterate through repos within the org diff --git a/src/apm_cli/deps/__init__.py b/src/apm_cli/deps/__init__.py index 0a17c675..c57662c3 100644 --- a/src/apm_cli/deps/__init__.py +++ b/src/apm_cli/deps/__init__.py @@ -1,4 +1,4 @@ -"""Dependencies management package for APM-CLI.""" +"""Dependencies management package for APM.""" from .apm_resolver import APMDependencyResolver from .dependency_graph import ( diff --git a/src/apm_cli/deps/aggregator.py b/src/apm_cli/deps/aggregator.py index e25ae7dd..4090b923 100644 --- a/src/apm_cli/deps/aggregator.py +++ b/src/apm_cli/deps/aggregator.py @@ -1,4 +1,4 @@ -"""Workflow dependency aggregator for APM-CLI.""" +"""Workflow dependency aggregator for APM.""" import os import glob diff --git a/src/apm_cli/integration/skill_integrator.py b/src/apm_cli/integration/skill_integrator.py index 56b5df3c..3c4314bf 100644 --- a/src/apm_cli/integration/skill_integrator.py +++ b/src/apm_cli/integration/skill_integrator.py @@ -974,7 +974,7 @@ def integrate_package_skill(self, package_info, project_root: Path) -> SkillInte # Determine target paths - write to .github/skills/{skill-name}/ # Use the install folder name for simplicity and consistency - # e.g., apm_modules/danielmeppiel/design-guidelines β†’ design-guidelines + # e.g., apm_modules/microsoft/apm-sample-package β†’ apm-sample-package skill_name = package_path.name skill_dir = project_root / ".github" / "skills" / skill_name skill_dir.mkdir(parents=True, exist_ok=True) diff --git a/src/apm_cli/models/apm_package.py b/src/apm_cli/models/apm_package.py index 9de71844..003f72e5 100644 --- a/src/apm_cli/models/apm_package.py +++ b/src/apm_cli/models/apm_package.py @@ -162,9 +162,9 @@ def get_virtual_package_name(self) -> str: """Generate a package name for this virtual package. For virtual packages, we create a sanitized name from the path: - - github/awesome-copilot/prompts/code-review.prompt.md β†’ awesome-copilot-code-review - - github/awesome-copilot/collections/project-planning β†’ awesome-copilot-project-planning - - github/awesome-copilot/collections/project-planning.collection.yml β†’ awesome-copilot-project-planning + - owner/repo/prompts/code-review.prompt.md β†’ repo-code-review + - owner/repo/collections/project-planning β†’ repo-project-planning + - owner/repo/collections/project-planning.collection.yml β†’ repo-project-planning """ if not self.is_virtual or not self.virtual_path: return self.repo_url.split('/')[-1] # Return repo name as fallback diff --git a/src/apm_cli/registry/__init__.py b/src/apm_cli/registry/__init__.py index 293c559a..59807192 100644 --- a/src/apm_cli/registry/__init__.py +++ b/src/apm_cli/registry/__init__.py @@ -1,4 +1,4 @@ -"""MCP Registry module for APM-CLI.""" +"""MCP Registry module for APM.""" from .client import SimpleRegistryClient from .integration import RegistryIntegration diff --git a/src/apm_cli/utils/console.py b/src/apm_cli/utils/console.py index 5a96cb52..07a6f9b4 100644 --- a/src/apm_cli/utils/console.py +++ b/src/apm_cli/utils/console.py @@ -170,7 +170,7 @@ def show_download_spinner(repo_name: str): """Show spinner during download operations. Usage: - with show_download_spinner("danielmeppiel/design-guidelines"): + with show_download_spinner("microsoft/apm-sample-package"): # Long-running download here pass """ diff --git a/src/apm_cli/utils/helpers.py b/src/apm_cli/utils/helpers.py index 78043abb..ac8c346c 100644 --- a/src/apm_cli/utils/helpers.py +++ b/src/apm_cli/utils/helpers.py @@ -1,4 +1,4 @@ -"""Helper utility functions for APM-CLI.""" +"""Helper utility functions for APM.""" import os import platform diff --git a/src/apm_cli/utils/version_checker.py b/src/apm_cli/utils/version_checker.py index a1674915..72d69971 100644 --- a/src/apm_cli/utils/version_checker.py +++ b/src/apm_cli/utils/version_checker.py @@ -7,7 +7,7 @@ def get_latest_version_from_github( - repo: str = "danielmeppiel/apm", timeout: int = 2 + repo: str = "microsoft/apm", timeout: int = 2 ) -> Optional[str]: """ Fetch the latest release version from GitHub API. @@ -117,10 +117,10 @@ def get_update_cache_path() -> Path: """Get path to version update cache file.""" # Use a cache directory in user's home if sys.platform == "win32": - cache_dir = Path.home() / "AppData" / "Local" / "apm-cli" / "cache" + cache_dir = Path.home() / "AppData" / "Local" / "apm" / "cache" else: # Unix-like systems (macOS, Linux) - cache_dir = Path.home() / ".cache" / "apm-cli" + cache_dir = Path.home() / ".cache" / "apm" cache_dir.mkdir(parents=True, exist_ok=True) return cache_dir / "last_version_check" diff --git a/templates/hello-world/README.md b/templates/hello-world/README.md index 2df366de..a39d441c 100644 --- a/templates/hello-world/README.md +++ b/templates/hello-world/README.md @@ -74,4 +74,4 @@ apm compile --chatmode backend-engineer This project was created with APM - The package manager for AI-Native Development. -Learn more at: https://github.com/danielmeppiel/apm-cli +Learn more at: https://github.com/microsoft/apm diff --git a/templates/hello-world/apm.yml b/templates/hello-world/apm.yml index 4cab7e31..1468c8a9 100644 --- a/templates/hello-world/apm.yml +++ b/templates/hello-world/apm.yml @@ -10,7 +10,7 @@ scripts: dependencies: apm: - - danielmeppiel/design-guidelines # Accessibility rules + UI review workflows + - microsoft/apm-sample-package # Design standards, prompts, and skills mcp: - microsoft/azure-devops-mcp diff --git a/tests/integration/test_ado_e2e.py b/tests/integration/test_ado_e2e.py index 9b1f0334..e007a5a8 100644 --- a/tests/integration/test_ado_e2e.py +++ b/tests/integration/test_ado_e2e.py @@ -220,7 +220,7 @@ def test_virtual_package_not_orphaned(self, tmp_path): class TestMixedDependencies: """Test mixed GitHub and ADO dependencies.""" - GITHUB_PACKAGE = "danielmeppiel/design-guidelines" + GITHUB_PACKAGE = "microsoft/apm-sample-package" ADO_PACKAGE = "dev.azure.com/dmeppiel-org/market-js-app/_git/compliance-rules" def test_mixed_install(self, tmp_path): @@ -247,7 +247,7 @@ def test_mixed_install(self, tmp_path): apm_modules = project_dir / "apm_modules" # GitHub: 2-level - github_path = apm_modules / "danielmeppiel" / "design-guidelines" + github_path = apm_modules / "microsoft" / "apm-sample-package" assert github_path.exists(), f"GitHub package not found: {github_path}" # ADO: 3-level diff --git a/tests/integration/test_apm_dependencies.py b/tests/integration/test_apm_dependencies.py index e18d015b..bf9bcb43 100644 --- a/tests/integration/test_apm_dependencies.py +++ b/tests/integration/test_apm_dependencies.py @@ -2,8 +2,8 @@ Integration tests for APM Dependencies system using real GitHub repositories. Tests the complete dependency workflow with actual repositories: -- danielmeppiel/compliance-rules - Primary dependency test target -- danielmeppiel/design-guidelines - Secondary dependency for multi-dependency scenarios +- microsoft/apm-sample-package - Primary dependency test target (full APM package) +- github/awesome-copilot/skills/review-and-refactor - Virtual subdirectory package test target These tests validate: - Complete dependency installation workflow @@ -73,10 +73,10 @@ def create_apm_yml(self, dependencies: List[str] = None, **kwargs): return config @pytest.mark.integration - def test_single_dependency_installation_compliance_rules(self): - """Test installation of single dependency: compliance-rules.""" + def test_single_dependency_installation_sample_package(self): + """Test installation of single dependency: apm-sample-package.""" # Create project with single dependency - self.create_apm_yml(dependencies=['danielmeppiel/compliance-rules']) + self.create_apm_yml(dependencies=['microsoft/apm-sample-package']) # Initialize downloader downloader = GitHubPackageDownloader() @@ -86,83 +86,67 @@ def test_single_dependency_installation_compliance_rules(self): dependencies = project_package.get_apm_dependencies() assert len(dependencies) == 1 - assert dependencies[0].repo_url == 'danielmeppiel/compliance-rules' + assert dependencies[0].repo_url == 'microsoft/apm-sample-package' # Create apm_modules directory apm_modules_dir = self.test_dir / 'apm_modules' apm_modules_dir.mkdir() # Download the dependency - package_dir = apm_modules_dir / 'compliance-rules' + package_dir = apm_modules_dir / 'microsoft' / 'apm-sample-package' result = downloader.download_package(str(dependencies[0]), package_dir) # Verify installation assert package_dir.exists() assert (package_dir / 'apm.yml').exists() assert (package_dir / '.apm').exists() - assert (package_dir / 'compliance-audit.prompt.md').exists() - assert (package_dir / 'gdpr-assessment.prompt.md').exists() - assert (package_dir / 'legal-review.prompt.md').exists() + assert (package_dir / '.apm' / 'prompts' / 'design-review.prompt.md').exists() + assert (package_dir / '.apm' / 'prompts' / 'accessibility-audit.prompt.md').exists() # Verify APM structure - assert (package_dir / '.apm' / 'chatmodes').exists() - assert (package_dir / '.apm' / 'context').exists() assert (package_dir / '.apm' / 'instructions').exists() # Verify package info - assert result.package.name == 'compliance-rules' + assert result.package.name == 'apm-sample-package' assert result.package.version == '1.0.0' assert result.install_path == package_dir @pytest.mark.integration - def test_single_dependency_installation_design_guidelines(self): - """Test installation of single dependency: design-guidelines.""" - # Create project with single dependency - self.create_apm_yml(dependencies=['danielmeppiel/design-guidelines']) + def test_single_dependency_installation_virtual_package(self): + """Test installation of a virtual subdirectory package from github/awesome-copilot.""" + # Create project with virtual subdirectory dependency (skill) + self.create_apm_yml(dependencies=['github/awesome-copilot/skills/review-and-refactor']) - # Initialize downloader and resolver + # Initialize downloader downloader = GitHubPackageDownloader() - resolver = APMDependencyResolver() # Load project package project_package = APMPackage.from_apm_yml(self.apm_yml_path) dependencies = project_package.get_apm_dependencies() assert len(dependencies) == 1 - assert dependencies[0].repo_url == 'danielmeppiel/design-guidelines' + assert dependencies[0].is_virtual + assert dependencies[0].is_virtual_subdirectory() # Create apm_modules directory apm_modules_dir = self.test_dir / 'apm_modules' apm_modules_dir.mkdir() - # Download the dependency - package_dir = apm_modules_dir / 'design-guidelines' + # Download the virtual subdirectory package + package_dir = apm_modules_dir / 'github' / 'awesome-copilot' / 'skills' / 'review-and-refactor' result = downloader.download_package(str(dependencies[0]), package_dir) # Verify installation assert package_dir.exists() - assert (package_dir / 'apm.yml').exists() - assert (package_dir / '.apm').exists() - assert (package_dir / 'accessibility-audit.prompt.md').exists() - assert (package_dir / 'design-review.prompt.md').exists() - assert (package_dir / 'style-guide-check.prompt.md').exists() - - # Verify APM structure - assert (package_dir / '.apm' / 'context').exists() - assert (package_dir / '.apm' / 'instructions').exists() - - # Verify package info - assert result.package.name == 'design-guidelines' - assert result.package.version == '1.0.0' - assert result.install_path == package_dir + assert (package_dir / 'SKILL.md').exists() or (package_dir / 'apm.yml').exists() @pytest.mark.integration def test_multi_dependency_installation(self): - """Test installation of both dependencies in multi-dependency scenario.""" - # Create project with multiple dependencies + """Test installation of both a full package and virtual package.""" + # Create project with multiple dependencies (full + virtual) self.create_apm_yml(dependencies=[ - 'danielmeppiel/compliance-rules', - 'danielmeppiel/design-guidelines' + 'microsoft/apm-sample-package', + 'github/awesome-copilot/skills/review-and-refactor' ]) # Initialize downloader @@ -179,39 +163,35 @@ def test_multi_dependency_installation(self): apm_modules_dir.mkdir() # Download both dependencies - results = {} - for dep in dependencies: - package_name = dep.repo_url.split('/')[-1] - package_dir = apm_modules_dir / package_name - result = downloader.download_package(str(dep), package_dir) - results[package_name] = result - - # Verify both installations - compliance_dir = apm_modules_dir / 'compliance-rules' - design_dir = apm_modules_dir / 'design-guidelines' - - assert compliance_dir.exists() - assert design_dir.exists() - - # Verify compliance-rules - assert (compliance_dir / 'apm.yml').exists() - assert (compliance_dir / '.apm' / 'chatmodes').exists() - assert len(list(compliance_dir.glob('*.prompt.md'))) == 3 - - # Verify design-guidelines - assert (design_dir / 'apm.yml').exists() - assert (design_dir / '.apm' / 'context').exists() - assert len(list(design_dir.glob('*.prompt.md'))) == 3 + # Full package + full_pkg_dir = apm_modules_dir / 'microsoft' / 'apm-sample-package' + full_pkg_dir.mkdir(parents=True) + result_full = downloader.download_package(str(dependencies[0]), full_pkg_dir) + + # Virtual subdirectory package + virtual_pkg_dir = apm_modules_dir / 'github' / 'awesome-copilot' / 'skills' / 'review-and-refactor' + virtual_pkg_dir.mkdir(parents=True) + result_virtual = downloader.download_package(str(dependencies[1]), virtual_pkg_dir) + + # Verify full package + assert full_pkg_dir.exists() + assert (full_pkg_dir / 'apm.yml').exists() + assert (full_pkg_dir / '.apm' / 'prompts').exists() + assert len(list((full_pkg_dir / '.apm' / 'prompts').glob('*.prompt.md'))) >= 2 + + # Verify virtual subdirectory package + assert virtual_pkg_dir.exists() + assert (virtual_pkg_dir / 'apm.yml').exists() or (virtual_pkg_dir / 'SKILL.md').exists() # Verify no conflicts (both should install successfully) - assert len(results) == 2 - assert all(result.package is not None for result in results.values()) + assert result_full.package is not None + assert result_virtual.package is not None @pytest.mark.integration def test_dependency_compilation_integration(self): """Test compilation integration with dependencies to verify source attribution.""" # Create project with dependencies - self.create_apm_yml(dependencies=['danielmeppiel/compliance-rules']) + self.create_apm_yml(dependencies=['microsoft/apm-sample-package']) # Create some local primitives that might conflict local_apm_dir = self.test_dir / '.apm' @@ -221,14 +201,14 @@ def test_dependency_compilation_integration(self): instructions_dir.mkdir() # Create a local instruction that should override dependency - local_instruction = instructions_dir / 'legal-compliance.instructions.md' + local_instruction = instructions_dir / 'design-override.instructions.md' local_instruction.write_text("""--- -title: Local Legal Compliance +title: Local Design Override applyTo: ["*.py", "*.js"] -tags: ["legal", "local-override"] +tags: ["design", "local-override"] --- -# Local Legal Compliance Override +# Local Design Override This local instruction should override any dependency instruction. """) @@ -238,8 +218,8 @@ def test_dependency_compilation_integration(self): apm_modules_dir = self.test_dir / 'apm_modules' apm_modules_dir.mkdir() - package_dir = apm_modules_dir / 'compliance-rules' - dep_ref = DependencyReference(repo_url='danielmeppiel/compliance-rules') + package_dir = apm_modules_dir / 'apm-sample-package' + dep_ref = DependencyReference(repo_url='microsoft/apm-sample-package') downloader.download_package(str(dep_ref), package_dir) # Compile AGENTS.md to verify source attribution @@ -265,7 +245,7 @@ def test_dependency_compilation_integration(self): def test_dependency_branch_reference(self): """Test dependency installation with specific branch reference.""" # Create project with branch-specific dependency - self.create_apm_yml(dependencies=['danielmeppiel/compliance-rules#main']) + self.create_apm_yml(dependencies=['microsoft/apm-sample-package#main']) downloader = GitHubPackageDownloader() project_package = APMPackage.from_apm_yml(self.apm_yml_path) @@ -273,7 +253,7 @@ def test_dependency_branch_reference(self): assert len(dependencies) == 1 dep = dependencies[0] - assert dep.repo_url == 'danielmeppiel/compliance-rules' + assert dep.repo_url == 'microsoft/apm-sample-package' assert dep.reference == 'main' # Create apm_modules directory @@ -281,7 +261,7 @@ def test_dependency_branch_reference(self): apm_modules_dir.mkdir() # Download with branch reference - package_dir = apm_modules_dir / 'compliance-rules' + package_dir = apm_modules_dir / 'apm-sample-package' result = downloader.download_package(str(dep), package_dir) # Verify installation @@ -301,7 +281,7 @@ def test_dependency_error_handling_invalid_repo(self): # Test with invalid repository with pytest.raises((RuntimeError, ValueError)): - downloader.download_package('danielmeppiel/non-existent-repo-12345', package_dir) + downloader.download_package('acme/non-existent-repo-12345', package_dir) @pytest.mark.integration def test_dependency_network_error_simulation(self): @@ -316,23 +296,23 @@ def test_dependency_network_error_simulation(self): apm_modules_dir = self.test_dir / 'apm_modules' apm_modules_dir.mkdir() - package_dir = apm_modules_dir / 'compliance-rules' + package_dir = apm_modules_dir / 'apm-sample-package' with pytest.raises(RuntimeError, match="Failed to clone repository"): - downloader.download_package('danielmeppiel/compliance-rules', package_dir) + downloader.download_package('microsoft/apm-sample-package', package_dir) @pytest.mark.integration def test_cli_deps_commands_with_real_dependencies(self): """Test CLI deps commands with real installed dependencies.""" # Install dependencies first - self.create_apm_yml(dependencies=['danielmeppiel/compliance-rules']) + self.create_apm_yml(dependencies=['microsoft/apm-sample-package']) downloader = GitHubPackageDownloader() apm_modules_dir = self.test_dir / 'apm_modules' apm_modules_dir.mkdir() - package_dir = apm_modules_dir / 'compliance-rules' - dep_ref = DependencyReference(repo_url='danielmeppiel/compliance-rules') + package_dir = apm_modules_dir / 'apm-sample-package' + dep_ref = DependencyReference(repo_url='microsoft/apm-sample-package') downloader.download_package(str(dep_ref), package_dir) # Import and test CLI commands @@ -341,25 +321,25 @@ def test_cli_deps_commands_with_real_dependencies(self): # Test file counting context_count, workflow_count = _count_package_files(package_dir) assert context_count >= 0 # May have context files in .apm structure - assert workflow_count == 3 # Should have 3 .prompt.md files + assert workflow_count >= 2 # Should have prompt files # Test package display info package_info = _get_package_display_info(package_dir) - assert package_info['name'] == 'compliance-rules' + assert package_info['name'] == 'apm-sample-package' assert package_info['version'] == '1.0.0' @pytest.mark.integration def test_dependency_update_workflow(self): """Test dependency update workflow with real repository.""" # Install initial dependency - self.create_apm_yml(dependencies=['danielmeppiel/compliance-rules']) + self.create_apm_yml(dependencies=['microsoft/apm-sample-package']) downloader = GitHubPackageDownloader() apm_modules_dir = self.test_dir / 'apm_modules' apm_modules_dir.mkdir() - package_dir = apm_modules_dir / 'compliance-rules' - dep_ref = DependencyReference(repo_url='danielmeppiel/compliance-rules') + package_dir = apm_modules_dir / 'apm-sample-package' + dep_ref = DependencyReference(repo_url='microsoft/apm-sample-package') result1 = downloader.download_package(str(dep_ref), package_dir) original_commit = result1.resolved_reference.resolved_commit @@ -369,7 +349,7 @@ def test_dependency_update_workflow(self): result2 = downloader.download_package(str(dep_ref), package_dir) # Verify update completed - assert result2.package.name == 'compliance-rules' + assert result2.package.name == 'apm-sample-package' assert result2.install_path == package_dir # Commits should be the same since we're pulling from the same state assert result2.resolved_reference.resolved_commit == original_commit @@ -382,17 +362,17 @@ def test_integration_test_infrastructure_smoke_test(self): assert downloader is not None # Test that dependency reference can be created - dep_ref = DependencyReference(repo_url='danielmeppiel/compliance-rules') - assert dep_ref.repo_url == 'danielmeppiel/compliance-rules' - assert dep_ref.get_display_name() == 'danielmeppiel/compliance-rules' # Display name is the full repo name + dep_ref = DependencyReference(repo_url='microsoft/apm-sample-package') + assert dep_ref.repo_url == 'microsoft/apm-sample-package' + assert dep_ref.get_display_name() == 'microsoft/apm-sample-package' # Display name is the full repo name # Test that APM package can be created from config - self.create_apm_yml(dependencies=['danielmeppiel/compliance-rules']) + self.create_apm_yml(dependencies=['microsoft/apm-sample-package']) project_package = APMPackage.from_apm_yml(self.apm_yml_path) dependencies = project_package.get_apm_dependencies() assert len(dependencies) == 1 - assert dependencies[0].repo_url == 'danielmeppiel/compliance-rules' + assert dependencies[0].repo_url == 'microsoft/apm-sample-package' # Test directory structure apm_modules_dir = self.test_dir / 'apm_modules' @@ -431,7 +411,7 @@ def test_cross_platform_dependency_download(self): apm_modules_dir = temp_dir / 'apm_modules' apm_modules_dir.mkdir() - package_dir = apm_modules_dir / 'compliance-rules' + package_dir = apm_modules_dir / 'apm-sample-package' assert package_dir.parent.exists() # Verify path separators work correctly diff --git a/tests/integration/test_auto_install_e2e.py b/tests/integration/test_auto_install_e2e.py index eb479f4c..6f32c55b 100644 --- a/tests/integration/test_auto_install_e2e.py +++ b/tests/integration/test_auto_install_e2e.py @@ -2,7 +2,7 @@ End-to-end tests for auto-install feature (README Hero Scenario). Tests the exact zero-config flow from the README: - apm run github/awesome-copilot/prompts/architecture-blueprint-generator + apm run github/awesome-copilot/skills/architecture-blueprint-generator This validates that users can run virtual packages without manual installation. @@ -75,7 +75,7 @@ def test_auto_install_virtual_prompt_first_run(self, temp_e2e_home): """Test auto-install on first run with virtual package reference. This is the exact README hero scenario: - apm run github/awesome-copilot/prompts/architecture-blueprint-generator + apm run github/awesome-copilot/skills/architecture-blueprint-generator Expected behavior: 1. Package doesn't exist locally @@ -97,7 +97,7 @@ def test_auto_install_virtual_prompt_first_run(self, temp_e2e_home): [ "apm", "run", - "github/awesome-copilot/prompts/architecture-blueprint-generator" + "github/awesome-copilot/skills/architecture-blueprint-generator" ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -143,16 +143,12 @@ def test_auto_install_virtual_prompt_first_run(self, temp_e2e_home): assert execution_started, "Should have started execution (✨ Package installed and ready to run)" # Verify package was installed - package_path = apm_modules / "github" / "awesome-copilot-architecture-blueprint-generator" + package_path = apm_modules / "github" / "awesome-copilot" / "skills" / "architecture-blueprint-generator" assert package_path.exists(), f"Package should be installed at {package_path}" - # Verify apm.yml was created in the virtual package - apm_yml = package_path / "apm.yml" - assert apm_yml.exists(), "Virtual package should have apm.yml" - - # Verify the prompt file exists - prompt_file = package_path / ".apm" / "prompts" / "architecture-blueprint-generator.prompt.md" - assert prompt_file.exists(), f"Prompt file should exist at {prompt_file}" + # Verify SKILL.md or apm.yml exists in the virtual package + assert (package_path / "SKILL.md").exists() or (package_path / "apm.yml").exists(), \ + "Virtual package should have SKILL.md or apm.yml" print(f"βœ… Auto-install successful: {package_path}") @@ -173,7 +169,7 @@ def test_auto_install_uses_cache_on_second_run(self, temp_e2e_home): [ "apm", "run", - "github/awesome-copilot/prompts/architecture-blueprint-generator" + "github/awesome-copilot/skills/architecture-blueprint-generator" ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -195,7 +191,7 @@ def test_auto_install_uses_cache_on_second_run(self, temp_e2e_home): process.wait() # Verify package exists - package_path = Path("apm_modules/github/awesome-copilot-architecture-blueprint-generator") + package_path = Path("apm_modules") / "github" / "awesome-copilot" / "skills" / "architecture-blueprint-generator" assert package_path.exists(), "Package should exist after first run" # Second run - should use cache with early termination @@ -203,7 +199,7 @@ def test_auto_install_uses_cache_on_second_run(self, temp_e2e_home): [ "apm", "run", - "github/awesome-copilot/prompts/architecture-blueprint-generator" + "github/awesome-copilot/skills/architecture-blueprint-generator" ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -253,7 +249,7 @@ def test_simple_name_works_after_install(self, temp_e2e_home): [ "apm", "run", - "github/awesome-copilot/prompts/architecture-blueprint-generator" + "github/awesome-copilot/skills/architecture-blueprint-generator" ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -315,7 +311,7 @@ def test_auto_install_with_qualified_path(self, temp_e2e_home): """Test auto-install works with qualified path format. Tests both formats: - - Full: github/awesome-copilot/prompts/file.prompt.md + - Full: github/awesome-copilot/skills/review-and-refactor - Qualified: github/awesome-copilot/architecture-blueprint-generator """ # Set up environment @@ -327,7 +323,7 @@ def test_auto_install_with_qualified_path(self, temp_e2e_home): [ "apm", "run", - "github/awesome-copilot/prompts/architecture-blueprint-generator" + "github/awesome-copilot/skills/architecture-blueprint-generator" ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -350,12 +346,12 @@ def test_auto_install_with_qualified_path(self, temp_e2e_home): process.wait() # Check that package was installed - package_path = Path("apm_modules/github/awesome-copilot-architecture-blueprint-generator") + package_path = Path("apm_modules/github/awesome-copilot/skills/architecture-blueprint-generator") assert package_path.exists(), "Package should be installed" - # Check that prompt file exists - prompt_file = package_path / ".apm" / "prompts" / "architecture-blueprint-generator.prompt.md" - assert prompt_file.exists(), "Prompt file should exist" + # Check that SKILL.md file exists + skill_file = package_path / "SKILL.md" + assert skill_file.exists(), "SKILL.md should exist" print("βœ… Auto-install works with qualified path") diff --git a/tests/integration/test_collection_install.py b/tests/integration/test_collection_install.py index 428d6d2b..8000ac7b 100644 --- a/tests/integration/test_collection_install.py +++ b/tests/integration/test_collection_install.py @@ -14,18 +14,18 @@ class TestCollectionInstallation: def test_parse_collection_dependency(self): """Test parsing a collection dependency reference.""" - dep_ref = DependencyReference.parse("github/awesome-copilot/collections/awesome-copilot") + dep_ref = DependencyReference.parse("owner/test-repo/collections/awesome-copilot") assert dep_ref.is_virtual is True assert dep_ref.is_virtual_collection() is True assert dep_ref.is_virtual_file() is False - assert dep_ref.repo_url == "github/awesome-copilot" + assert dep_ref.repo_url == "owner/test-repo" assert dep_ref.virtual_path == "collections/awesome-copilot" - assert dep_ref.get_virtual_package_name() == "awesome-copilot-awesome-copilot" + assert dep_ref.get_virtual_package_name() == "test-repo-awesome-copilot" def test_parse_collection_with_reference(self): """Test parsing a collection dependency with git reference.""" - dep_ref = DependencyReference.parse("github/awesome-copilot/collections/project-planning#main") + dep_ref = DependencyReference.parse("owner/test-repo/collections/project-planning#main") assert dep_ref.is_virtual is True assert dep_ref.is_virtual_collection() is True @@ -34,6 +34,7 @@ def test_parse_collection_with_reference(self): @pytest.mark.integration @pytest.mark.slow + @pytest.mark.skip(reason="github/awesome-copilot no longer has collections/ directory (deprecated in favor of plugins)") def test_download_small_collection(self): """Test downloading a small collection from awesome-copilot. diff --git a/tests/integration/test_golden_scenario_e2e.py b/tests/integration/test_golden_scenario_e2e.py index 60d43038..da45960f 100644 --- a/tests/integration/test_golden_scenario_e2e.py +++ b/tests/integration/test_golden_scenario_e2e.py @@ -306,7 +306,7 @@ def test_complete_golden_scenario_copilot(self, temp_e2e_home, apm_binary): env['HOME'] = temp_e2e_home # Run with real-time output streaming (using 'start' script which calls Copilot CLI) - cmd = f'{apm_binary} run start --param name="danielmeppiel"' + cmd = f'{apm_binary} run start --param name="developer"' print(f"Executing: {cmd}") try: @@ -350,14 +350,14 @@ def test_complete_golden_scenario_copilot(self, temp_e2e_home, apm_binary): # Verify output contains expected elements (using "Developer" instead of "E2E Tester") output_lower = full_output.lower() - assert "danielmeppiel" in output_lower, \ + assert "developer" in output_lower, \ f"Parameter substitution failed. Expected 'Developer', got: {full_output}" assert len(full_output.strip()) > 50, \ f"Output seems too short, API call might have failed. Output: {full_output}" print(f"\nβœ… Golden scenario completed successfully!") print(f"Output length: {len(full_output)} characters") - print(f"Contains parameter: {'βœ“' if 'danielmeppiel' in output_lower else '❌'}") + print(f"Contains parameter: {'βœ“' if 'developer' in output_lower else '❌'}") except subprocess.TimeoutExpired: process.kill() @@ -468,7 +468,7 @@ def test_complete_golden_scenario_codex(self, temp_e2e_home, apm_binary): env['HOME'] = temp_e2e_home # Run the Codex command with proper environment (use 'debug' script which calls Codex CLI) - cmd = f'{apm_binary} run debug --param name="danielmeppiel"' + cmd = f'{apm_binary} run debug --param name="developer"' process = subprocess.Popen( cmd, shell=True, @@ -494,7 +494,7 @@ def test_complete_golden_scenario_codex(self, temp_e2e_home, apm_binary): # Verify execution (Codex CLI might have different authentication requirements) if return_code == 0: output = full_output.lower() - assert "danielmeppiel" in output, "Parameter substitution failed" + assert "developer" in output, "Parameter substitution failed" assert len(output.strip()) > 50, "Output seems too short" print(f"\nβœ… Codex CLI scenario completed successfully!") print(f"Output length: {len(full_output)} characters") @@ -613,7 +613,7 @@ def test_complete_golden_scenario_llm(self, temp_e2e_home, apm_binary): env['GITHUB_MODELS_KEY'] = github_token # Run the LLM command with proper environment (use 'llm' script, not 'start') - cmd = f'{apm_binary} run llm --param name="danielmeppiel"' + cmd = f'{apm_binary} run llm --param name="developer"' process = subprocess.Popen( cmd, shell=True, @@ -636,7 +636,7 @@ def test_complete_golden_scenario_llm(self, temp_e2e_home, apm_binary): # Verify execution (LLM might have different authentication requirements) if return_code == 0: output = full_output.lower() - assert "danielmeppiel" in output, "Parameter substitution failed" + assert "developer" in output, "Parameter substitution failed" assert len(output.strip()) > 50, "Output seems too short" print(f"\\n=== LLM scenario output ===\\n{full_output}") else: diff --git a/tests/integration/test_guardrailing_hero_e2e.py b/tests/integration/test_guardrailing_hero_e2e.py index 32521af8..b0a7616c 100644 --- a/tests/integration/test_guardrailing_hero_e2e.py +++ b/tests/integration/test_guardrailing_hero_e2e.py @@ -3,15 +3,15 @@ Tests the exact 2-minute guardrailing flow from README (lines 46-60): 1. apm init my-project && cd my-project -2. apm install danielmeppiel/design-guidelines -3. apm install danielmeppiel/compliance-rules +2. apm install microsoft/apm-sample-package +3. apm install github/awesome-copilot/skills/review-and-refactor 4. apm compile 5. apm run design-review This validates that: - Multiple APM packages can be installed - AGENTS.md is generated with combined guardrails -- Prompts from installed packages work correctly +- Skills from installed packages work correctly """ import os @@ -110,8 +110,8 @@ def test_2_minute_guardrailing_flow(self, apm_binary): Validates: 1. apm init my-project creates minimal project - 2. apm install danielmeppiel/design-guidelines succeeds - 3. apm install danielmeppiel/compliance-rules succeeds + 2. apm install microsoft/apm-sample-package succeeds + 3. apm install github/awesome-copilot/skills/review-and-refactor succeeds 4. apm compile generates AGENTS.md with both packages 5. apm run design-review executes prompt from installed package """ @@ -128,11 +128,11 @@ def test_2_minute_guardrailing_flow(self, apm_binary): print("βœ“ Project initialized") - # Step 2: apm install danielmeppiel/design-guidelines - print("\n=== Step 2: apm install danielmeppiel/design-guidelines ===") + # Step 2: apm install microsoft/apm-sample-package + print("\n=== Step 2: apm install microsoft/apm-sample-package ===") env = os.environ.copy() result = run_command( - f"{apm_binary} install danielmeppiel/design-guidelines", + f"{apm_binary} install microsoft/apm-sample-package", cwd=project_dir, show_output=True, env=env @@ -140,28 +140,28 @@ def test_2_minute_guardrailing_flow(self, apm_binary): assert result.returncode == 0, f"design-guidelines install failed: {result.stderr}" # Verify installation - design_pkg = project_dir / "apm_modules" / "danielmeppiel" / "design-guidelines" + design_pkg = project_dir / "apm_modules" / "microsoft" / "apm-sample-package" assert design_pkg.exists(), "design-guidelines package not installed" assert (design_pkg / "apm.yml").exists(), "design-guidelines apm.yml not found" print("βœ“ design-guidelines installed") - # Step 3: apm install danielmeppiel/compliance-rules - print("\n=== Step 3: apm install danielmeppiel/compliance-rules ===") + # Step 3: apm install github/awesome-copilot/skills/review-and-refactor + print("\n=== Step 3: apm install github/awesome-copilot/skills/review-and-refactor ===") result = run_command( - f"{apm_binary} install danielmeppiel/compliance-rules", + f"{apm_binary} install github/awesome-copilot/skills/review-and-refactor", cwd=project_dir, show_output=True, env=env ) - assert result.returncode == 0, f"compliance-rules install failed: {result.stderr}" + assert result.returncode == 0, f"virtual package install failed: {result.stderr}" - # Verify installation - compliance_pkg = project_dir / "apm_modules" / "danielmeppiel" / "compliance-rules" - assert compliance_pkg.exists(), "compliance-rules package not installed" - assert (compliance_pkg / "apm.yml").exists(), "compliance-rules apm.yml not found" + # Verify installation (virtual subdirectory package is installed under github/awesome-copilot/skills/review-and-refactor) + virtual_pkg = project_dir / "apm_modules" / "github" / "awesome-copilot" / "skills" / "review-and-refactor" + assert virtual_pkg.exists(), "virtual package not installed" + assert (virtual_pkg / "SKILL.md").exists() or (virtual_pkg / "apm.yml").exists(), "virtual package content not found" - print("βœ“ compliance-rules installed") + print("βœ“ virtual package installed") # Step 4: apm compile print("\n=== Step 4: apm compile ===") @@ -176,8 +176,8 @@ def test_2_minute_guardrailing_flow(self, apm_binary): agents_content = agents_md.read_text() assert "design-guidelines" in agents_content.lower() or "design" in agents_content.lower(), \ "AGENTS.md doesn't contain design-guidelines content" - assert "compliance" in agents_content.lower() or "gdpr" in agents_content.lower(), \ - "AGENTS.md doesn't contain compliance-rules content" + assert "code-review" in agents_content.lower() or "review" in agents_content.lower(), \ + "AGENTS.md doesn't contain code-review content" print(f"βœ“ AGENTS.md generated ({len(agents_content)} bytes)") print(f" Contains design-guidelines: βœ“") diff --git a/tests/integration/test_integration.py b/tests/integration/test_integration.py index ed81def6..307b55eb 100644 --- a/tests/integration/test_integration.py +++ b/tests/integration/test_integration.py @@ -1,4 +1,4 @@ -"""Integration tests for APM-CLI.""" +"""Integration tests for APM.""" import os import json @@ -34,7 +34,7 @@ def safe_rmdir(path): class TestIntegration(unittest.TestCase): - """Integration test cases for APM-CLI.""" + """Integration test cases for APM.""" def setUp(self): """Set up test fixtures.""" diff --git a/tests/integration/test_mixed_deps.py b/tests/integration/test_mixed_deps.py index 735b8975..2f09cdf0 100644 --- a/tests/integration/test_mixed_deps.py +++ b/tests/integration/test_mixed_deps.py @@ -64,7 +64,7 @@ def test_install_apm_package_and_claude_skill(self, temp_project, apm_command): """Install an APM package and a Claude Skill in the same project.""" # Install APM package first result1 = subprocess.run( - [apm_command, "install", "danielmeppiel/compliance-rules"], + [apm_command, "install", "microsoft/apm-sample-package"], cwd=temp_project, capture_output=True, text=True, @@ -73,7 +73,7 @@ def test_install_apm_package_and_claude_skill(self, temp_project, apm_command): # May fail if package doesn't exist or no access if result1.returncode != 0: - pytest.skip(f"Could not install compliance-rules: {result1.stderr}") + pytest.skip(f"Could not install apm-sample-package: {result1.stderr}") # Install Claude Skill result2 = subprocess.run( @@ -86,7 +86,7 @@ def test_install_apm_package_and_claude_skill(self, temp_project, apm_command): assert result2.returncode == 0, f"Skill install failed: {result2.stderr}" # Verify both are installed - apm_package_path = temp_project / "apm_modules" / "danielmeppiel" / "compliance-rules" + apm_package_path = temp_project / "apm_modules" / "microsoft" / "apm-sample-package" skill_path = temp_project / "apm_modules" / "ComposioHQ" / "awesome-claude-skills" / "brand-guidelines" assert apm_package_path.exists(), "APM package not installed" @@ -96,7 +96,7 @@ def test_apm_yml_contains_both_dependency_types(self, temp_project, apm_command) """Verify apm.yml lists both APM packages and Claude Skills.""" # Install both subprocess.run( - [apm_command, "install", "danielmeppiel/compliance-rules"], + [apm_command, "install", "microsoft/apm-sample-package"], cwd=temp_project, capture_output=True, text=True, @@ -117,7 +117,7 @@ def test_apm_yml_contains_both_dependency_types(self, temp_project, apm_command) # Verify the skill is in dependencies has_skill = "awesome-claude-skills/brand-guidelines" in content - # At least the skill should be there (compliance-rules may fail) + # At least the skill should be there (apm-sample-package may fail) assert has_skill, "Claude Skill not in apm.yml" @@ -196,7 +196,7 @@ class TestDependencyTypeDetection: def test_apm_package_has_apm_yml(self, temp_project, apm_command): """APM packages have apm.yml at root.""" result = subprocess.run( - [apm_command, "install", "danielmeppiel/compliance-rules"], + [apm_command, "install", "microsoft/apm-sample-package"], cwd=temp_project, capture_output=True, text=True, @@ -204,9 +204,9 @@ def test_apm_package_has_apm_yml(self, temp_project, apm_command): ) if result.returncode != 0: - pytest.skip("Could not install compliance-rules") + pytest.skip("Could not install apm-sample-package") - pkg_path = temp_project / "apm_modules" / "danielmeppiel" / "compliance-rules" + pkg_path = temp_project / "apm_modules" / "microsoft" / "apm-sample-package" assert (pkg_path / "apm.yml").exists(), "APM package missing apm.yml" def test_claude_skill_has_skill_md(self, temp_project, apm_command): diff --git a/tests/integration/test_runnable_prompts_integration.py b/tests/integration/test_runnable_prompts_integration.py index c40fad2b..228bcb3e 100644 --- a/tests/integration/test_runnable_prompts_integration.py +++ b/tests/integration/test_runnable_prompts_integration.py @@ -257,11 +257,11 @@ def test_virtual_package_prompt_workflow(self, tmp_path): name: test-project dependencies: apm: - - github/awesome-copilot/prompts/architecture-blueprint-generator.prompt.md + - owner/test-repo/prompts/architecture-blueprint-generator.prompt.md """) # Simulate installed virtual package structure - virtual_pkg_dir = tmp_path / "apm_modules" / "github" / "awesome-copilot-architecture-blueprint-generator" / ".apm" / "prompts" + virtual_pkg_dir = tmp_path / "apm_modules" / "owner" / "test-repo-architecture-blueprint-generator" / ".apm" / "prompts" virtual_pkg_dir.mkdir(parents=True) prompt_file = virtual_pkg_dir / "architecture-blueprint-generator.prompt.md" prompt_file.write_text("""--- diff --git a/tests/integration/test_virtual_package_orphan_detection.py b/tests/integration/test_virtual_package_orphan_detection.py index 799bae3b..3084751a 100644 --- a/tests/integration/test_virtual_package_orphan_detection.py +++ b/tests/integration/test_virtual_package_orphan_detection.py @@ -1,7 +1,7 @@ """ Integration tests for orphan detection with virtual packages. -Tests that virtual packages (individual files and collections) are correctly +Tests that virtual packages (individual files, plugins, and subdirectory packages) are correctly recognized and not flagged as orphaned when they are declared in apm.yml. Also tests Azure DevOps (ADO) packages which use a 3-level directory structure @@ -132,18 +132,18 @@ def _find_orphaned_packages(project_dir): @pytest.mark.integration def test_virtual_collection_not_flagged_as_orphan(tmp_path): - """Test that installed virtual collection is not flagged as orphaned.""" + """Test that installed virtual plugin is not flagged as orphaned.""" # Create test project structure project_dir = tmp_path / "test-project" project_dir.mkdir() - # Create apm.yml with collection dependency + # Create apm.yml with plugin subdirectory dependency apm_yml_content = { "name": "test-project", "version": "1.0.0", "dependencies": { "apm": [ - "github/awesome-copilot/collections/awesome-copilot" + "github/awesome-copilot/plugins/awesome-copilot" ] } } @@ -151,31 +151,39 @@ def test_virtual_collection_not_flagged_as_orphan(tmp_path): with open(project_dir / "apm.yml", "w") as f: yaml.dump(apm_yml_content, f) - # Simulate installed virtual collection package - # Virtual collections are installed as: apm_modules/{org}/{repo-name}-{collection-name}/ - collection_dir = project_dir / "apm_modules" / "github" / "awesome-copilot-awesome-copilot" - collection_dir.mkdir(parents=True) + # Simulate installed virtual subdirectory plugin package + # Subdirectory packages are installed at natural path: apm_modules/{org}/{repo}/{subdir} + plugin_dir = project_dir / "apm_modules" / "github" / "awesome-copilot" / "plugins" / "awesome-copilot" + plugin_dir.mkdir(parents=True) - # Create generated apm.yml in the collection - collection_apm = { - "name": "awesome-copilot-awesome-copilot", + # Create apm.yml in the plugin + plugin_apm = { + "name": "awesome-copilot", "version": "1.0.0", - "description": "Virtual collection package" + "description": "Plugin package" } - with open(collection_dir / "apm.yml", "w") as f: - yaml.dump(collection_apm, f) + with open(plugin_dir / "apm.yml", "w") as f: + yaml.dump(plugin_apm, f) # Add some files to make it realistic - (collection_dir / ".apm").mkdir() - (collection_dir / ".apm" / "prompts").mkdir() - (collection_dir / ".apm" / "prompts" / "test.prompt.md").write_text("# Test prompt") + (plugin_dir / ".apm").mkdir() + (plugin_dir / ".apm" / "skills").mkdir() + (plugin_dir / ".apm" / "skills" / "test").mkdir() + (plugin_dir / ".apm" / "skills" / "test" / "SKILL.md").write_text("# Test skill") - # Check for orphans using shared helper - orphaned_packages, _ = _find_orphaned_packages(project_dir) + # Build expected set from declared dependencies + package = APMPackage.from_apm_yml(project_dir / "apm.yml") + expected_installed = _build_expected_installed_packages(package.get_apm_dependencies()) - # Assert no orphans found + # Compute a unified view of all installed packages (2-3 level + 4+ level) + installed_pkgs = set(_find_installed_packages(project_dir / "apm_modules")) + installed_pkgs.update(_find_installed_subdirectory_packages(project_dir / "apm_modules")) + + orphaned_packages = [pkg for pkg in installed_pkgs if pkg not in expected_installed] + + assert "github/awesome-copilot/plugins/awesome-copilot" in expected_installed assert len(orphaned_packages) == 0, \ - f"Virtual collection should not be flagged as orphaned. Found: {orphaned_packages}" + f"Plugin should not be flagged as orphaned. Found: {orphaned_packages}" @pytest.mark.integration @@ -185,13 +193,13 @@ def test_virtual_file_not_flagged_as_orphan(tmp_path): project_dir = tmp_path / "test-project" project_dir.mkdir() - # Create apm.yml with virtual file dependency + # Create apm.yml with virtual skill dependency apm_yml_content = { "name": "test-project", "version": "1.0.0", "dependencies": { "apm": [ - "github/awesome-copilot/prompts/code-review.prompt.md" + "github/awesome-copilot/skills/review-and-refactor" ] } } @@ -199,31 +207,36 @@ def test_virtual_file_not_flagged_as_orphan(tmp_path): with open(project_dir / "apm.yml", "w") as f: yaml.dump(apm_yml_content, f) - # Simulate installed virtual file package - # Virtual files are installed as: apm_modules/{org}/{repo-name}-{file-name}/ - file_pkg_dir = project_dir / "apm_modules" / "github" / "awesome-copilot-code-review" + # Simulate installed virtual subdirectory skill package + # Subdirectory packages are installed at natural path + file_pkg_dir = project_dir / "apm_modules" / "github" / "awesome-copilot" / "skills" / "review-and-refactor" file_pkg_dir.mkdir(parents=True) - # Create generated apm.yml in the package + # Create apm.yml in the package file_pkg_apm = { - "name": "awesome-copilot-code-review", + "name": "review-and-refactor", "version": "1.0.0", - "description": "Virtual file package" + "description": "Virtual skill package" } with open(file_pkg_dir / "apm.yml", "w") as f: yaml.dump(file_pkg_apm, f) - # Add the prompt file - (file_pkg_dir / ".apm").mkdir() - (file_pkg_dir / ".apm" / "prompts").mkdir() - (file_pkg_dir / ".apm" / "prompts" / "code-review.prompt.md").write_text("# Code review prompt") + # Add the SKILL.md file + (file_pkg_dir / "SKILL.md").write_text("# Review and Refactor skill") - # Check for orphans using shared helper - orphaned_packages, _ = _find_orphaned_packages(project_dir) + # Build expected set from declared dependencies + package = APMPackage.from_apm_yml(project_dir / "apm.yml") + expected_installed = _build_expected_installed_packages(package.get_apm_dependencies()) - # Assert no orphans found + # Compute a unified view of all installed packages (2-3 level + 4+ level) + installed_pkgs = set(_find_installed_packages(project_dir / "apm_modules")) + installed_pkgs.update(_find_installed_subdirectory_packages(project_dir / "apm_modules")) + + orphaned_packages = [pkg for pkg in installed_pkgs if pkg not in expected_installed] + + assert "github/awesome-copilot/skills/review-and-refactor" in expected_installed assert len(orphaned_packages) == 0, \ - f"Virtual file should not be flagged as orphaned. Found: {orphaned_packages}" + f"Virtual skill should not be flagged as orphaned. Found: {orphaned_packages}" @pytest.mark.integration @@ -239,9 +252,9 @@ def test_mixed_dependencies_orphan_detection(tmp_path): "version": "1.0.0", "dependencies": { "apm": [ - "danielmeppiel/design-guidelines", # Regular package - "github/awesome-copilot/collections/awesome-copilot", # Virtual collection - "danielmeppiel/compliance-rules/prompts/gdpr.prompt.md" # Virtual file + "microsoft/apm-sample-package", # Regular package + "github/awesome-copilot/plugins/awesome-copilot", # Virtual plugin + "github/awesome-copilot/skills/code-exemplars-blueprint-generator" # Virtual skill ] } } @@ -253,22 +266,29 @@ def test_mixed_dependencies_orphan_detection(tmp_path): apm_modules_dir = project_dir / "apm_modules" # Regular package - regular_dir = apm_modules_dir / "danielmeppiel" / "design-guidelines" + regular_dir = apm_modules_dir / "microsoft" / "apm-sample-package" regular_dir.mkdir(parents=True) - (regular_dir / "apm.yml").write_text("name: design-guidelines\nversion: 1.0.0") + (regular_dir / "apm.yml").write_text("name: apm-sample-package\nversion: 1.0.0") - # Virtual collection - collection_dir = apm_modules_dir / "github" / "awesome-copilot-awesome-copilot" - collection_dir.mkdir(parents=True) - (collection_dir / "apm.yml").write_text("name: awesome-copilot-awesome-copilot\nversion: 1.0.0") + # Virtual plugin subdirectory + plugin_dir = apm_modules_dir / "github" / "awesome-copilot" / "plugins" / "awesome-copilot" + plugin_dir.mkdir(parents=True) + (plugin_dir / "apm.yml").write_text("name: awesome-copilot\nversion: 1.0.0") - # Virtual file - file_dir = apm_modules_dir / "danielmeppiel" / "compliance-rules-gdpr" - file_dir.mkdir(parents=True) - (file_dir / "apm.yml").write_text("name: compliance-rules-gdpr\nversion: 1.0.0") + # Virtual skill subdirectory + skill_dir = apm_modules_dir / "github" / "awesome-copilot" / "skills" / "code-exemplars-blueprint-generator" + skill_dir.mkdir(parents=True) + (skill_dir / "apm.yml").write_text("name: code-exemplars-blueprint-generator\nversion: 1.0.0") - # Check for orphans using shared helper - orphaned_packages, expected_installed = _find_orphaned_packages(project_dir) + # Build expected set from declared dependencies + package = APMPackage.from_apm_yml(project_dir / "apm.yml") + expected_installed = _build_expected_installed_packages(package.get_apm_dependencies()) + + # Compute a unified view of all installed packages + installed_pkgs = set(_find_installed_packages(project_dir / "apm_modules")) + installed_pkgs.update(_find_installed_subdirectory_packages(project_dir / "apm_modules")) + + orphaned_packages = [pkg for pkg in installed_pkgs if pkg not in expected_installed] # Assert no orphans found assert len(orphaned_packages) == 0, \ @@ -276,9 +296,9 @@ def test_mixed_dependencies_orphan_detection(tmp_path): # Verify expected counts assert len(expected_installed) == 3, "Should have 3 expected packages" - assert "danielmeppiel/design-guidelines" in expected_installed - assert "github/awesome-copilot-awesome-copilot" in expected_installed - assert "danielmeppiel/compliance-rules-gdpr" in expected_installed + assert "microsoft/apm-sample-package" in expected_installed + assert "github/awesome-copilot/plugins/awesome-copilot" in expected_installed + assert "github/awesome-copilot/skills/code-exemplars-blueprint-generator" in expected_installed @pytest.mark.integration @@ -428,8 +448,8 @@ def test_get_dependency_declaration_order_mixed_github_and_ado(tmp_path): "version": "1.0.0", "dependencies": { "apm": [ - "danielmeppiel/design-guidelines", # GitHub regular - "github/awesome-copilot/prompts/code-review.prompt.md", # GitHub virtual file + "microsoft/apm-sample-package", # GitHub regular + "github/awesome-copilot/skills/review-and-refactor", # GitHub virtual subdirectory "dev.azure.com/company/project/repo", # ADO regular "dev.azure.com/company/my-azurecollection/copilot-instructions/collections/csharp-ddd" # ADO virtual collection ] @@ -444,8 +464,8 @@ def test_get_dependency_declaration_order_mixed_github_and_ado(tmp_path): # Verify all dependency paths are returned correctly assert len(dep_order) == 4 - assert dep_order[0] == "danielmeppiel/design-guidelines" # GitHub regular: owner/repo - assert dep_order[1] == "github/awesome-copilot-code-review" # GitHub virtual: owner/virtual-pkg-name + assert dep_order[0] == "microsoft/apm-sample-package" # GitHub regular: owner/repo + assert dep_order[1] == "github/awesome-copilot/skills/review-and-refactor" # GitHub virtual subdirectory: owner/repo/subdir assert dep_order[2] == "company/project/repo" # ADO regular: org/project/repo assert dep_order[3] == "company/my-azurecollection/copilot-instructions-csharp-ddd" # ADO virtual: org/project/virtual-pkg-name diff --git a/tests/test_apm_package_models.py b/tests/test_apm_package_models.py index 3496fa56..0129307c 100644 --- a/tests/test_apm_package_models.py +++ b/tests/test_apm_package_models.py @@ -276,18 +276,18 @@ def test_parse_virtual_package_with_malicious_host(self): def test_parse_virtual_file_package(self): """Test parsing virtual file package (individual file).""" - dep = DependencyReference.parse("github/awesome-copilot/prompts/code-review.prompt.md") - assert dep.repo_url == "github/awesome-copilot" + dep = DependencyReference.parse("owner/test-repo/prompts/code-review.prompt.md") + assert dep.repo_url == "owner/test-repo" assert dep.is_virtual is True assert dep.virtual_path == "prompts/code-review.prompt.md" assert dep.is_virtual_file() is True assert dep.is_virtual_collection() is False - assert dep.get_virtual_package_name() == "awesome-copilot-code-review" + assert dep.get_virtual_package_name() == "test-repo-code-review" def test_parse_virtual_file_with_reference(self): """Test parsing virtual file package with git reference.""" - dep = DependencyReference.parse("github/awesome-copilot/prompts/code-review.prompt.md#v1.0.0") - assert dep.repo_url == "github/awesome-copilot" + dep = DependencyReference.parse("owner/test-repo/prompts/code-review.prompt.md#v1.0.0") + assert dep.repo_url == "owner/test-repo" assert dep.is_virtual is True assert dep.virtual_path == "prompts/code-review.prompt.md" assert dep.reference == "v1.0.0" @@ -305,18 +305,18 @@ def test_parse_virtual_file_all_extensions(self): def test_parse_virtual_collection(self): """Test parsing virtual collection package.""" - dep = DependencyReference.parse("github/awesome-copilot/collections/project-planning") - assert dep.repo_url == "github/awesome-copilot" + dep = DependencyReference.parse("owner/test-repo/collections/project-planning") + assert dep.repo_url == "owner/test-repo" assert dep.is_virtual is True assert dep.virtual_path == "collections/project-planning" assert dep.is_virtual_file() is False assert dep.is_virtual_collection() is True - assert dep.get_virtual_package_name() == "awesome-copilot-project-planning" + assert dep.get_virtual_package_name() == "test-repo-project-planning" def test_parse_virtual_collection_with_reference(self): """Test parsing virtual collection with git reference.""" - dep = DependencyReference.parse("github/awesome-copilot/collections/testing#main") - assert dep.repo_url == "github/awesome-copilot" + dep = DependencyReference.parse("owner/test-repo/collections/testing#main") + assert dep.repo_url == "owner/test-repo" assert dep.is_virtual is True assert dep.virtual_path == "collections/testing" assert dep.reference == "main" @@ -340,14 +340,14 @@ def test_virtual_package_str_representation(self): Note: After PR #33, host is explicit in string representation. """ - dep = DependencyReference.parse("github/awesome-copilot/prompts/code-review.prompt.md#v1.0.0") + dep = DependencyReference.parse("owner/test-repo/prompts/code-review.prompt.md#v1.0.0") # Check that key components are present (host may be explicit now) - assert "github/awesome-copilot" in str(dep) + assert "owner/test-repo" in str(dep) assert "prompts/code-review.prompt.md" in str(dep) assert "#v1.0.0" in str(dep) - dep_with_alias = DependencyReference.parse("github/awesome-copilot/prompts/test.prompt.md@myalias") - assert "github/awesome-copilot" in str(dep_with_alias) + dep_with_alias = DependencyReference.parse("owner/test-repo/prompts/test.prompt.md@myalias") + assert "owner/test-repo" in str(dep_with_alias) assert "prompts/test.prompt.md" in str(dep_with_alias) assert "@myalias" in str(dep_with_alias) diff --git a/tests/test_collision_integration.py b/tests/test_collision_integration.py index d3f8f54c..bf0b2e49 100644 --- a/tests/test_collision_integration.py +++ b/tests/test_collision_integration.py @@ -34,13 +34,13 @@ def test_collision_detection_with_helpful_error(self, tmp_path): """Test that collision detection provides helpful error message. This simulates the real scenario where a user has installed: - - github/awesome-copilot/prompts/code-review.prompt.md + - owner/test-repo/prompts/code-review.prompt.md - acme/dev-tools/prompts/code-review.prompt.md And tries to run: apm run code-review """ # Setup: Create realistic virtual package structure - github_pkg = tmp_path / "apm_modules" / "github" / "awesome-copilot-code-review" / ".apm" / "prompts" + github_pkg = tmp_path / "apm_modules" / "github" / "test-repo-code-review" / ".apm" / "prompts" github_pkg.mkdir(parents=True) (github_pkg / "code-review.prompt.md").write_text("---\n---\nGitHub Copilot code review") @@ -59,7 +59,7 @@ def test_collision_detection_with_helpful_error(self, tmp_path): # Verify error message is helpful assert "Multiple prompts found for 'code-review'" in error_msg - assert "github/awesome-copilot-code-review" in error_msg + assert "github/test-repo-code-review" in error_msg assert "acme/dev-tools-code-review" in error_msg assert "Please specify using qualified path" in error_msg assert "apm run" in error_msg @@ -69,11 +69,11 @@ def test_qualified_path_resolves_collision(self, tmp_path): """Test that using qualified path resolves collision. User can disambiguate by using: - - apm run github/awesome-copilot-code-review/code-review + - apm run github/test-repo-code-review/code-review - apm run acme/dev-tools-code-review/code-review """ # Setup - github_pkg = tmp_path / "apm_modules" / "github" / "awesome-copilot-code-review" / ".apm" / "prompts" + github_pkg = tmp_path / "apm_modules" / "github" / "test-repo-code-review" / ".apm" / "prompts" github_pkg.mkdir(parents=True) (github_pkg / "code-review.prompt.md").write_text("---\n---\nGitHub version") @@ -85,10 +85,10 @@ def test_qualified_path_resolves_collision(self, tmp_path): runner = ScriptRunner() # Test GitHub qualified path - github_result = runner._discover_prompt_file("github/awesome-copilot-code-review/code-review") + github_result = runner._discover_prompt_file("github/test-repo-code-review/code-review") assert github_result is not None assert "github" in str(github_result) - assert "awesome-copilot-code-review" in str(github_result) + assert "test-repo-code-review" in str(github_result) # Test Acme qualified path acme_result = runner._discover_prompt_file("acme/dev-tools-code-review/code-review") @@ -102,7 +102,7 @@ def test_qualified_path_resolves_collision(self, tmp_path): def test_no_collision_with_single_dependency(self, tmp_path): """Test that single dependency works without requiring qualified path.""" # Setup: Only one package with the prompt - github_pkg = tmp_path / "apm_modules" / "github" / "awesome-copilot-code-review" / ".apm" / "prompts" + github_pkg = tmp_path / "apm_modules" / "github" / "test-repo-code-review" / ".apm" / "prompts" github_pkg.mkdir(parents=True) (github_pkg / "code-review.prompt.md").write_text("---\n---\nGitHub version") @@ -119,7 +119,7 @@ def test_local_overrides_all_dependencies_no_collision(self, tmp_path): # Setup: Local + two dependencies with same name (tmp_path / "code-review.prompt.md").write_text("---\n---\nLocal version") - github_pkg = tmp_path / "apm_modules" / "github" / "awesome-copilot-code-review" / ".apm" / "prompts" + github_pkg = tmp_path / "apm_modules" / "github" / "test-repo-code-review" / ".apm" / "prompts" github_pkg.mkdir(parents=True) (github_pkg / "code-review.prompt.md").write_text("---\n---\nGitHub version") diff --git a/tests/test_console.py b/tests/test_console.py index e96e93c6..82363d9f 100644 --- a/tests/test_console.py +++ b/tests/test_console.py @@ -16,7 +16,7 @@ def test_read_url(): """Test the read-url command with proper temp directory cleanup.""" - url = "https://www.danielmeppiel.dev" + url = "https://www.example.com" temp_dir = tempfile.mkdtemp() try: result = runner.invoke(app, ["read-url", url, "--output-dir", temp_dir]) diff --git a/tests/test_runnable_prompts.py b/tests/test_runnable_prompts.py index 59fed430..58685f34 100644 --- a/tests/test_runnable_prompts.py +++ b/tests/test_runnable_prompts.py @@ -147,7 +147,7 @@ def test_discover_multiple_dependencies_same_filename(self, tmp_path): this and raises an error with helpful disambiguation options. """ # Setup: Create two different packages with same prompt filename - dep1_dir = tmp_path / "apm_modules" / "github" / "awesome-copilot-code-review" / ".apm" / "prompts" + dep1_dir = tmp_path / "apm_modules" / "github" / "test-repo-code-review" / ".apm" / "prompts" dep1_dir.mkdir(parents=True) dep1_prompt = dep1_dir / "code-review.prompt.md" dep1_prompt.write_text("---\n---\nGitHub Copilot code review") @@ -166,7 +166,7 @@ def test_discover_multiple_dependencies_same_filename(self, tmp_path): error_msg = str(exc_info.value) assert "Multiple prompts found for 'code-review'" in error_msg - assert "github/awesome-copilot-code-review" in error_msg + assert "github/test-repo-code-review" in error_msg assert "acme/dev-tools-code-review" in error_msg assert "apm run" in error_msg assert "qualified path" in error_msg @@ -177,7 +177,7 @@ def test_discover_collision_local_wins(self, tmp_path): local_prompt = tmp_path / "code-review.prompt.md" local_prompt.write_text("---\n---\nLocal code review") - dep1_dir = tmp_path / "apm_modules" / "github" / "awesome-copilot-code-review" / ".apm" / "prompts" + dep1_dir = tmp_path / "apm_modules" / "github" / "test-repo-code-review" / ".apm" / "prompts" dep1_dir.mkdir(parents=True) dep1_prompt = dep1_dir / "code-review.prompt.md" dep1_prompt.write_text("---\n---\nGitHub Copilot code review") @@ -201,11 +201,11 @@ def test_discover_virtual_package_naming_convention(self, tmp_path): """Test discovery works with virtual package directory naming. Virtual packages use format: {repo-name}-{filename-without-extension} - Example: github/awesome-copilot/prompts/architecture-blueprint-generator.prompt.md - β†’ Directory: github/awesome-copilot-architecture-blueprint-generator/ + Example: github/test-repo/prompts/architecture-blueprint-generator.prompt.md + β†’ Directory: github/test-repo-architecture-blueprint-generator/ """ # Setup: Create virtual package structure as it would be installed - virt_pkg_dir = tmp_path / "apm_modules" / "github" / "awesome-copilot-architecture-blueprint-generator" / ".apm" / "prompts" + virt_pkg_dir = tmp_path / "apm_modules" / "github" / "test-repo-architecture-blueprint-generator" / ".apm" / "prompts" virt_pkg_dir.mkdir(parents=True) prompt_file = virt_pkg_dir / "architecture-blueprint-generator.prompt.md" prompt_file.write_text("---\n---\nArchitecture blueprint generator") @@ -216,20 +216,20 @@ def test_discover_virtual_package_naming_convention(self, tmp_path): assert result is not None assert result.name == "architecture-blueprint-generator.prompt.md" - assert "awesome-copilot-architecture-blueprint-generator" in str(result) + assert "test-repo-architecture-blueprint-generator" in str(result) def test_discover_multiple_virtual_packages_different_repos_same_filename(self, tmp_path): """Test collision between virtual packages from different repos with same filename. This is the critical collision scenario: - - github/awesome-copilot/prompts/code-review.prompt.md + - github/test-repo/prompts/code-review.prompt.md - acme/dev-tools/prompts/code-review.prompt.md Both install as virtual packages with different directory names but same prompt filename. Now properly detects collision and provides disambiguation. """ # Setup: Two virtual packages from different repos - github_pkg = tmp_path / "apm_modules" / "github" / "awesome-copilot-code-review" / ".apm" / "prompts" + github_pkg = tmp_path / "apm_modules" / "github" / "test-repo-code-review" / ".apm" / "prompts" github_pkg.mkdir(parents=True) github_prompt = github_pkg / "code-review.prompt.md" github_prompt.write_text("---\n---\nGitHub version") @@ -248,13 +248,13 @@ def test_discover_multiple_virtual_packages_different_repos_same_filename(self, error_msg = str(exc_info.value) assert "Multiple prompts found" in error_msg - assert "github/awesome-copilot-code-review" in error_msg + assert "github/test-repo-code-review" in error_msg assert "acme/dev-tools-code-review" in error_msg def test_discover_qualified_path_github(self, tmp_path): """Test discovery using qualified path for GitHub package.""" # Setup: Two virtual packages with same prompt name - github_pkg = tmp_path / "apm_modules" / "github" / "awesome-copilot-code-review" / ".apm" / "prompts" + github_pkg = tmp_path / "apm_modules" / "github" / "test-repo-code-review" / ".apm" / "prompts" github_pkg.mkdir(parents=True) github_prompt = github_pkg / "code-review.prompt.md" github_prompt.write_text("---\n---\nGitHub version") @@ -268,17 +268,17 @@ def test_discover_qualified_path_github(self, tmp_path): runner = ScriptRunner() # Use qualified path to specify which one - result = runner._discover_prompt_file("github/awesome-copilot-code-review/code-review") + result = runner._discover_prompt_file("github/test-repo-code-review/code-review") assert result is not None assert result.name == "code-review.prompt.md" assert "github" in str(result) - assert "awesome-copilot-code-review" in str(result) + assert "test-repo-code-review" in str(result) def test_discover_qualified_path_acme(self, tmp_path): """Test discovery using qualified path for Acme package.""" # Setup: Two virtual packages with same prompt name - github_pkg = tmp_path / "apm_modules" / "github" / "awesome-copilot-code-review" / ".apm" / "prompts" + github_pkg = tmp_path / "apm_modules" / "github" / "test-repo-code-review" / ".apm" / "prompts" github_pkg.mkdir(parents=True) github_prompt = github_pkg / "code-review.prompt.md" github_prompt.write_text("---\n---\nGitHub version") diff --git a/tests/test_virtual_package_multi_install.py b/tests/test_virtual_package_multi_install.py index a946c8d1..4ef22750 100644 --- a/tests/test_virtual_package_multi_install.py +++ b/tests/test_virtual_package_multi_install.py @@ -18,17 +18,17 @@ def test_unique_key_for_regular_package(self): def test_unique_key_for_virtual_file_package(self): """Virtual file packages use repo_url + virtual_path as unique key.""" - dep_ref = DependencyReference.parse("github/awesome-copilot/prompts/code-review.prompt.md") + dep_ref = DependencyReference.parse("owner/test-repo/prompts/code-review.prompt.md") unique_key = dep_ref.get_unique_key() - assert unique_key == "github/awesome-copilot/prompts/code-review.prompt.md" + assert unique_key == "owner/test-repo/prompts/code-review.prompt.md" assert dep_ref.is_virtual - assert dep_ref.repo_url == "github/awesome-copilot" + assert dep_ref.repo_url == "owner/test-repo" assert dep_ref.virtual_path == "prompts/code-review.prompt.md" def test_unique_key_for_different_files_from_same_repo(self): """Two virtual files from same repo have different unique keys.""" - dep_ref1 = DependencyReference.parse("github/awesome-copilot/prompts/file1.prompt.md") - dep_ref2 = DependencyReference.parse("github/awesome-copilot/prompts/file2.prompt.md") + dep_ref1 = DependencyReference.parse("owner/test-repo/prompts/file1.prompt.md") + dep_ref2 = DependencyReference.parse("owner/test-repo/prompts/file2.prompt.md") key1 = dep_ref1.get_unique_key() key2 = dep_ref2.get_unique_key() @@ -37,7 +37,7 @@ def test_unique_key_for_different_files_from_same_repo(self): assert key1 != key2 # But both share the same repo_url - assert dep_ref1.repo_url == dep_ref2.repo_url == "github/awesome-copilot" + assert dep_ref1.repo_url == dep_ref2.repo_url == "owner/test-repo" # And both are virtual assert dep_ref1.is_virtual and dep_ref2.is_virtual @@ -51,9 +51,9 @@ def test_dependency_graph_resolution_with_multiple_virtual_packages(self, tmp_pa version: 1.0.0 dependencies: apm: - - github/awesome-copilot/prompts/file1.prompt.md - - github/awesome-copilot/prompts/file2.prompt.md - - github/awesome-copilot/prompts/file3.prompt.md + - owner/test-repo/prompts/file1.prompt.md + - owner/test-repo/prompts/file2.prompt.md + - owner/test-repo/prompts/file3.prompt.md """) # Resolve dependencies @@ -70,7 +70,7 @@ def test_dependency_graph_resolution_with_multiple_virtual_packages(self, tmp_pa # All should be virtual packages from the same repo for dep in deps_list: assert dep.is_virtual - assert dep.repo_url == "github/awesome-copilot" + assert dep.repo_url == "owner/test-repo" # Each should have a different virtual_path virtual_paths = {dep.virtual_path for dep in deps_list} @@ -88,8 +88,8 @@ def test_dependency_graph_with_mix_of_regular_and_virtual_packages(self, tmp_pat dependencies: apm: - github/design-guidelines - - github/awesome-copilot/prompts/file1.prompt.md - - github/awesome-copilot/prompts/file2.prompt.md + - owner/test-repo/prompts/file1.prompt.md + - owner/test-repo/prompts/file2.prompt.md - github/compliance-rules """) @@ -118,8 +118,8 @@ def test_dependency_tree_node_unique_ids(self): from src.apm_cli.models.apm_package import APMPackage # Create two virtual packages from same repo - dep_ref1 = DependencyReference.parse("github/awesome-copilot/prompts/file1.prompt.md") - dep_ref2 = DependencyReference.parse("github/awesome-copilot/prompts/file2.prompt.md") + dep_ref1 = DependencyReference.parse("owner/test-repo/prompts/file1.prompt.md") + dep_ref2 = DependencyReference.parse("owner/test-repo/prompts/file2.prompt.md") # Create placeholder packages pkg1 = APMPackage(name="file1", version="1.0.0") @@ -131,16 +131,16 @@ def test_dependency_tree_node_unique_ids(self): # Node IDs should be different even though repo_url is same assert node1.get_id() != node2.get_id() - assert node1.get_id() == "github/awesome-copilot/prompts/file1.prompt.md" - assert node2.get_id() == "github/awesome-copilot/prompts/file2.prompt.md" + assert node1.get_id() == "owner/test-repo/prompts/file1.prompt.md" + assert node2.get_id() == "owner/test-repo/prompts/file2.prompt.md" def test_flat_dependency_map_uses_unique_keys(self): """Test that FlatDependencyMap properly uses unique keys for storage.""" from src.apm_cli.deps.dependency_graph import FlatDependencyMap # Create multiple virtual packages from same repo - dep_ref1 = DependencyReference.parse("github/awesome-copilot/prompts/file1.prompt.md") - dep_ref2 = DependencyReference.parse("github/awesome-copilot/prompts/file2.prompt.md") + dep_ref1 = DependencyReference.parse("owner/test-repo/prompts/file1.prompt.md") + dep_ref2 = DependencyReference.parse("owner/test-repo/prompts/file2.prompt.md") # Add to flat map flat_map = FlatDependencyMap() @@ -165,8 +165,8 @@ def test_no_false_conflicts_for_virtual_packages(self): """Virtual packages from same repo should not be flagged as conflicts.""" from src.apm_cli.deps.dependency_graph import FlatDependencyMap - dep_ref1 = DependencyReference.parse("github/awesome-copilot/prompts/file1.prompt.md") - dep_ref2 = DependencyReference.parse("github/awesome-copilot/prompts/file2.prompt.md") + dep_ref1 = DependencyReference.parse("owner/test-repo/prompts/file1.prompt.md") + dep_ref2 = DependencyReference.parse("owner/test-repo/prompts/file2.prompt.md") flat_map = FlatDependencyMap() flat_map.add_dependency(dep_ref1, is_conflict=False) diff --git a/tests/unit/integration/test_agent_integrator.py b/tests/unit/integration/test_agent_integrator.py index fb6da896..76624e96 100644 --- a/tests/unit/integration/test_agent_integrator.py +++ b/tests/unit/integration/test_agent_integrator.py @@ -113,7 +113,7 @@ def test_copy_agent_verbatim(self): def test_get_target_filename_agent_format(self): """Test target filename generation with -apm suffix for .agent.md.""" source = Path("/package/security.agent.md") - package_name = "danielmeppiel/security-standards" + package_name = "acme/security-standards" target = self.integrator.get_target_filename(source, package_name) # Intent-first naming: -apm suffix before extension @@ -122,7 +122,7 @@ def test_get_target_filename_agent_format(self): def test_get_target_filename_chatmode_format(self): """Test target filename generation with -apm suffix for .chatmode.md.""" source = Path("/package/default.chatmode.md") - package_name = "danielmeppiel/design-guidelines" + package_name = "microsoft/apm-sample-package" target = self.integrator.get_target_filename(source, package_name) # Preserve original extension diff --git a/tests/unit/integration/test_prompt_integrator.py b/tests/unit/integration/test_prompt_integrator.py index 0337e22b..ea8e0552 100644 --- a/tests/unit/integration/test_prompt_integrator.py +++ b/tests/unit/integration/test_prompt_integrator.py @@ -102,7 +102,7 @@ def test_copy_prompt_preserves_existing_frontmatter(self): def test_get_target_filename(self): """Test target filename generation with -apm suffix (intent-first naming).""" source = Path("/package/accessibility-audit.prompt.md") - package_name = "danielmeppiel/design-guidelines" + package_name = "microsoft/apm-sample-package" target = self.integrator.get_target_filename(source, package_name) # Intent-first naming: -apm suffix before extension @@ -351,7 +351,7 @@ def test_sync_integration_ignores_apm_package_param(self): apm_package = Mock() apm_package.get_apm_dependencies.return_value = [ DependencyReference( - repo_url="danielmeppiel/design-guidelines", + repo_url="microsoft/apm-sample-package", reference="main" ) ] diff --git a/tests/unit/integration/test_skill_integrator.py b/tests/unit/integration/test_skill_integrator.py index 33273b5d..92406723 100644 --- a/tests/unit/integration/test_skill_integrator.py +++ b/tests/unit/integration/test_skill_integrator.py @@ -39,7 +39,7 @@ def test_with_spaces(self): def test_owner_repo_format(self): """Test owner/repo format extracts repo name.""" - assert to_hyphen_case("danielmeppiel/design-guidelines") == "design-guidelines" + assert to_hyphen_case("microsoft/apm-sample-package") == "apm-sample-package" assert to_hyphen_case("owner/MyRepo") == "my-repo" def test_mixed_separators(self): @@ -1392,7 +1392,7 @@ def test_normalize_removes_dots(self): def test_normalize_extracts_repo_name(self): """Test owner/repo format extracts repo name.""" assert normalize_skill_name("owner/my-package") == "my-package" - assert normalize_skill_name("danielmeppiel/compliance-rules") == "compliance-rules" + assert normalize_skill_name("acme/compliance-rules") == "compliance-rules" def test_normalize_extracts_and_converts_repo_name(self): """Test owner/repo format with conversion needed.""" @@ -1438,7 +1438,7 @@ def test_normalize_produces_valid_names(self): def test_normalize_realistic_package_names(self): """Test normalization of realistic package names.""" test_cases = [ - ("danielmeppiel/design-guidelines", "design-guidelines"), + ("microsoft/apm-sample-package", "apm-sample-package"), ("ComposioHQ/awesome-claude-skills", "awesome-claude-skills"), ("github/awesome-copilot", "awesome-copilot"), ("My_Awesome_Package", "my-awesome-package"), diff --git a/tests/unit/test_ado_path_structure.py b/tests/unit/test_ado_path_structure.py index c82bdd75..87b4d15a 100644 --- a/tests/unit/test_ado_path_structure.py +++ b/tests/unit/test_ado_path_structure.py @@ -24,16 +24,16 @@ class TestADOPathStructure: def test_github_dependency_uses_2_part_path(self): """Test that GitHub dependencies use owner/repo (2-part) structure.""" - dep = DependencyReference.parse("danielmeppiel/design-guidelines") + dep = DependencyReference.parse("microsoft/apm-sample-package") assert dep.is_azure_devops() is False - assert dep.repo_url == "danielmeppiel/design-guidelines" + assert dep.repo_url == "microsoft/apm-sample-package" # Path parts for installation parts = dep.repo_url.split("/") assert len(parts) == 2 - assert parts[0] == "danielmeppiel" - assert parts[1] == "design-guidelines" + assert parts[0] == "microsoft" + assert parts[1] == "apm-sample-package" def test_ado_dependency_uses_3_part_path(self): """Test that ADO dependencies use org/project/repo (3-part) structure.""" @@ -104,10 +104,10 @@ def _create_instruction_file(self, file_path: Path, apply_to: str, content: str) def test_discovery_finds_github_2_level_deps(self, temp_project): """Test discovery finds primitives in GitHub 2-level structure.""" # Create apm.yml with GitHub dependency - self._create_apm_yml(temp_project, ["danielmeppiel/design-guidelines"]) + self._create_apm_yml(temp_project, ["microsoft/apm-sample-package"]) # Create GitHub-style 2-level directory structure - dep_path = temp_project / "apm_modules" / "danielmeppiel" / "design-guidelines" / ".apm" / "instructions" + dep_path = temp_project / "apm_modules" / "microsoft" / "apm-sample-package" / ".apm" / "instructions" dep_path.mkdir(parents=True) self._create_instruction_file( dep_path / "style.instructions.md", @@ -121,7 +121,7 @@ def test_discovery_finds_github_2_level_deps(self, temp_project): # Should find the instruction assert len(collection.instructions) == 1 assert collection.instructions[0].apply_to == "**/*.css" - assert "dependency:danielmeppiel/design-guidelines" in collection.instructions[0].source + assert "dependency:microsoft/apm-sample-package" in collection.instructions[0].source def test_discovery_finds_ado_3_level_deps(self, temp_project): """Test discovery finds primitives in ADO 3-level structure.""" @@ -149,12 +149,12 @@ def test_discovery_mixed_github_and_ado_deps(self, temp_project): """Test discovery works with both GitHub and ADO dependencies.""" # Create apm.yml with both types self._create_apm_yml(temp_project, [ - "danielmeppiel/design-guidelines", + "microsoft/apm-sample-package", "dev.azure.com/dmeppiel-org/market-js-app/_git/compliance-rules" ]) # Create GitHub 2-level structure - github_path = temp_project / "apm_modules" / "danielmeppiel" / "design-guidelines" / ".apm" / "instructions" + github_path = temp_project / "apm_modules" / "microsoft" / "apm-sample-package" / ".apm" / "instructions" github_path.mkdir(parents=True) self._create_instruction_file( github_path / "style.instructions.md", @@ -179,14 +179,14 @@ def test_discovery_mixed_github_and_ado_deps(self, temp_project): # Verify sources sources = [inst.source for inst in collection.instructions] - assert any("danielmeppiel/design-guidelines" in s for s in sources) + assert any("microsoft/apm-sample-package" in s for s in sources) assert any("dmeppiel-org/market-js-app/compliance-rules" in s for s in sources) def test_get_dependency_order_returns_full_ado_path(self, temp_project): """Test that get_dependency_declaration_order returns full 3-part ADO paths.""" self._create_apm_yml(temp_project, [ "dev.azure.com/org1/proj1/_git/repo1", - "danielmeppiel/simple-repo" + "acme/simple-repo" ]) dep_order = get_dependency_declaration_order(str(temp_project)) @@ -195,7 +195,7 @@ def test_get_dependency_order_returns_full_ado_path(self, temp_project): # ADO should have 3 parts assert dep_order[0] == "org1/proj1/repo1" # GitHub should have 2 parts - assert dep_order[1] == "danielmeppiel/simple-repo" + assert dep_order[1] == "acme/simple-repo" class TestADOCompilation: @@ -408,7 +408,7 @@ class TestADOVirtualPackagePaths: def test_github_virtual_package_uses_2_level_path(self): """Verify GitHub virtual packages install to 2-level path.""" - dep = DependencyReference.parse("github/awesome-copilot/collections/project-planning") + dep = DependencyReference.parse("owner/test-repo/collections/project-planning") assert dep.is_virtual is True assert dep.is_virtual_collection() is True @@ -425,7 +425,7 @@ def test_github_virtual_package_uses_2_level_path(self): install_path = virtual_name # Should be 2 levels for GitHub: owner/virtual-pkg-name - assert install_path == "github/awesome-copilot-project-planning" + assert install_path == "owner/test-repo-project-planning" def test_ado_virtual_collection_uses_3_level_path(self): """Verify ADO virtual collections install to 3-level path.""" diff --git a/tests/unit/test_orphan_detection.py b/tests/unit/test_orphan_detection.py index 64b1cc5c..93f7038d 100644 --- a/tests/unit/test_orphan_detection.py +++ b/tests/unit/test_orphan_detection.py @@ -203,11 +203,11 @@ def test_sync_removes_virtual_package_files(self): create_test_integrated_file( prompts_dir / "code-review-apm.prompt.md", source_repo="github/awesome-copilot", - source_dependency="github/awesome-copilot/prompts/code-review.prompt.md" + source_dependency="github/awesome-copilot/skills/review-and-refactor" ) apm_package = create_mock_apm_package([ - "github/awesome-copilot/prompts/code-review.prompt.md" + "github/awesome-copilot/skills/review-and-refactor" ]) integrator = PromptIntegrator() @@ -256,16 +256,16 @@ def test_multiple_virtual_packages_from_same_repo(self): create_test_integrated_file( agents_dir / "azure-apm.agent.md", source_repo="github/awesome-copilot", - source_dependency="github/awesome-copilot/collections/azure" + source_dependency="github/awesome-copilot/plugins/azure-cloud-development" ) create_test_integrated_file( agents_dir / "aws-apm.agent.md", source_repo="github/awesome-copilot", - source_dependency="github/awesome-copilot/collections/aws" + source_dependency="github/awesome-copilot/plugins/testing-automation" ) apm_package = create_mock_apm_package([ - "github/awesome-copilot/collections/azure" + "github/awesome-copilot/plugins/azure-cloud-development" ]) integrator = AgentIntegrator() @@ -292,13 +292,13 @@ def test_regular_and_virtual_packages_mixed(self): create_test_integrated_file( prompts_dir / "virtual-apm.prompt.md", source_repo="github/awesome-copilot", - source_dependency="github/awesome-copilot/prompts/virtual.prompt.md" + source_dependency="github/awesome-copilot/skills/create-readme" ) # Mock package with both installed apm_package = create_mock_apm_package([ "owner/regular-pkg", - "github/awesome-copilot/prompts/virtual.prompt.md" + "github/awesome-copilot/skills/create-readme" ]) integrator = PromptIntegrator() diff --git a/tests/unit/test_package_identity.py b/tests/unit/test_package_identity.py index ceec194f..6aec1917 100644 --- a/tests/unit/test_package_identity.py +++ b/tests/unit/test_package_identity.py @@ -64,18 +64,18 @@ def test_regular_github_package_with_reference_and_alias(self): def test_virtual_file_package(self): """Virtual file includes full path.""" - dep = DependencyReference.parse("github/awesome-copilot/prompts/code-review.prompt.md") - assert dep.get_canonical_dependency_string() == "github/awesome-copilot/prompts/code-review.prompt.md" + dep = DependencyReference.parse("owner/test-repo/prompts/code-review.prompt.md") + assert dep.get_canonical_dependency_string() == "owner/test-repo/prompts/code-review.prompt.md" def test_virtual_collection_package(self): """Virtual collection includes full path.""" - dep = DependencyReference.parse("github/awesome-copilot/collections/azure-cloud-development") - assert dep.get_canonical_dependency_string() == "github/awesome-copilot/collections/azure-cloud-development" + dep = DependencyReference.parse("owner/test-repo/collections/azure-cloud-development") + assert dep.get_canonical_dependency_string() == "owner/test-repo/collections/azure-cloud-development" def test_virtual_package_with_reference(self): """Virtual package with reference - reference not in canonical string.""" - dep = DependencyReference.parse("github/awesome-copilot/collections/testing#main") - assert dep.get_canonical_dependency_string() == "github/awesome-copilot/collections/testing" + dep = DependencyReference.parse("owner/test-repo/collections/testing#main") + assert dep.get_canonical_dependency_string() == "owner/test-repo/collections/testing" def test_ado_regular_package(self): """ADO package returns org/project/repo.""" @@ -112,28 +112,28 @@ def test_regular_github_package_with_reference(self): def test_virtual_file_package(self): """Virtual file: apm_modules/owner/.""" - dep = DependencyReference.parse("github/awesome-copilot/prompts/code-review.prompt.md") + dep = DependencyReference.parse("owner/test-repo/prompts/code-review.prompt.md") apm_modules = Path("/project/apm_modules") - # Virtual package name: awesome-copilot-code-review - expected = apm_modules / "github" / "awesome-copilot-code-review" + # Virtual package name: test-repo-code-review + expected = apm_modules / "owner" / "test-repo-code-review" assert dep.get_install_path(apm_modules) == expected def test_virtual_collection_package(self): """Virtual collection: apm_modules/owner/.""" - dep = DependencyReference.parse("github/awesome-copilot/collections/azure-cloud-development") + dep = DependencyReference.parse("owner/test-repo/collections/azure-cloud-development") apm_modules = Path("/project/apm_modules") - # Virtual package name: awesome-copilot-azure-cloud-development - expected = apm_modules / "github" / "awesome-copilot-azure-cloud-development" + # Virtual package name: test-repo-azure-cloud-development + expected = apm_modules / "owner" / "test-repo-azure-cloud-development" assert dep.get_install_path(apm_modules) == expected def test_virtual_collection_with_reference(self): """Reference does not affect virtual package install path.""" - dep = DependencyReference.parse("github/awesome-copilot/collections/testing#main") + dep = DependencyReference.parse("owner/test-repo/collections/testing#main") apm_modules = Path("/project/apm_modules") - expected = apm_modules / "github" / "awesome-copilot-testing" + expected = apm_modules / "owner" / "test-repo-testing" assert dep.get_install_path(apm_modules) == expected def test_ado_regular_package(self): @@ -175,8 +175,8 @@ class TestInstallPathConsistency: def test_consistency_with_get_virtual_package_name(self): """Install path uses same package name as get_virtual_package_name.""" test_cases = [ - "github/awesome-copilot/prompts/code-review.prompt.md", - "github/awesome-copilot/collections/azure-cloud-development", + "owner/test-repo/prompts/code-review.prompt.md", + "owner/test-repo/collections/azure-cloud-development", "owner/repo/agents/security.agent.md", "user/pkg/instructions/coding.instructions.md", ] @@ -222,18 +222,18 @@ class TestUninstallScenarios: def test_uninstall_virtual_collection_finds_correct_path(self): """Uninstalling virtual collection should find owner/virtual-pkg-name, not owner/repo/collections/name.""" - dep_str = "github/awesome-copilot/collections/azure-cloud-development" + dep_str = "owner/test-repo/collections/azure-cloud-development" dep = DependencyReference.parse(dep_str) apm_modules = Path("apm_modules") install_path = dep.get_install_path(apm_modules) - # Should be owner/awesome-copilot-azure-cloud-development - # NOT github/awesome-copilot/collections/azure-cloud-development - assert install_path == apm_modules / "github" / "awesome-copilot-azure-cloud-development" + # Should be owner/test-repo-azure-cloud-development + # NOT owner/test-repo/collections/azure-cloud-development + assert install_path == apm_modules / "owner" / "test-repo-azure-cloud-development" # The wrong path (from raw path segments) would be: - wrong_path = apm_modules / "github" / "awesome-copilot" / "collections" / "azure-cloud-development" + wrong_path = apm_modules / "owner" / "test-repo" / "collections" / "azure-cloud-development" assert install_path != wrong_path def test_uninstall_virtual_file_finds_correct_path(self): @@ -257,7 +257,7 @@ def test_canonical_string_matches_apm_yml_entry(self): # These are the strings that would appear in apm.yml dependencies apm_yml_entries = [ "owner/repo", - "github/awesome-copilot/collections/azure-cloud-development", + "owner/test-repo/collections/azure-cloud-development", "owner/pkg/prompts/file.prompt.md", "dev.azure.com/org/proj/repo/agents/test.agent.md", ] @@ -291,8 +291,8 @@ def test_unique_key_matches_canonical_string(self): """get_unique_key and get_canonical_dependency_string should be consistent.""" test_cases = [ "owner/repo", - "github/awesome-copilot/prompts/code-review.prompt.md", - "github/awesome-copilot/collections/testing", + "owner/test-repo/prompts/code-review.prompt.md", + "owner/test-repo/collections/testing", ] for dep_str in test_cases: diff --git a/tests/unit/test_script_runner.py b/tests/unit/test_script_runner.py index 0bd92372..8cb6ea99 100644 --- a/tests/unit/test_script_runner.py +++ b/tests/unit/test_script_runner.py @@ -329,7 +329,7 @@ def test_resolve_prompt_file_dependency_root(self): os.chdir(tmpdir) # Create apm_modules structure with org/repo hierarchy - dep_dir = Path("apm_modules/danielmeppiel/design-guidelines") + dep_dir = Path("apm_modules/microsoft/apm-sample-package") dep_dir.mkdir(parents=True) # Create prompt file in dependency root @@ -373,9 +373,9 @@ def test_resolve_prompt_file_multiple_dependencies(self): os.chdir(tmpdir) # Create multiple dependency directories with org/repo structure - compliance_dir = Path("apm_modules/danielmeppiel/compliance-rules") + compliance_dir = Path("apm_modules/acme/compliance-rules") compliance_dir.mkdir(parents=True) - design_dir = Path("apm_modules/danielmeppiel/design-guidelines") + design_dir = Path("apm_modules/microsoft/apm-sample-package") design_dir.mkdir(parents=True) # Create prompt files in both (first one found should win) @@ -420,9 +420,9 @@ def test_resolve_prompt_file_not_found_anywhere(self): os.chdir(tmpdir) # Create apm_modules with dependencies but no prompt files - compliance_dir = Path("apm_modules/danielmeppiel/compliance-rules") + compliance_dir = Path("apm_modules/acme/compliance-rules") compliance_dir.mkdir(parents=True) - design_dir = Path("apm_modules/danielmeppiel/design-guidelines") + design_dir = Path("apm_modules/microsoft/apm-sample-package") design_dir.mkdir(parents=True) with pytest.raises(FileNotFoundError) as exc_info: @@ -432,8 +432,8 @@ def test_resolve_prompt_file_not_found_anywhere(self): assert "Prompt file 'hello-world.prompt.md' not found" in error_msg assert "Local: hello-world.prompt.md" in error_msg assert "Dependencies:" in error_msg - assert "danielmeppiel/compliance-rules/hello-world.prompt.md" in error_msg - assert "danielmeppiel/design-guidelines/hello-world.prompt.md" in error_msg + assert "acme/compliance-rules/hello-world.prompt.md" in error_msg + assert "microsoft/apm-sample-package/hello-world.prompt.md" in error_msg finally: os.chdir(original_cwd) @@ -450,7 +450,7 @@ def test_resolve_prompt_file_local_takes_precedence(self): local_prompt.write_text("Hello from local!") # Create dependency with same file - dep_dir = Path("apm_modules/danielmeppiel/design-guidelines") + dep_dir = Path("apm_modules/microsoft/apm-sample-package") dep_dir.mkdir(parents=True) dep_prompt = dep_dir / "hello-world.prompt.md" dep_prompt.write_text("Hello from dependency!") @@ -466,7 +466,7 @@ def test_resolve_prompt_file_local_takes_precedence(self): def test_compile_with_dependency_resolution(self, mock_file, mock_mkdir): """Test compile method uses dependency resolution correctly.""" with patch.object(self.compiler, '_resolve_prompt_file') as mock_resolve: - mock_resolve.return_value = Path("apm_modules/danielmeppiel/design-guidelines/test.prompt.md") + mock_resolve.return_value = Path("apm_modules/microsoft/apm-sample-package/test.prompt.md") file_content = "Hello ${input:name}!" mock_file.return_value.read.return_value = file_content @@ -479,7 +479,7 @@ def test_compile_with_dependency_resolution(self, mock_file, mock_mkdir): # Verify file was opened with resolved path mock_file.assert_called() opened_path = mock_file.call_args_list[0][0][0] - assert str(opened_path) == "apm_modules/danielmeppiel/design-guidelines/test.prompt.md" + assert str(opened_path) == "apm_modules/microsoft/apm-sample-package/test.prompt.md" class TestScriptRunnerAutoInstall: @@ -492,19 +492,19 @@ def setup_method(self): def test_is_virtual_package_reference_valid_file(self): """Test detection of valid virtual file package references.""" # Valid virtual file package reference - ref = "github/awesome-copilot/prompts/architecture-blueprint-generator.prompt.md" + ref = "owner/test-repo/prompts/architecture-blueprint-generator.prompt.md" assert self.script_runner._is_virtual_package_reference(ref) is True def test_is_virtual_package_reference_valid_collection(self): """Test detection of valid virtual collection package references.""" # Valid virtual collection package reference - ref = "github/awesome-copilot/collections/project-planning" + ref = "owner/test-repo/collections/project-planning" assert self.script_runner._is_virtual_package_reference(ref) is True def test_is_virtual_package_reference_regular_package(self): """Test detection rejects regular packages.""" # Regular package (not virtual) - ref = "danielmeppiel/design-guidelines" + ref = "microsoft/apm-sample-package" assert self.script_runner._is_virtual_package_reference(ref) is False def test_is_virtual_package_reference_simple_name(self): @@ -531,14 +531,14 @@ def test_auto_install_virtual_package_file_success(self, mock_exists, mock_mkdir # Mock package info mock_package = MagicMock() - mock_package.name = "awesome-copilot-architecture-blueprint-generator" + mock_package.name = "test-repo-architecture-blueprint-generator" mock_package.version = "1.0.0" mock_package_info = MagicMock() mock_package_info.package = mock_package mock_downloader.download_virtual_file_package.return_value = mock_package_info # Test auto-install - ref = "github/awesome-copilot/prompts/architecture-blueprint-generator.prompt.md" + ref = "owner/test-repo/prompts/architecture-blueprint-generator.prompt.md" result = self.script_runner._auto_install_virtual_package(ref) assert result is True @@ -556,14 +556,14 @@ def test_auto_install_virtual_package_collection_success(self, mock_exists, mock # Mock package info mock_package = MagicMock() - mock_package.name = "awesome-copilot-project-planning" + mock_package.name = "test-repo-project-planning" mock_package.version = "1.0.0" mock_package_info = MagicMock() mock_package_info.package = mock_package mock_downloader.download_virtual_collection_package.return_value = mock_package_info # Test auto-install - ref = "github/awesome-copilot/collections/project-planning" + ref = "owner/test-repo/collections/project-planning" result = self.script_runner._auto_install_virtual_package(ref) assert result is True @@ -575,7 +575,7 @@ def test_auto_install_virtual_package_already_installed(self, mock_exists): # Package already exists mock_exists.return_value = True - ref = "github/awesome-copilot/prompts/architecture-blueprint-generator.prompt.md" + ref = "owner/test-repo/prompts/architecture-blueprint-generator.prompt.md" result = self.script_runner._auto_install_virtual_package(ref) assert result is True # Should return True (success) without downloading @@ -594,7 +594,7 @@ def test_auto_install_virtual_package_download_failure(self, mock_exists, mock_m mock_downloader.download_virtual_file_package.side_effect = RuntimeError("Download failed") # Test auto-install - ref = "github/awesome-copilot/prompts/architecture-blueprint-generator.prompt.md" + ref = "owner/test-repo/prompts/architecture-blueprint-generator.prompt.md" result = self.script_runner._auto_install_virtual_package(ref) assert result is False # Should return False on failure @@ -602,7 +602,7 @@ def test_auto_install_virtual_package_download_failure(self, mock_exists, mock_m def test_auto_install_virtual_package_invalid_reference(self): """Test auto-install rejects invalid references.""" # Not a virtual package - ref = "danielmeppiel/design-guidelines" + ref = "microsoft/apm-sample-package" result = self.script_runner._auto_install_virtual_package(ref) assert result is False @@ -617,12 +617,12 @@ def test_run_script_triggers_auto_install(self, mock_file, mock_exists, mock_exe mock_runtime, mock_discover, mock_auto_install): """Test that run_script triggers auto-install for virtual package references.""" mock_exists.return_value = True # apm.yml exists - mock_discover.side_effect = [None, Path("apm_modules/github/awesome-copilot-architecture-blueprint-generator/.apm/prompts/architecture-blueprint-generator.prompt.md")] + mock_discover.side_effect = [None, Path("apm_modules/github/test-repo-architecture-blueprint-generator/.apm/prompts/architecture-blueprint-generator.prompt.md")] mock_auto_install.return_value = True mock_runtime.return_value = "copilot" mock_execute.return_value = True - ref = "github/awesome-copilot/prompts/architecture-blueprint-generator.prompt.md" + ref = "owner/test-repo/prompts/architecture-blueprint-generator.prompt.md" result = self.script_runner.run_script(ref, {}) # Verify auto-install was called @@ -644,7 +644,7 @@ def test_run_script_auto_install_failure_shows_error(self, mock_file, mock_exist mock_discover.return_value = None mock_auto_install.return_value = False # Auto-install failed - ref = "github/awesome-copilot/prompts/architecture-blueprint-generator.prompt.md" + ref = "owner/test-repo/prompts/architecture-blueprint-generator.prompt.md" with pytest.raises(RuntimeError) as exc_info: self.script_runner.run_script(ref, {}) @@ -682,11 +682,11 @@ def test_run_script_uses_cached_package(self, mock_file, mock_exists, mock_execu """Test that run_script uses already-installed package without re-downloading.""" mock_exists.return_value = True # apm.yml exists # Package already discovered (no auto-install needed) - mock_discover.return_value = Path("apm_modules/github/awesome-copilot-architecture-blueprint-generator/.apm/prompts/architecture-blueprint-generator.prompt.md") + mock_discover.return_value = Path("apm_modules/github/test-repo-architecture-blueprint-generator/.apm/prompts/architecture-blueprint-generator.prompt.md") mock_runtime.return_value = "copilot" mock_execute.return_value = True - ref = "github/awesome-copilot/prompts/architecture-blueprint-generator.prompt.md" + ref = "owner/test-repo/prompts/architecture-blueprint-generator.prompt.md" result = self.script_runner.run_script(ref, {}) # Verify discovery found it on first try @@ -706,7 +706,7 @@ def test_run_script_handles_install_success_but_no_prompt(self, mock_file, mock_ mock_discover.side_effect = [None, None] # Not found before or after install mock_auto_install.return_value = True # Install succeeded - ref = "github/awesome-copilot/prompts/architecture-blueprint-generator.prompt.md" + ref = "owner/test-repo/prompts/architecture-blueprint-generator.prompt.md" with pytest.raises(RuntimeError) as exc_info: self.script_runner.run_script(ref, {}) diff --git a/tests/unit/test_selective_install.py b/tests/unit/test_selective_install.py index 5088409a..15285e42 100644 --- a/tests/unit/test_selective_install.py +++ b/tests/unit/test_selective_install.py @@ -88,7 +88,7 @@ def test_real_bug_case_mcp_builder_vs_design_guidelines(self): # Should NOT match design-guidelines assert not self._matches_filter( - "github.com/danielmeppiel/design-guidelines", + "github.com/microsoft/apm-sample-package", filter_list ) diff --git a/tests/unit/test_version_checker.py b/tests/unit/test_version_checker.py index ab81a288..3aa8b4e8 100644 --- a/tests/unit/test_version_checker.py +++ b/tests/unit/test_version_checker.py @@ -110,7 +110,7 @@ def test_fetch_successful(self, mock_get): # Verify API call mock_get.assert_called_once() call_args = mock_get.call_args - self.assertIn("danielmeppiel/apm", call_args[0][0]) + self.assertIn("microsoft/apm", call_args[0][0]) @patch("requests.get") def test_fetch_without_v_prefix(self, mock_get):