From 9b634ff59d22bb542bc374c734ff8842da70e97d Mon Sep 17 00:00:00 2001 From: Karl Krukow Date: Tue, 2 Jun 2026 11:25:52 +0200 Subject: [PATCH] docs(skill): correct upstream-sync skill file mapping and add pitfall Phase 10 self-review of the update-upstream skill after the v1.0.0-beta.12 sync surfaced documentation drift: - AGENTS.md Project Structure tree was missing `tool_set.clj` and the top-level `github.copilot-sdk` namespace (`copilot_sdk.clj`), which holds the curated public `event-types` / `session-events` sets. - references/PROJECT.md mapped the public `event-types` set to `client.clj` (it lives in `copilot_sdk.clj`) and referenced a non-existent `subscribe-events!`. Corrected, split curated-vs-generated event sets, and added the `toolSet.ts` -> `tool_set.clj` mapping. - SKILL.md gains pitfall #5: outbound optional wire fields must match upstream's omit-vs-null behavior per RPC (compute the value and gate on `(some? v)` when the request schema has no null variant, as with `session.model.switchTo`). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/copilot-instructions.md | 3 +++ .github/skills/update-upstream/SKILL.md | 2 ++ .github/skills/update-upstream/references/PROJECT.md | 7 +++++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 0e707e5..cf28b7a 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -174,11 +174,14 @@ This project emphasizes **rigor and correctness**, particularly for: ## Project Structure ``` +src/github/copilot_sdk.clj # Top-level public API namespace (github.copilot-sdk): + # re-exports + curated public `event-types` / `session-events` sets src/github/copilot_sdk/ ├── client.clj # Main client API (create-client, create-session, etc.) ├── session.clj # Session operations (send!, send-and-wait!, etc.) ├── helpers.clj # Convenience functions (query, query-seq!, query-chan, etc.) ├── tools.clj # Helper functions for defining tools (define-tool, result-success, etc.) +├── tool_set.clj # Source-qualified tool filter patterns (:available-tools/:excluded-tools) ├── specs.clj # clojure.spec definitions for all data shapes ├── instrument.clj # Function specs (fdefs) and instrumentation ├── util.clj # Wire conversion (camelCase ↔ kebab-case), MCP helpers diff --git a/.github/skills/update-upstream/SKILL.md b/.github/skills/update-upstream/SKILL.md index e1eeec5..d540d68 100644 --- a/.github/skills/update-upstream/SKILL.md +++ b/.github/skills/update-upstream/SKILL.md @@ -172,4 +172,6 @@ Real recurring traps when porting upstream changes: 4. **Test fixtures: match the shape the layer actually produces.** Mock server responses use wire shape; client-side assertions use idiomatic shape. Production conversion (`util/wire->clj`) only transforms keyword keys — string-keyed fixtures silently bypass it and produce tests that pass for the wrong reason. +5. **Outbound optional fields: match upstream's omit-vs-null behavior per RPC.** Don't reflexively gate an optional wire field on `contains?` and emit JSON `null`. Some patch RPCs (e.g. `session.options.update`) genuinely accept `null` to clear a value; others (e.g. `session.model.switchTo`) have no null variant in the schema — upstream spreads `...options`, dropping `undefined`. Check the upstream call site and the request schema: if the field has no null union, compute the wire value first and gate on `(some? v)` so a `nil` option omits the key instead of sending `null`. + For the mechanics of camelCase ↔ kebab-case conversion (including the `?`-suffix rule), see the cheat sheet in `references/PROJECT.md`. diff --git a/.github/skills/update-upstream/references/PROJECT.md b/.github/skills/update-upstream/references/PROJECT.md index b208fd2..7593057 100644 --- a/.github/skills/update-upstream/references/PROJECT.md +++ b/.github/skills/update-upstream/references/PROJECT.md @@ -18,6 +18,7 @@ When syncing, map upstream changes to the corresponding Clojure files: | `nodejs/src/index.ts` | Public exports (defines the public API surface) | | `nodejs/src/generated/session-events.ts` | All event types and data shapes | | `nodejs/src/generated/rpc.ts` | RPC method signatures | +| `nodejs/src/toolSet.ts` | `ToolSet` / `BuiltInTools` tool-filter helpers | ### Clojure Counterparts @@ -26,9 +27,11 @@ When syncing, map upstream changes to the corresponding Clojure files: | Types / config | `specs.clj` | Session config, event data, permissions, tools | | Client methods | `client.clj` | Broadcast handlers, create-client, create-session | | Session methods | `session.clj` | send/receive, UI convenience methods | -| Event types | `client.clj` | `event-types` set, `subscribe-events!` | +| Curated public event sets | `copilot_sdk.clj` | Top-level `github.copilot-sdk` ns: hand-curated public `event-types` / `session-events` sets | +| Generated event specs | `generated/event_specs.clj` | AUTO-GENERATED full `event-types` set + wire specs (`bb codegen`) | | RPC methods | `protocol.clj` | JSON-RPC protocol layer | -| Public exports | `client.clj`, `helpers.clj`, `tools.clj` | Public API surface | +| Tool-filter helpers | `tool_set.clj` | Source-qualified `:available-tools` / `:excluded-tools` patterns | +| Public exports | `copilot_sdk.clj`, `client.clj`, `helpers.clj`, `tools.clj` | Public API surface | | Function specs | `instrument.clj` | fdefs for all public functions | ## Wire Conversion Cheat Sheet