用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/majiayu000/claude-skill-registry --skill openapi-schemas命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
LLM token logprobs and calibration. Per-decision confidence, ECE, Brier, reliability diagrams, low-confidence triage.
Analyze LLM token logprobs and calibration. Use for per-decision confidence, ECE, Brier scores, reliability diagrams, and low-confidence triage.
回顾最近 N 天的 Claude Code 使用记录——扫描原始会话数据,按主题分组汇总"我都做了什么",并从个人操作系统视角输出模式、风险与增删建议。当用户说 /recap、"看看我这几天做了什么"、"回顾一下我最近的会话"、"这两天我用 claude 干了啥"、"活动回顾" 时使用。
基于 SOC 职业分类
正在显示 SKILL.md
| name | openapi-schemas |
| description | OpenAPI schema rules 14-24 for response models, nullable handling, and data modeling |
Schema design, response patterns, and data modeling
Response schemas MUST map directly to the main business object, NOT envelope/wrapper objects
# ❌ WRONG - Includes envelope (status, data, meta)
responses:
'200':
schema:
type: object
properties:
status: { type: string }
data: { $ref: '#/components/schemas/User' }
meta: { type: object }
# ✅ CORRECT - Direct reference to main business object
responses:
'200':
schema:
$ref: '#/components/schemas/User'
# ✅ CORRECT - Array of main business objects
responses:
'200':
schema:
type: array
items:
$ref: '#/components/schemas/User'
WHY: Framework handles status/metadata separately. Mappers extract main object from API envelope.
🚨 CRITICAL: NEVER use nullable in api.yml
# ❌ FORBIDDEN
properties:
name:
type: string
nullable: true # NO! Never use nullable
# ✅ CORRECT - Optional without nullable
properties:
name:
type: string # Optional = not in required array
WHY: TypeScript uses | undefined for optional fields. Mappers convert null → undefined.
ALL ID fields MUST use type: string even if external API uses numbers
# ✅ CORRECT
properties:
id: { type: string }
userId: { type: string }
organizationId: { type: string }
# ❌ WRONG
properties:
id: { type: integer } # NO! Always use string
Rationale: IDs are identifiers not quantities - prevents precision/overflow issues.
# ✅ CORRECT - List operation uses plural path
/resources:
get:
operationId: listResources
# ✅ CORRECT - Get operation uses singular path
/resources/{resourceId}:
get:
operationId: getResource
# ❌ WRONG - Mismatch
/resource:
get:
operationId: listResources # List but singular path!
# ✅ CORRECT - Clean resource paths
/users
/users/{userId}
/users/{userId}/repositories
/users/{userId}/repositories/{repositoryId}
# ❌ WRONG - External API style paths
/api/v1/users # NO! No /api/v1 prefix
/{owner}/{repo}/issues # NO! Use /repositories/{repositoryId}/issues
/users/{username}/repos # NO! Use userId not username in path
Rationale: Module creates clean, consistent resource-based paths regardless of external API structure.
# ✅ CORRECT - Nested object uses $ref
properties:
owner:
$ref: '#/components/schemas/User'
repository:
$ref: '#/components/schemas/Repository'
# ❌ WRONG - Inline nested object
properties:
owner:
type: object
properties:
id: { type: string }
name: { type: string }
WHY: Reusability, maintainability, and type safety.
When adding new operations, check if response schemas already exist in the spec. If YES and schemas differ:
# Scenario: Adding "getAccessToken" but "AccessToken" schema exists
# with different structure than new operation needs
# Option 1: Use existing if compatible
responses:
'200':
schema:
$ref: '#/components/schemas/AccessToken'
# Option 2: Create operation-specific schema if incompatible
components:
schemas:
AccessTokenDetails: # New schema for this specific operation
properties:
token: { type: string }
expiresIn: { type: integer }
# ... different from existing AccessToken
WHY: Prevents breaking existing operations when adding new ones.
🚨 CRITICAL: When implementing operations, NEVER modify connectionProfile.yml or connectionState.yml
# ❌ WRONG Flow
1. Implementing getAccessToken operation
2. Notice we need to store refreshToken
3. Add refreshToken to connectionState.yml # NO! STOP!
# ✅ CORRECT Flow
1. Implementing getAccessToken operation
2. Notice we need refreshToken
3. STOP and report: "connectionState needs refreshToken field"
4. User reviews and updates connection schemas
5. Resume operation implementation
WHY: Connection profile changes affect ALL operations. Must be reviewed separately.
CRITICAL: Enum values MUST preserve the semantic meaning from the external API. Case normalization to snake_case is allowed, but semantic transformation is forbidden.
# ✅ CORRECT - Case normalization (ActiveUser → active_user)
status:
type: string
enum: [active_user, suspended_user, inactive_user] # snake_case normalized
x-enum-descriptions:
active_user: User account is active and can be used
suspended_user: User account has been suspended
inactive_user: User account is inactive
# ✅ CORRECT - Original values when already simple
status:
type: string
enum: [A, S, I] # Keep as-is when API uses codes
x-enum-descriptions:
A: Active - Account is active and can be used
S: Suspended - Account has been
[, , ]
[, , ]
[, ]
Allowed transformations:
ActiveUser → active_userPENDING → pendingSuspended-User → suspended_userForbidden transformations:
A → active (code to word)admin → user_admin (adding prefix)active_user → active (removing suffix)inactive → disabled (different word)WHY:
toEnum() default snake_case transformation handles itMapper behavior:
// ✅ GOOD - Case normalization (toEnum default behavior)
// API returns: "ActiveUser"
// Schema has: "active_user"
status: toEnum(UserInfo.StatusEnum, raw.status) // toEnum converts to snake_case
// ✅ GOOD - No transformation needed
// API returns: "active"
// Schema has: "active"
status: toEnum(UserInfo.StatusEnum, raw.status) // Direct match
// ❌ BAD - Semantic transformation required
// API returns: "A"
// Schema has: "active"
status: toEnum(UserInfo.StatusEnum, raw.status, (apiValue: string) => {
const statusMap = { A: 'active', S: 'suspended', I: 'inactive' }; // NO!
return statusMap[apiValue] || 'active';
})
Every response schema property must map to external API field:
# ✅ COMPLETE - All fields documented
User:
properties:
id:
type: string # Maps to: id
name:
type: string # Maps to: display_name
email:
type: string # Maps to: email_address
createdAt:
type: string # Maps to: created_at
When a schema is used in BOTH nested contexts AND as direct response, consider separating:
# ✅ GOOD - Separate Summary and Full schemas
components:
schemas:
UserSummary: # For nested usage (10+ properties)
properties:
id: { type: string }
name: { type: string }
email: { type: string }
User: # For direct response (full details)
allOf:
- $ref: '#/components/schemas/UserSummary'
- properties:
bio: { type: string }
location: { type: string }
# ... 20+ more properties
# Usage:
/users/{userId}:
get:
responses:
'200':
schema:
$ref: '#/components/schemas/User' # Full details
/organizations/{orgId}:
get:
responses:
'200':
schema:
properties:
owner:
$ref: '#/components/schemas/UserSummary' # Nested = summary
WHEN: Schema used in BOTH contexts AND has 10+ properties WHY: Avoids circular references, reduces payload size for nested usage
Before finalizing schemas:
nullable anywhere in api.ymltype: stringThese schema rules ensure clean, reusable, and maintainable data models.
Resource schema naming must be consistent and make sense for the resource.
# ✅ CORRECT - Consistent with resource name
Configuration: # Main resource
properties:
id: { type: string }
name: { type: string }
settings: { type: object }
ConfigurationBase: # Common properties (not returned by API)
properties:
id: { type: string }
name: { type: string }
ConfigurationInfo: # Extended with org context
allOf:
- $ref: '#/components/schemas/Configuration'
- properties:
org: { $ref: '#/components/schemas/OrganizationRef' }
ConfigurationSummary: # Lightweight for nested usage
properties:
id: { type: string }
name: { type: string }
# ❌ WRONG - Non-standard suffixes
ConfigurationDetails: # Invalid - use Configuration or ConfigurationInfo
ConfigurationSettings: # Invalid - 'Settings' not a standard suffix
ConfigurationData: # Invalid - 'Data' not a standard suffix
Rule: If your resource is named Configuration, then ConfigurationInfo, ConfigurationSummary, ConfigurationBase are valid. Stay consistent across the entire API.
Base schemas:
allOf# ✅ CORRECT - Base for composition only
UserBase:
properties:
id: { type: string }
status: { type: string }
User:
allOf:
- $ref: '#/components/schemas/UserBase'
- properties:
email: { type: string }
UserInfo:
allOf:
- $ref: '#/components/schemas/UserBase'
- properties:
org: { $ref: '#/components/schemas/OrganizationRef' }
# ❌ WRONG - Base returned by API
/users/{userId}:
get:
responses:
'200':
schema:
$ref: '#/components/schemas/UserBase' # NO! Use User or UserInfo
components:
schemas:
ResourceBase:
type: object
properties:
id:
type: string
format: uuid
createdAt:
type: string
format: date-time
Resource:
allOf:
- $ref: '#/components/schemas/ResourceBase'
- type: object
properties:
name:
type: string
description:
type: string
When to use: Common properties shared across multiple schemas
# For nested usage (lightweight)
WebhookSummary:
type: object
required: [id, name, active]
properties:
id:
type: string
name:
type: string
active:
type: boolean
# For direct endpoint responses (full details)
Webhook:
allOf:
- $ref: '#/components/schemas/WebhookSummary'
- type: object
properties:
config:
$ref: '#/components/schemas/WebhookConfig'
events:
type: array
items:
type: string
createdAt:
type: string
format: date-time
When to use: Schema used in BOTH nested and direct contexts, 10+ properties
# ❌ WRONG - Inline nested object
Webhook:
type: object
properties:
config:
type: object # NO!
properties:
url: { type: string }
# ✅ CORRECT - Use $ref
Webhook:
type: object
properties:
config:
$ref: '#/components/schemas/WebhookConfig'
WebhookConfig:
type: object
properties:
url:
type: string
format: uri
Always required: ALL nested objects MUST use $ref
properties:
id:
type: string
format: uuid # ✅ For UUIDs
createdAt:
type: string
format: date-time # ✅ For timestamps
website:
type: string
format: uri # ✅ For URLs
email:
type: string
format: email # ✅ For emails
See type-mapping skill for complete format reference.
# No inline schemas in responses
yq eval '.paths.*.*.responses.*.content.*.schema | select(has("properties"))' api.yml
# Should only return $ref or array items
# All nested objects use $ref
grep -A 5 "type: object" api.yml | grep -B 2 "properties:" | grep -v "\$ref"
# Should return minimal matches (only root schemas)
# No nullable usage (CRITICAL)
grep "nullable:" api.yml
# Must return nothing
# WHY: We transform null values to undefined in mappers, not via nullable in schema
# Formats applied
yq eval '.. | select(has("format")) | .format' api.yml
# Should show: uuid, date-time, uri, email
# Check if any schema used in BOTH nested and direct contexts
# Manual review required - look for schemas referenced in multiple places
grep -r "ref.*schemas/User" api.yml
Run these checks before finalizing schemas:
cd package/{vendor}/{service}
# 1. No inline schemas
yq eval '.paths.*.*.responses.*.content.*.schema | select(has("properties"))' api.yml
# 2. No nullable (CRITICAL)
grep "nullable:" api.yml
# Must be empty
# 3. All IDs are strings
yq eval '..| select(.properties.id) | .properties.id.type' api.yml
# All should be "string"
# 4. Nested objects use $ref
grep -A 5 "type: object" api.yml | grep -B 2 "properties:" | grep -v "\$ref"
# Minimal results
# 5. Formats applied
yq eval '.. | select(has("format")) | .format' api.yml | sort | uniq
# Should show format types used
Schema design is complete when: