From 6213aaa31e4476ba880e8e169375b42dba01efb5 Mon Sep 17 00:00:00 2001 From: jackchuka Date: Mon, 8 Jun 2026 19:31:37 +0900 Subject: [PATCH] chore(skills): add sdk-sample-sync skill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a Claude Code skill that verifies and updates the hand-written @tailor-platform/sdk code samples in this repo (tutorials, guides, getting-started) against the currently published SDK, and keeps the companion source in tailor-platform/templates in sync. The docs/sdk reference is auto-synced from the SDK package, but the hand-written tutorials are not — so they silently rot when the SDK API changes. This skill captures the verify-empirically workflow: npm pack the published package as source of truth, prove fixes against the runnable templates project (install -> tailor-sdk generate -> tsc), and probe for silent failures (a snippet can compile yet be wrong, e.g. webhook body vs requestBody). - .claude/skills/sdk-sample-sync/SKILL.md - .claude/skills/sdk-sample-sync/scripts/verify-sdk-project.sh --- .claude/skills/sdk-sample-sync/SKILL.md | 155 ++++++++++++++++++ .../scripts/verify-sdk-project.sh | 68 ++++++++ 2 files changed, 223 insertions(+) create mode 100644 .claude/skills/sdk-sample-sync/SKILL.md create mode 100755 .claude/skills/sdk-sample-sync/scripts/verify-sdk-project.sh diff --git a/.claude/skills/sdk-sample-sync/SKILL.md b/.claude/skills/sdk-sample-sync/SKILL.md new file mode 100644 index 0000000..76595e1 --- /dev/null +++ b/.claude/skills/sdk-sample-sync/SKILL.md @@ -0,0 +1,155 @@ +--- +name: sdk-sample-sync +description: >- + Verify and update the hand-written @tailor-platform/sdk code samples in this docs + repo (tutorials, guides, getting-started) against the currently published SDK, and + keep the companion source in tailor-platform/templates in sync. Use this whenever a + new @tailor-platform/sdk version ships, when someone reports a tutorial snippet that + no longer compiles or deploys, when reviewing or editing any SDK code block in the + docs, or when asked to "update the SDK tutorial", "check the docs code samples", + "the SDK API changed", "migrate the develop-from-scratch guide", or similar. Reach + for it even when the request only mentions a single broken snippet — the same drift + usually spans several pages and the matching templates project. +metadata: + author: jackchuka + scope: tailor-platform/docs + verification: empirical +--- + +# Syncing SDK code samples with the published SDK + +## Why this skill exists + +This repo has two kinds of SDK documentation, and they age differently: + +- **`docs/sdk/` is auto-synced.** `scripts/docs-sync/main.ts` copies the SDK package's + own `docs/` into `docs/sdk/` (see `sdk-docs-sync` CI). Never hand-edit it — your + changes get overwritten on the next sync. +- **The tutorials and guides are hand-written.** `docs/tutorials/develop-from-scratch/`, + `docs/getting-started/`, and the SDK examples scattered through `docs/guides/` contain + code blocks a human typed. Nothing regenerates them, so when the SDK changes its API + they silently rot. That rot is what this skill fixes. + +The samples also have a twin: the runnable source in +`tailor-platform/templates/docs/build-from-scratch/sdk/step-0X/`, which each tutorial +page links to. The prose and the runnable code must agree, so this skill updates both +in lockstep. + +The hard-won lesson from the last migration: **a snippet can compile and still be +wrong.** The webhook `body:` field type-checked fine but was silently ignored at +runtime (the real field is `requestBody:`). Reading release notes is not enough — +verify empirically. + +## The process + +### 1. Establish the source of truth for the new SDK + +Don't trust memory or training data — pull the actual published package and read the +docs it ships with. + +```bash +cd /tmp && rm -rf sdk-inspect && mkdir sdk-inspect && cd sdk-inspect +npm pack @tailor-platform/sdk@latest >/dev/null 2>&1 && tar -xzf *.tgz +# Read these — they are the authoritative API reference for the version you're targeting: +ls package/docs package/docs/services package/docs/cli +cat package/CHANGELOG.md # what changed and when +node -e "console.log(require('./package/package.json').version)" +``` + +The bundled `package/docs/` is the same content that becomes `docs/sdk/` here, so it +*is* canonical. When the prose and a code block disagree, the bundled service docs +(e.g. `docs/services/executor.md`) win. + +If you only need to confirm an exported symbol or a method exists, inspect the entry +type defs or check at runtime against an installed copy: + +```bash +node -e "import('@tailor-platform/sdk').then(m => console.log(Object.keys(m.t)))" +``` + +### 2. Find every hand-written SDK sample + +Cast a wide net — the same drift repeats across pages. + +```bash +cd +# import lines, config keys, and CLI invocations are the highest-signal anchors +grep -rn "@tailor-platform/sdk\|tailor-sdk\|defineConfig\|createResolver\|createExecutor\|db\.enum\|db\.type" \ + docs --include="*.md" | grep -v "docs/sdk/" # exclude the auto-synced reference +``` + +Group hits by page. Note which pages have a companion templates project (the +develop-from-scratch steps map 1:1 to `templates/docs/build-from-scratch/sdk/step-0X`). + +### 3. Diagnose against the new API + +For each distinct API surface a sample uses, confirm the current shape from the +bundled docs in step 1 — not from memory of how the old version worked. The package's +`CHANGELOG.md` tells you what moved; the bundled service docs tell you the current +shape. Treat both as inputs to the empirical check in step 4, not as a substitute for +it (the CHANGELOG misses things — see the silent `body`/`requestBody` case). + +### 4. Verify empirically — this is the point of the skill + +Apply the candidate fix to the **templates** project and prove it works, because the +templates project is a real, runnable SDK app. `scripts/verify-sdk-project.sh` runs +the full pipeline (install → `tailor-sdk generate` → `tsc --noEmit`) and cleans up the +generated artifacts afterward: + +```bash +.claude/skills/sdk-sample-sync/scripts/verify-sdk-project.sh \ + /templates/docs/build-from-scratch/sdk/step-03 +``` + +When an API choice is ambiguous (two fields both compile, unsure which is real), force +the question with a deliberate type error. The decisive test from last time: + +```ts +// In the executor, the wrong payload field leaves the callback param untyped: +requestBody: ({ newRecord }) => ({ ... }) // OK — newRecord is typed +body: ({ newRecord }) => ({ ... }) // TS7031 'newRecord' implicitly 'any' → body is NOT the field +``` + +`TS7031 implicitly has 'any'` on a callback parameter is the tell that a field name is +unrecognized (silently dropped), not validated. Excess-property checks alone won't +catch it. Prefer this kind of probe over assuming. + +### 5. Apply to both repos in lockstep + +- **templates**: edit the runnable source; re-run `verify-sdk-project.sh` until green. + Use `git mv` for renames (e.g. `src/pipeline/` → `src/resolver/`) so history is + preserved. Don't commit generated artifacts (`tailor.d.ts`, `src/generated/`) — they + aren't tracked. +- **docs**: update the prose code blocks to match the verified source exactly. Also fix + surrounding prose that describes the API (deploy commands, env var names, field + explanations) — these rot too. Keep the `[Source code on GitHub]` links pointing at + the right paths. + +### 6. Validate the docs site and open PRs + +```bash +pnpm lint && pnpm build # schema-check, link-check, typo_check run in CI too +``` + +Branch off `main` in **each** repo (never reuse an unrelated checked-out branch), open +a **draft** PR in each, and cross-link them in the PR descriptions so a reviewer sees +they ship together. Do not push or open PRs until the user has reviewed — confirm +first. + +## What to watch for + +- **Silent compiles.** The whole reason for step 4. Type-checking green ≠ correct. + Always sanity-check payload/field names against the bundled service docs. +- **Don't touch `docs/sdk/`.** It's regenerated; edits are lost. +- **Prose, not just code.** Env vars (`WORKSPACE_ID` → `TAILOR_PLATFORM_WORKSPACE_ID`), + CLI flags, and conceptual names (pipeline → resolver) live in sentences too. +- **Pin vs. `latest`.** Templates `package.json` historically pins an exact version; + the docs sometimes show `"latest"`. Match the existing convention of each file rather + than imposing one. +- **CHANGELOG gaps.** Not every breaking change is in the CHANGELOG. The empirical + pipeline is your safety net for the ones that aren't. + +## Bundled resources + +- `scripts/verify-sdk-project.sh` — install + generate + typecheck any SDK project dir, + then clean up untracked generated files. Use it as the verification gate in step 4. diff --git a/.claude/skills/sdk-sample-sync/scripts/verify-sdk-project.sh b/.claude/skills/sdk-sample-sync/scripts/verify-sdk-project.sh new file mode 100755 index 0000000..e238dd5 --- /dev/null +++ b/.claude/skills/sdk-sample-sync/scripts/verify-sdk-project.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +# Verify a @tailor-platform/sdk project compiles end to end. +# +# Runs the same pipeline a developer would: install deps, generate the kysely +# types (no-op if the project declares no generators), then `tsc --noEmit`. +# Generated artifacts that the repo does not track (tailor.d.ts, src/generated/) +# are removed afterward so the working tree is left clean. +# +# Usage: verify-sdk-project.sh +# Exit: 0 = typecheck passed, non-zero = something failed (output shows what). + +set -uo pipefail + +DIR="${1:-}" +if [[ -z "$DIR" || ! -d "$DIR" ]]; then + echo "usage: $0 " >&2 + exit 2 +fi +cd "$DIR" || exit 2 + +if [[ ! -f package.json ]]; then + echo "no package.json in $DIR — not an SDK project" >&2 + exit 2 +fi + +echo "==> $DIR" + +# Track which generated paths were untracked before we ran, so cleanup only +# removes things we created (never a checked-in file). +GENERATED=(tailor.d.ts src/generated) +declare -a TO_CLEAN=() +for p in "${GENERATED[@]}"; do + if ! git ls-files --error-unmatch "$p" >/dev/null 2>&1; then + TO_CLEAN+=("$p") + fi +done + +cleanup() { + for p in "${TO_CLEAN[@]}"; do + rm -rf "$p" + done +} +trap cleanup EXIT + +echo "==> npm install" +if ! npm install >/tmp/sdk-verify-install.log 2>&1; then + echo "FAIL: npm install" >&2 + tail -20 /tmp/sdk-verify-install.log >&2 + exit 1 +fi + +# Generate is harmless when no generators are configured; it produces the +# kysely types that resolver/executor snippets import. +echo "==> tailor-sdk generate" +npx tailor-sdk generate >/tmp/sdk-verify-generate.log 2>&1 || { + echo "(generate reported issues — continuing to typecheck; see /tmp/sdk-verify-generate.log)" >&2 +} + +echo "==> typecheck" +if npm run --silent typecheck >/tmp/sdk-verify-tc.log 2>&1 \ + || npx tsc --noEmit >/tmp/sdk-verify-tc.log 2>&1; then + echo "PASS: $DIR" + exit 0 +fi + +echo "FAIL: typecheck" >&2 +grep -E "error TS" /tmp/sdk-verify-tc.log >&2 || tail -30 /tmp/sdk-verify-tc.log >&2 +exit 1