diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json index b4a5e55e..de9302d6 100644 --- a/.agents/plugins/marketplace.json +++ b/.agents/plugins/marketplace.json @@ -48,7 +48,7 @@ "path": "./plugins/dotnet-skills" }, "policy": { - "installation": "NOT_AVAILABLE", + "installation": "AVAILABLE", "authentication": "ON_INSTALL" }, "category": "Developer Tools" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3cca6dfd..fc1ff774 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -165,6 +165,13 @@ scripts/release.sh custom 1.2.3 Use the release modes in [`docs/maintainers/release-modes.md`](./docs/maintainers/release-modes.md) when preparing the actual release. Use `standard` for root-only releases and `subtrees` when a release also needs subtree pull/push accounting. +Before opening or merging a release PR that changes marketplace entries, +plugin manifests, or child plugin payloads, run the appropriate temporary +`CODEX_HOME` smoke check from +[`docs/maintainers/plugin-install-testing.md`](./docs/maintainers/plugin-install-testing.md) +so the release proves the marketplace add path without touching a production +Codex install. + If the changed surface also introduces or expands Python-backed repo checks, add the required tools to the repo-local `uv` dev group and document the corresponding `uv run pytest`, `uv run ruff check .`, and `uv run mypy` commands where that repo's contributors will actually look. When editing docs, also review the rendered Markdown structure and cross-links for the files you changed. diff --git a/README.md b/README.md index 2afa2414..d542f1f3 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Promo audio: [Socket Codex Marketplace Promo](./docs/media/socket-codex-marketpl ### Status -`socket` is maintained and supported by Gale. +`socket` is maintained by Gaelic Ghost. ### What This Project Is @@ -31,7 +31,7 @@ Socket is a Marketplace of Plugins, Hooks, and MCP servers for Apple Platform De ### Motivation -Agents are great, but to do specialized work, they need specialized tools. As I continued building skills for my workflows, I needed a place to distribute them from. Socket is that place. I hope you find these as useful as I have. +Agents are great, but to do specialized work, they need specialized tools. Socket is a shared catalog for focused Codex plugins, hooks, skills, and MCP-backed workflows. ## Quick Start @@ -53,13 +53,14 @@ Newly added plugins can be installed from the same plugin directory inside Codex ## Usage -Use `socket` when you want one Codex catalog for Gale's agent-focused plugin set. +Use `socket` when you want one Codex catalog for focused agent workflow plugins. Currently available from the catalog: - `agent-plugin-skills` - `apple-dev-skills` - `cardhop-app` +- `dotnet-skills` - `productivity-skills` - `python-skills` - `speak-swiftly` @@ -75,6 +76,7 @@ Current Socket catalog shape: - `agent-plugin-skills`: maintainer skills for skills-export and plugin-export repositories - `apple-dev-skills`: Apple, Swift, SwiftUI, Xcode, and DocC workflows with its own roadmap - `cardhop-app`: mixed skill plus bundled MCP server for Cardhop.app contact workflows +- `dotnet-skills`: .NET, F#, and C# project-shape, bootstrap, implementation, test, package, diagnostics, ASP.NET Core, interop, CI, upgrade, and tooling guidance - `productivity-skills`: general-purpose maintainer and documentation workflow baseline - `python-skills`: Python, `uv`, FastAPI, FastMCP, and pytest workflow plugin - `speak-swiftly`: Git-backed Speak Swiftly plugin from the standalone SpeakSwiftlyServer repository @@ -83,7 +85,6 @@ Current Socket catalog shape: Placeholder directories for future plugins (not available for install): -- `dotnet-skills` - `rust-skills` - `spotify` - `web-dev-skills` diff --git a/ROADMAP.md b/ROADMAP.md index 12808ce2..fb2cebb5 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -6,12 +6,13 @@ - [Product Principles](#product-principles) - [Milestone Progress](#milestone-progress) - [Milestone 5: SwiftASB skills plugin](#milestone-5-swiftasb-skills-plugin) +- [Milestone 6: Dotnet skills plugin](#milestone-6-dotnet-skills-plugin) - [Backlog Candidates](#backlog-candidates) - [History](#history) ## Vision -- Keep `socket` as the honest superproject layer for Gale's public Codex plugin and skills ecosystem, with subtree imports, root marketplace wiring, and cross-repo maintainer guidance kept consistent. +- Keep `socket` as the honest superproject layer for a public Codex plugin and skills ecosystem, with subtree imports, root marketplace wiring, and cross-repo maintainer guidance kept consistent. ## Product Principles @@ -23,6 +24,7 @@ ## Milestone Progress - Milestone 5: SwiftASB skills plugin - In Progress +- Milestone 6: Dotnet skills plugin - In Progress ## Milestone 5: SwiftASB skills plugin @@ -55,6 +57,37 @@ In Progress - [x] The new skills guide SwiftUI, AppKit, and Swift package integrations without duplicating broad Apple framework guidance that belongs to `apple-dev-skills`. - [x] Root Socket docs, marketplace wiring, and validation agree on the plugin's install surface. +## Milestone 6: Dotnet skills plugin + +### Status + +In Progress + +### Scope + +- [x] Turn the placeholder `dotnet-skills` child plugin into an installable `.NET` guidance plugin. +- [x] Treat F# and C# as equal first-party `.NET` language choices in plugin metadata, skill descriptions, examples, scaffolding guidance, and diagnostics. +- [x] Keep the plugin as a companion guidance surface rather than a runtime plugin: do not bundle an MCP server, custom package manager, private template feed, or machine-local SDK state. + +### Tickets + +- [x] Record the detailed plugin plan in [`docs/maintainers/dotnet-skills-plugin-plan.md`](./docs/maintainers/dotnet-skills-plugin-plan.md). +- [x] Update `plugins/dotnet-skills/AGENTS.md` with the F#/C# parity policy and `.NET` validation expectations. +- [x] Update `plugins/dotnet-skills/.codex-plugin/plugin.json` so plugin metadata includes F# and avoids C#-only wording. +- [x] Add first-slice skills for project-shape choice, solution bootstrap, F# project implementation, C# project implementation, and test workflow. +- [x] Add second-slice skills for package workflow, diagnostics, ASP.NET Core services, F#/C# interop, CI, upgrades, and tooling/style alignment. +- [x] Switch the root marketplace entry for `dotnet-skills` from placeholder to installable only after real skill content exists. +- [x] Update root README and maintainer docs so users understand the new installable child plugin surface. +- [x] Run root metadata validation with `uv run scripts/validate_socket_metadata.py` and any child-plugin checks added by the new plugin. + +### Exit Criteria + +- [x] The Socket marketplace exposes `dotnet-skills` as an installable child plugin. +- [x] The new skills can help an agent choose a `.NET` project shape before implementation. +- [x] The new skills guide F# and C# implementation without making either language a secondary path. +- [x] The testing guidance uses `dotnet test` as the stable command surface while respecting repo-local test framework choices. +- [x] Root Socket docs, marketplace wiring, and validation agree on the plugin's install surface. + ## Backlog Candidates - [x] Overhaul `agent-plugin-skills` so its docs, tests, generated bootstrap content, and sync audit logic target Codex/OpenAI plus the open `.agents/skills` discovery mirror only. Remove stale expectations for retired child maintainer docs such as reality-audit and install-surface docs, and keep the wording away from unsupported non-Codex or generic multi-agent surfaces. diff --git a/docs/maintainers/dotnet-skills-plugin-plan.md b/docs/maintainers/dotnet-skills-plugin-plan.md new file mode 100644 index 00000000..cb5863bc --- /dev/null +++ b/docs/maintainers/dotnet-skills-plugin-plan.md @@ -0,0 +1,356 @@ +# .NET Skills Plugin Plan + +This plan records the first durable shape for a Socket-hosted `.NET` skills plugin. + +The plugin's job is to help agents build, test, package, and maintain `.NET` projects while treating F# and C# as equal first-party language choices. F# should stay visibly first-class, so the plugin should avoid silently centering C# in examples, scaffold defaults, skill names, or decision language. + +## Intent + +The `dotnet-skills` plugin should help agents do five things: + +- choose a `.NET` project shape before scaffolding or implementation starts +- bootstrap reproducible `.NET` solutions, projects, tests, and package surfaces +- write idiomatic F# and C# without translating one language's habits into the other +- run and explain `.NET` build, test, package, and diagnostics workflows +- keep `.NET` guidance grounded in official Microsoft documentation and fetchable package sources + +This is a companion guidance plugin, not a runtime plugin. The first version should not bundle an MCP server, custom package manager, private template feed, or local machine-specific SDK state. + +## Packaging Direction + +Package the guidance as an independent child plugin under: + +```text +plugins/dotnet-skills/ +``` + +The child plugin should own its Codex-facing guidance surface: + +- `.codex-plugin/plugin.json` +- `skills/` +- plugin metadata, skill metadata, `AGENTS.md`, or maintainer notes that explain the plugin's role +- any validation scripts needed for the plugin's own authored guidance + +The root Socket marketplace now lists `dotnet-skills` as an installable child plugin because the first real skills have landed. If the plugin ever loses its exported skill content, switch the marketplace entry back to `NOT_AVAILABLE` in the same pass. + +## F# And C# Parity + +F# and C# must be treated as equal first-party `.NET` languages. + +That means: + +- do not describe F# as secondary, niche, or merely compatible with `.NET` +- do not silently choose C# when the user has not named a language +- ask for language preference before scaffolding when the user's request is ambiguous +- present F# and C# as peer options in project-shape and bootstrap guidance +- include F# in plugin keywords, skill descriptions, examples, and testing guidance +- prefer F# examples first when no broader user-facing default is required +- include both `.fsproj` and `.csproj` examples when the guidance is language-neutral but project-file details matter +- call out F# compile-order behavior, module organization, records, discriminated unions, options, async/task interop, and testing style explicitly instead of treating F# as C# with different syntax +- call out C# nullable reference types, records/classes, analyzers, async/task behavior, and idiomatic project layout explicitly instead of treating C# as the universal `.NET` baseline + +The plugin identity can stay `dotnet-skills` because `.NET` is the platform surface. The authored guidance should consistently say `.NET, F#, and C#` where language parity matters. + +## Documentation Sources + +Use official Microsoft documentation first for `.NET` behavior: + +- [.NET documentation](https://learn.microsoft.com/dotnet/) +- [.NET CLI documentation](https://learn.microsoft.com/dotnet/core/tools/) +- [F# documentation](https://learn.microsoft.com/dotnet/fsharp/) +- [C# documentation](https://learn.microsoft.com/dotnet/csharp/) +- [`global.json` documentation](https://learn.microsoft.com/dotnet/core/tools/global-json) +- [`dotnet test` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-test) +- [`dotnet pack` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-pack) +- [ASP.NET Core documentation](https://learn.microsoft.com/aspnet/core/) + +When a skill relies on documentation, translate the relevant rule into practical workflow guidance. Do not drop citations into a skill as a substitute for explaining the effect on scaffolding, validation, project layout, or user-facing behavior. + +## Proposed Skill Inventory + +### `dotnet:choose-project-shape` + +Help an agent decide how `.NET` should fit into a user's project before implementation starts. + +This skill should classify the requested work: + +- console app +- library package +- test project +- CLI tool +- ASP.NET Core service +- worker service +- multi-project solution +- mixed F# and C# solution +- package maintenance or upgrade pass + +The output should recommend language choice, project templates, solution layout, validation commands, package boundaries, and documentation updates. It should ask about F# versus C# when the user has not decided. + +### `dotnet:bootstrap-solution` + +Create or guide a reproducible `.NET` solution scaffold. + +This skill should cover: + +- SDK selection and `global.json` when reproducibility matters +- solution and project naming +- F# and C# project creation with the `dotnet` CLI +- library, app, and test project layout +- project references +- `.editorconfig` +- package restore +- initial build and test validation +- optional initial commit when the user asks for it + +The scaffold path should require an explicit language choice or an interactive decision before creating source files. + +### `dotnet:build-fsharp-project` + +Guide agents through idiomatic F# project implementation. + +This skill should emphasize: + +- modules, namespaces, records, discriminated unions, options, and results +- functional data flow and explicit inputs and outputs +- file ordering in `.fsproj` +- async/task interop for modern `.NET` APIs +- public API shape for libraries +- test project layout and assertion style +- interop boundaries when a solution also contains C# + +This is a language-specific skill, not a translation layer from C# examples. + +### `dotnet:build-csharp-project` + +Guide agents through idiomatic C# project implementation. + +This skill should emphasize: + +- nullable reference types +- records, classes, interfaces, and primary constructors where appropriate +- async/task behavior +- analyzers and warnings-as-errors when a repo already uses them +- public API shape for libraries +- test project layout and assertion style +- interop boundaries when a solution also contains F# + +This is a language-specific skill, not the default `.NET` skill. + +### `dotnet:testing-workflow` + +Run, debug, filter, and explain `.NET` tests. + +This skill should cover: + +- `dotnet test` +- targeted test filters +- solution-level versus project-level testing +- test output and logger choices +- failing restore, build, and test phases +- F# test project expectations +- C# test project expectations +- when to add focused tests versus broader integration checks + +### `dotnet:package-workflow` + +Build and validate `.NET` package surfaces. + +This skill should cover: + +- package metadata in project files +- `dotnet pack` +- local package smoke checks +- semantic versioning +- NuGet package-source expectations +- release notes and upgrade guidance +- F# and C# library package examples + +It should not publish packages by default. Publishing is a release activity and should require an explicit user request or repo-local release workflow. + +### `dotnet:diagnose-project` + +Help agents debug `.NET` restore, build, test, package, SDK, and project-reference failures. + +This skill should cover: + +- missing or mismatched SDKs +- target framework drift +- package restore failures +- broken project references +- F# compile-order failures +- C# nullable or analyzer failures +- test discovery problems +- package metadata failures +- ambiguous or vague error messages that need human-friendly explanation + +Diagnostics should report what broke, where it broke, the likely cause, and the smallest useful next check. + +### `dotnet:aspnet-core-service-workflow` + +Guide agents through ASP.NET Core service work after the core `.NET` project shape is settled. + +This skill should cover: + +- host project ownership +- F# service, C# service, and mixed C# host plus F# domain-library shapes +- endpoint behavior +- configuration and secret boundaries +- dependency injection only where it solves a real dependency boundary +- domain tests versus endpoint or integration tests +- `dotnet build` and `dotnet test` validation + +It should not make ASP.NET Core the default `.NET` project shape when a library, CLI, or package would fit better. + +### `dotnet:fsharp-csharp-interop` + +Guide agents through mixed F# and C# solution boundaries. + +This skill should cover: + +- when mixed language projects are useful enough to justify the boundary +- project-reference direction +- F# domain libraries consumed by C# hosts +- C# infrastructure projects consumed by F# apps or libraries +- public API shape for options, records, discriminated unions, nullability, and async/task interop +- tests from the consuming side when a boundary is public or fragile + +It should avoid flattening F# domain modeling into C#-shaped classes just for convenience. + +### `dotnet:ci-workflow` + +Guide agents through .NET CI setup and maintenance. + +This skill should cover: + +- SDK setup +- `global.json` versus workflow-pinned SDKs +- restore, build, test, format, and pack checks +- F# and C# path filters +- OS and SDK matrix decisions +- keeping local and CI commands aligned + +It should not publish packages unless the user explicitly asks for release automation. + +### `dotnet:upgrade-workflow` + +Guide agents through .NET SDK, target framework, package, and language-version upgrades. + +This skill should cover: + +- current SDK and target framework inventory +- `global.json` +- package version sources +- official breaking-change notes +- F# compiler or language-version behavior +- C# nullable and analyzer behavior +- staged restore, build, test, and pack validation +- migration notes for contributors or package consumers + +### `dotnet:tooling-style-workflow` + +Guide agents through .NET formatting and analyzer alignment. + +This skill should cover: + +- `.editorconfig` +- `dotnet format` +- analyzers +- warnings-as-errors +- local .NET tools +- CI style checks +- which tooling actually applies to F# sources versus C# sources + +It should keep formatting-only sweeps separate from behavior changes when practical. + +## First Implementation Slice + +The first slice should be intentionally small but installable: + +- [x] Update `plugins/dotnet-skills/AGENTS.md` with the F#/C# parity policy and `.NET` validation expectations. +- [x] Update `plugins/dotnet-skills/.codex-plugin/plugin.json` so plugin metadata includes F# and avoids C#-only wording. +- [x] Add `dotnet:choose-project-shape`. +- [x] Add `dotnet:bootstrap-solution`. +- [x] Add `dotnet:build-fsharp-project`. +- [x] Add `dotnet:build-csharp-project`. +- [x] Add `dotnet:testing-workflow`. +- [x] Decide not to add per-skill `agents/openai.yaml` metadata in the first slice because this child plugin follows the existing SwiftASB skills shape. +- [x] Switch the root marketplace entry for `dotnet-skills` to installable only after real skill content exists. +- [x] Update `README.md` and `ROADMAP.md` so Socket documents the new child plugin surface. +- [x] Run `uv run scripts/validate_socket_metadata.py`. +- [x] Run any child-plugin validation added by the new plugin; no child-local validator was added in the first slice. + +## Second Implementation Slice + +The second slice broadens the plugin from core project/test guidance into package, service, interop, CI, upgrade, and tooling guidance: + +- [x] `dotnet:package-workflow`. +- [x] `dotnet:diagnose-project`. +- [x] `dotnet:aspnet-core-service-workflow`. +- [x] `dotnet:fsharp-csharp-interop`. +- [x] `dotnet:ci-workflow`. +- [x] `dotnet:upgrade-workflow`. +- [x] `dotnet:tooling-style-workflow`. +- [ ] install testing with a temporary `CODEX_HOME`. + +## Deferred Scope + +After the first two slices prove useful, consider deeper specialized workflows. These are useful but should not block the current installable plugin: + +- Blazor app workflows +- .NET Aspire workflows +- .NET MAUI workflows +- advanced performance profiling +- C# source generators +- NuGet publishing automation +- custom project template generation +- bundled MCP servers or app connectors + +## Open Decisions Before Implementation + +### Skill Names + +Decision for the first slice: use short names such as `build-fsharp-project` because the plugin namespace already supplies the `.NET` context. + +Longer names can be reconsidered only if skills are later copied outside the `dotnet-skills` plugin context. + +### Scaffolding Depth + +Decision for the first slice: keep `dotnet:bootstrap-solution` as pure guidance. + +A script becomes useful if repeatable solution scaffolds with F# and C# parity need to be baked into command generation, but it also creates a validation and maintenance surface. Defer that until the guidance shape proves itself. + +### Default Test Frameworks + +Updated decision: recommend xUnit as the default scaffold template for new F# and C# test projects. + +Read existing repo choices first and preserve them in existing projects. For new scaffolds without a repo-local test framework, use `dotnet new xunit` because it is the common .NET CLI template path documented by Microsoft, then use `dotnet test` as the stable command surface. + +### Formatting And Analyzer Policy + +Decision for the first slice: respect existing repo configuration and keep new-project style guidance conservative. + +A later `tooling-style-workflow` can make `dotnet format`, analyzers, `.editorconfig`, warnings-as-errors, and language-specific style more complete. + +### ASP.NET Core Timing + +Decision for the first slice: defer ASP.NET Core service guidance to the second slice. + +Core `.NET` solution, language, and test guidance should land first so web-service guidance can reuse stable project and validation rules. + +### Versioning And Marketplace Timing + +Decision for the first implementation: treat this as a likely Socket minor release candidate. + +Because this turns a placeholder plugin into an installable plugin with real user-facing capability, a minor release is the likely SemVer shape for publication. + +## Definition Of Done + +The plugin is ready for first release when: + +- [x] Socket exposes `dotnet-skills` as an installable child plugin. +- [x] The plugin metadata names both F# and C#. +- [x] The skills consistently treat F# and C# as equal first-party `.NET` choices. +- [x] Ambiguous scaffolding guidance asks for language preference instead of silently choosing C#. +- [x] The first skill set covers project choice, solution bootstrap, F# implementation, C# implementation, and testing workflow. +- [x] The guidance uses official Microsoft documentation as the source of truth for `.NET` SDK, CLI, language, test, and package behavior. +- [x] Root Socket docs, marketplace wiring, and validation agree on the plugin's install surface. diff --git a/docs/maintainers/plugin-install-testing.md b/docs/maintainers/plugin-install-testing.md index 9de86d12..2e758ae3 100644 --- a/docs/maintainers/plugin-install-testing.md +++ b/docs/maintainers/plugin-install-testing.md @@ -52,6 +52,19 @@ Expected result for the Speak Swiftly catalog split: - Removing `socket` leaves no configured marketplace in the temporary Codex home. +For ordinary child-plugin releases, inspect the changed plugin entry instead of +`speak-swiftly`. The smoke check should verify: + +- Codex reports an added marketplace named `socket` from the local checkout. +- The changed child plugin entry has the expected `policy.installation` value. +- The changed child plugin entry points at the expected source path or + Git-backed source. +- The changed child plugin root exposes `.codex-plugin/plugin.json`. +- The changed child plugin manifest exposes every expected `skills`, `hooks`, + `mcpServers`, or `apps` component. +- Removing `socket` leaves no configured marketplace in the temporary Codex + home. + ## Socket Git-Backed Test Run this after the Socket branch has landed in GitHub state that users can diff --git a/docs/maintainers/release-modes.md b/docs/maintainers/release-modes.md index fa3b00e7..251c3d38 100644 --- a/docs/maintainers/release-modes.md +++ b/docs/maintainers/release-modes.md @@ -10,18 +10,19 @@ Both modes treat `socket` as the release owner for the umbrella repository: 1. make the intended commits 2. validate the changed surface -3. publish through a branch and pull request when the change is not already on `main` -4. check CI and fix failures before continuing -5. check PR comments and requested changes before continuing -6. merge to `main` -7. fast-forward local `main` -8. create the `socket` tag locally from the reviewed `main` -9. push the tag -10. create the GitHub release from the existing tag -11. verify the GitHub release object exists -12. verify `git log origin/main..main` is empty -13. account for every local branch not contained by `main` -14. refresh the local Codex marketplace cache with `codex plugin marketplace upgrade socket` +3. run the relevant temporary `CODEX_HOME` smoke check from [`plugin-install-testing.md`](./plugin-install-testing.md) +4. publish through a branch and pull request when the change is not already on `main` +5. check CI and fix failures before continuing +6. check PR comments and requested changes before continuing +7. merge to `main` +8. fast-forward local `main` +9. create the `socket` tag locally from the reviewed `main` +10. push the tag +11. create the GitHub release from the existing tag +12. verify the GitHub release object exists +13. verify `git log origin/main..main` is empty +14. account for every local branch not contained by `main` +15. refresh the local Codex marketplace cache with `codex plugin marketplace upgrade socket` `codex plugin marketplace upgrade socket` is always the final release step. Never run it before the GitHub release exists and has been verified, subtree accounting is complete, and branch accounting has been recorded. @@ -85,6 +86,7 @@ Before tagging `socket`: - confirm the subtree policy table above was followed - run `uv run scripts/validate_socket_metadata.py` +- run the relevant temporary `CODEX_HOME` smoke check from [`plugin-install-testing.md`](./plugin-install-testing.md) - confirm local `main` is fast-forwarded to `origin/main` - run `scripts/release.sh release-ready X.Y.Z` - confirm `git log origin/main..main` is empty diff --git a/plugins/agent-plugin-skills/.codex-plugin/plugin.json b/plugins/agent-plugin-skills/.codex-plugin/plugin.json index 3d626eba..7d8e5048 100644 --- a/plugins/agent-plugin-skills/.codex-plugin/plugin.json +++ b/plugins/agent-plugin-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "agent-plugin-skills", - "version": "6.8.0", + "version": "6.9.0", "description": "Installable maintainer skills for skills-export repositories.", "author": { "name": "Gale", diff --git a/plugins/agent-plugin-skills/pyproject.toml b/plugins/agent-plugin-skills/pyproject.toml index 240cae64..a76f7715 100644 --- a/plugins/agent-plugin-skills/pyproject.toml +++ b/plugins/agent-plugin-skills/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "agent-plugin-skills-maintenance" -version = "6.8.0" +version = "6.9.0" description = "Maintainer-only Python tooling baseline for agent-plugin-skills." requires-python = ">=3.11" dependencies = [] diff --git a/plugins/agent-plugin-skills/uv.lock b/plugins/agent-plugin-skills/uv.lock index df572cbb..01878104 100644 --- a/plugins/agent-plugin-skills/uv.lock +++ b/plugins/agent-plugin-skills/uv.lock @@ -4,7 +4,7 @@ requires-python = ">=3.11" [[package]] name = "agent-plugin-skills-maintenance" -version = "6.8.0" +version = "6.9.0" source = { virtual = "." } [package.dev-dependencies] diff --git a/plugins/apple-dev-skills/.codex-plugin/plugin.json b/plugins/apple-dev-skills/.codex-plugin/plugin.json index 8d664e74..7d83b4e2 100644 --- a/plugins/apple-dev-skills/.codex-plugin/plugin.json +++ b/plugins/apple-dev-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "apple-dev-skills", - "version": "6.8.0", + "version": "6.9.0", "description": "Apple development workflows for Codex, including SwiftUI architecture, Safari extensions, and DocC authoring guidance.", "author": { "name": "Gale", diff --git a/plugins/apple-dev-skills/pyproject.toml b/plugins/apple-dev-skills/pyproject.toml index 3df5b5fd..a59bbdbd 100644 --- a/plugins/apple-dev-skills/pyproject.toml +++ b/plugins/apple-dev-skills/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "apple-dev-skills-maintainer" -version = "6.8.0" +version = "6.9.0" description = "Maintainer tooling for the apple-dev-skills repository" requires-python = ">=3.9" dependencies = [] diff --git a/plugins/apple-dev-skills/uv.lock b/plugins/apple-dev-skills/uv.lock index b35f7019..0850d01d 100644 --- a/plugins/apple-dev-skills/uv.lock +++ b/plugins/apple-dev-skills/uv.lock @@ -8,7 +8,7 @@ resolution-markers = [ [[package]] name = "apple-dev-skills-maintainer" -version = "6.8.0" +version = "6.9.0" source = { virtual = "." } [package.dev-dependencies] diff --git a/plugins/cardhop-app/.codex-plugin/plugin.json b/plugins/cardhop-app/.codex-plugin/plugin.json index 1ba02d39..45be5918 100644 --- a/plugins/cardhop-app/.codex-plugin/plugin.json +++ b/plugins/cardhop-app/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "cardhop-app", - "version": "6.8.0", + "version": "6.9.0", "description": "Cardhop.app workflow guidance plus a bundled local MCP server for contact capture and updates on macOS.", "author": { "name": "Gale", diff --git a/plugins/cardhop-app/mcp/pyproject.toml b/plugins/cardhop-app/mcp/pyproject.toml index 3241c899..ba66644e 100644 --- a/plugins/cardhop-app/mcp/pyproject.toml +++ b/plugins/cardhop-app/mcp/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "cardhop-app-mcp" -version = "6.8.0" +version = "6.9.0" requires-python = ">=3.13" dependencies = [ "fastmcp>=3.0.2", diff --git a/plugins/cardhop-app/mcp/uv.lock b/plugins/cardhop-app/mcp/uv.lock index e7846e06..e4f28181 100644 --- a/plugins/cardhop-app/mcp/uv.lock +++ b/plugins/cardhop-app/mcp/uv.lock @@ -93,7 +93,7 @@ wheels = [ [[package]] name = "cardhop-app-mcp" -version = "6.8.0" +version = "6.9.0" source = { virtual = "." } dependencies = [ { name = "fastmcp" }, diff --git a/plugins/dotnet-skills/.codex-plugin/plugin.json b/plugins/dotnet-skills/.codex-plugin/plugin.json index a90c72e2..aa23b1ca 100644 --- a/plugins/dotnet-skills/.codex-plugin/plugin.json +++ b/plugins/dotnet-skills/.codex-plugin/plugin.json @@ -1,33 +1,48 @@ { "name": "dotnet-skills", - "version": "6.8.0", - "description": "Standalone plugin repository for future .NET-focused Codex skills.", + "version": "6.9.0", + "description": "Codex skills for choosing, bootstrapping, building, testing, packaging, diagnosing, and maintaining .NET projects with F# and C# as equal first-party languages.", "author": { "name": "Gale", "email": "mail@galewilliams.com", "url": "https://github.com/gaelic-ghost" }, - "homepage": "https://github.com/gaelic-ghost/dotnet-skills", - "repository": "https://github.com/gaelic-ghost/dotnet-skills", + "homepage": "https://github.com/gaelic-ghost/socket/tree/main/plugins/dotnet-skills", + "repository": "https://github.com/gaelic-ghost/socket", "license": "Apache-2.0", "keywords": [ "codex", "plugin", "skills", "dotnet", + "fsharp", "csharp" ], + "skills": "./skills/", "interface": { - "displayName": "Dotnet Skills", - "shortDescription": "Future .NET-focused Codex skills.", - "longDescription": "Standalone plugin repository for future .NET-focused Codex skills and maintainer workflows.", - "developerName": "Gale", + "displayName": ".NET Skills", + "shortDescription": ".NET, F#, and C# workflow guidance for Codex.", + "longDescription": "Guide Codex agents through choosing .NET project shapes, bootstrapping reproducible solutions, building idiomatic F# and C# projects, running tests, validating packages, diagnosing failures, designing ASP.NET Core services, maintaining mixed-language boundaries, and aligning CI, upgrades, and tooling through the .NET CLI.", + "developerName": "gaelic-ghost", "category": "Developer Tools", "capabilities": [ "Read", "Write" ], - "websiteURL": "https://github.com/gaelic-ghost/dotnet-skills", - "brandColor": "#512BD4" + "websiteURL": "https://github.com/gaelic-ghost/socket/tree/main/plugins/dotnet-skills", + "defaultPrompt": [ + "Choose the right .NET project shape before we start implementing.", + "Bootstrap a .NET solution while treating F# and C# as equal options.", + "Build this F# project idiomatically instead of translating from C#.", + "Build this C# project idiomatically while respecting existing repo conventions.", + "Run and explain the .NET testing workflow for this solution.", + "Validate this .NET package surface without publishing it.", + "Diagnose why this .NET restore, build, test, or pack command failed.", + "Design the F# and C# boundary in this mixed .NET solution.", + "Align this .NET repo's CI, upgrade, formatting, and analyzer workflow." + ], + "brandColor": "#512BD4", + "composerIcon": "./assets/sharp-icon.jpg", + "logo": "./assets/sharp-icon.jpg" } } diff --git a/plugins/dotnet-skills/AGENTS.md b/plugins/dotnet-skills/AGENTS.md index fa81c303..6197bf06 100644 --- a/plugins/dotnet-skills/AGENTS.md +++ b/plugins/dotnet-skills/AGENTS.md @@ -4,11 +4,21 @@ This file is the .NET Skills child-repo override for work done from `socket`. Fo ## Scope -- `dotnet-skills` is a placeholder source for future .NET-focused Codex skills. -- Keep the repo intentionally minimal until the first real skill lands. -- [`.codex-plugin/plugin.json`](./.codex-plugin/plugin.json) is the required plugin root today. +- `dotnet-skills` is a monorepo-owned Socket child and the canonical source of truth for shipped .NET workflow skills. +- Root [`skills/`](./skills/) is the authored workflow surface. +- The repo root is the Codex plugin root through [`.codex-plugin/plugin.json`](./.codex-plugin/plugin.json). +- Treat `productivity-skills` as the default baseline maintainer layer for general repo-doc and maintenance work; use this repo when .NET, F#, C#, SDK, CLI, project, package, or test behavior should materially change the workflow. ## Local Rules -- Do not add extra packaging layers, repo-local install machinery, or broad maintainer automation before real skill content exists. -- Prefer adding actual skill content before expanding docs or workflow complexity. +- Match the `socket` shared semantic version exactly; use the Socket root release workflow for version inventory and bumps. +- Treat F# and C# as equal first-party .NET language choices. +- Do not describe F# as secondary, niche, or merely compatible with .NET. +- Do not silently choose C# when the user has not named a language. +- Ask for language preference before scaffolding when the user's request is ambiguous. +- Prefer F# examples first when no broader public default is required, so F# stays visibly first-class in neutral examples. +- Keep .NET examples grounded in the `dotnet` CLI unless a repository already documents a different tool path. +- Use official Microsoft documentation first for .NET SDK, CLI, F#, C#, ASP.NET Core, testing, package, and project behavior. +- Keep package dependencies fetchable from NuGet, GitHub, package registries, or other real remote repositories; do not commit machine-local SDK, package, or project references. +- For validation guidance, prefer the narrowest relevant `dotnet restore`, `dotnet build`, `dotnet test`, or `dotnet pack` command for the project shape. +- Do not add extra packaging layers, repo-local install machinery, broad maintainer automation, custom template feeds, or bundled MCP servers unless a later plan explicitly calls for that scope. diff --git a/plugins/dotnet-skills/assets/sharp-icon.jpg b/plugins/dotnet-skills/assets/sharp-icon.jpg new file mode 100644 index 00000000..5a747ea6 Binary files /dev/null and b/plugins/dotnet-skills/assets/sharp-icon.jpg differ diff --git a/plugins/dotnet-skills/skills/aspnet-core-service-workflow/SKILL.md b/plugins/dotnet-skills/skills/aspnet-core-service-workflow/SKILL.md new file mode 100644 index 00000000..0308063a --- /dev/null +++ b/plugins/dotnet-skills/skills/aspnet-core-service-workflow/SKILL.md @@ -0,0 +1,116 @@ +--- +name: aspnet-core-service-workflow +description: Plan, build, and validate ASP.NET Core service surfaces for F#, C#, or mixed .NET solutions using explicit project ownership, configuration, endpoints, tests, and dotnet CLI validation. +license: Apache-2.0 +compatibility: Designed for Codex and compatible Agent Skills clients working with ASP.NET Core services on the .NET SDK. +metadata: + owner: gaelic-ghost + repo: socket + category: dotnet-aspnet-core +allowed-tools: Read Bash(rg:*) Bash(git:*) Bash(dotnet:*) +--- + +# ASP.NET Core Service Workflow + +## Purpose + +Build or modify an ASP.NET Core service with clear ownership, configuration, endpoints, tests, and validation. + +The practical decision is what the service exposes, which project owns the HTTP host, where domain logic lives, how configuration reaches the app, and how tests prove behavior without turning the whole service into a fragile integration fixture. + +## When To Use + +- Use this skill when adding or changing an ASP.NET Core API or service. +- Use this skill when deciding whether a .NET project should be a web service or a library consumed by one. +- Use this skill when adding endpoints, middleware, configuration, dependency injection, or service tests. +- Use this skill after `dotnet:choose-project-shape` has identified an ASP.NET Core service shape. + +## Source Check + +Use official Microsoft documentation first: + +- [ASP.NET Core documentation](https://learn.microsoft.com/aspnet/core/) +- [Minimal APIs documentation](https://learn.microsoft.com/aspnet/core/fundamentals/minimal-apis) +- [ASP.NET Core configuration](https://learn.microsoft.com/aspnet/core/fundamentals/configuration/) +- [ASP.NET Core dependency injection](https://learn.microsoft.com/aspnet/core/fundamentals/dependency-injection) +- [ASP.NET Core integration tests](https://learn.microsoft.com/aspnet/core/test/integration-tests) + +## Planning Workflow + +1. Inspect project shape: + - web project + - domain library + - test project + - config files + - existing endpoints + - existing hosting style +2. Identify the service job: + - HTTP API + - local service + - webhook receiver + - background worker plus HTTP health surface + - internal admin tool +3. Choose language and boundary: + - F# service + - C# service + - C# host with F# domain library + - F# host with C# infrastructure library +4. Keep domain logic outside endpoint handlers when it has real behavior. +5. Keep configuration explicit and environment-safe. +6. Add tests at the smallest useful level. +7. Validate with `dotnet build` and `dotnet test`. + +## F# Service Notes + +For F# services: + +- keep endpoint functions small +- model request and response data clearly +- keep domain transformations in modules that can be tested without the HTTP host +- be explicit at task/async boundaries +- preserve `.fsproj` file ordering + +## C# Service Notes + +For C# services: + +- keep nullable request/response contracts clear +- avoid overbuilding service classes for one endpoint +- use dependency injection for real external dependencies, not as decoration +- keep middleware and endpoint registration readable +- respect analyzers and warnings-as-errors + +## Configuration And Secrets + +Do not commit secrets. + +For local development, follow repo conventions first. If none exist, recommend committed safe defaults and ignored local overrides rather than hard-coded secrets. Explain which settings are required for the app to start and which settings are optional. + +## Testing + +Choose the smallest test that proves the behavior: + +- pure domain test for business rules +- endpoint-level test for routing, validation, or response shape +- integration test for host/config/middleware behavior + +Do not run live external services as ordinary unit tests unless the repo already has an isolated test harness for that purpose. + +## Output Shape + +Return: + +1. `Service shape`: host project, domain project, and test project. +2. `Language boundary`: F#, C#, or mixed. +3. `Endpoint behavior`: routes, inputs, outputs, and errors. +4. `Configuration`: required settings and local override behavior. +5. `Tests`: level and command. +6. `Validation`: exact `dotnet` commands and results. + +## Guardrails + +- Do not add a new service layer without naming the real duplication or testability issue it removes. +- Do not put significant business rules directly inside endpoint registration. +- Do not commit secrets or machine-local configuration. +- Do not make ASP.NET Core the default .NET app shape when a library or CLI would fit better. +- Do not ignore F# compile ordering or C# nullable/analyzer settings. diff --git a/plugins/dotnet-skills/skills/bootstrap-solution/SKILL.md b/plugins/dotnet-skills/skills/bootstrap-solution/SKILL.md new file mode 100644 index 00000000..4b626d81 --- /dev/null +++ b/plugins/dotnet-skills/skills/bootstrap-solution/SKILL.md @@ -0,0 +1,150 @@ +--- +name: bootstrap-solution +description: Bootstrap or guide a reproducible .NET solution with explicit F# or C# language choice, SDK selection, project layout, test project setup, and initial validation commands. +license: Apache-2.0 +compatibility: Designed for Codex and compatible Agent Skills clients working with .NET SDK, F#, C#, and the dotnet CLI on macOS or other supported .NET development environments. +metadata: + owner: gaelic-ghost + repo: socket + category: dotnet-bootstrap +allowed-tools: Read Bash(rg:*) Bash(git:*) Bash(dotnet:*) +--- + +# Bootstrap .NET Solution + +## Purpose + +Create or guide a reproducible .NET solution scaffold without making C# the silent default. + +The user should leave with a clear project layout, explicit F# or C# choice, predictable SDK behavior, and validation commands that prove the scaffold works. + +## When To Use + +- Use this skill when creating a new .NET solution or project. +- Use this skill when adding a test project to an existing .NET repository. +- Use this skill when a repo needs `global.json`, solution-level layout, or explicit validation commands. +- Use this skill after `dotnet:choose-project-shape` when the project shape is settled. + +## Source Check + +Use official Microsoft documentation first: + +- [.NET CLI documentation](https://learn.microsoft.com/dotnet/core/tools/) +- [`dotnet new` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-new) +- [`global.json` documentation](https://learn.microsoft.com/dotnet/core/tools/global-json) +- [`dotnet build` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-build) +- [`dotnet test` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-test) + +Check the local SDK only when implementation actually needs it: + +```bash +dotnet --info +dotnet --list-sdks +``` + +## Required Inputs + +- target path +- project or solution name +- project shape +- language: F#, C#, or mixed +- test project expectation +- test framework expectation; default to xUnit for new scaffolds unless the repo or user chooses another framework +- SDK pinning expectation +- git initialization or commit expectation + +If the user has not selected F# or C#, ask before scaffolding. + +## Guidance Workflow + +1. Inspect the target: + - existing files + - git state + - `.sln` or `.slnx` + - `global.json` + - `Directory.Build.props` + - `.fsproj` or `.csproj` +2. Confirm the project shape and language. +3. Choose SDK behavior: + - use existing `global.json` when present + - add `global.json` when reproducibility matters and the user accepts the SDK pin + - avoid inventing a machine-local SDK path +4. Create projects with the `dotnet` CLI. +5. Add project references. +6. Add tests when the project has behavior worth preserving. Use the existing repo test framework if one exists; otherwise default new scaffolds to xUnit. +7. Run validation. +8. Report the generated paths and exact commands. + +## Command Recipes + +These recipes use xUnit intentionally. It is the recommended default for new scaffolds in this plugin because it is a common .NET CLI test template and Microsoft documents `dotnet test` workflows with xUnit examples. Preserve existing repo test-framework choices when adding to an established repository. + +F# console app with tests: + +```bash +dotnet new sln --name MyTool +dotnet new console --language "F#" --name MyTool --output src/MyTool +dotnet new xunit --language "F#" --name MyTool.Tests --output tests/MyTool.Tests +dotnet sln add src/MyTool/MyTool.fsproj +dotnet sln add tests/MyTool.Tests/MyTool.Tests.fsproj +dotnet add tests/MyTool.Tests/MyTool.Tests.fsproj reference src/MyTool/MyTool.fsproj +dotnet test +``` + +C# console app with tests: + +```bash +dotnet new sln --name MyTool +dotnet new console --language "C#" --name MyTool --output src/MyTool +dotnet new xunit --language "C#" --name MyTool.Tests --output tests/MyTool.Tests +dotnet sln add src/MyTool/MyTool.csproj +dotnet sln add tests/MyTool.Tests/MyTool.Tests.csproj +dotnet add tests/MyTool.Tests/MyTool.Tests.csproj reference src/MyTool/MyTool.csproj +dotnet test +``` + +Library package shape: + +```bash +dotnet new sln --name MyLibrary +dotnet new classlib --language "F#" --name MyLibrary --output src/MyLibrary +dotnet new xunit --language "F#" --name MyLibrary.Tests --output tests/MyLibrary.Tests +dotnet sln add src/MyLibrary/MyLibrary.fsproj +dotnet sln add tests/MyLibrary.Tests/MyLibrary.Tests.fsproj +dotnet add tests/MyLibrary.Tests/MyLibrary.Tests.fsproj reference src/MyLibrary/MyLibrary.fsproj +dotnet test +``` + +Use C# by changing `--language "F#"` to `--language "C#"` and project extensions from `.fsproj` to `.csproj`. + +## F# Specific Checks + +- Confirm file order in `.fsproj` after adding files. +- Prefer explicit modules and domain types over class-shaped code unless interop calls for classes. +- Keep examples idiomatic instead of direct translations from C#. + +## C# Specific Checks + +- Enable or preserve nullable reference type behavior when the repo already uses it. +- Respect existing analyzer and warnings-as-errors settings. +- Keep examples idiomatic instead of pretending C# is the only .NET shape. + +## Output Shape + +Return: + +1. `Created or planned layout`: solution, source projects, test projects. +2. `Language`: F#, C#, or mixed. +3. `SDK behavior`: existing SDK, pinned SDK, or not pinned. +4. `Commands`: exact commands run or recommended. +5. `Validation`: restore, build, test, or pack results. +6. `Next skill`: implementation or testing handoff. + +## Guardrails + +- Do not scaffold into a non-empty directory without checking the user's intent. +- Do not silently choose C#. +- Do not add a scaffolding script for this first slice; this skill is guidance-only. +- Do not replace an existing test framework with xUnit unless the user explicitly asks for that migration. +- Do not publish packages. +- Do not commit generated files unless the user asks for a commit or the active repo workflow calls for one. diff --git a/plugins/dotnet-skills/skills/build-csharp-project/SKILL.md b/plugins/dotnet-skills/skills/build-csharp-project/SKILL.md new file mode 100644 index 00000000..b2369ff4 --- /dev/null +++ b/plugins/dotnet-skills/skills/build-csharp-project/SKILL.md @@ -0,0 +1,107 @@ +--- +name: build-csharp-project +description: Build or modify idiomatic C# .NET projects using nullable-aware APIs, records/classes, async/task behavior, analyzer conventions, tests, and repo-local validation. +license: Apache-2.0 +compatibility: Designed for Codex and compatible Agent Skills clients working with C# projects on the .NET SDK. +metadata: + owner: gaelic-ghost + repo: socket + category: dotnet-csharp +allowed-tools: Read Bash(rg:*) Bash(git:*) Bash(dotnet:*) +--- + +# Build C# Project + +## Purpose + +Implement or modify a C# .NET project in C#'s own shape while keeping F# as an equal peer elsewhere in the plugin. + +The practical goal is clear nullable-aware APIs, focused types, useful async boundaries, tests that cover changed behavior, and validation through the repository's .NET commands. + +## When To Use + +- Use this skill when the chosen language is C#. +- Use this skill when an existing `.csproj` needs new source, tests, or package-facing API. +- Use this skill when a mixed solution has a C# host, app, API, or interop surface. +- Use this skill when the user asks for C# implementation specifically. + +## Source Check + +Use official Microsoft documentation first: + +- [C# documentation](https://learn.microsoft.com/dotnet/csharp/) +- [C# language reference](https://learn.microsoft.com/dotnet/csharp/language-reference/) +- [.NET CLI documentation](https://learn.microsoft.com/dotnet/core/tools/) +- [`dotnet test` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-test) + +Inspect the repository before editing: + +```bash +rg --files -g '*.cs' -g '*.csproj' -g '*.sln' -g '*.slnx' -g 'global.json' -g '.editorconfig' +``` + +## Implementation Workflow + +1. Read the existing project file and analyzer/style settings. +2. Check nullable reference type behavior. +3. Identify the public API or app behavior being changed. +4. Use records for value-like data when that matches the domain. +5. Use classes for identity, behavior, mutable state, or framework integration. +6. Use interfaces only when there is a real alternate implementation, test boundary, or public contract. +7. Keep async APIs async only when they perform asynchronous work or match an existing contract. +8. Add or update tests around the behavior changed. +9. Run the narrowest useful validation command. + +## Nullable And Analyzer Behavior + +Respect existing repo configuration first. + +When nullable reference types are enabled: + +- avoid `!` unless the invariant is real and local +- prefer explicit null handling at boundaries +- keep public method contracts clear + +When analyzers or warnings-as-errors are configured: + +- fix warnings instead of suppressing them by default +- add suppressions only with a concrete reason +- avoid adding new style rules inside a feature change unless the user asked for tooling work + +## API Shape + +For library APIs: + +- keep public types small and purposeful +- prefer immutable inputs and outputs unless mutation is part of the model +- keep exceptions for exceptional failure and use result-like values only when the repo already has that convention + +For apps: + +- keep process, environment, filesystem, and network effects explicit +- keep business rules testable without shelling out +- write human-friendly errors that name what failed and likely cause + +## Testing + +Use the repository's existing test framework and command if present. + +When no convention exists yet, use xUnit as the recommended scaffold default and keep command guidance centered on `dotnet test`. Preserve existing repo choices instead of migrating test frameworks casually. + +## Output Shape + +Return: + +1. `C# change`: what type, method, project, or behavior changed. +2. `Contracts`: nullable, async, public API, or analyzer choices. +3. `Tests`: what behavior is covered. +4. `Validation`: exact `dotnet` commands and result. +5. `F# boundary`: if relevant, how this C# code interacts with F# projects. + +## Guardrails + +- Do not treat C# as the automatic .NET default in user-facing explanations. +- Do not add interfaces, services, factories, or managers without naming the concrete caller or pain they address. +- Do not disable nullable or analyzers to make a change pass. +- Do not skip tests for behavior changes when the repo has a test surface. +- Do not rewrite a mixed F#/C# boundary without explaining the practical effect. diff --git a/plugins/dotnet-skills/skills/build-fsharp-project/SKILL.md b/plugins/dotnet-skills/skills/build-fsharp-project/SKILL.md new file mode 100644 index 00000000..3cf81d88 --- /dev/null +++ b/plugins/dotnet-skills/skills/build-fsharp-project/SKILL.md @@ -0,0 +1,111 @@ +--- +name: build-fsharp-project +description: Build or modify idiomatic F# .NET projects using explicit modules, domain types, functional data flow, file ordering, async/task interop, tests, and repo-local validation. +license: Apache-2.0 +compatibility: Designed for Codex and compatible Agent Skills clients working with F# projects on the .NET SDK. +metadata: + owner: gaelic-ghost + repo: socket + category: dotnet-fsharp +allowed-tools: Read Bash(rg:*) Bash(git:*) Bash(dotnet:*) +--- + +# Build F# Project + +## Purpose + +Implement or modify an F# .NET project in F#'s own shape. + +The practical goal is readable domain modeling, explicit data flow, good module boundaries, correct file ordering, useful tests, and validation through the repository's .NET commands. + +## When To Use + +- Use this skill when the chosen language is F#. +- Use this skill when an existing `.fsproj` needs new source, tests, or package-facing API. +- Use this skill when a mixed solution needs an F# library or domain project. +- Use this skill when code looks like translated C# and should be made idiomatic F#. + +## Source Check + +Use official Microsoft documentation first: + +- [F# documentation](https://learn.microsoft.com/dotnet/fsharp/) +- [F# language reference](https://learn.microsoft.com/dotnet/fsharp/language-reference/) +- [.NET CLI documentation](https://learn.microsoft.com/dotnet/core/tools/) +- [`dotnet test` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-test) + +Inspect the repository before editing: + +```bash +rg --files -g '*.fs' -g '*.fsproj' -g '*.sln' -g '*.slnx' -g 'global.json' +``` + +## Implementation Workflow + +1. Read the existing `.fsproj` and source ordering. +2. Identify the domain values and transformations. +3. Prefer small modules with explicit inputs and outputs. +4. Use records for named product data. +5. Use discriminated unions for closed sets of alternatives. +6. Use options and results for expected absence or recoverable failure. +7. Keep side effects at the edge of the workflow. +8. Add or update tests around the behavior changed. +9. Run the narrowest useful validation command. + +## File Ordering + +F# compiles files in project order. + +Before adding a new file: + +- decide which later files depend on it +- place shared domain types before modules that use them +- place entry points after the implementation they call +- update `.fsproj` deliberately + +Do not assume globbed source discovery unless the project already proves it. + +## API Shape + +For library APIs: + +- expose a small set of clear modules and functions +- keep constructors and helpers close to the types they create +- avoid leaking implementation-only records or unions into public API +- provide C#-friendly APIs only when there is a real C# consumer + +For apps: + +- keep parsing, IO, environment reads, and process exits at the edge +- keep core transformations testable without shelling out +- return values that describe what happened before printing or logging them + +## Async And Task Interop + +Use the existing project style first. + +When calling modern .NET APIs from F#, be explicit about whether a function returns `Async<'T>`, `Task<'T>`, or a plain value. Avoid hiding task conversion in unrelated helpers. Explain the boundary when a public API exposes tasks for C# consumers. + +## Testing + +Use the repository's existing test framework and command if present. + +When no convention exists yet, use xUnit as the recommended scaffold default and keep command guidance centered on `dotnet test`. Preserve existing repo choices instead of migrating test frameworks casually. + +## Output Shape + +Return: + +1. `F# change`: what module, type, function, or project behavior changed. +2. `Data flow`: inputs, transformations, side effects, and outputs. +3. `Project ordering`: any `.fsproj` ordering changes. +4. `Tests`: what behavior is covered. +5. `Validation`: exact `dotnet` commands and result. + +## Guardrails + +- Do not translate C# examples line-by-line into F#. +- Do not hide mutation or IO inside broad helpers when a pure transformation would be clearer. +- Do not add compatibility APIs for C# unless a C# caller exists or the user asks for one. +- Do not ignore `.fsproj` file ordering. +- Do not skip tests for behavior changes when the repo has a test surface. diff --git a/plugins/dotnet-skills/skills/choose-project-shape/SKILL.md b/plugins/dotnet-skills/skills/choose-project-shape/SKILL.md new file mode 100644 index 00000000..846dd8d0 --- /dev/null +++ b/plugins/dotnet-skills/skills/choose-project-shape/SKILL.md @@ -0,0 +1,139 @@ +--- +name: choose-project-shape +description: Choose the right .NET project shape before implementation, including F# versus C# language choice, solution layout, validation commands, package boundaries, and documentation updates. +license: Apache-2.0 +compatibility: Designed for Codex and compatible Agent Skills clients working with .NET SDK, F#, C#, and the dotnet CLI on macOS or other supported .NET development environments. +metadata: + owner: gaelic-ghost + repo: socket + category: dotnet-planning +allowed-tools: Read Bash(rg:*) Bash(git:*) Bash(dotnet:*) +--- + +# Choose .NET Project Shape + +## Purpose + +Pick the smallest correct .NET project shape before code changes begin. + +The practical decision is what kind of project the user needs, whether F# or C# is the better fit, how many projects belong in the solution, which validation commands should prove the work, and where package or application boundaries should sit. + +## When To Use + +- Use this skill when the user wants a new .NET project but has not chosen app, library, test, package, or service shape. +- Use this skill before scaffolding a .NET solution. +- Use this skill when the repository already has .NET files and the next change could cross project or package boundaries. +- Use this skill when the user asks whether F# or C# is the right language for the work. + +## Source Check + +Use official Microsoft documentation first before making claims about SDK, CLI, language, or project behavior: + +- [.NET CLI documentation](https://learn.microsoft.com/dotnet/core/tools/) +- [F# documentation](https://learn.microsoft.com/dotnet/fsharp/) +- [C# documentation](https://learn.microsoft.com/dotnet/csharp/) +- [`global.json` documentation](https://learn.microsoft.com/dotnet/core/tools/global-json) +- [`dotnet new` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-new) +- [`dotnet test` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-test) + +Translate any documentation rule into the concrete repository decision it changes. + +## Classification Workflow + +1. Inspect the repository shape: + - `.sln` or `.slnx` + - `global.json` + - `Directory.Build.props` + - `Directory.Packages.props` + - `.fsproj` + - `.csproj` + - test projects + - package metadata + - existing CI commands +2. Identify the user-visible job: + - command-line app + - reusable library + - NuGet package + - test project + - ASP.NET Core service + - worker service + - multi-project solution + - mixed F# and C# solution + - package maintenance or upgrade pass +3. Choose language intentionally: + - Ask for language preference when the user has not chosen. + - Prefer F# when the user asks for a neutral default and no external constraint points elsewhere. + - Prefer C# when the repository is already C#-dominant and the requested change belongs inside that existing surface. + - Use mixed F# and C# only when the boundary is useful and explicit. +4. Choose the project layout: + - one project for a small app or library + - app plus test project for normal implementation + - library plus app plus tests when the reusable API and executable are separate + - solution-level props only when shared settings reduce real duplication +5. Choose validation: + - `dotnet restore` when dependency or SDK resolution is part of the task + - `dotnet build` for compile and analyzer checks + - `dotnet test` for behavior + - `dotnet pack` for package surfaces + +## Recommendations + +### Console App + +Use a single app project plus a test project when behavior is non-trivial. + +For F#, prefer small modules, explicit domain types, and pure transformations where practical. For C#, prefer nullable-aware models, clear service boundaries, and async APIs only where work is truly asynchronous. + +Handoff: + +- `dotnet:bootstrap-solution` for new project creation +- `dotnet:build-fsharp-project` for F# implementation +- `dotnet:build-csharp-project` for C# implementation +- `dotnet:testing-workflow` for tests + +### Library Package + +Use a library project plus a test project. Add package metadata only when the library is intended to be packed or published. + +For F#, shape the public API around clear functions and domain types. For C#, shape the public API around nullable-aware types, interfaces only where they have real callers, and explicit async contracts. + +Handoff: + +- `dotnet:package-workflow` when package validation or NuGet metadata matters +- `dotnet:testing-workflow` for test execution and failure triage + +### ASP.NET Core Service + +Use ASP.NET Core guidance only after the core solution, language, and test shape is clear. Keep the first decision focused on project ownership, configuration, tests, and whether the service belongs in an existing solution. + +Handoff: + +- `dotnet:aspnet-core-service-workflow` for service-specific guidance +- `dotnet:bootstrap-solution` for scaffold guidance + +### Mixed F# And C# Solution + +Use mixed language projects only when the boundary is useful enough to explain. + +Good reasons include an F# domain/modeling library consumed by a C# host, or a C# app surface that needs to stay close to an existing ecosystem while F# owns the domain transformations. + +Avoid mixed solutions when the only reason is uncertainty. Ask for the language decision instead. + +## Output Shape + +Return: + +1. `Chosen shape`: console app, library package, test project, ASP.NET Core service, worker service, multi-project solution, mixed F#/C# solution, or maintenance pass. +2. `Language decision`: F#, C#, mixed, or user decision needed. +3. `Project layout`: projects, references, and package boundaries. +4. `Validation path`: exact restore, build, test, or pack commands. +5. `Documentation updates`: README, roadmap, package notes, or repo-local guidance. +6. `Next skill`: the next .NET skill to use. + +## Guardrails + +- Do not silently choose C# when the user has not named a language. +- Do not describe F# as secondary or niche. +- Do not add shared props, helper projects, or package boundaries without naming the duplication or workflow problem they remove. +- Do not publish packages by default. +- Do not commit machine-local SDK, package, or project references. diff --git a/plugins/dotnet-skills/skills/ci-workflow/SKILL.md b/plugins/dotnet-skills/skills/ci-workflow/SKILL.md new file mode 100644 index 00000000..e0ef0998 --- /dev/null +++ b/plugins/dotnet-skills/skills/ci-workflow/SKILL.md @@ -0,0 +1,117 @@ +--- +name: ci-workflow +description: Design and maintain .NET CI workflows for F#, C#, and mixed solutions with SDK setup, restore, build, test, format checks, package checks, caching, and matrix decisions. +license: Apache-2.0 +compatibility: Designed for Codex and compatible Agent Skills clients working with .NET projects and GitHub Actions or equivalent CI systems. +metadata: + owner: gaelic-ghost + repo: socket + category: dotnet-ci +allowed-tools: Read Bash(rg:*) Bash(git:*) Bash(dotnet:*) +--- + +# .NET CI Workflow + +## Purpose + +Make .NET CI prove the same behavior maintainers care about locally. + +The practical job is to choose SDK setup, restore/build/test commands, optional format/package checks, path filters, and matrix scope without making CI broader or noisier than the project needs. + +## When To Use + +- Use this skill when adding or changing CI for a .NET repository. +- Use this skill when local validation and CI disagree. +- Use this skill when adding F# or C# projects to an existing CI workflow. +- Use this skill before package or release workflows depend on CI results. + +## Source Check + +Use official documentation first: + +- [GitHub Actions and .NET](https://learn.microsoft.com/dotnet/devops/github-actions-overview) +- [Create a .NET test validation GitHub workflow](https://learn.microsoft.com/dotnet/devops/dotnet-test-github-action) +- [`actions/setup-dotnet`](https://github.com/actions/setup-dotnet) +- [`dotnet restore` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-restore) +- [`dotnet build` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-build) +- [`dotnet test` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-test) + +## CI Planning Workflow + +1. Inspect local validation commands. +2. Inspect existing workflow files: + ```bash + rg --files .github/workflows -g '*.yml' -g '*.yaml' + ``` +3. Check SDK source: + - `global.json` + - workflow `dotnet-version` + - repository docs +4. Decide job scope: + - restore + - build + - test + - format check + - pack check +5. Decide matrix scope: + - one OS for library CI unless cross-platform behavior matters + - multiple OSes for filesystem, process, path, native dependency, or user-facing CLI differences +6. Keep local and CI commands aligned. + +## Baseline Command Order + +Prefer a simple shape: + +```bash +dotnet restore +dotnet build --configuration Release --no-restore +dotnet test --configuration Release --no-build +``` + +Add package validation only for package surfaces: + +```bash +dotnet pack --configuration Release --no-build +``` + +Add formatting verification only when the repo has `.editorconfig` and expects it: + +```bash +dotnet format --verify-no-changes +``` + +## F# And C# Notes + +For F#: + +- make sure CI builds the projects that prove `.fsproj` ordering +- do not path-filter only `**.cs` when F# files exist + +For C#: + +- keep nullable/analyzer failures visible +- respect warnings-as-errors behavior already used by the repo + +For mixed solutions: + +- include `**.fs`, `**.fsproj`, `**.cs`, and `**.csproj` in path filters when filters are used +- run solution-level validation when project references cross language boundaries + +## Output Shape + +Return: + +1. `CI scope`: restore, build, test, format, pack. +2. `SDK source`: `global.json`, workflow version, or repo docs. +3. `Matrix`: OS and SDK versions. +4. `Commands`: local and CI command match. +5. `Path filters`: F#, C#, project, props, and workflow files. +6. `Residual risk`: what CI intentionally does not cover. + +## Guardrails + +- Do not make CI publish packages unless the user asks for a release workflow. +- Do not filter out F# paths in a plugin that promises F# parity. +- Do not add large OS matrices without naming the cross-platform behavior they protect. +- Do not hide build warnings if the repo treats warnings as errors locally. +- Do not make CI commands differ from documented local validation without explaining why. diff --git a/plugins/dotnet-skills/skills/diagnose-project/SKILL.md b/plugins/dotnet-skills/skills/diagnose-project/SKILL.md new file mode 100644 index 00000000..645ad4b9 --- /dev/null +++ b/plugins/dotnet-skills/skills/diagnose-project/SKILL.md @@ -0,0 +1,111 @@ +--- +name: diagnose-project +description: Diagnose .NET SDK, restore, build, test, package, target framework, F# compile-order, C# analyzer, and project-reference failures with concrete next checks. +license: Apache-2.0 +compatibility: Designed for Codex and compatible Agent Skills clients diagnosing .NET SDK projects in F#, C#, and mixed-language solutions. +metadata: + owner: gaelic-ghost + repo: socket + category: dotnet-diagnostics +allowed-tools: Read Bash(rg:*) Bash(git:*) Bash(dotnet:*) +--- + +# Diagnose .NET Project + +## Purpose + +Find the first meaningful cause of a .NET failure and explain it in human terms. + +The useful answer is not "build failed." It is what command failed, which project failed, which phase failed, why it most likely failed, and the smallest next check or fix. + +## When To Use + +- Use this skill when `dotnet restore`, `dotnet build`, `dotnet test`, or `dotnet pack` fails. +- Use this skill when SDK selection, target framework, package restore, or project references are unclear. +- Use this skill when F# compile order or C# analyzer/nullability failures need explanation. +- Use this skill before widening into refactors after a vague .NET error. + +## Source Check + +Use official Microsoft documentation first: + +- [.NET CLI documentation](https://learn.microsoft.com/dotnet/core/tools/) +- [`dotnet restore` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-restore) +- [`dotnet build` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-build) +- [`dotnet test` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-test) +- [`dotnet pack` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-pack) +- [`global.json` documentation](https://learn.microsoft.com/dotnet/core/tools/global-json) + +## Diagnostic Workflow + +1. Capture repository shape: + ```bash + rg --files -g '*.sln' -g '*.slnx' -g '*.fsproj' -g '*.csproj' -g 'global.json' -g 'Directory.Build.props' -g 'Directory.Packages.props' -g 'NuGet.config' + ``` +2. Check SDK context only when relevant: + ```bash + dotnet --info + dotnet --list-sdks + ``` +3. Re-run the narrowest failing command. +4. Classify the failure phase: + - SDK selection + - restore + - build + - test discovery + - test execution + - pack + - publish or release +5. Identify the first meaningful error. +6. Explain likely cause and next check. + +## Common Failure Classes + +### SDK Selection + +Look for `global.json`, installed SDK versions, target framework, and CI SDK setup. + +Report when a repo asks for an SDK that is not installed or when local and CI SDK versions likely differ. + +### Restore + +Look for package source, authentication, locked mode, central package management, and `NuGet.config`. + +Do not turn an authenticated feed problem into a generic network diagnosis. Name the package source or credential surface when visible. + +### Build + +Look for target framework mismatch, project references, analyzer failures, nullable failures, generated code, and compile order. + +For F#, inspect `.fsproj` file ordering when names are unresolved. For C#, inspect nullable and analyzer settings before suppressing warnings. + +### Test + +Separate test discovery from test execution. + +Discovery failures usually point at framework adapters, target frameworks, build output, or project type. Execution failures usually point at behavior, environment, timing, or fixture setup. + +### Pack + +Look for missing metadata, invalid project type, failed Release build, project references, and artifact output path. + +Remember that package publication is separate from package creation. + +## Output Shape + +Return: + +1. `Command`: exact failing command. +2. `Phase`: SDK, restore, build, discovery, execution, pack, or release. +3. `Project`: solution or project path involved. +4. `First meaningful error`: short quoted or paraphrased error. +5. `Likely cause`: concrete explanation. +6. `Next check`: one or two smallest useful commands or edits. + +## Guardrails + +- Do not bury the first meaningful error under a long transcript. +- Do not rerun broad commands repeatedly before narrowing the phase. +- Do not delete build artifacts, caches, or lockfiles without explaining why and getting approval when destructive. +- Do not suppress warnings to make a build pass unless the suppression is intentional and documented. +- Do not assume C# project behavior explains an F# compile-order failure. diff --git a/plugins/dotnet-skills/skills/fsharp-csharp-interop/SKILL.md b/plugins/dotnet-skills/skills/fsharp-csharp-interop/SKILL.md new file mode 100644 index 00000000..665a3744 --- /dev/null +++ b/plugins/dotnet-skills/skills/fsharp-csharp-interop/SKILL.md @@ -0,0 +1,109 @@ +--- +name: fsharp-csharp-interop +description: Design and maintain explicit F# and C# boundaries in mixed .NET solutions, including project references, public API shape, async/task interop, nullability, options, records, and package-facing contracts. +license: Apache-2.0 +compatibility: Designed for Codex and compatible Agent Skills clients working with mixed F# and C# .NET solutions. +metadata: + owner: gaelic-ghost + repo: socket + category: dotnet-interop +allowed-tools: Read Bash(rg:*) Bash(git:*) Bash(dotnet:*) +--- + +# F# And C# Interop + +## Purpose + +Keep mixed F# and C# solutions intentional. + +The practical job is to decide which language owns which responsibility, make the project-reference direction explicit, and shape public APIs so each language can call the other without awkward translation code leaking everywhere. + +## When To Use + +- Use this skill when a solution contains both `.fsproj` and `.csproj` projects. +- Use this skill when adding an F# library to a C# app or service. +- Use this skill when adding a C# host or infrastructure project around F# domain code. +- Use this skill when public package APIs need to work well from both F# and C#. + +## Source Check + +Use official Microsoft documentation first: + +- [F# documentation](https://learn.microsoft.com/dotnet/fsharp/) +- [C# documentation](https://learn.microsoft.com/dotnet/csharp/) +- [.NET CLI documentation](https://learn.microsoft.com/dotnet/core/tools/) +- [`dotnet add reference` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-add-reference) + +## Boundary Workflow + +1. Inspect project graph: + ```bash + rg --files -g '*.fsproj' -g '*.csproj' -g '*.sln' -g '*.slnx' + ``` +2. Identify the language-owned responsibilities: + - F# domain library + - C# host app + - C# ASP.NET Core service + - F# CLI + - shared abstractions + - tests +3. Choose dependency direction. +4. Shape the API at the boundary. +5. Add tests from the consuming side when the boundary is public or fragile. +6. Run solution-level build and tests. + +## Good Mixed Shapes + +Common durable shapes: + +- F# domain library consumed by a C# app or ASP.NET Core host +- F# transformation package consumed by C# tools +- C# infrastructure adapter consumed by an F# application +- shared test projects that verify public package behavior from both languages + +Avoid mixed language solutions when the only reason is indecision. Ask for a language choice instead. + +## API Boundary Notes + +When C# consumes F#: + +- be careful with options, tuples, curried functions, and discriminated unions +- expose C#-friendly functions or classes only at the boundary that needs them +- keep the idiomatic F# API intact when F# callers still matter + +When F# consumes C#: + +- handle nullability explicitly +- wrap exception-heavy APIs into clearer result shapes when useful +- keep async/task conversion visible at the edge + +## Project References + +Use `dotnet add reference` or direct project-file edits that match the repo style. + +After reference changes, run: + +```bash +dotnet build +dotnet test +``` + +Use package references instead of project references only when the dependency is intentionally versioned and released independently. + +## Output Shape + +Return: + +1. `Boundary`: which language owns which project. +2. `Dependency direction`: project references and rationale. +3. `API shape`: F#-native, C#-friendly, or dual surface. +4. `Interop risks`: nullability, options, unions, async/task, file ordering. +5. `Validation`: exact build and test commands. + +## Guardrails + +- Do not add mixed language projects without naming the concrete benefit. +- Do not flatten F# domain modeling into C#-shaped classes just for convenience. +- Do not expose awkward F# internals to C# consumers when a small boundary API would be clearer. +- Do not hide nullability or task conversion problems. +- Do not change dependency direction casually in an existing solution. diff --git a/plugins/dotnet-skills/skills/package-workflow/SKILL.md b/plugins/dotnet-skills/skills/package-workflow/SKILL.md new file mode 100644 index 00000000..02d40392 --- /dev/null +++ b/plugins/dotnet-skills/skills/package-workflow/SKILL.md @@ -0,0 +1,115 @@ +--- +name: package-workflow +description: Validate .NET package surfaces for F# and C# libraries with project metadata, dotnet pack, local package smoke checks, semantic versioning, and release-boundary guidance. +license: Apache-2.0 +compatibility: Designed for Codex and compatible Agent Skills clients working with NuGet package-oriented .NET SDK projects in F#, C#, or mixed-language solutions. +metadata: + owner: gaelic-ghost + repo: socket + category: dotnet-packaging +allowed-tools: Read Bash(rg:*) Bash(git:*) Bash(dotnet:*) +--- + +# .NET Package Workflow + +## Purpose + +Validate a .NET library package before release or publication. + +The practical job is to make package metadata explicit, build and test the library, run `dotnet pack`, inspect the generated package, and keep publishing as an explicit release step rather than an accidental side effect. + +## When To Use + +- Use this skill when a .NET library is intended to become a NuGet package. +- Use this skill when package metadata, versioning, or release notes are changed. +- Use this skill when adding package validation to F#, C#, or mixed solutions. +- Use this skill before package publication, but do not publish unless the user asks for that release step. + +## Source Check + +Use official Microsoft documentation first: + +- [`dotnet pack` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-pack) +- [`dotnet build` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-build) +- [`dotnet restore` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-restore) +- [NuGet package creation guidance](https://learn.microsoft.com/nuget/create-packages/creating-a-package-dotnet-cli) +- [NuGet package versioning](https://learn.microsoft.com/nuget/concepts/package-versioning) + +Translate documentation into the specific package, project file, and release decision in front of you. + +## Inspection Workflow + +1. Identify package-bearing projects: + - `.fsproj` + - `.csproj` + - `Directory.Build.props` + - `Directory.Packages.props` + - package metadata fields +2. Confirm the intended package boundary: + - one package per public library project + - no accidental app project packages + - no hidden machine-local references +3. Check metadata: + - `PackageId` + - `Version` or repository-owned version source + - `Authors` + - `Description` + - `PackageTags` + - `RepositoryUrl` + - `PackageLicenseExpression` or license file policy + - README and release notes if the repo ships them +4. Run validation: + - `dotnet restore` + - `dotnet build --configuration Release` + - `dotnet test` + - `dotnet pack --configuration Release --no-build` +5. Inspect generated package output. + +## F# Package Notes + +For F# packages: + +- check `.fsproj` compile order before packaging +- keep public modules and types intentional +- avoid exposing implementation-only records or unions as accidental public API +- add C#-friendly API shapes only when there is a real C# consumer or package promise + +## C# Package Notes + +For C# packages: + +- keep nullable reference type behavior explicit +- respect analyzer and warnings-as-errors settings +- avoid publishing broad interfaces or service types that only exist for test setup +- document public async contracts clearly + +## Local Smoke Checks + +When package behavior matters, create a temporary consumer outside the package source tree or in an ignored scratch path. + +The smoke check should prove: + +- the package can be restored from a local output directory +- the public API can be referenced by a fresh project +- F# and C# consumers work when the package promises both + +Do not commit scratch consumers unless the repo intentionally keeps package integration tests. + +## Output Shape + +Return: + +1. `Package boundary`: which project or projects produce packages. +2. `Metadata`: fields changed or verified. +3. `Validation`: exact restore, build, test, and pack commands. +4. `Artifacts`: package output paths. +5. `Consumer check`: skipped, passed, failed, or not applicable. +6. `Release boundary`: whether publication is still pending and what explicit release step would be needed. + +## Guardrails + +- Do not publish packages unless the user explicitly asks or the repo-local release workflow requires it. +- Do not pack app projects accidentally. +- Do not commit package metadata that points at machine-local paths. +- Do not use `--no-build` unless a successful Release build already ran in the same validation flow. +- Do not treat package creation as proof that public API design is good; inspect the API boundary too. diff --git a/plugins/dotnet-skills/skills/testing-workflow/SKILL.md b/plugins/dotnet-skills/skills/testing-workflow/SKILL.md new file mode 100644 index 00000000..46a2ba5f --- /dev/null +++ b/plugins/dotnet-skills/skills/testing-workflow/SKILL.md @@ -0,0 +1,123 @@ +--- +name: testing-workflow +description: Run, filter, debug, and explain .NET tests for F#, C#, and mixed solutions using dotnet test while respecting repo-local test framework choices. +license: Apache-2.0 +compatibility: Designed for Codex and compatible Agent Skills clients working with .NET SDK test workflows for F#, C#, and mixed-language solutions. +metadata: + owner: gaelic-ghost + repo: socket + category: dotnet-testing +allowed-tools: Read Bash(rg:*) Bash(git:*) Bash(dotnet:*) +--- + +# .NET Testing Workflow + +## Purpose + +Run and explain .NET tests without assuming one language owns the platform. + +The stable command surface is `dotnet test`. The repository's existing test framework, project layout, SDK pin, and CI commands are the source of truth for how broad the check should be. For new scaffolds with no repo-local test framework, recommend xUnit as the default test template. + +## When To Use + +- Use this skill when the user asks to run, add, debug, or explain .NET tests. +- Use this skill after changing F# or C# behavior. +- Use this skill when `dotnet test` fails and the failure needs triage. +- Use this skill when deciding whether to run project-level or solution-level tests. + +## Source Check + +Use official Microsoft documentation first: + +- [`dotnet test` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-test) +- [.NET CLI documentation](https://learn.microsoft.com/dotnet/core/tools/) +- [F# documentation](https://learn.microsoft.com/dotnet/fsharp/) +- [C# documentation](https://learn.microsoft.com/dotnet/csharp/) +- [Unit testing C# with xUnit and `dotnet test`](https://learn.microsoft.com/dotnet/core/testing/unit-testing-csharp-with-xunit) + +Inspect the repository before running broad checks: + +```bash +rg --files -g '*.sln' -g '*.slnx' -g '*.fsproj' -g '*.csproj' -g 'global.json' -g 'Directory.Build.props' +``` + +## Test Selection + +Choose the narrowest useful test command first: + +- changed test project: `dotnet test path/to/Project.Tests.fsproj` +- changed C# test project: `dotnet test path/to/Project.Tests.csproj` +- changed shared library used by many tests: `dotnet test` +- dependency or SDK issue: `dotnet restore` before `dotnet test` +- compile issue without tests: `dotnet build` + +Use solution-level `dotnet test` before commit, push, PR, release, or any change that could affect multiple projects. + +## Test Framework Choice + +Preserve the repository's current test framework in existing projects. + +For new scaffolds without a repo-local convention, recommend xUnit: + +```bash +dotnet new xunit --language "F#" --name MyLibrary.Tests --output tests/MyLibrary.Tests +dotnet new xunit --language "C#" --name MyLibrary.Tests --output tests/MyLibrary.Tests +``` + +The recommendation is a scaffold default, not a migration rule. Do not replace MSTest, NUnit, or another established test stack unless the user asks for that migration. + +## Failure Triage + +Classify failures by phase: + +- SDK selection +- restore +- build +- test discovery +- test execution +- logger or result output + +Report: + +- what command ran +- which project failed +- which phase failed +- the first meaningful error +- the likely cause +- the smallest next check + +## F# Test Notes + +For F# tests: + +- check `.fsproj` file ordering when test helpers or fixtures are added +- keep domain examples idiomatic F# instead of translated C# +- test pure transformations directly when possible +- keep async/task boundaries explicit in test code + +## C# Test Notes + +For C# tests: + +- respect nullable and analyzer behavior in test projects too +- avoid over-broad mocks when a small value-based test would prove the behavior +- keep async tests aligned with the framework's expected async pattern +- avoid suppressing warnings only in tests unless the suppression has a clear reason + +## Output Shape + +Return: + +1. `Command`: exact test command. +2. `Scope`: project, solution, or targeted filter. +3. `Result`: pass, fail, skipped, or blocked. +4. `Failure phase`: SDK, restore, build, discovery, execution, or output. +5. `Next step`: smallest useful fix or broader validation. + +## Guardrails + +- Do not run multiple build or test toolchains concurrently. +- Do not replace an existing test framework with xUnit unless the user explicitly asks for that migration. +- Do not hide restore or build failures under a generic "tests failed" summary. +- Do not skip tests after behavior changes when a relevant test surface exists. +- Do not broaden to package publishing or release workflow unless the user explicitly asks. diff --git a/plugins/dotnet-skills/skills/tooling-style-workflow/SKILL.md b/plugins/dotnet-skills/skills/tooling-style-workflow/SKILL.md new file mode 100644 index 00000000..84f6f10c --- /dev/null +++ b/plugins/dotnet-skills/skills/tooling-style-workflow/SKILL.md @@ -0,0 +1,118 @@ +--- +name: tooling-style-workflow +description: Align .NET formatting, analyzers, .editorconfig, warnings-as-errors, local tools, and validation commands for F#, C#, and mixed solutions without overriding repo-local conventions. +license: Apache-2.0 +compatibility: Designed for Codex and compatible Agent Skills clients maintaining .NET style and tooling workflows for F#, C#, and mixed-language solutions. +metadata: + owner: gaelic-ghost + repo: socket + category: dotnet-tooling +allowed-tools: Read Bash(rg:*) Bash(git:*) Bash(dotnet:*) +--- + +# .NET Tooling And Style Workflow + +## Purpose + +Keep .NET formatting and analyzer behavior explicit. + +The practical job is to respect existing repo conventions, use `.editorconfig` and `dotnet format` where they fit, keep analyzers and warnings understandable, and make local validation match CI. + +## When To Use + +- Use this skill when adding or changing `.editorconfig`, analyzers, or warnings-as-errors. +- Use this skill when `dotnet format` is part of local or CI validation. +- Use this skill when style drift causes noisy diffs. +- Use this skill when F# and C# projects need one documented validation story. + +## Source Check + +Use official documentation first: + +- [`dotnet format` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-format) +- [.NET code analysis overview](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/overview) +- [EditorConfig settings for .NET](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/code-style-rule-options) +- [.NET local tools](https://learn.microsoft.com/dotnet/core/tools/local-tools-how-to-use) + +## Inspection Workflow + +1. Inspect tooling files: + ```bash + rg --files -g '.editorconfig' -g 'Directory.Build.props' -g 'Directory.Packages.props' -g 'dotnet-tools.json' -g '*.fsproj' -g '*.csproj' + ``` +2. Read existing repo guidance and CI. +3. Identify what is already enforced: + - `dotnet format` + - analyzers + - warnings-as-errors + - local tools + - custom scripts +4. Decide the smallest alignment: + - document existing commands + - add missing `.editorconfig` + - add format verification + - adjust analyzers + - add local tool restore +5. Run validation. + +## dotnet format Guidance + +`dotnet format` formats a project or solution according to `.editorconfig` settings when present. + +Use verification mode for CI or pre-commit checks: + +```bash +dotnet format --verify-no-changes +``` + +Use normal mode only when the user asked for formatting or when the change is explicitly a formatting pass: + +```bash +dotnet format +``` + +Keep formatting-only sweeps separate from behavior changes when practical. + +## Analyzer Guidance + +Respect existing analyzer settings first. + +When adding analyzer rules: + +- explain what bug class or style drift the rule catches +- start conservative +- avoid turning every suggestion into a blocking error at once +- keep suppressions narrow and documented + +For F#, check whether the proposed tooling actually applies to F# sources before promising enforcement. + +For C#, nullable reference types and analyzer severity are often part of the public code quality contract. Do not disable them to make a change pass. + +## Local Tools + +When a repo uses local .NET tools, restore them through: + +```bash +dotnet tool restore +``` + +Do not assume globally installed tools are available in CI or on another contributor's machine. + +## Output Shape + +Return: + +1. `Existing tooling`: `.editorconfig`, analyzers, warnings-as-errors, local tools, CI. +2. `Change`: documentation, formatting, analyzer, local tool, or CI alignment. +3. `Commands`: exact format/build/test/tool commands. +4. `F# coverage`: what applies to F# sources. +5. `C# coverage`: what applies to C# sources. +6. `Residual risk`: anything not enforced automatically. + +## Guardrails + +- Do not make a broad formatting sweep inside an unrelated behavior change. +- Do not promise F# formatting/analyzer coverage from C#-only tooling. +- Do not depend on globally installed tools when a local tool manifest is appropriate. +- Do not disable analyzers or nullable checks to hide real issues. +- Do not add warnings-as-errors across an existing noisy repo without a cleanup plan. diff --git a/plugins/dotnet-skills/skills/upgrade-workflow/SKILL.md b/plugins/dotnet-skills/skills/upgrade-workflow/SKILL.md new file mode 100644 index 00000000..6b00da1d --- /dev/null +++ b/plugins/dotnet-skills/skills/upgrade-workflow/SKILL.md @@ -0,0 +1,101 @@ +--- +name: upgrade-workflow +description: Plan and validate .NET SDK, target framework, package, and language-version upgrades for F#, C#, and mixed solutions with compatibility checks and staged validation. +license: Apache-2.0 +compatibility: Designed for Codex and compatible Agent Skills clients upgrading .NET SDK projects in F#, C#, and mixed-language solutions. +metadata: + owner: gaelic-ghost + repo: socket + category: dotnet-upgrade +allowed-tools: Read Bash(rg:*) Bash(git:*) Bash(dotnet:*) +--- + +# .NET Upgrade Workflow + +## Purpose + +Upgrade .NET projects without losing track of compatibility, validation, or language-specific behavior. + +The practical job is to inventory SDK and target framework state, choose the upgrade boundary, apply the smallest coherent change, run staged validation, and document migration notes when users or package consumers need them. + +## When To Use + +- Use this skill when changing `TargetFramework` or `TargetFrameworks`. +- Use this skill when changing `global.json`. +- Use this skill when upgrading package versions across a .NET solution. +- Use this skill when moving between .NET major versions. +- Use this skill when F# or C# language behavior may change with the SDK or target framework. + +## Source Check + +Use official documentation first: + +- [.NET breaking changes reference](https://learn.microsoft.com/dotnet/core/compatibility/breaking-changes) +- [Breaking changes may occur when porting code](https://learn.microsoft.com/dotnet/core/porting/breaking-changes) +- [`global.json` documentation](https://learn.microsoft.com/dotnet/core/tools/global-json) +- [`dotnet sdk check` documentation](https://learn.microsoft.com/dotnet/core/tools/dotnet-sdk-check) +- [.NET CLI documentation](https://learn.microsoft.com/dotnet/core/tools/) + +## Upgrade Workflow + +1. Inventory current state: + ```bash + rg -n "TargetFramework|TargetFrameworks|LangVersion|PackageReference|PackageVersion|Sdk=" . + rg --files -g 'global.json' -g 'Directory.Build.props' -g 'Directory.Packages.props' -g '*.fsproj' -g '*.csproj' -g '*.sln' -g '*.slnx' + ``` +2. Check installed SDKs when local validation is required: + ```bash + dotnet --list-sdks + dotnet sdk check + ``` +3. Decide upgrade boundary: + - SDK only + - target framework only + - package versions only + - SDK plus target framework + - package plus framework compatibility pass +4. Read breaking-change notes for the source and target versions. +5. Apply one coherent upgrade slice. +6. Run staged validation: + - `dotnet restore` + - `dotnet build` + - `dotnet test` + - `dotnet pack` when package surfaces exist +7. Update docs or release notes when public behavior, package requirements, or contributor setup changes. + +## F# Upgrade Notes + +For F#: + +- check compiler or language-version behavior before changing project defaults +- inspect `.fsproj` ordering after automated edits +- watch for APIs that become more awkward across async/task boundaries +- run tests that cover discriminated union, option, and record serialization when those are public contracts + +## C# Upgrade Notes + +For C#: + +- check nullable and analyzer behavior after SDK changes +- avoid broad warning suppression after analyzer updates +- decide whether new language features belong in the repo style before using them +- check source generators or analyzers when present + +## Output Shape + +Return: + +1. `Upgrade boundary`: SDK, target framework, packages, or combination. +2. `Before`: current SDK, TFM, package, and language state. +3. `After`: target SDK, TFM, package, and language state. +4. `Compatibility notes`: breaking changes or migration concerns checked. +5. `Validation`: exact commands and results. +6. `Docs`: README, contributing, release notes, or package guidance updated. + +## Guardrails + +- Do not upgrade multiple unrelated surfaces in one commit without a clear reason. +- Do not ignore official breaking-change notes for major upgrades. +- Do not commit machine-local SDK paths or private package feeds. +- Do not suppress new analyzer warnings without explaining the rule and reason. +- Do not call an upgrade complete until build and tests have run or the blocker is explicit. diff --git a/plugins/productivity-skills/.codex-plugin/plugin.json b/plugins/productivity-skills/.codex-plugin/plugin.json index eb910509..6ae6925b 100644 --- a/plugins/productivity-skills/.codex-plugin/plugin.json +++ b/plugins/productivity-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "productivity-skills", - "version": "6.8.0", + "version": "6.9.0", "description": "Broadly useful productivity workflows for Codex.", "author": { "name": "Gale", diff --git a/plugins/productivity-skills/pyproject.toml b/plugins/productivity-skills/pyproject.toml index 63a94488..b9f1fe19 100644 --- a/plugins/productivity-skills/pyproject.toml +++ b/plugins/productivity-skills/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "productivity-skills-maintenance" -version = "6.8.0" +version = "6.9.0" description = "Maintainer-only Python tooling baseline for productivity-skills." requires-python = ">=3.11" dependencies = [] diff --git a/plugins/productivity-skills/uv.lock b/plugins/productivity-skills/uv.lock index 81bb2d91..43f13830 100644 --- a/plugins/productivity-skills/uv.lock +++ b/plugins/productivity-skills/uv.lock @@ -40,7 +40,7 @@ wheels = [ [[package]] name = "productivity-skills-maintenance" -version = "6.8.0" +version = "6.9.0" source = { virtual = "." } [package.dev-dependencies] diff --git a/plugins/python-skills/.codex-plugin/plugin.json b/plugins/python-skills/.codex-plugin/plugin.json index ca67bbcb..00b295bd 100644 --- a/plugins/python-skills/.codex-plugin/plugin.json +++ b/plugins/python-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "python-skills", - "version": "6.8.0", + "version": "6.9.0", "description": "Bundled Python-focused Codex skills for uv bootstrapping, FastAPI and FastMCP scaffolding, FastAPI/FastMCP integration, and pytest workflows.", "author": { "name": "Gale", diff --git a/plugins/python-skills/pyproject.toml b/plugins/python-skills/pyproject.toml index e7f38625..c810ea2e 100644 --- a/plugins/python-skills/pyproject.toml +++ b/plugins/python-skills/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "python-skills-maintainer" -version = "6.8.0" +version = "6.9.0" description = "Maintainer tooling for the python-skills repository" requires-python = ">=3.11" dependencies = [] diff --git a/plugins/python-skills/uv.lock b/plugins/python-skills/uv.lock index d9026f58..d1e5ae74 100644 --- a/plugins/python-skills/uv.lock +++ b/plugins/python-skills/uv.lock @@ -206,7 +206,7 @@ wheels = [ [[package]] name = "python-skills-maintainer" -version = "6.8.0" +version = "6.9.0" source = { virtual = "." } [package.dev-dependencies] diff --git a/plugins/rust-skills/.codex-plugin/plugin.json b/plugins/rust-skills/.codex-plugin/plugin.json index fa7e4d75..f04c0f0e 100644 --- a/plugins/rust-skills/.codex-plugin/plugin.json +++ b/plugins/rust-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "rust-skills", - "version": "6.8.0", + "version": "6.9.0", "description": "Standalone plugin repository for future Rust-focused Codex skills.", "author": { "name": "Gale", diff --git a/plugins/spotify/.codex-plugin/plugin.json b/plugins/spotify/.codex-plugin/plugin.json index 314d031a..a4894525 100644 --- a/plugins/spotify/.codex-plugin/plugin.json +++ b/plugins/spotify/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "spotify", - "version": "6.8.0", + "version": "6.9.0", "description": "Placeholder plugin repository for future Spotify-focused Codex workflows.", "author": { "name": "Gale", diff --git a/plugins/swiftasb-skills/.codex-plugin/plugin.json b/plugins/swiftasb-skills/.codex-plugin/plugin.json index 53bc354c..916d4979 100644 --- a/plugins/swiftasb-skills/.codex-plugin/plugin.json +++ b/plugins/swiftasb-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "swiftasb-skills", - "version": "6.8.0", + "version": "6.9.0", "description": "Codex skills for explaining SwiftASB and building SwiftUI, AppKit, and Swift package integrations on top of it.", "author": { "name": "Gale", diff --git a/plugins/things-app/.codex-plugin/plugin.json b/plugins/things-app/.codex-plugin/plugin.json index b283a384..9ebef96a 100644 --- a/plugins/things-app/.codex-plugin/plugin.json +++ b/plugins/things-app/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "things-app", - "version": "6.8.0", + "version": "6.9.0", "description": "Things.app skills and a bundled local MCP server for reminders, planning digests, and structured task workflows.", "author": { "name": "Gale", diff --git a/plugins/things-app/mcp/pyproject.toml b/plugins/things-app/mcp/pyproject.toml index 7f49f4a8..b1a2c55a 100644 --- a/plugins/things-app/mcp/pyproject.toml +++ b/plugins/things-app/mcp/pyproject.toml @@ -7,7 +7,7 @@ packages = ["app"] [project] name = "things-mcp" -version = "6.8.0" +version = "6.9.0" requires-python = ">=3.13" dependencies = [ "fastmcp>=3.0.2", diff --git a/plugins/things-app/mcp/uv.lock b/plugins/things-app/mcp/uv.lock index edb9661c..71b4556b 100644 --- a/plugins/things-app/mcp/uv.lock +++ b/plugins/things-app/mcp/uv.lock @@ -1118,7 +1118,7 @@ wheels = [ [[package]] name = "things-mcp" -version = "6.8.0" +version = "6.9.0" source = { editable = "." } dependencies = [ { name = "fastmcp" }, diff --git a/plugins/things-app/pyproject.toml b/plugins/things-app/pyproject.toml index f72a37e7..6859425a 100644 --- a/plugins/things-app/pyproject.toml +++ b/plugins/things-app/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "things-app-maintenance" -version = "6.8.0" +version = "6.9.0" description = "Maintainer-only Python tooling baseline for things-app skills and plugin packaging." requires-python = ">=3.11" dependencies = [] diff --git a/plugins/things-app/uv.lock b/plugins/things-app/uv.lock index e6d941bf..34a591ef 100644 --- a/plugins/things-app/uv.lock +++ b/plugins/things-app/uv.lock @@ -120,7 +120,7 @@ wheels = [ [[package]] name = "things-app-maintenance" -version = "6.8.0" +version = "6.9.0" source = { virtual = "." } [package.dev-dependencies] diff --git a/plugins/web-dev-skills/.codex-plugin/plugin.json b/plugins/web-dev-skills/.codex-plugin/plugin.json index a1d2a503..c2d75a84 100644 --- a/plugins/web-dev-skills/.codex-plugin/plugin.json +++ b/plugins/web-dev-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "web-dev-skills", - "version": "6.8.0", + "version": "6.9.0", "description": "Standalone plugin repository for future web-focused Codex skills.", "author": { "name": "Gale", diff --git a/pyproject.toml b/pyproject.toml index 311e9545..f5f97412 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "socket-maintenance" -version = "6.8.0" +version = "6.9.0" description = "Root uv tooling baseline for the socket superproject." requires-python = ">=3.11" dependencies = [] diff --git a/scripts/validate_socket_metadata.py b/scripts/validate_socket_metadata.py index 0c7d6a8e..d8a68f28 100644 --- a/scripts/validate_socket_metadata.py +++ b/scripts/validate_socket_metadata.py @@ -18,6 +18,8 @@ INSTALLATION_POLICIES = {"AVAILABLE", "INSTALLED_BY_DEFAULT", "NOT_AVAILABLE"} AUTHENTICATION_POLICIES = {"ON_INSTALL", "ON_FIRST_USE"} MARKETPLACE_INTERFACE_ASSET_FIELDS = {"banner"} +PLUGIN_INTERFACE_ASSET_FIELDS = {"composerIcon", "logo"} +PLUGIN_INTERFACE_ASSET_LIST_FIELDS = {"screenshots"} def fail(message: str) -> NoReturn: @@ -194,6 +196,49 @@ def manifest_exports_content(*, plugin_root: Path, plugin_manifest: dict[str, ob return False +def validate_plugin_interface_assets( + *, + plugin_name: str, + plugin_root: Path, + plugin_manifest: dict[str, object], +) -> None: + interface = plugin_manifest.get("interface") + if interface is None: + return + if not isinstance(interface, dict): + fail(f"Packaged plugin manifest for `{plugin_name}` has an invalid `interface` object.") + + for field_name in PLUGIN_INTERFACE_ASSET_FIELDS: + field_value = interface.get(field_name) + if field_value is None: + continue + validate_manifest_path( + plugin_name=plugin_name, + plugin_root=plugin_root, + field_name=f"interface.{field_name}", + field_value=field_value, + expected_kind="file", + ) + + for field_name in PLUGIN_INTERFACE_ASSET_LIST_FIELDS: + field_value = interface.get(field_name) + if field_value is None: + continue + if not isinstance(field_value, list): + fail( + f"Packaged plugin manifest for `{plugin_name}` must define " + f"`interface.{field_name}` as a list of repo-relative paths." + ) + for index, item in enumerate(field_value): + validate_manifest_path( + plugin_name=plugin_name, + plugin_root=plugin_root, + field_name=f"interface.{field_name}[{index}]", + field_value=item, + expected_kind="file", + ) + + def validate_local_plugin_entry( *, name: str, @@ -252,6 +297,12 @@ def validate_local_plugin_entry( "policy.installation `NOT_AVAILABLE` until they ship content." ) + validate_plugin_interface_assets( + plugin_name=name, + plugin_root=plugin_root, + plugin_manifest=plugin_manifest, + ) + skills_dir = plugin_root / "skills" skills_path = plugin_manifest.get("skills") if skills_dir.is_dir(): diff --git a/tests/test_swiftasb_skills_install.py b/tests/test_swiftasb_skills_install.py index eeb4bf09..61266a2a 100644 --- a/tests/test_swiftasb_skills_install.py +++ b/tests/test_swiftasb_skills_install.py @@ -1,5 +1,6 @@ from __future__ import annotations +import json import os import shutil import subprocess @@ -46,6 +47,16 @@ def test_swiftasb_skills_marketplace_installs_in_temporary_codex_home( marketplace_path = REPO_ROOT / ".agents" / "plugins" / "marketplace.json" assert marketplace_path.is_file() + marketplace = json.loads(marketplace_path.read_text(encoding="utf-8")) + dotnet_entry = next( + plugin for plugin in marketplace["plugins"] if plugin["name"] == "dotnet-skills" + ) + assert dotnet_entry["policy"]["installation"] == "AVAILABLE" + assert dotnet_entry["source"] == { + "source": "local", + "path": "./plugins/dotnet-skills", + } + plugin_root = REPO_ROOT / "plugins" / "swiftasb-skills" assert (plugin_root / ".codex-plugin" / "plugin.json").is_file() assert (plugin_root / "skills" / "explain-swiftasb" / "SKILL.md").is_file() @@ -54,3 +65,22 @@ def test_swiftasb_skills_marketplace_installs_in_temporary_codex_home( assert (plugin_root / "skills" / "build-appkit-app" / "SKILL.md").is_file() assert (plugin_root / "skills" / "build-swift-package" / "SKILL.md").is_file() assert (plugin_root / "skills" / "diagnose-integration" / "SKILL.md").is_file() + + +def test_dotnet_skills_plugin_exposes_expected_skill_inventory() -> None: + plugin_root = REPO_ROOT / "plugins" / "dotnet-skills" + + assert (plugin_root / ".codex-plugin" / "plugin.json").is_file() + assert (plugin_root / "assets" / "sharp-icon.jpg").is_file() + assert (plugin_root / "skills" / "choose-project-shape" / "SKILL.md").is_file() + assert (plugin_root / "skills" / "bootstrap-solution" / "SKILL.md").is_file() + assert (plugin_root / "skills" / "build-fsharp-project" / "SKILL.md").is_file() + assert (plugin_root / "skills" / "build-csharp-project" / "SKILL.md").is_file() + assert (plugin_root / "skills" / "testing-workflow" / "SKILL.md").is_file() + assert (plugin_root / "skills" / "package-workflow" / "SKILL.md").is_file() + assert (plugin_root / "skills" / "diagnose-project" / "SKILL.md").is_file() + assert (plugin_root / "skills" / "aspnet-core-service-workflow" / "SKILL.md").is_file() + assert (plugin_root / "skills" / "fsharp-csharp-interop" / "SKILL.md").is_file() + assert (plugin_root / "skills" / "ci-workflow" / "SKILL.md").is_file() + assert (plugin_root / "skills" / "upgrade-workflow" / "SKILL.md").is_file() + assert (plugin_root / "skills" / "tooling-style-workflow" / "SKILL.md").is_file() diff --git a/tests/test_validate_socket_metadata.py b/tests/test_validate_socket_metadata.py index db0f7ffb..4c91d84f 100644 --- a/tests/test_validate_socket_metadata.py +++ b/tests/test_validate_socket_metadata.py @@ -28,6 +28,9 @@ def make_marketplace_repo(tmp_path: Path, manifest: dict[str, object]) -> Path: repo_root / ".agents" / "plugins" / "marketplace.json", json.dumps( { + "interface": { + "displayName": "Test Marketplace", + }, "plugins": [ { "name": "example-skills", @@ -62,6 +65,9 @@ def make_remote_marketplace_repo( repo_root / ".agents" / "plugins" / "marketplace.json", json.dumps( { + "interface": { + "displayName": "Test Marketplace", + }, "plugins": [ { "name": "speak-swiftly", @@ -106,6 +112,49 @@ def test_main_accepts_plugin_manifest_with_root_skills_component( run_validator(repo_root, monkeypatch) +def test_main_accepts_plugin_manifest_with_interface_assets( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, +) -> None: + repo_root = make_marketplace_repo( + tmp_path, + { + "name": "example-skills", + "skills": "./skills/", + "interface": { + "composerIcon": "./assets/icon.jpg", + "logo": "./assets/logo.jpg", + "screenshots": ["./assets/screenshot.jpg"], + }, + }, + ) + plugin_root = repo_root / "plugins" / "example-skills" + write(plugin_root / "assets" / "icon.jpg", "icon") + write(plugin_root / "assets" / "logo.jpg", "logo") + write(plugin_root / "assets" / "screenshot.jpg", "screenshot") + + run_validator(repo_root, monkeypatch) + + +def test_main_rejects_plugin_manifest_with_missing_interface_asset( + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, +) -> None: + repo_root = make_marketplace_repo( + tmp_path, + { + "name": "example-skills", + "skills": "./skills/", + "interface": { + "composerIcon": "./assets/missing.jpg", + }, + }, + ) + + with pytest.raises(SystemExit): + run_validator(repo_root, monkeypatch) + + def test_main_rejects_plugin_manifest_missing_root_skills_component( tmp_path: Path, monkeypatch: pytest.MonkeyPatch, @@ -131,6 +180,9 @@ def test_main_accepts_unavailable_empty_placeholder_plugin( repo_root / ".agents" / "plugins" / "marketplace.json", json.dumps( { + "interface": { + "displayName": "Test Marketplace", + }, "plugins": [ { "name": "placeholder-skills", diff --git a/uv.lock b/uv.lock index b17b9ab8..4fde04e5 100644 --- a/uv.lock +++ b/uv.lock @@ -286,7 +286,7 @@ wheels = [ [[package]] name = "socket-maintenance" -version = "6.8.0" +version = "6.9.0" source = { virtual = "." } [package.dev-dependencies]