diff --git a/ROADMAP.md b/ROADMAP.md index ed281c96..318f8b2a 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -130,8 +130,8 @@ In Progress - [x] Create `plugins/swiftasb-skills/` with its own `.codex-plugin/plugin.json` and authored `skills/` source. - [x] Add first-slice skills for explaining SwiftASB, choosing an integration shape, and building a SwiftUI app on top of SwiftASB. -- [ ] Add `swiftasb:build-appkit-app` for AppKit apps after the first slice proves useful. -- [ ] Add `swiftasb:build-swift-package` for Swift package authors after the first slice proves useful. +- [x] Add `swiftasb:build-appkit-app` for AppKit apps after the first slice proves useful. +- [x] Add `swiftasb:build-swift-package` for Swift package authors after the first slice proves useful. - [x] Add an integration diagnostics skill for runtime discovery, app-server startup, threads, turns, approvals, diagnostics, MCP status, history reads, and live-test isolation. - [x] Wire `swiftasb-skills` into the root Socket marketplace as a normal local child plugin. - [x] Update root README and maintainer docs so users understand the split between the SwiftASB package source of truth and the Socket-hosted Codex guidance plugin. @@ -141,7 +141,7 @@ In Progress - [x] The Socket marketplace exposes `swiftasb-skills` as an installable child plugin. - [x] The new skills can help an agent explain SwiftASB to a user before implementation, including when SwiftASB is not the right fit. -- [ ] The new skills guide SwiftUI, AppKit, and Swift package integrations without duplicating broad Apple framework guidance that belongs to `apple-dev-skills`. +- [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. ## Backlog Candidates diff --git a/docs/maintainers/swiftasb-skills-plugin-plan.md b/docs/maintainers/swiftasb-skills-plugin-plan.md index 22faa4ce..56e36d91 100644 --- a/docs/maintainers/swiftasb-skills-plugin-plan.md +++ b/docs/maintainers/swiftasb-skills-plugin-plan.md @@ -153,18 +153,18 @@ The first slice should be intentionally small: - [x] Add `swiftasb:build-swiftui-app`. - [x] Wire `swiftasb-skills` into `.agents/plugins/marketplace.json`. - [x] Update `README.md` and `ROADMAP.md` so Socket documents the new child plugin surface. -- [ ] Run `uv run scripts/validate_socket_metadata.py`. -- [ ] Run any child-plugin validation added by the new plugin. +- [x] Run `uv run scripts/validate_socket_metadata.py`. +- [x] Run any child-plugin validation added by the new plugin. ## Later Slices After the first slice proves useful, add: -- [ ] `swiftasb:build-appkit-app`. -- [ ] `swiftasb:build-swift-package`. +- [x] `swiftasb:build-appkit-app`. +- [x] `swiftasb:build-swift-package`. - [x] `swiftasb:diagnose-integration`. -- [ ] Examples that show how agents should explain SwiftASB to users before implementation. -- [ ] Install testing with a temporary `CODEX_HOME`. +- [x] Examples that show how agents should explain SwiftASB to users before implementation. +- [x] Install testing with a temporary `CODEX_HOME`. - [x] Decide against a SwiftASB repo-local marketplace because SwiftASB is expected to be consumed as a Swift package dependency inside other apps, command-line tools, and packages; Codex-visible guidance belongs in the Socket-hosted companion plugin. ## Definition Of Done @@ -175,4 +175,4 @@ The plugin is ready for first release when: - [x] The skills consistently describe SwiftASB as a Swift-native app-server client rather than a general AI SDK or a raw protocol dump. - [x] The guidance sends Apple framework questions through Apple Dev Skills instead of duplicating broad SwiftUI or AppKit rules. - [x] The guidance points agents back to the SwiftASB package docs for source-of-truth API, licensing, release, and compatibility details. -- [ ] Root Socket docs, marketplace wiring, and validation all agree on the plugin's install surface. +- [x] Root Socket docs, marketplace wiring, and validation all agree on the plugin's install surface. diff --git a/plugins/agent-plugin-skills/.agents/skills b/plugins/agent-plugin-skills/.agents/skills new file mode 120000 index 00000000..42c5394a --- /dev/null +++ b/plugins/agent-plugin-skills/.agents/skills @@ -0,0 +1 @@ +../skills \ No newline at end of file diff --git a/plugins/agent-plugin-skills/.codex-plugin/plugin.json b/plugins/agent-plugin-skills/.codex-plugin/plugin.json index dc60ccfc..da951c0f 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.4.1", + "version": "6.5.0", "description": "Installable maintainer skills for skills-export repositories.", "author": { "name": "Gale", diff --git a/plugins/agent-plugin-skills/AGENTS.md b/plugins/agent-plugin-skills/AGENTS.md index 13d518f4..036bb40f 100644 --- a/plugins/agent-plugin-skills/AGENTS.md +++ b/plugins/agent-plugin-skills/AGENTS.md @@ -30,6 +30,7 @@ Use this file for durable repo-local guidance that Codex should follow before ch - Keep Codex plugin guidance aligned with the current OpenAI docs: only `plugin.json` belongs in `.codex-plugin/`, while `skills/` stays at the plugin root and the manifest points to it with `"skills": "./skills/"`. - Keep Codex plugin-boundary wording factual and explicit: repo-visible plugins come from the documented marketplace model, and OpenAI does not document a richer repo-private scoping model beyond that. - Default user-facing install and update guidance to Git-backed marketplace sources with `codex plugin marketplace add /` and `codex plugin marketplace upgrade `. Use explicit refs such as `/@vX.Y.Z` only for pinned reproducible installs. Manual local marketplace roots and copied plugin payloads are development, unpublished-testing, or fallback paths. +- Do not recreate `skills/install-plugin-to-socket` or `skills/validate-plugin-install-surfaces`; those retired installer and validation workflows encouraged manual install-surface thinking that this repo now keeps out of the standard Codex path. - For Python-backed maintainer repositories, require `uv` plus repo-local dev dependencies in `pyproject.toml` for the tools the repo expects to run. - Do not teach or rely on machine-global `uv tool install` as the primary baseline for repo validation when the repo can declare `pytest`, `ruff`, and `mypy` directly in its dev dependency group. diff --git a/plugins/agent-plugin-skills/docs/maintainers/codex-plugin-install-surfaces.md b/plugins/agent-plugin-skills/docs/maintainers/codex-plugin-install-surfaces.md index a8b175a7..151cd3e4 100644 --- a/plugins/agent-plugin-skills/docs/maintainers/codex-plugin-install-surfaces.md +++ b/plugins/agent-plugin-skills/docs/maintainers/codex-plugin-install-surfaces.md @@ -88,6 +88,8 @@ codex plugin marketplace add gaelic-ghost/SpeakSwiftlyServer After the marketplace is added or upgraded, restart Codex, open the plugin directory in the Codex GUI, choose the marketplace, and install or enable the desired plugin there. Use explicit refs such as `gaelic-ghost/socket@vX.Y.Z` only for pinned reproducible installs. Manual local marketplace files and copied payload directories are development and fallback tools, not the preferred user path. +When an active Codex workflow needs a companion skill or plugin, first route through the Codex harness surfaces that are already available in the current session. Name the current-session skill to use before giving installation advice. If the companion skill is not exposed, add or update the marketplace and install the plugin through Codex's plugin directory for future sessions instead of presenting `config.toml` edits, copied payload folders, or arbitrary checkout searches as the standard path. + ## Marketplace Identity Codex tracks plugin enabled-state by plugin name plus marketplace name. diff --git a/plugins/agent-plugin-skills/pyproject.toml b/plugins/agent-plugin-skills/pyproject.toml index e6d9740d..37bee6de 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.4.1" +version = "6.5.0" description = "Maintainer-only Python tooling baseline for agent-plugin-skills." requires-python = ">=3.11" dependencies = [] diff --git a/plugins/agent-plugin-skills/skills/sync-skills-repo-guidance/SKILL.md b/plugins/agent-plugin-skills/skills/sync-skills-repo-guidance/SKILL.md index 4d781e33..c53b1f64 100644 --- a/plugins/agent-plugin-skills/skills/sync-skills-repo-guidance/SKILL.md +++ b/plugins/agent-plugin-skills/skills/sync-skills-repo-guidance/SKILL.md @@ -47,6 +47,8 @@ When this skill touches Codex plugin guidance, keep these surfaces distinct inst Default user-facing install and update guidance to the official Git-backed marketplace commands. Use explicit refs such as `/@vX.Y.Z` only for pinned reproducible installs. Use manual local marketplace or copied-payload instructions only for local development, testing unpublished changes, or fallback cases where the Git-backed path is not available. +When a workflow depends on a companion skill or plugin, first route through the Codex harness surfaces that are already available in the current session. Name the current-session skill to use, such as `productivity-skills:maintain-project-repo`, before giving install advice. If the companion skill is missing from the session, tell the user to add or update the marketplace and install the plugin through Codex's plugin directory for future sessions; do not imply that editing `config.toml`, copying payload folders, or searching an arbitrary checkout is the standard way to make a skill callable from Codex. + For `socket`, prefer: ```bash diff --git a/plugins/agent-plugin-skills/skills/sync-skills-repo-guidance/scripts/sync_skills_repo_guidance.py b/plugins/agent-plugin-skills/skills/sync-skills-repo-guidance/scripts/sync_skills_repo_guidance.py index d573291e..74e24a3c 100644 --- a/plugins/agent-plugin-skills/skills/sync-skills-repo-guidance/scripts/sync_skills_repo_guidance.py +++ b/plugins/agent-plugin-skills/skills/sync-skills-repo-guidance/scripts/sync_skills_repo_guidance.py @@ -14,7 +14,7 @@ EXACT_NO_FINDINGS = "No findings." README_SNIPPETS = [ - "Installable maintainer skills for skills-export repositories.", + "Installable maintainer skills for skills-export and plugin-export repositories.", "does not document a richer repo-private scoping model", "codex plugin marketplace add gaelic-ghost/socket", "codex plugin marketplace upgrade socket", @@ -26,7 +26,7 @@ "only `plugin.json` belongs in `.codex-plugin/`", ] AGENTS_SNIPPETS = [ - "Root `skills/` is the canonical authored and exported surface", + "canonical authored and exported surface", 'the manifest points to it with `"skills": "./skills/"`', "Resolve shared project dependencies only from GitHub repository URLs, package managers, package registries, or other real remote repositories", "Machine-local dependency paths are expressly prohibited in any project that is public or intended to be shared publicly", @@ -50,6 +50,8 @@ "codex plugin marketplace upgrade socket", "Documented plugin path: `~/.codex/config.toml`", "project-scoped `.codex/config.toml`, label it as a general Codex config capability", + "first route through the Codex harness surfaces that are already available in the current session", + "install the plugin through Codex's plugin directory for future sessions", ] WORKFLOW_ATLAS_SNIPPETS = [ "No skill in this repo should treat repo-local Codex plugin installs as a richer private scoping model than the marketplace-based behavior OpenAI documents.", diff --git a/plugins/agent-plugin-skills/skills/sync-skills-repo-guidance/tests/test_sync_skills_repo_guidance.py b/plugins/agent-plugin-skills/skills/sync-skills-repo-guidance/tests/test_sync_skills_repo_guidance.py index e83b05c9..baa09c4e 100644 --- a/plugins/agent-plugin-skills/skills/sync-skills-repo-guidance/tests/test_sync_skills_repo_guidance.py +++ b/plugins/agent-plugin-skills/skills/sync-skills-repo-guidance/tests/test_sync_skills_repo_guidance.py @@ -26,7 +26,7 @@ def _write_repo(repo_root: Path, _plugin_name: str) -> None: (repo_root / "README.md").write_text( "\n".join( [ - "Installable maintainer skills for skills-export repositories.", + "Installable maintainer skills for skills-export and plugin-export repositories.", "OpenAI's documented Codex plugin system exposes repo-visible plugins through marketplace catalogs and does not document a richer repo-private scoping model beyond that.", "codex plugin marketplace add gaelic-ghost/socket", "codex plugin marketplace upgrade socket", @@ -44,7 +44,7 @@ def _write_repo(repo_root: Path, _plugin_name: str) -> None: (repo_root / "AGENTS.md").write_text( "\n".join( [ - "Root `skills/` is the canonical authored and exported surface", + "canonical authored and exported surface", 'the manifest points to it with `"skills": "./skills/"`', "Resolve shared project dependencies only from GitHub repository URLs, package managers, package registries, or other real remote repositories", "Machine-local dependency paths are expressly prohibited in any project that is public or intended to be shared publicly", @@ -83,6 +83,8 @@ def _write_repo(repo_root: Path, _plugin_name: str) -> None: "codex plugin marketplace upgrade socket", "Documented plugin path: `~/.codex/config.toml`", "If you mention project-scoped `.codex/config.toml`, label it as a general Codex config capability rather than part of the documented plugin install-surface map.", + "first route through the Codex harness surfaces that are already available in the current session", + "install the plugin through Codex's plugin directory for future sessions", ] ) + "\n", diff --git a/plugins/agent-plugin-skills/uv.lock b/plugins/agent-plugin-skills/uv.lock index 57bdfbfa..11e74dfc 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.4.1" +version = "6.5.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 bd734fdd..a9caeac3 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.4.1", + "version": "6.5.0", "description": "Apple development workflows for Codex and Claude Code, including SwiftUI architecture and DocC authoring guidance.", "author": { "name": "Gale", diff --git a/plugins/apple-dev-skills/pyproject.toml b/plugins/apple-dev-skills/pyproject.toml index 5beca0f3..8dc6dc85 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.4.1" +version = "6.5.0" description = "Maintainer tooling for the apple-dev-skills repository" requires-python = ">=3.9" dependencies = [] diff --git a/plugins/apple-dev-skills/skills/sync-swift-package-guidance/SKILL.md b/plugins/apple-dev-skills/skills/sync-swift-package-guidance/SKILL.md index 13976bf5..2699906a 100644 --- a/plugins/apple-dev-skills/skills/sync-swift-package-guidance/SKILL.md +++ b/plugins/apple-dev-skills/skills/sync-swift-package-guidance/SKILL.md @@ -11,7 +11,7 @@ Bring an existing Swift package repository up to the expected guidance baseline ## Companion Plugin Requirement -This skill can be discovered from a standalone `apple-dev-skills` install, but its mutating guidance-sync path refreshes repo-maintenance files through the companion [`productivity-skills`](https://github.com/gaelic-ghost/productivity-skills) plugin. If the companion `maintain-project-repo` runner is missing, tell the user to install `productivity-skills` alongside `apple-dev-skills`, or add the [`socket`](https://github.com/gaelic-ghost/socket) marketplace with `codex plugin marketplace add gaelic-ghost/socket` and then install or enable both `apple-dev-skills` and `productivity-skills` from the Socket catalog. +This skill can be discovered from a standalone `apple-dev-skills` install, but its mutating guidance-sync path refreshes repo-maintenance files through the companion [`productivity-skills`](https://github.com/gaelic-ghost/productivity-skills) plugin. Before giving filesystem-level fallback instructions, first check the skills exposed in the current Codex session and use the harness-discovered `productivity-skills:maintain-project-repo` workflow when it is available. If the companion skill is not exposed, tell the user to add the [`socket`](https://github.com/gaelic-ghost/socket) marketplace with `codex plugin marketplace add gaelic-ghost/socket`, then install the relevant plugins from Codex's plugin directory so future sessions expose both `apple-dev-skills` and `productivity-skills`. ## When To Use diff --git a/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/SKILL.md b/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/SKILL.md index 7aae26da..f092631a 100644 --- a/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/SKILL.md +++ b/plugins/apple-dev-skills/skills/sync-xcode-project-guidance/SKILL.md @@ -11,7 +11,7 @@ Bring an existing Xcode app repository up to the expected guidance baseline with ## Companion Plugin Requirement -This skill can be discovered from a standalone `apple-dev-skills` install, but its mutating guidance-sync path refreshes repo-maintenance files through the companion [`productivity-skills`](https://github.com/gaelic-ghost/productivity-skills) plugin. If the companion `maintain-project-repo` runner is missing, tell the user to install `productivity-skills` alongside `apple-dev-skills`, or add the [`socket`](https://github.com/gaelic-ghost/socket) marketplace with `codex plugin marketplace add gaelic-ghost/socket` and then install or enable both `apple-dev-skills` and `productivity-skills` from the Socket catalog. +This skill can be discovered from a standalone `apple-dev-skills` install, but its mutating guidance-sync path refreshes repo-maintenance files through the companion [`productivity-skills`](https://github.com/gaelic-ghost/productivity-skills) plugin. Before giving filesystem-level fallback instructions, first check the skills exposed in the current Codex session and use the harness-discovered `productivity-skills:maintain-project-repo` workflow when it is available. If the companion skill is not exposed, tell the user to add the [`socket`](https://github.com/gaelic-ghost/socket) marketplace with `codex plugin marketplace add gaelic-ghost/socket`, then install the relevant plugins from Codex's plugin directory so future sessions expose both `apple-dev-skills` and `productivity-skills`. ## When To Use diff --git a/plugins/apple-dev-skills/uv.lock b/plugins/apple-dev-skills/uv.lock index c01b2e09..b453ce35 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.4.1" +version = "6.5.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 e8012e98..305eaa7a 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.4.1", + "version": "6.5.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 fb6c49bf..e5b1be06 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.4.1" +version = "6.5.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 85ee6d05..4b73e784 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.4.1" +version = "6.5.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 87d4f887..5d68a6a1 100644 --- a/plugins/dotnet-skills/.codex-plugin/plugin.json +++ b/plugins/dotnet-skills/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "dotnet-skills", - "version": "6.4.1", + "version": "6.5.0", "description": "Standalone plugin repository for future .NET-focused Codex skills.", "author": { "name": "Gale", diff --git a/plugins/productivity-skills/.codex-plugin/plugin.json b/plugins/productivity-skills/.codex-plugin/plugin.json index f38025a9..267dcd5a 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.4.1", + "version": "6.5.0", "description": "Broadly useful productivity workflows for Codex and Claude Code.", "author": { "name": "Gale", diff --git a/plugins/productivity-skills/pyproject.toml b/plugins/productivity-skills/pyproject.toml index 939a84ce..531f0bf5 100644 --- a/plugins/productivity-skills/pyproject.toml +++ b/plugins/productivity-skills/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "productivity-skills-maintenance" -version = "6.4.1" +version = "6.5.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 2e8b7eae..9554232f 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.4.1" +version = "6.5.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 2e4eee85..781dbf46 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.4.1", + "version": "6.5.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 5d3326e0..f42a5fba 100644 --- a/plugins/python-skills/pyproject.toml +++ b/plugins/python-skills/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "python-skills-maintainer" -version = "6.4.1" +version = "6.5.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 527604b7..6a2241bf 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.4.1" +version = "6.5.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 96e6c92c..ab977f08 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.4.1", + "version": "6.5.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 2f50d847..99959c5d 100644 --- a/plugins/spotify/.codex-plugin/plugin.json +++ b/plugins/spotify/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "spotify", - "version": "6.4.1", + "version": "6.5.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 dffc8530..d225de2d 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.4.1", + "version": "6.5.0", "description": "Codex skills for explaining SwiftASB and building SwiftUI, AppKit, and Swift package integrations on top of it.", "author": { "name": "Gale", @@ -33,8 +33,10 @@ "websiteURL": "https://github.com/gaelic-ghost/socket/tree/main/plugins/swiftasb-skills", "defaultPrompt": [ "Explain whether SwiftASB is the right fit for this Swift app before we start building.", - "Choose a SwiftASB integration shape for this SwiftUI or AppKit project.", + "Choose a SwiftASB integration shape for this SwiftUI, AppKit, package, or helper project.", "Add a SwiftUI-facing SwiftASB client model using observable companions.", + "Add an AppKit-facing SwiftASB owner for a window, document, or controller.", + "Design a Swift package API that uses SwiftASB internally without leaking raw wire models.", "Diagnose why this SwiftASB-backed app or test is failing." ], "brandColor": "#F05138" diff --git a/plugins/swiftasb-skills/AGENTS.md b/plugins/swiftasb-skills/AGENTS.md index 39e65b84..a3321274 100644 --- a/plugins/swiftasb-skills/AGENTS.md +++ b/plugins/swiftasb-skills/AGENTS.md @@ -12,7 +12,7 @@ Use this file for durable guidance that applies inside the `swiftasb-skills` chi ## Source Of Truth - Use the current SwiftASB repository, README, DocC docs, release notes, and public Swift API as the source of truth for package behavior. -- SwiftASB `v1.0.0` is the first supported public API baseline, but active development may move ahead of that release. Verify the local or GitHub package state before writing exact API guidance. +- SwiftASB `v1.0.0` is the first supported public API baseline, and `v1.0.1` is the current released baseline. Active development may move ahead of that release, so verify the local or GitHub package state before writing exact API guidance. - Do not copy SwiftASB source, generated wire models, or schema files into this plugin. - Do not describe generated `CodexWire...` models as the intended public integration surface. SwiftASB's public surface is the hand-owned Swift API. diff --git a/plugins/swiftasb-skills/README.md b/plugins/swiftasb-skills/README.md index bd91d7b2..de527cea 100644 --- a/plugins/swiftasb-skills/README.md +++ b/plugins/swiftasb-skills/README.md @@ -11,6 +11,7 @@ Codex skills for explaining [SwiftASB](https://github.com/gaelic-ghost/SwiftASB) - [Release Notes](#release-notes) - [License](#license) - [Active Skills](#active-skills) +- [Examples](#examples) - [Packaging](#packaging) - [Repository Layout](#repository-layout) @@ -20,11 +21,11 @@ Codex skills for explaining [SwiftASB](https://github.com/gaelic-ghost/SwiftASB) ### Status -This directory is active as normal monorepo-owned content inside `socket` and ships the first SwiftASB workflow skills. +This directory is active as normal monorepo-owned content inside `socket` and ships the SwiftASB companion workflow set. ### What This Project Is -This plugin helps Codex agents explain SwiftASB, choose an integration shape, implement SwiftUI-facing SwiftASB work, diagnose integration failures, and prepare later AppKit and package-author integrations. SwiftASB itself remains the source of truth for the Swift package, public API, DocC, release notes, generated wire maintenance, and licensing. +This plugin helps Codex agents explain SwiftASB, choose an integration shape, implement SwiftUI-facing, AppKit-facing, and package-author SwiftASB work, and diagnose integration failures. SwiftASB itself remains the source of truth for the Swift package, public API, DocC, release notes, generated wire maintenance, and licensing. ### Motivation @@ -45,7 +46,7 @@ Use `apple-dev-skills` for Apple framework rules, Xcode workflow selection, Swif Treat root [`skills/`](./skills/) as the source of truth for shipped workflow content. Treat [`.codex-plugin/plugin.json`](./.codex-plugin/plugin.json) as install-surface metadata. -Before changing exact SwiftASB API guidance, verify the current SwiftASB package state through the local checkout or [GitHub repository](https://github.com/gaelic-ghost/SwiftASB). The first supported public API baseline is `v1.0.0`, but the local package may be under active development. +Before changing exact SwiftASB API guidance, verify the current SwiftASB package state through the local checkout or [GitHub repository](https://github.com/gaelic-ghost/SwiftASB). The first supported public API baseline is `v1.0.0`; the current released baseline is `v1.0.1`, and the local package may be under active development. ## Verification @@ -72,8 +73,14 @@ See [LICENSE](../../LICENSE) for the Socket superproject license. SwiftASB packa - `explain-swiftasb` - `choose-integration-shape` - `build-swiftui-app` +- `build-appkit-app` +- `build-swift-package` - `diagnose-integration` +## Examples + +Use [examples/explain-before-implementation.md](./examples/explain-before-implementation.md) when an agent needs a short, user-facing SwiftASB fit explanation before implementation starts. + ## Packaging This repository intentionally keeps authored content and plugin metadata separate. diff --git a/plugins/swiftasb-skills/examples/explain-before-implementation.md b/plugins/swiftasb-skills/examples/explain-before-implementation.md new file mode 100644 index 00000000..811047c5 --- /dev/null +++ b/plugins/swiftasb-skills/examples/explain-before-implementation.md @@ -0,0 +1,59 @@ +# SwiftASB Explanation Examples + +Use these examples when an agent needs to explain SwiftASB before implementation starts. They are intentionally short and decision-oriented. The agent should still verify the current SwiftASB README, DocC docs, release notes, and public API before making exact claims. + +## Strong Fit: SwiftUI Workspace Inspector + +Recommendation: SwiftASB is a good fit for this app. + +What SwiftASB would do here: SwiftASB would let the SwiftUI app start the local Codex runtime, open a thread for the workspace, start turns, and read live progress through Swift-native handles instead of replaying raw app-server JSON. + +What the app would own: The app still owns its windows, navigation, inspector layout, persistence choices, user preferences, and approval UI. SwiftUI and Observation should own view updates. + +What SwiftASB would own: `CodexAppServer` owns the subprocess and app-wide capability reads, `CodexThread` owns one conversation, `CodexTurnHandle` owns one active turn, and companions such as `Dashboard`, `Minimap`, `RecentTurns`, `RecentFiles`, and `RecentCommands` provide UI-friendly state. + +Tradeoffs: The app depends on a local Codex CLI runtime, same-thread overlapping turns are rejected, and compatibility follows SwiftASB's reviewed Codex support window. + +Next integration step: Use `swiftasb:choose-integration-shape`, then `swiftasb:build-swiftui-app`. + +## Strong Fit: AppKit Document Window + +Recommendation: SwiftASB is a good fit if each document or workspace window needs its own Codex thread. + +What SwiftASB would do here: SwiftASB would provide the typed runtime, thread, turn, diagnostic, and history surfaces. The AppKit app can connect those surfaces to window-controller actions, menu validation, toolbar controls, sheets, panels, and inspector views. + +What the app would own: AppKit still owns application lifecycle, document/window ownership, main-actor UI updates, menu state, toolbar actions, and user-facing presentation. + +What SwiftASB would own: SwiftASB owns Codex startup, initialization, thread creation or resume, active turn events, request responses, interruption, diagnostics, and local history reads. + +Tradeoffs: The app needs explicit process lifetime decisions. A window controller should not secretly own app-wide Codex runtime work if multiple windows share one runtime. + +Next integration step: Use `swiftasb:choose-integration-shape`, then `swiftasb:build-appkit-app`. + +## Conditional Fit: Swift Package Library + +Recommendation: SwiftASB can fit, but only if the package intentionally depends on a local Codex runtime. + +What SwiftASB would do here: SwiftASB would sit inside the package implementation and provide typed Codex runtime control. The package should expose its own narrow request, result, progress, and error types unless consumers genuinely need direct SwiftASB handles. + +What the package would own: The package owns its public API, versioning promises, test strategy, runtime documentation, and consumer-facing error model. + +What SwiftASB would own: SwiftASB owns app-server startup, thread and turn handles, diagnostics, interactive request routing, and local history helpers. + +Tradeoffs: Normal `swift test` should stay deterministic. Live Codex probes need explicit environment flags, temporary workspaces, serial execution, and hard timeouts. + +Next integration step: Use `swiftasb:choose-integration-shape`, then `swiftasb:build-swift-package`. + +## Poor Fit: Hosted Multi-User Service + +Recommendation: SwiftASB is probably not the right foundation. + +What SwiftASB would do here: SwiftASB drives a local Codex app-server from Swift. It is not a hosted multi-user agent platform and does not remove the need for product-level auth, tenancy, job isolation, deployment, or server operations. + +What the app would own: A hosted service would need to own user accounts, authorization, rate limits, workspace isolation, queueing, secrets, audit logs, and deployment health. + +What SwiftASB would own: SwiftASB could still help a local Swift tool or internal helper drive Codex, but it should not be described as a complete hosted platform. + +Tradeoffs: Treating SwiftASB as the server platform would hide major product and security decisions. + +Next integration step: Use `swiftasb:explain-swiftasb` to document why the fit is weak, then choose a hosted architecture separately. diff --git a/plugins/swiftasb-skills/skills/build-appkit-app/SKILL.md b/plugins/swiftasb-skills/skills/build-appkit-app/SKILL.md new file mode 100644 index 00000000..dfc6147a --- /dev/null +++ b/plugins/swiftasb-skills/skills/build-appkit-app/SKILL.md @@ -0,0 +1,214 @@ +--- +name: build-appkit-app +description: Build or refactor an AppKit app feature on top of SwiftASB using explicit application, window, document, thread, and turn ownership with main-actor UI updates and clear runtime diagnostics. +license: Apache-2.0 +compatibility: Designed for Codex and compatible Agent Skills clients working with SwiftASB v1.0.1 or newer, Swift 6, SwiftPM, AppKit, Xcode, and local Codex app-server integrations. +metadata: + owner: gaelic-ghost + repo: socket + package: SwiftASB + category: swiftasb-appkit +allowed-tools: Read Bash(rg:*) Bash(git:*) Bash(swift:*) Bash(xcodebuild:*) +--- + +# Build AppKit App With SwiftASB + +## Purpose + +Help an AppKit app use [SwiftASB](https://github.com/gaelic-ghost/SwiftASB) to start local Codex work, show thread and turn progress, answer approvals or elicitation requests, and expose recent history from app-owned controllers or models. + +The real job is to keep AppKit's app, window, document, and view-controller lifetimes in charge of UI behavior while SwiftASB owns the local Codex subprocess, typed thread and turn handles, events, request responses, diagnostics, and local history. + +## Required Documentation Gate + +Before implementing or proposing AppKit structure, read the relevant Apple documentation through Apple Dev Skills or official Apple docs. + +Minimum rules to rely on: + +- `NSApplication` manages the app's main event loop, windows, menus, events, and app-wide resources. +- `NSApplicationDelegate` handles app lifecycle callbacks such as launch, termination, activation, reopen, and window-update behavior. +- `NSWindowController` manages a window and often participates in document-based ownership. +- `NSViewController` manages a view and has lifecycle methods suitable for window content. +- AppKit UI types such as `NSWindow` and many delegate callbacks are main-actor UI surfaces; update AppKit views and controllers from the main actor. + +Authoritative docs: + +- [AppKit](https://developer.apple.com/documentation/AppKit) +- [NSApplication](https://developer.apple.com/documentation/appkit/nsapplication) +- [NSApplicationDelegate](https://developer.apple.com/documentation/AppKit/NSApplicationDelegate) +- [NSWindowController](https://developer.apple.com/documentation/appkit/nswindowcontroller) +- [NSViewController](https://developer.apple.com/documentation/AppKit/NSViewController) +- [NSWindow](https://developer.apple.com/documentation/appkit/nswindow) + +## When To Use + +- Use this skill when an AppKit app needs a SwiftASB-backed feature. +- Use this skill after `swiftasb:choose-integration-shape` selects an AppKit, document, window-controller, or menu-bar app shape. +- Use this skill when AppKit menus, toolbar actions, sidebars, inspectors, document windows, or panels need to start, steer, interrupt, or inspect Codex turns. +- Use this skill for refactors that move AppKit code away from raw JSON-RPC, ad hoc process ownership, or generated wire models and toward SwiftASB's public handles. + +## Source Check + +Verify current SwiftASB docs and public API before editing: + +- [SwiftASB GitHub repository](https://github.com/gaelic-ghost/SwiftASB) +- `README.md` +- `Sources/SwiftASB/SwiftASB.docc/GettingStartedWithSwiftASB.md` +- `Sources/SwiftASB/SwiftASB.docc/HandlingTurnProgressAndApprovals.md` +- `Sources/SwiftASB/SwiftASB.docc/ReadingDiagnosticsAndHistory.md` +- `Sources/SwiftASB/Public/CodexAppServer.swift` +- `Sources/SwiftASB/Public/CodexThread+Dashboard.swift` +- `Sources/SwiftASB/Public/CodexTurnHandle.swift` + +As of SwiftASB `v1.0.1`, AppKit-facing integrations should prefer: + +- `CodexAppServer` for subprocess startup, initialization, diagnostics, stored-thread operations, model reads, and MCP status reads +- `CodexThread` for conversation-scoped turn creation, thread events, thread actions, request responses, and local history +- `CodexTurnHandle` for one active turn, including events, steering, interruption, request responses, minimap state, and completion handoff +- `CodexThread.makeDashboard()` and `CodexTurnHandle.minimap` as UI-friendly current-state mirrors +- local history helpers and recent companions for inspector panels, transcript sidebars, and completed work views + +## Implementation Workflow + +1. Confirm the AppKit ownership shape: app delegate, document, window controller, view controller, menu-bar controller, or helper object. +2. Read the Apple docs for the framework behavior the change relies on. +3. Add SwiftASB as a package dependency only if it is not already present: + - package URL: `https://github.com/gaelic-ghost/SwiftASB` + - minimum version: `1.0.0` + - product: `SwiftASB` +4. Choose the SwiftASB owner: + - application-level model owns `CodexAppServer` when one runtime serves many windows + - document or window model owns `CodexThread` when work belongs to one workspace or document + - active command method or controller owns `CodexTurnHandle` while one turn is running +5. Start and initialize the app-server from an explicit async lifecycle point. +6. Create, resume, or fork a thread for the window, document, or workspace. +7. Route menu and toolbar actions into local controller methods that start, steer, interrupt, or inspect turns. +8. Update AppKit views on the main actor from SwiftASB events, dashboard, minimap, diagnostics, and local history. +9. Route approval and elicitation responses through the matching `CodexTurnHandle` or `CodexThread`. +10. Make startup, compatibility, turn, approval, cancellation, and shutdown errors human-readable. +11. Validate with the repository's documented Xcode path. + +## Ownership Pattern + +Prefer one AppKit-facing object that makes lifetime visible: + +```swift +import AppKit +import SwiftASB + +@MainActor +final class CodexWorkspaceWindowController: NSWindowController { + private let appServer: CodexAppServer + private var thread: CodexThread? + private var currentTurn: CodexTurnHandle? + + @IBOutlet private var statusField: NSTextField! + + init(appServer: CodexAppServer) { + self.appServer = appServer + super.init(window: nil) + } + + required init?(coder: NSCoder) { + nil + } + + func connect(workspacePath: String) { + Task { @MainActor in + do { + try await appServer.start() + _ = try await appServer.cliExecutableDiagnostics() + try await appServer.initialize( + .init( + clientInfo: .init( + name: "ExampleApp", + title: "Example App", + version: "1.0.0" + ) + ) + ) + + thread = try await appServer.startThread( + .init(currentDirectoryPath: workspacePath) + ) + statusField.stringValue = "Codex is ready." + } catch { + statusField.stringValue = "SwiftASB could not start Codex: \(error)" + } + } + } + + @IBAction func runSelectedTask(_ sender: Any?) { + guard let thread else { + statusField.stringValue = "SwiftASB cannot start a turn before a thread exists." + return + } + + Task { @MainActor in + do { + let turn = try await thread.startTextTurn("Summarize the current workspace.") + currentTurn = turn + + for try await event in turn.events { + if case .completed = event { + _ = try await turn.complete() + currentTurn = nil + statusField.stringValue = "Codex turn finished." + return + } + } + } catch { + currentTurn = nil + statusField.stringValue = "SwiftASB turn failed: \(error)" + } + } + } + + @IBAction func interruptTurn(_ sender: Any?) { + Task { @MainActor in + do { + try await currentTurn?.interrupt() + statusField.stringValue = "Interrupt sent to Codex." + } catch { + statusField.stringValue = "SwiftASB could not interrupt the turn: \(error)" + } + } + } +} +``` + +Use this as a shape, not as a file to paste blindly. Match the app's actual nib/storyboard/programmatic-window setup, document model, and error UI. + +## UI Guidance + +- Show Codex runtime startup and compatibility failures before enabling menu or toolbar actions. +- Keep menu validation tied to real state: no thread, active turn, waiting approval, or idle. +- Disable same-thread start actions while a turn is active, or create a separate thread when concurrent work is truly intended. +- Show approvals as concrete AppKit UI: sheet, popover, panel, or inspector row that names the command, file change, permission, or MCP action. +- Use `dashboard` and `minimap` state for activity views instead of replaying every raw event into controller-owned arrays. +- Keep document and window closure explicit: interrupt active work or make it clear that background work continues elsewhere. +- Surface diagnostics and MCP status in places a Mac maintainer can actually inspect, such as a status item, inspector, log pane, or preferences diagnostics view. + +## Validation + +Use the repository's documented Xcode build and test path. For Xcode projects, do not assume SwiftPM validation is enough because scheme, target membership, entitlements, sandboxing, signing, and resources may be Xcode-owned. + +Live Codex integration tests should be opt-in, isolated in temporary workspaces, and bounded by hard timeouts. + +## Handoffs + +- Use `swiftasb:explain-swiftasb` when the user needs adoption tradeoffs before implementation. +- Use `swiftasb:choose-integration-shape` when ownership or app shape is unclear. +- Use `swiftasb:diagnose-integration` when startup, turn, approval, MCP, diagnostics, or history behavior fails. +- Use `apple-dev-skills:explore-apple-swift-docs` for AppKit, SwiftUI, SwiftPM, or Observation documentation. +- Use Apple build, test, or Xcode workflow skills for project execution and diagnostics. + +## Guardrails + +- Do not make a window or view controller secretly own app-wide Codex runtime work if the app has multiple windows that should share one `CodexAppServer`. +- Do not mutate AppKit UI from detached background work without returning to the main actor. +- Do not put raw generated `CodexWire...` models into AppKit controller or view state. +- Do not introduce a command bus or broad coordinator just to forward SwiftASB events; use local AppKit actions and SwiftASB handles unless the app already has a real architecture surface for that job. +- Do not start overlapping turns on the same thread; SwiftASB rejects that because the live app-server does not expose a reliable independent lifecycle for them. +- Do not hide local Codex CLI discovery, compatibility, or startup failures behind generic messages. +- Do not run multiple SwiftPM or Xcode build/test commands concurrently. diff --git a/plugins/swiftasb-skills/skills/build-swift-package/SKILL.md b/plugins/swiftasb-skills/skills/build-swift-package/SKILL.md new file mode 100644 index 00000000..aa882ac4 --- /dev/null +++ b/plugins/swiftasb-skills/skills/build-swift-package/SKILL.md @@ -0,0 +1,198 @@ +--- +name: build-swift-package +description: Build or refactor a Swift package API on top of SwiftASB without leaking raw app-server wire models, while keeping live Codex probes opt-in, isolated, timeout-bounded, and documented. +license: Apache-2.0 +compatibility: Designed for Codex and compatible Agent Skills clients working with SwiftASB v1.0.1 or newer, Swift 6, SwiftPM, package libraries, command-line tools, and local Codex app-server integrations. +metadata: + owner: gaelic-ghost + repo: socket + package: SwiftASB + category: swiftasb-package +allowed-tools: Read Bash(rg:*) Bash(git:*) Bash(swift:*) +--- + +# Build Swift Package With SwiftASB + +## Purpose + +Help a Swift package use [SwiftASB](https://github.com/gaelic-ghost/SwiftASB) internally while exposing the package's own small, Swift-native API to its callers. + +The real job is to keep the package's public surface understandable. SwiftASB can own Codex runtime startup, typed threads, turns, events, diagnostics, and local history inside the implementation, but the package author should decide deliberately whether consumers see SwiftASB handles directly or a narrower domain-specific API. + +## Required Documentation Gate + +Before implementing or proposing package structure, read the relevant SwiftPM and Swift documentation through Apple Dev Skills, Swift.org, or official Apple docs. + +Minimum rules to rely on: + +- A Swift package is configured by a `Package.swift` manifest at the package root. +- `Package` defines package name, products, targets, dependencies, platforms, resources, and Swift language mode. +- A library product is the externally visible artifact clients import. +- A package dependency should resolve from a real remote source that other contributors can fetch. +- Version-based dependency requirements are the recommended default for published package dependencies. + +Authoritative docs: + +- [Swift Package Manager](https://www.swift.org/documentation/package-manager/) +- [PackageDescription](https://developer.apple.com/documentation/packagedescription) +- [Package](https://developer.apple.com/documentation/PackageDescription/Package) +- [Swift Package Manager PackageDescription API](https://docs.swift.org/package-manager/PackageDescription/PackageDescription.html) + +## When To Use + +- Use this skill when a Swift package wants to build features on top of SwiftASB. +- Use this skill after `swiftasb:choose-integration-shape` selects a package library, command-line package, helper package, or test harness shape. +- Use this skill when a package should expose SwiftASB-backed capabilities without making raw app-server wire types its public API. +- Use this skill when live Codex behavior needs to be tested or documented without becoming a normal unit-test dependency. + +## Source Check + +Verify current SwiftASB docs and public API before editing: + +- [SwiftASB GitHub repository](https://github.com/gaelic-ghost/SwiftASB) +- `README.md` +- `Sources/SwiftASB/SwiftASB.docc/GettingStartedWithSwiftASB.md` +- `Sources/SwiftASB/SwiftASB.docc/HandlingTurnProgressAndApprovals.md` +- `Sources/SwiftASB/SwiftASB.docc/ReadingDiagnosticsAndHistory.md` +- `Sources/SwiftASB/Public/CodexAppServer.swift` +- `Sources/SwiftASB/Public/CodexThread.swift` +- `Sources/SwiftASB/Public/CodexTurnHandle.swift` + +As of SwiftASB `v1.0.1`, package integrations should prefer: + +- `CodexAppServer` for subprocess startup, initialization, diagnostics, stored-thread operations, model reads, and MCP status reads +- `CodexThread` for conversation-scoped turn creation, thread actions, request responses, and local history +- `CodexTurnHandle` for one active turn, including events, steering, interruption, request responses, and completion handoff +- package-owned public types for the user's domain when consumers do not need direct SwiftASB handles + +## Implementation Workflow + +1. Inspect the package manifest and target layout. +2. Read the SwiftPM docs for the package behavior the change relies on. +3. Decide whether SwiftASB is implementation detail or public API: + - implementation detail: expose package-owned request, result, progress, and error types + - public dependency: expose selected SwiftASB handles only when consumers genuinely need them +4. Add SwiftASB as a dependency only if it is not already present: + - package URL: `https://github.com/gaelic-ghost/SwiftASB` + - minimum version: `1.0.0` + - product: `SwiftASB` +5. Add the dependency to the target that owns Codex behavior, not every target by default. +6. Keep startup, turn, approval, cancellation, diagnostics, and history errors descriptive and package-specific. +7. Keep normal tests deterministic with package-owned fakes, adapters, fixtures, or small pure transformations. +8. Add live Codex probes only behind explicit opt-in flags, temporary workspaces, serial execution, and hard timeouts. +9. Document runtime requirements, compatibility expectations, and live-test flags in the package README or contributor docs. +10. Validate with `swift build` and `swift test`, plus any repo-documented checks. + +## Public API Pattern + +Prefer a narrow package-owned facade when the package is not primarily a SwiftASB wrapper: + +```swift +import SwiftASB + +public struct WorkspaceSummaryRequest: Sendable { + public var workspacePath: String + public var prompt: String + + public init(workspacePath: String, prompt: String) { + self.workspacePath = workspacePath + self.prompt = prompt + } +} + +public struct WorkspaceSummary: Sendable { + public var text: String +} + +public actor WorkspaceSummarizer { + private let appServer: CodexAppServer + + public init() { + self.appServer = CodexAppServer() + } + + public func shutdown() async { + await appServer.stop() + } + + public func summarize(_ request: WorkspaceSummaryRequest) async throws -> WorkspaceSummary { + try await appServer.start() + try await appServer.initialize( + .init( + clientInfo: .init( + name: "WorkspaceSummarizer", + title: "Workspace Summarizer", + version: "1.0.0" + ) + ) + ) + + let thread = try await appServer.startThread( + .init(currentDirectoryPath: request.workspacePath) + ) + let turn = try await thread.startTextTurn(request.prompt) + + for try await event in turn.events { + if case .completed = event { + _ = try await turn.complete() + return WorkspaceSummary(text: "Summary completed.") + } + } + + throw WorkspaceSummaryError.turnEndedWithoutCompletion + } +} + +public enum WorkspaceSummaryError: Error, Sendable { + case turnEndedWithoutCompletion +} +``` + +Use this as a shape, not as a file to paste blindly. Most packages should return their own real result data, stream their own progress values, and map SwiftASB failures into errors their consumers can understand. + +## API Design Guidance + +- Keep the public API focused on the package's job, not on exposing every SwiftASB capability. +- Prefer typed request, result, progress, and options values over strings, booleans, or parallel parameters. +- Expose `CodexAppServer`, `CodexThread`, or `CodexTurnHandle` only when the package is intentionally a thin SwiftASB extension surface. +- Keep generated `CodexWire...` models out of public API unless the user explicitly asks for protocol-level work. +- Keep cancellation explicit; do not drop a `CodexTurnHandle` silently when the package promises cancellation behavior. +- Document that a local Codex CLI/app-server runtime is required. +- Document SwiftASB compatibility as a reviewed support window, not a generic promise that every future Codex app-server schema is public API. + +## Testing Guidance + +- Keep default `swift test` deterministic and free of live Codex subprocess requirements. +- Use fakes or protocol-shaped seams for package-owned behavior when the test is about your package, not Codex runtime compatibility. +- Put live Codex probes behind an explicit environment flag such as `SWIFTASB_LIVE_TESTS=1`. +- Run live probes in temporary workspaces with hard timeouts. +- Do not run live probes concurrently with other SwiftPM or Xcode build/test commands. +- Make live failure text name the exact boundary: executable discovery, startup, initialization, thread start, turn start, request response, diagnostics, history, or shutdown. + +## Validation + +Run the repository's documented validation path. For plain Swift packages, the baseline is: + +```bash +swift build +swift test +``` + +If the package is also an Xcode app workspace, use the repository's documented Xcode workflow instead of assuming SwiftPM is sufficient. + +## Handoffs + +- Use `swiftasb:explain-swiftasb` when the user needs adoption tradeoffs before implementation. +- Use `swiftasb:choose-integration-shape` when ownership or public API shape is unclear. +- Use `swiftasb:diagnose-integration` when startup, turn, approval, MCP, diagnostics, or history behavior fails. +- Use `apple-dev-skills:sync-swift-package-guidance` when the package repo's `AGENTS.md` or maintainer workflow needs alignment. +- Use Apple Swift package workflow skills for package build, test, manifest, resource, DocC, or release execution. + +## Guardrails + +- Do not commit machine-local SwiftASB dependency paths such as `/Users/...`, `~/...`, or `../SwiftASB` into public package manifests. +- Do not make live Codex subprocess work part of normal unit tests. +- Do not expose raw generated app-server wire models as the default public API. +- Do not treat same-thread overlapping turns as supported; SwiftASB rejects them because the live app-server does not expose a reliable independent lifecycle for that case. +- Do not hide local Codex CLI discovery, compatibility, startup, or protocol failures behind generic errors. +- Do not run multiple SwiftPM or Xcode build/test commands concurrently. diff --git a/plugins/swiftasb-skills/skills/build-swiftui-app/SKILL.md b/plugins/swiftasb-skills/skills/build-swiftui-app/SKILL.md index 8c8d7a39..4d5cc716 100644 --- a/plugins/swiftasb-skills/skills/build-swiftui-app/SKILL.md +++ b/plugins/swiftasb-skills/skills/build-swiftui-app/SKILL.md @@ -2,7 +2,7 @@ name: build-swiftui-app description: Build or refactor a SwiftUI app feature on top of SwiftASB using framework-owned SwiftUI state, SwiftASB thread and turn handles, observable companions, clear runtime diagnostics, and safe validation. license: Apache-2.0 -compatibility: Designed for Codex and compatible Agent Skills clients working with SwiftASB v1.0.0 or newer, Swift 6, SwiftPM, SwiftUI, Observation, Xcode, and local Codex app-server integrations. +compatibility: Designed for Codex and compatible Agent Skills clients working with SwiftASB v1.0.1 or newer, Swift 6, SwiftPM, SwiftUI, Observation, Xcode, and local Codex app-server integrations. metadata: owner: gaelic-ghost repo: socket @@ -56,7 +56,7 @@ Verify current SwiftASB docs and public API before editing: - `Sources/SwiftASB/Public/CodexThread+Dashboard.swift` - `Sources/SwiftASB/Public/CodexTurnHandle.swift` -As of SwiftASB `v1.0.0`, SwiftUI-facing integrations should prefer: +As of SwiftASB `v1.0.1`, SwiftUI-facing integrations should prefer: - `CodexAppServer` for process startup, initialization, diagnostics, thread creation, and app-wide capability reads - `CodexThread` for conversation-scoped turn creation, request routing, thread actions, and local history diff --git a/plugins/swiftasb-skills/skills/choose-integration-shape/SKILL.md b/plugins/swiftasb-skills/skills/choose-integration-shape/SKILL.md index c60ed6e5..d8cfcac4 100644 --- a/plugins/swiftasb-skills/skills/choose-integration-shape/SKILL.md +++ b/plugins/swiftasb-skills/skills/choose-integration-shape/SKILL.md @@ -2,7 +2,7 @@ name: choose-integration-shape description: Choose the right SwiftASB integration shape for a SwiftUI app, AppKit app, command-line tool, helper service, package library, test harness, or mixed Swift project before implementation starts. license: Apache-2.0 -compatibility: Designed for Codex and compatible Agent Skills clients working with SwiftASB v1.0.0 or newer, Swift 6, SwiftPM, SwiftUI, AppKit, and local Codex app-server integrations. +compatibility: Designed for Codex and compatible Agent Skills clients working with SwiftASB v1.0.1 or newer, Swift 6, SwiftPM, SwiftUI, AppKit, and local Codex app-server integrations. metadata: owner: gaelic-ghost repo: socket @@ -96,6 +96,8 @@ Plan: - how menu or toolbar actions start, steer, interrupt, or inspect turns - how streamed events reach AppKit views safely +Handoff: `swiftasb:build-appkit-app`. + ### Command-Line Tool Use `CodexAppServer` in a short-lived async main flow. Start, initialize, create or resume a thread, start a turn, stream terminal output or summary, and stop the app-server predictably. @@ -114,6 +116,8 @@ Expose the package's own narrow API instead of re-exporting all SwiftASB types b Keep live Codex tests opt-in and timeout-bounded. +Handoff: `swiftasb:build-swift-package`. + ### Test Harness Prefer mock or deterministic transport tests for package behavior. Use live Codex probes only when the test's purpose is runtime compatibility, and isolate them with temporary directories and environment flags. diff --git a/plugins/swiftasb-skills/skills/diagnose-integration/SKILL.md b/plugins/swiftasb-skills/skills/diagnose-integration/SKILL.md index b967dd33..07575923 100644 --- a/plugins/swiftasb-skills/skills/diagnose-integration/SKILL.md +++ b/plugins/swiftasb-skills/skills/diagnose-integration/SKILL.md @@ -2,7 +2,7 @@ name: diagnose-integration description: Diagnose SwiftASB integration failures across Codex CLI discovery, app-server startup, initialization, threads, turns, approvals, MCP status, diagnostics, history paging, and live-test isolation. license: Apache-2.0 -compatibility: Designed for Codex and compatible Agent Skills clients working with SwiftASB v1.0.0 or newer, Swift 6, SwiftPM, SwiftUI, AppKit, CLI tools, package libraries, and local Codex app-server integrations. +compatibility: Designed for Codex and compatible Agent Skills clients working with SwiftASB v1.0.1 or newer, Swift 6, SwiftPM, SwiftUI, AppKit, CLI tools, package libraries, and local Codex app-server integrations. metadata: owner: gaelic-ghost repo: socket diff --git a/plugins/swiftasb-skills/skills/explain-swiftasb/SKILL.md b/plugins/swiftasb-skills/skills/explain-swiftasb/SKILL.md index 4ce535d5..3c2bb19c 100644 --- a/plugins/swiftasb-skills/skills/explain-swiftasb/SKILL.md +++ b/plugins/swiftasb-skills/skills/explain-swiftasb/SKILL.md @@ -2,7 +2,7 @@ name: explain-swiftasb description: Explain SwiftASB in user-facing terms, including what it does, what it does not do, adoption tradeoffs, licensing, and when it is or is not the right foundation for a Swift app or package. license: Apache-2.0 -compatibility: Designed for Codex and compatible Agent Skills clients working with SwiftASB v1.0.0 or newer, Swift 6, SwiftPM, SwiftUI, AppKit, and local Codex app-server integrations. +compatibility: Designed for Codex and compatible Agent Skills clients working with SwiftASB v1.0.1 or newer, Swift 6, SwiftPM, SwiftUI, AppKit, and local Codex app-server integrations. metadata: owner: gaelic-ghost repo: socket @@ -36,7 +36,7 @@ Before giving exact API claims, inspect the current SwiftASB source of truth: - the public files under `Sources/SwiftASB/Public/` - the latest release notes or tags -As of SwiftASB `v1.0.0`, the supported public surface centers on: +As of SwiftASB `v1.0.1`, the supported public surface centers on: - `CodexAppServer`, the owner of the local Codex subprocess and app-wide capability reads - `CodexThread`, the handle for one Codex conversation thread @@ -98,6 +98,8 @@ Answer in this order: - Use `swiftasb:choose-integration-shape` when the user wants to proceed but the app shape is not settled. - Use `swiftasb:build-swiftui-app` when the chosen target is a SwiftUI app. +- Use `swiftasb:build-appkit-app` when the chosen target is an AppKit app. +- Use `swiftasb:build-swift-package` when the chosen target is a package library, command-line package, helper package, or test harness. - Use `apple-dev-skills:explore-apple-swift-docs` before making Apple framework claims. - Use Apple build or Xcode workflow skills when the task shifts from explanation to project execution. diff --git a/plugins/things-app/.codex-plugin/plugin.json b/plugins/things-app/.codex-plugin/plugin.json index a81bd495..7dde8be9 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.4.1", + "version": "6.5.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 8f83c134..39dafea7 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.4.1" +version = "6.5.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 982ade08..2d1fb1a4 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.4.1" +version = "6.5.0" source = { editable = "." } dependencies = [ { name = "fastmcp" }, diff --git a/plugins/things-app/pyproject.toml b/plugins/things-app/pyproject.toml index befdd5d0..c96c0459 100644 --- a/plugins/things-app/pyproject.toml +++ b/plugins/things-app/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "things-app-maintenance" -version = "6.4.1" +version = "6.5.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 66b565f3..cedc5553 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.4.1" +version = "6.5.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 4935c8c7..f70a12a6 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.4.1", + "version": "6.5.0", "description": "Standalone plugin repository for future web-focused Codex skills.", "author": { "name": "Gale", diff --git a/pyproject.toml b/pyproject.toml index ae3283ef..5fac6824 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "socket-maintenance" -version = "6.4.1" +version = "6.5.0" description = "Root uv tooling baseline for the socket superproject." requires-python = ">=3.11" dependencies = [] diff --git a/tests/test_swiftasb_skills_install.py b/tests/test_swiftasb_skills_install.py new file mode 100644 index 00000000..eeb4bf09 --- /dev/null +++ b/tests/test_swiftasb_skills_install.py @@ -0,0 +1,56 @@ +from __future__ import annotations + +import os +import shutil +import subprocess +import tomllib +from pathlib import Path + +import pytest + + +REPO_ROOT = Path(__file__).resolve().parent.parent + + +def test_swiftasb_skills_marketplace_installs_in_temporary_codex_home( + tmp_path: Path, +) -> None: + codex = shutil.which("codex") + if codex is None: + pytest.skip("codex CLI is not available") + + codex_home = tmp_path / "codex-home" + codex_home.mkdir() + + env = os.environ.copy() + env["CODEX_HOME"] = str(codex_home) + + result = subprocess.run( + [codex, "plugin", "marketplace", "add", str(REPO_ROOT)], + check=True, + capture_output=True, + env=env, + text=True, + ) + + assert "Added marketplace `socket`" in result.stdout + + config_path = codex_home / "config.toml" + assert config_path.is_file() + + config = tomllib.loads(config_path.read_text(encoding="utf-8")) + socket_marketplace = config["marketplaces"]["socket"] + assert socket_marketplace["source_type"] == "local" + assert socket_marketplace["source"] == str(REPO_ROOT) + + marketplace_path = REPO_ROOT / ".agents" / "plugins" / "marketplace.json" + assert marketplace_path.is_file() + + 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() + assert (plugin_root / "skills" / "choose-integration-shape" / "SKILL.md").is_file() + assert (plugin_root / "skills" / "build-swiftui-app" / "SKILL.md").is_file() + 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() diff --git a/uv.lock b/uv.lock index 09f2e85a..006e9e2d 100644 --- a/uv.lock +++ b/uv.lock @@ -286,7 +286,7 @@ wheels = [ [[package]] name = "socket-maintenance" -version = "6.4.1" +version = "6.5.0" source = { virtual = "." } [package.dev-dependencies]