Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 33 additions & 18 deletions .agents/skills/repo-review/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,38 +14,47 @@ compatibility: Requires GitHub CLI (gh) authenticated and installed.
This skill performs a "deep read" of a repository. It avoids superficial listings by first understanding the project's architecture and then evaluating open items against that context.

## Prerequisites
* **Tooling:** The agent must have access to the `gh` CLI.
* **Auth:** The user must be authenticated (`gh auth status`).

- **Tooling:** The agent must have access to the `gh` CLI.
- **Auth:** The user must be authenticated (`gh auth status`).

## Instructions

### Step 1: Initialize the Mental Model

Before looking at tasks, understand the environment. Run these commands in sequence:

1. **Metadata:** `gh repo view <owner/repo> --json name,description,stargazerCount,forkCount`
2. **Structure:** `gh api repos/<owner/repo>/contents/`
3. **Identity:** Read the project manifest (e.g., `package.json`, `go.mod`, `pyproject.toml`) and `README.md`.
4. **Entry Point:** Read the primary entry file (e.g., `index.ts`, `main.go`) to identify the Public API surface.

### Step 2: Retrieve State & Delta

Fetch current items and recent changes:

1. **Issues:** `gh issue list --repo <owner/repo> --state open --json number,title,body,author,createdAt,updatedAt,labels,comments`
2. **PRs:** `gh pr list --repo <owner/repo> --state open --json number,title,body,author,createdAt,updatedAt,labels,additions,deletions,changedFiles,headRefName`
3. **24h Delta:** `gh issue list --state closed --since 24h` and `gh pr list --state merged --since 24h`.

### Step 3: Deep Analysis Logic

For every issue and PR, do not just summarize the text. Perform a logic check:
* **Issues:** Use `gh api repos/<owner/repo>/contents/<path>` to inspect the code mentioned in the report.
* **PRs:** Use `gh pr diff <number>` to review actual implementation. Evaluate if the code follows the patterns found in Step 1.
* **Flags:**
* 🚨 **SECURITY:** Scan for credentials, auth bypass, or injection keywords.
* 🤝 **EXTERNAL:** Prioritize PRs from non-maintainers.
* ✅ **READY:** Verify mergeability with `gh pr view <number> --json mergeable,statusCheckRollup`.

- **Issues:** Use `gh api repos/<owner/repo>/contents/<path>` to inspect the code mentioned in the report.
- **PRs:** Use `gh pr diff <number>` to review actual implementation. Evaluate if the code follows the patterns found in Step 1.
- **Flags:**
- 🚨 **SECURITY:** Scan for credentials, auth bypass, or injection keywords.
- 🤝 **EXTERNAL:** Prioritize PRs from non-maintainers.
- ✅ **READY:** Verify mergeability with `gh pr view <number> --json mergeable,statusCheckRollup`.

### Step 4: Pattern Synthesis

Group items into high-level insights:
* **Bug Clusters:** Identify if 3+ issues share a root cause in a specific module.
* **Hot Modules:** Flag files that appear in multiple open items.
* **Client Patterns:** Group issues by consumer (e.g., "VS Code users are reporting X").

- **Bug Clusters:** Identify if 3+ issues share a root cause in a specific module.
- **Hot Modules:** Flag files that appear in multiple open items.
- **Client Patterns:** Group issues by consumer (e.g., "VS Code users are reporting X").

## Output Template

Expand All @@ -54,22 +63,28 @@ Group items into high-level insights:
**Snapshot:** {N} Issues ({+X} since yesterday) | {M} PRs ({+Y} since yesterday)

### ⚡ Suggested Actions Today

1. **[Priority] #{Num}:** {One-line reason}
2. **[Priority] #{Num}:** {One-line reason}

---

### 📂 Open Issues Deep Dive

#### [Flag] #{Num} — {Title}
* **Context:** Plain-English explanation of the "why" and "where" in the codebase.
* **Key Evidence:** > {Blockquote of critical user text}
* **Resolution Path:** {Quick fix/Design decision/Blocked}

- **Context:** Plain-English explanation of the "why" and "where" in the codebase.
- **Key Evidence:** > {Blockquote of critical user text}
- **Resolution Path:** {Quick fix/Design decision/Blocked}

### 🔀 Pull Request Analysis

#### [Flag] #{Num} — {Title}
* **Impact:** Summary of files changed and architectural fit.
* **Quality Note:** Honest assessment of implementation and CI status.

