用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/majiayu000/claude-skill-registry --skill producer-implementation命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 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 | producer-implementation |
| description | Producer implementation patterns for API operations and business logic |
// ❌ WRONG - Duplicating connection context
class UserProducer {
async getUser(
userId: string,
apiKey: string, // NO! In ConnectionProfile
baseUrl: string, // NO! In ConnectionProfile
orgId: string // NO! In ConnectionState
): Promise<User> {
// ...
}
}
// ✅ CORRECT - Only operation-specific parameters
class UserProducer {
constructor(private client: GitHubClient) {}
async getUser(userId: string): Promise<User> {
// Client already has apiKey, baseUrl, orgId from profile/state
const { data } = await this.client.apiClient
.request({
url: `/users/${userId}`, // baseUrl handled by client
method: 'get'
// apiKey/auth handled by client interceptor
// orgId available via this.client.getOrganizationId()
})
.catch(handleAxiosError);
return toUser(data);
}
}
RULES:
WHY: Connection context is established once during connect() and managed by the client. Operations should focus on business logic, not connection details.
class UserProducer {
constructor(private client: GitHubClient) {}
// List operation
async listUsers(
results: PagedResults<User>,
name?: string
): Promise<void> {
const { data } = await this.client.apiClient
.request({
url: '/users',
method: 'get',
params: {
limit: results.pageSize,
page: results.pageNumber,
name
}
})
.catch(handleAxiosError);
// Manual assignment (NOT ingest)
results.items = data.map(toUser) || [];
// Update count if API provides it
if (data.total !== undefined) {
results.count = data.total;
}
}
// Get operation
async getUser(userId: string): Promise<User> {
const { data } = ..
.({
: ,
:
})
.(handleAxiosError);
(data);
}
(: ): <> {
{ data } = ..
.({
: ,
: ,
: input
})
.(handleAxiosError);
(data);
}
(: ): <> {
..
.({
: ,
:
})
.(handleAxiosError);
}
}
any in producer method signaturesresults.items = ...ingest() - Unreliable trimming behaviorresults.count when API provides totalresults.pageToken for token-based paginationpageNumber, pageSize, or pageCountconst output: Type pattern// ✅ REQUIRED PATTERN
export function toUser(data: any): User {
// Validate required fields first
if (!data?.id || !data?.name) {
throw new InvalidInputError('user', 'Missing required fields');
}
const output: User = {
id: map(UUID, data.id), // Required - validated above
name: data.name, // Required - validated above
email: map(Email, data.email), // Optional - returns Email | undefined
website: map(URL, data.website), // Optional - returns URL | undefined
createdAt: map(DateTime, data.created_at)?.toDate() // DateTime requires .toDate()
};
return output;
}
CRITICAL:
! (non-null assertion) - Design code to avoid itmap() over constructors - Use map() from @auditmation/util-hub-module-utils unless map() doesn't meet requirementsType | undefined automaticallymap(DateTime, value)?.toDate() since interface expects Date not DateTime|| undefined or map() which handles this)// ⚠️ AVOID - Using constructors without checking if map() works
export function toUser(data: any): User {
const output: User = {
id: new UUID(data.id), // ⚠️ Try map(UUID, ...) first
email: new Email(data.email), // ⚠️ Try map(Email, ...) first
createdAt: new DateTime(data.created_at).toDate() // ⚠️ Try map(DateTime, ...)?.toDate() first
};
return output;
}
// Only use constructors if map() doesn't meet requirements
🚨 CRITICAL: API spec never uses nullable: true, mappers convert null → undefined
RULE: If external API returns null values, convert them to undefined in mappers.
// ✅ CORRECT - map() automatically converts null → undefined
export function toUser(data: any): User {
const output: User = {
id: map(UUID, data.id), // map() returns undefined if data.id is null
name: data.name || undefined, // Explicit: null → undefined
email: map(Email, data.email), // map() handles null → undefined
website: map(URL, data.website) // map() handles null → undefined
};
return output;
}
// ✅ CORRECT - Explicit conversion for non-map fields
export function toOrganization(data: any): Organization {
const output: Organization = {
id: data.id !== null ? String(data.id) : undefined, // null → undefined
name: data. || ,
: data. ??
};
output;
}
(): {
: = {
: (, data.),
: data.,
: data.
};
output;
}
WHY:
| undefined for optional fields, not | nullnullable: true (keeps it clean)Type | undefined, not Type | nullmap() function behavior:
map(Type, null) → returns undefinedmap(Type, undefined) → returns undefinedmap(Type, value) → returns Type instance or undefined|| undefined on number fields// ❌ WRONG - Turns 0 into undefined
count: data.count || undefined // 0 becomes undefined!
age: data.age || undefined // 0 becomes undefined!
balance: data.balance || undefined // 0 becomes undefined!
// ✅ CORRECT - Preserves 0 values
count: data.count ?? undefined // 0 stays 0, null/undefined → undefined
age: data.age !== null ? data.age : undefined // Explicit null check
balance: data.balance !== undefined ? data.balance : undefined
WHY: 0 || undefined evaluates to undefined because 0 is falsy.
?? undefined (nullish coalescing) for numbers!== null / !== undefined checks|| undefined is ONLY safe for strings, objects, and arraysexport function toUserInfo(data: any): UserInfo {
const output: UserInfo = {
...toUser(data), // Reuse base mapper
lastLogin: map(DateTime, data.last_login)?.toDate(),
permissions: data.permissions || []
};
return output;
}
MANDATORY 3-STEP:
// Interface has 5 fields → Mapper must map 5 fields
interface UserInfo {
id: UUID; // Required
name: string; // Required
email?: Email; // Optional
createdAt: Date; // Required
status?: StatusEnum;// Optional
}
export function toUserInfo(raw: any): UserInfo {
const output: UserInfo = {
// Required (3)
id: map(UUID, raw.id),
name: raw.name,
createdAt: map(Date, raw.created_at),
// Optional (2) - MUST be mapped too
email: map(Email, raw.email),
status: toEnum(StatusEnum, raw.status)
};
return output;
}
🚨 CRITICAL: Mappers MUST throw errors for missing required fields
// ✅ CORRECT - Validate required fields
export function toOrganization(data: any): Organization | undefined {
if (!data) return undefined;
// Required field validation - MUST throw error
if (!data.id && data.id !== 0) {
throw new InvalidInputError('organization', 'Missing required field: id');
}
return {
id: String(data.id),
name: data.name || undefined, // Optional field
};
}
// ❌ WRONG - Silently returning undefined for missing required field
export function toOrganization(data: any): Organization | undefined {
if (!data) return undefined;
if (!data.id) return undefined; // NO! Should throw error
return {
id: String(data.id),
name: data. || ,
};
}
When objects appear in nested contexts and might have incomplete data, the parent mapper handles validation errors:
// Parent mapper catches validation errors from child mappers
export function toTokenScope(data: any): TokenScope {
// Nested org might have null id in some API responses
let org: Organization | undefined;
if (data.org) {
try {
org = toOrganization(data.org); // May throw if id is null
} catch (error) {
// Incomplete nested organization - treat as undefined
org = undefined;
}
}
return {
org,
user: data.user ? toUser(data.user) : undefined,
scope: data.scope || undefined,
};
}
RULE:
🚨 CRITICAL: Enum values MUST be snake_case
STANDARD: All enum values in this codebase use snake_case format.
toEnum(EnumClass, value)toEnum automatically converts input to snake_case (matches our standard)// ✅ CORRECT - Default snake_case transform (PREFERRED)
const status = toEnum(StatusEnum, data.status);
// Input: "ActiveUser" or "active_user" or "ACTIVE_USER" → Converted to "active_user" → Mapped to enum
// This is the standard - use this unless API has special requirements
// ⚠️ RARE - Custom transform only when API doesn't use snake_case
const status = toEnum(StatusEnum, data.status, (val) => val);
// Only use if API truly returns exact enum values in non-snake_case format
// Most APIs return snake_case, so this is rarely needed
// For required enums, validate first
if (!data?.status) {
throw new InvalidInputError('resource', 'Missing status');
}
const status = toEnum(StatusEnum, data.status); // Safe - uses default snake_case
Why snake_case is our standard:
toEnum default behavior aligns with this standardWhen custom transform might be needed (rare):
IMPORTANT: Before using custom transform, verify the API truly doesn't accept snake_case. Most APIs accept multiple formats but prefer snake_case.
function toAddress(data: any): Address | undefined {
if (!data) return undefined;
const output: Address = {
street: data.street,
city: data.city,
country: toCountry(data.country)
};
return output;
}
function toUsers(data: any[]): User[] {
if (!Array.isArray(data)) return [];
return data.map(toUser);
}
function toTreeNode(data: any): TreeNode {
const output: TreeNode = {
id: data.id,
name: data.name,
children: data.children?.map(toTreeNode)
};
return output;
}
# Check producers don't have connection parameters
grep -E "async (get|list|create|update|delete).*\(.*[,\s](apiKey|token|baseUrl|organizationId)" src/*Producer.ts && echo "❌ Producer has connection params!" || echo "✅ Producers clean"
# Check producers use error handler
grep -E "\.catch\(handleAxiosError\)" src/*Producer.ts && echo "✅ Error handling present" || echo "⚠️ Missing error handler"
# Check no Promise<any> in producers
grep -E "Promise<any>" src/*Producer.ts && echo "❌ Found Promise<any>!" || echo "✅ No Promise<any>"
# Check mappers use const output pattern
grep -E "const output: [A-Z]" src/Mappers.ts && echo "✅ Using output pattern" || echo "⚠️ Check mapper pattern"
# Check mappers validate required fields
grep -E "throw new InvalidInputError.*Missing required" src/Mappers.ts && echo "✅ Required field validation present" || echo "⚠️ Check required field validation"
# Check no non-null assertions
grep "!" src/Mappers.ts | grep -v "//" | grep -v "!=" && echo "❌ Found non-null assertions!" || echo "✅ No non-null assertions"
# Check PagedResults uses manual assignment (not ingest)
grep -E "results\.items\s*=" src/*Producer.ts && echo "✅ Manual assignment" || echo "⚠️ Check PagedResults pattern"
# Check no ingest() usage
grep "ingest(" src/*Producer.ts && echo "❌ Found ingest()!" || echo "✅ No ingest()"
See code-comment-style skill for complete guidelines
NEVER comment standard patterns:
// ❌ WRONG - Commenting obvious pagination conversion
// Convert pageNumber/pageSize to offset/limit
if (results.pageNumber && results.pageSize) {
params.offset = (results.pageNumber - 1) * results.pageSize;
params.limit = Math.min(Math.max(results.pageSize, 1), 1000);
}
// ✅ CORRECT - Standard pattern needs no comment
if (results.pageNumber && results.pageSize) {
params.offset = (results.pageNumber - 1) * results.pageSize;
params.limit = Math.min(Math.max(results.pageSize, 1), 1000);
}
// ❌ WRONG - Commenting obvious mapper application
// Apply mappers and set pagination info from response structure
results.items = response.data.data.map(toUser);
results.count = response.data.totalCount || 0;
// ✅ CORRECT - Code is self-documenting
results.items = response.data.data.map(toUser);
results.count = response.data.totalCount || 0;
DO comment non-obvious API behavior:
// ✅ GOOD - Explains API quirk
// API returns user in response.data.data for single gets
// but directly in response.data for list operations
const rawData = response.data.data || response.data;
Reference: See code-comment-style.md for full guidelines