- **Impact:** Summary of files changed and architectural fit.
- **Quality Note:** Honest assessment of implementation and CI status.

### 🔍 Patterns & Health
* **Hot Modules:** `{list/of/files}`
* **Release Cadence:** Last release was `{days}` ago.

- **Hot Modules:** `{list/of/files}`
- **Release Cadence:** Last release was `{days}` ago.
50 changes: 27 additions & 23 deletions .agents/skills/stitch-sdk-bug-bash/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,48 +12,53 @@ This skill provides a framework and instructions for finding bugs in the Stitch
## The Mindset: Adversarial Exploration

When using this skill, do not just verify that the SDK works. Try to break it!
- Pass invalid or boundary parameters.
- Attempt operations on deleted or stale handles.
- Simulate unexpected API responses if possible or find edge cases where projection might fail.

- Pass invalid or boundary parameters.
- Attempt operations on deleted or stale handles.
- Simulate unexpected API responses if possible or find edge cases where projection might fail.

---

## Surface Areas to Cover

### 1. Root & Initialization (`Stitch`)
- **Zero Config**: Verify the singleton works without explicit config if `STITCH_API_KEY` is present.
- **Invalid Config**: Pass an empty API key or invalid base URL to `StitchToolClient` and verify that the first call fails with a clear authentication or connection error, not a generic noise error.

- **Zero Config**: Verify the singleton works without explicit config if `STITCH_API_KEY` is present.
- **Invalid Config**: Pass an empty API key or invalid base URL to `StitchToolClient` and verify that the first call fails with a clear authentication or connection error, not a generic noise error.

### 2. Project Lifecycle (`Project`)
- **Handle Creation**: Verify that `stitch.project('invalid-id')` does not throw (lazy instantiation) but the first call on it fails safely.
- **Factory vs API**: Verify that creating a project handle via the factory doesn't trigger API calls, but methods like `project.listScreens()` do.

- **Handle Creation**: Verify that `stitch.project('invalid-id')` does not throw (lazy instantiation) but the first call on it fails safely.
- **Factory vs API**: Verify that creating a project handle via the factory doesn't trigger API calls, but methods like `project.listScreens()` do.

### 3. Screen Lifecycle (`Screen`)
- **The Handover**: Verify that properties from `Project.generate()` are correctly populated on the returned `Screen` instances without a second fetch.
- **Null Safety in Projections**: Test tools or scenarios that return empty arrays or missing optional fields. Verify that the SDK handle handles them as `undefined` or empty arrays rather than crashing on null property access!

- **The Handover**: Verify that properties from `Project.generate()` are correctly populated on the returned `Screen` instances without a second fetch.
- **Null Safety in Projections**: Test tools or scenarios that return empty arrays or missing optional fields. Verify that the SDK handle handles them as `undefined` or empty arrays rather than crashing on null property access!

### 4. Design System (`DesignSystem`)
- **Application**: Create a design system, and apply it to a list of screens. Verify that if the list is empty or invalid, the SDK fails cleanly!
- **Handles**: Verify that `project.designSystem('ds-id')` correctly receives the `projectId` and injects it into calls like `ds.apply(...)`.

- **Application**: Create a design system, and apply it to a list of screens. Verify that if the list is empty or invalid, the SDK fails cleanly!
- **Handles**: Verify that `project.designSystem('ds-id')` correctly receives the `projectId` and injects it into calls like `ds.apply(...)`.

---

## Tricky Situations Matrix (Standard Functional Edges)

| Scenario | What to try | Expected Behavior |
| --- | --- | --- |
| **Stale Handles** | Create a screen, delete the project, then try to edit the screen handle. | Clean API error indicating resource not found, wrapped in `StitchError`. |
| **Empty Prompts** | Call `project.generate('')` or with only whitespace. | Safe rejection or clear API error, no crash in codegen. |
| Scenario | What to try | Expected Behavior |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Stale Handles** | Create a screen, delete the project, then try to edit the screen handle. | Clean API error indicating resource not found, wrapped in `StitchError`. |
| **Empty Prompts** | Call `project.generate('')` or with only whitespace. | Safe rejection or clear API error, no crash in codegen. |
| **Projections on null** | Force an API call that returns a response without the expected projection field (if you can simulate or find such a tool fallback case). | The SDK should use optional chaining (e.g., `raw?.prop`) and return `undefined` rather than throwing `TypeError: cannot read property of undefined`. |
| **Massive arrays** | Pass hundreds of screen IDs to `ds.apply()`. | Check if it hits payload limits gracefully or fails with a clear message. |
| **Massive arrays** | Pass hundreds of screen IDs to `ds.apply()`. | Check if it hits payload limits gracefully or fails with a clear message. |

---

## Diagnostic Hygiene

- Always wrap your test calls in `try/catch`.
- Log the error and inspect `error.code` or `error.name` to see if it's a `StitchError` or a generic raw error.
- If an execution throws a raw `TypeError` or "cannot read property of undefined", that is a **HIGH PRIORITY BUG** in the SDK's projection logic!
- Always wrap your test calls in `try/catch`.
- Log the error and inspect `error.code` or `error.name` to see if it's a `StitchError` or a generic raw error.
- If an execution throws a raw `TypeError` or "cannot read property of undefined", that is a **HIGH PRIORITY BUG** in the SDK's projection logic!

---

Expand All @@ -74,7 +79,7 @@ async function bash() {
try {
// 1. Create a fresh project
project = await stitch.createProject({
displayName: `Bug Bash ${new Date().toISOString()}`
displayName: `Bug Bash ${new Date().toISOString()}`,
});
console.log(`✓ Created Project: ${project.id}`);

Expand All @@ -89,7 +94,7 @@ async function bash() {
// 3. Create a design system
const ds = await project.createDesignSystem({
name: "Bash Style",
variables: { primaryColor: "#ff0000" }
variables: { primaryColor: "#ff0000" },
});
console.log(`✓ Created Design System: ${ds.id}`);

Expand All @@ -104,15 +109,14 @@ async function bash() {
} catch (e) {
console.log("✗ Did applying to empty list fail? Inspect error.");
}

} catch (error) {
console.error("💥 Bash failed with error:", error);
} finally {
// 6. Cleanup
if (project) {
console.log(`🧹 Cleaning up project ${project.id}...`);
// Assuming we have a deleteProject binding or we just leave it if not available
// await project.delete();
// await project.delete();
}
}
}
Expand Down
70 changes: 46 additions & 24 deletions .agents/skills/stitch-sdk-development/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,17 @@ When the Stitch MCP server adds a new tool:
`domain-map.json` expresses two things:

**Classes**: What domain objects exist and how they're constructed.

```json
{
"Screen": {
"constructorParams": ["projectId", "screenId"],
"fieldMapping": {
"projectId": { "from": "projectId" },
"screenId": { "from": "id", "fallback": { "field": "name", "splitOn": "/screens/" } }
"screenId": {
"from": "id",
"fallback": { "field": "name", "splitOn": "/screens/" }
}
},
"parentField": "projectId",
"idField": "screenId"
Expand All @@ -66,6 +70,7 @@ When the Stitch MCP server adds a new tool:
```

**Bindings**: How MCP tools map to class methods.

```json
{
"tool": "generate_screen_from_text",
Expand All @@ -74,7 +79,10 @@ When the Stitch MCP server adds a new tool:
"args": {
"projectId": { "from": "self" },
"prompt": { "from": "param" },
"name": { "from": "computed", "template": "projects/{projectId}/screens/{screenId}" }
"name": {
"from": "computed",
"template": "projects/{projectId}/screens/{screenId}"
}
},
"returns": {
"class": "Screen",
Expand All @@ -92,9 +100,13 @@ When the Stitch MCP server adds a new tool:
**Response projections**: Structured `ProjectionStep[]` arrays validated against `outputSchema`. Use `index` for single items, `each` for arrays. Empty `[]` = direct return.

**Cache**: Methods can specify a `cache` with a structured `projection` to check `this.data` before calling the API:

```json
{
"cache": { "projection": [{ "prop": "htmlCode" }, { "prop": "downloadUrl" }], "description": "Use cached download URL from generation response" }
"cache": {
"projection": [{ "prop": "htmlCode" }, { "prop": "downloadUrl" }],
"description": "Use cached download URL from generation response"
}
}
```

Expand All @@ -113,7 +125,7 @@ For AI agents and orchestration scripts. Raw tool pipe. The agent receives tool
The `stitch` singleton exposes both domain methods and tool methods via a `Proxy`. No instantiation needed — it lazily creates a `StitchToolClient` from env vars on first access.

```typescript
import { stitch } from '@google/stitch-sdk';
import { stitch } from "@google/stitch-sdk";

// Discover available tools
const { tools } = await stitch.listTools();
Expand All @@ -135,9 +147,9 @@ The singleton reads `STITCH_API_KEY` (or `STITCH_ACCESS_TOKEN` + `GOOGLE_CLOUD_P
For explicit control (multiple clients, custom config, testing), instantiate `StitchToolClient` directly:

```typescript
import { StitchToolClient } from '@google/stitch-sdk';
import { StitchToolClient } from "@google/stitch-sdk";

const client = new StitchToolClient({ apiKey: 'my-key' });
const client = new StitchToolClient({ apiKey: "my-key" });
const tools = await client.listTools();
const result = await client.callTool("create_project", { title: "My App" });
await client.close();
Expand All @@ -152,13 +164,13 @@ await client.close();
For agents built on the [Vercel AI SDK](https://sdk.vercel.ai/). Transforms MCP tool schemas into AI SDK-compatible tool definitions, enabling plug-and-play with `generateText()`.

```typescript
import { stitchTools } from '@google/stitch-sdk/ai';
import { generateText } from 'ai';
import { google } from '@ai-sdk/google';
import { stitchTools } from "@google/stitch-sdk/ai";
import { generateText } from "ai";
import { google } from "@ai-sdk/google";

const result = await generateText({
model: google("gemini-2.0-flash"),
tools: stitchTools(), // all tools
tools: stitchTools(), // all tools
// or: stitchTools({ include: ["create_project"] }) // filtered
prompt: "Create a project called My App",
});
Expand All @@ -170,9 +182,9 @@ const result = await generateText({

```typescript
const tool = stitch.toolMap.get("create_project");
tool.params; // ToolParam[] — flat, pre-parsed
tool.params.filter(p => p.required); // required params only
tool.inputSchema; // raw ToolInputSchema still available
tool.params; // ToolParam[] — flat, pre-parsed
tool.params.filter((p) => p.required); // required params only
tool.inputSchema; // raw ToolInputSchema still available
```

The raw `toolDefinitions` array and standalone `toolMap` are also exported from the main entry point.
Expand Down Expand Up @@ -228,8 +240,16 @@ The membrane is declared in `domain-map.json` via `sideEffects` on any class wit
"Project": {
"extensionPath": "../../src/project-ext.js",
"sideEffects": [
{ "method": "uploadImage", "reason": "private_rest", "specPath": "src/spec/upload.ts" },
{ "method": "downloadAssets", "reason": "filesystem_io", "specPath": "src/spec/download.ts" }
{
"method": "uploadImage",
"reason": "private_rest",
"specPath": "src/spec/upload.ts"
},
{
"method": "downloadAssets",
"reason": "filesystem_io",
"specPath": "src/spec/download.ts"
}
]
}
}
Expand All @@ -238,6 +258,7 @@ The membrane is declared in `domain-map.json` via `sideEffects` on any class wit
Valid `reason` values: `filesystem_io`, `binary_data`, `private_rest`, `complex_orchestration`.

The generator validates at Stage 3:

1. No `sideEffect.method` collides with a generated binding method name
2. Each `specPath` points to an existing file

Expand All @@ -257,13 +278,13 @@ Follow the Spec → Handler → Extension pattern:

#### Rules

| Rule | Rationale |
|---|---|
| Extension methods must NOT override generated methods | Prevents silent shadowing |
| Extension methods must delegate to a Handler | Prevents inline business logic |
| Handlers must implement a Spec interface | Typed service contract |
| Handlers must return Result, never throw | Consistent error surface |
| Extensions must NOT import from `singleton.ts` | Prevents circular dependencies |
| Rule | Rationale |
| ----------------------------------------------------- | ------------------------------ |
| Extension methods must NOT override generated methods | Prevents silent shadowing |
| Extension methods must delegate to a Handler | Prevents inline business logic |
| Handlers must implement a Spec interface | Typed service contract |
| Handlers must return Result, never throw | Consistent error surface |
| Extensions must NOT import from `singleton.ts` | Prevents circular dependencies |

---

Expand Down Expand Up @@ -323,7 +344,8 @@ Do not rely on cached descriptions of files or directory trees. Read the source.
## Import Convention

Use `.js` extensions for ESM compatibility:

```typescript
import { StitchError } from '../../src/spec/errors.js'; // ✓
import { StitchError } from '../../src/spec/errors'; // ✗
import { StitchError } from "../../src/spec/errors.js"; // ✓
import { StitchError } from "../../src/spec/errors"; // ✗
```
Loading
Loading