ethan-skill 1.11.0 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +272 -0
- package/README.md +84 -33
- package/dist/agents/index.d.ts +14 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +37 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/orchestrator.d.ts +10 -0
- package/dist/agents/orchestrator.d.ts.map +1 -0
- package/dist/agents/orchestrator.js +233 -0
- package/dist/agents/orchestrator.js.map +1 -0
- package/dist/agents/orchestrator.test.d.ts +2 -0
- package/dist/agents/orchestrator.test.d.ts.map +1 -0
- package/dist/agents/orchestrator.test.js +151 -0
- package/dist/agents/orchestrator.test.js.map +1 -0
- package/dist/agents/presets.d.ts +16 -0
- package/dist/agents/presets.d.ts.map +1 -0
- package/dist/agents/presets.js +123 -0
- package/dist/agents/presets.js.map +1 -0
- package/dist/agents/types.d.ts +29 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +7 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/cli/index.js +1168 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/loader/custom-agent-loader.d.ts +13 -0
- package/dist/loader/custom-agent-loader.d.ts.map +1 -0
- package/dist/loader/custom-agent-loader.js +120 -0
- package/dist/loader/custom-agent-loader.js.map +1 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +278 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/skills/27-tech-debt.d.ts +3 -0
- package/dist/skills/27-tech-debt.d.ts.map +1 -0
- package/dist/skills/27-tech-debt.js +149 -0
- package/dist/skills/27-tech-debt.js.map +1 -0
- package/dist/skills/28-api-mock.d.ts +3 -0
- package/dist/skills/28-api-mock.d.ts.map +1 -0
- package/dist/skills/28-api-mock.js +272 -0
- package/dist/skills/28-api-mock.js.map +1 -0
- package/dist/skills/29-data-migration.d.ts +3 -0
- package/dist/skills/29-data-migration.d.ts.map +1 -0
- package/dist/skills/29-data-migration.js +331 -0
- package/dist/skills/29-data-migration.js.map +1 -0
- package/dist/skills/30-llm-feature.d.ts +3 -0
- package/dist/skills/30-llm-feature.d.ts.map +1 -0
- package/dist/skills/30-llm-feature.js +328 -0
- package/dist/skills/30-llm-feature.js.map +1 -0
- package/dist/skills/31-threat-model.d.ts +3 -0
- package/dist/skills/31-threat-model.d.ts.map +1 -0
- package/dist/skills/31-threat-model.js +240 -0
- package/dist/skills/31-threat-model.js.map +1 -0
- package/dist/skills/32-green-code.d.ts +3 -0
- package/dist/skills/32-green-code.d.ts.map +1 -0
- package/dist/skills/32-green-code.js +346 -0
- package/dist/skills/32-green-code.js.map +1 -0
- package/dist/skills/33-service-catalog.d.ts +3 -0
- package/dist/skills/33-service-catalog.d.ts.map +1 -0
- package/dist/skills/33-service-catalog.js +334 -0
- package/dist/skills/33-service-catalog.js.map +1 -0
- package/dist/skills/34-mobile-review.d.ts +3 -0
- package/dist/skills/34-mobile-review.d.ts.map +1 -0
- package/dist/skills/34-mobile-review.js +390 -0
- package/dist/skills/34-mobile-review.js.map +1 -0
- package/dist/skills/35-data-pipeline.d.ts +3 -0
- package/dist/skills/35-data-pipeline.d.ts.map +1 -0
- package/dist/skills/35-data-pipeline.js +392 -0
- package/dist/skills/35-data-pipeline.js.map +1 -0
- package/dist/skills/36-ml-experiment.d.ts +3 -0
- package/dist/skills/36-ml-experiment.d.ts.map +1 -0
- package/dist/skills/36-ml-experiment.js +415 -0
- package/dist/skills/36-ml-experiment.js.map +1 -0
- package/dist/skills/index.d.ts +10 -0
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +41 -1
- package/dist/skills/index.js.map +1 -1
- package/dist/skills/pipeline.d.ts.map +1 -1
- package/dist/skills/pipeline.js +35 -0
- package/dist/skills/pipeline.js.map +1 -1
- package/dist/skills/skills.test.js +3 -3
- package/dist/skills/skills.test.js.map +1 -1
- package/package.json +1 -1
- package/rules/claude-code/CLAUDE.md +2963 -3
- package/rules/cline/.clinerules +2805 -2
- package/rules/codebuddy/CODEBUDDY.md +2913 -2
- package/rules/continue/.continuerules +2805 -2
- package/rules/copilot/copilot-instructions.md +2883 -2
- package/rules/cursor/.cursorrules +2952 -2
- package/rules/cursor/smart-flow.mdc +2952 -2
- package/rules/jetbrains/smart-flow.md +2883 -2
- package/rules/lingma/smart-flow.md +2904 -3
- package/rules/windsurf/.windsurf/rules/smart-flow.md +2884 -3
- package/rules/zed/smart-flow.rules +2794 -1
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.dataMigrationSkill = void 0;
|
|
4
|
+
exports.dataMigrationSkill = {
|
|
5
|
+
id: 'data-migration',
|
|
6
|
+
name: '数据迁移助手',
|
|
7
|
+
nameEn: 'data_migration',
|
|
8
|
+
order: 29,
|
|
9
|
+
description: '评估迁移风险,生成 UP/DOWN 双向脚本,制定零停机迁移与回滚方案',
|
|
10
|
+
descriptionEn: 'Assess migration risks, generate bidirectional UP/DOWN scripts, design zero-downtime migration and rollback plans',
|
|
11
|
+
detailDescription: `数据迁移是研发中风险最高的操作之一:一旦出错可能导致数据丢失或服务中断。
|
|
12
|
+
本 Skill 提供系统化的迁移方法论:从评估阶段的风险识别,到生成双向迁移脚本,
|
|
13
|
+
再到零停机迁移的"扩列→双写→切流→清旧"四步法,每个环节都有完整的验证与回滚手段,
|
|
14
|
+
让数据迁移从"胆战心惊"变为"有序可控"。`,
|
|
15
|
+
triggers: [
|
|
16
|
+
'数据迁移',
|
|
17
|
+
'data migration',
|
|
18
|
+
'schema migration',
|
|
19
|
+
'db migration',
|
|
20
|
+
'数据库迁移',
|
|
21
|
+
'migrate database',
|
|
22
|
+
'migration script',
|
|
23
|
+
'迁移脚本',
|
|
24
|
+
'@ethan data-migration',
|
|
25
|
+
'/data-migration',
|
|
26
|
+
],
|
|
27
|
+
steps: [
|
|
28
|
+
{
|
|
29
|
+
title: '1. 迁移评估',
|
|
30
|
+
content: `在编写任何脚本之前,先全面评估迁移的范围和风险:
|
|
31
|
+
|
|
32
|
+
**评估清单**
|
|
33
|
+
|
|
34
|
+
| 维度 | 问题 | 影响 |
|
|
35
|
+
|------|------|------|
|
|
36
|
+
| **数据量** | 涉及多少行/多少 GB? | 决定迁移时长和窗口 |
|
|
37
|
+
| **Schema 变更** | 新增/修改/删除了哪些列? | 影响向后兼容性 |
|
|
38
|
+
| **外键约束** | 是否有级联影响? | 需要临时禁用约束 |
|
|
39
|
+
| **业务流量** | 高峰期 QPS 是多少? | 影响迁移策略选择 |
|
|
40
|
+
| **停机容忍** | 是否接受停机?接受多长? | 决定是否需要零停机方案 |
|
|
41
|
+
| **数据一致性** | 允许最终一致性还是强一致? | 影响双写策略 |
|
|
42
|
+
|
|
43
|
+
**Schema 变更对比**
|
|
44
|
+
\`\`\`sql
|
|
45
|
+
-- 变更前
|
|
46
|
+
CREATE TABLE users (
|
|
47
|
+
id BIGINT PRIMARY KEY,
|
|
48
|
+
username VARCHAR(50),
|
|
49
|
+
created_at TIMESTAMP
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
-- 变更后(新增 email 列,重命名 username → name)
|
|
53
|
+
CREATE TABLE users (
|
|
54
|
+
id BIGINT PRIMARY KEY,
|
|
55
|
+
name VARCHAR(100), -- 原 username,扩大长度
|
|
56
|
+
email VARCHAR(255), -- 新增,NOT NULL 需要默认值
|
|
57
|
+
created_at TIMESTAMP,
|
|
58
|
+
updated_at TIMESTAMP -- 新增审计列
|
|
59
|
+
);
|
|
60
|
+
\`\`\`
|
|
61
|
+
|
|
62
|
+
**停机时间估算**
|
|
63
|
+
\`\`\`
|
|
64
|
+
数据行数: 5,000,000
|
|
65
|
+
迁移速度: ~10,000 行/秒(受磁盘 IO 限制)
|
|
66
|
+
估算时长: 5,000,000 ÷ 10,000 = 500 秒 ≈ 8.3 分钟
|
|
67
|
+
建议窗口: 低峰期(凌晨 2:00-4:00)
|
|
68
|
+
\`\`\`
|
|
69
|
+
|
|
70
|
+
**输出**:迁移评估报告(范围 + 风险 + 时长估算 + 策略选择)`,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
title: '2. 迁移脚本生成(UP/DOWN)',
|
|
74
|
+
content: `生成可逆的双向迁移脚本:
|
|
75
|
+
|
|
76
|
+
**Knex.js 迁移模板(Node.js)**
|
|
77
|
+
\`\`\`typescript
|
|
78
|
+
// migrations/20240115_add_email_rename_username.ts
|
|
79
|
+
import { Knex } from 'knex';
|
|
80
|
+
|
|
81
|
+
export async function up(knex: Knex): Promise<void> {
|
|
82
|
+
await knex.schema.alterTable('users', (table) => {
|
|
83
|
+
// 1. 新增列(先加,允许 NULL,稍后回填)
|
|
84
|
+
table.string('name', 100).nullable();
|
|
85
|
+
table.string('email', 255).nullable();
|
|
86
|
+
table.timestamp('updated_at').nullable();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// 2. 数据回填(分批处理,避免锁表)
|
|
90
|
+
const BATCH_SIZE = 1000;
|
|
91
|
+
let offset = 0;
|
|
92
|
+
while (true) {
|
|
93
|
+
const rows = await knex('users')
|
|
94
|
+
.select('id', 'username')
|
|
95
|
+
.limit(BATCH_SIZE)
|
|
96
|
+
.offset(offset);
|
|
97
|
+
if (rows.length === 0) break;
|
|
98
|
+
|
|
99
|
+
await knex('users')
|
|
100
|
+
.whereIn('id', rows.map((r) => r.id))
|
|
101
|
+
.update((row: any) => ({ name: row.username }));
|
|
102
|
+
|
|
103
|
+
offset += BATCH_SIZE;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// 3. 添加约束
|
|
107
|
+
await knex.schema.alterTable('users', (table) => {
|
|
108
|
+
table.string('name', 100).notNullable().alter();
|
|
109
|
+
table.dropColumn('username'); // 危险操作!确认数据回填完成后执行
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export async function down(knex: Knex): Promise<void> {
|
|
114
|
+
// 回滚:恢复 username 列
|
|
115
|
+
await knex.schema.alterTable('users', (table) => {
|
|
116
|
+
table.string('username', 50).nullable();
|
|
117
|
+
table.dropColumn('name');
|
|
118
|
+
table.dropColumn('email');
|
|
119
|
+
table.dropColumn('updated_at');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// 回填 username(从备份表恢复)
|
|
123
|
+
await knex.raw('UPDATE users u JOIN users_backup b ON u.id = b.id SET u.username = b.username');
|
|
124
|
+
}
|
|
125
|
+
\`\`\`
|
|
126
|
+
|
|
127
|
+
**Flyway SQL 迁移模板**
|
|
128
|
+
\`\`\`sql
|
|
129
|
+
-- V20240115__add_email_rename_username.sql
|
|
130
|
+
BEGIN;
|
|
131
|
+
|
|
132
|
+
-- 阶段1:新增列
|
|
133
|
+
ALTER TABLE users ADD COLUMN name VARCHAR(100);
|
|
134
|
+
ALTER TABLE users ADD COLUMN email VARCHAR(255);
|
|
135
|
+
ALTER TABLE users ADD COLUMN updated_at TIMESTAMP DEFAULT NOW();
|
|
136
|
+
|
|
137
|
+
-- 阶段2:数据回填
|
|
138
|
+
UPDATE users SET name = username WHERE name IS NULL;
|
|
139
|
+
|
|
140
|
+
-- 阶段3:添加约束(回填完成后)
|
|
141
|
+
ALTER TABLE users ALTER COLUMN name SET NOT NULL;
|
|
142
|
+
CREATE INDEX CONCURRENTLY idx_users_email ON users(email);
|
|
143
|
+
|
|
144
|
+
COMMIT;
|
|
145
|
+
\`\`\`
|
|
146
|
+
|
|
147
|
+
**输出**:可执行的 UP/DOWN 迁移脚本`,
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
title: '3. 数据验证策略',
|
|
151
|
+
content: `迁移前后必须验证数据完整性:
|
|
152
|
+
|
|
153
|
+
**三阶段验证**
|
|
154
|
+
|
|
155
|
+
**① 迁移前基线(Baseline)**
|
|
156
|
+
\`\`\`sql
|
|
157
|
+
-- 记录迁移前状态
|
|
158
|
+
CREATE TABLE migration_baseline AS
|
|
159
|
+
SELECT
|
|
160
|
+
COUNT(*) as total_rows,
|
|
161
|
+
COUNT(DISTINCT id) as unique_ids,
|
|
162
|
+
SUM(CASE WHEN email IS NOT NULL THEN 1 ELSE 0 END) as non_null_email,
|
|
163
|
+
MD5(STRING_AGG(id::text, ',' ORDER BY id)) as row_checksum
|
|
164
|
+
FROM users;
|
|
165
|
+
\`\`\`
|
|
166
|
+
|
|
167
|
+
**② 迁移后验证(Post-Migration)**
|
|
168
|
+
\`\`\`sql
|
|
169
|
+
-- 行数对比
|
|
170
|
+
SELECT
|
|
171
|
+
(SELECT COUNT(*) FROM users) as after_count,
|
|
172
|
+
(SELECT total_rows FROM migration_baseline) as before_count,
|
|
173
|
+
(SELECT COUNT(*) FROM users) - (SELECT total_rows FROM migration_baseline) as diff;
|
|
174
|
+
|
|
175
|
+
-- 关键字段空值检查
|
|
176
|
+
SELECT COUNT(*) as null_names FROM users WHERE name IS NULL;
|
|
177
|
+
SELECT COUNT(*) as null_emails FROM users WHERE email IS NULL;
|
|
178
|
+
|
|
179
|
+
-- 数据一致性抽样(对比10%数据)
|
|
180
|
+
SELECT u.id, u.name, b.username
|
|
181
|
+
FROM users u
|
|
182
|
+
JOIN users_backup b ON u.id = b.id
|
|
183
|
+
WHERE u.name != b.username
|
|
184
|
+
LIMIT 100;
|
|
185
|
+
\`\`\`
|
|
186
|
+
|
|
187
|
+
**③ 业务验证(Smoke Test)**
|
|
188
|
+
\`\`\`bash
|
|
189
|
+
# 验证核心业务接口
|
|
190
|
+
curl -X POST /api/auth/login -d '{"email":"test@example.com","password":"xxx"}'
|
|
191
|
+
curl -X GET /api/users/1
|
|
192
|
+
curl -X POST /api/orders -d '{"userId":1,"items":[...]}'
|
|
193
|
+
\`\`\`
|
|
194
|
+
|
|
195
|
+
**验证通过标准**
|
|
196
|
+
- [ ] 行数差异为 0(或符合预期的新增/删除)
|
|
197
|
+
- [ ] 关键字段 NULL 率为 0
|
|
198
|
+
- [ ] 数据抽样一致性 100%
|
|
199
|
+
- [ ] Smoke Test 全部通过
|
|
200
|
+
- [ ] 数据库慢查询无异常增加
|
|
201
|
+
|
|
202
|
+
**输出**:验证脚本套件 + 通过标准 Checklist`,
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
title: '4. 回滚方案',
|
|
206
|
+
content: `制定多层次回滚机制,确保任何阶段都可以安全撤退:
|
|
207
|
+
|
|
208
|
+
**三级回滚策略**
|
|
209
|
+
|
|
210
|
+
**Level 1:脚本级回滚(最快,< 5 分钟)**
|
|
211
|
+
\`\`\`bash
|
|
212
|
+
# 直接执行 DOWN 脚本
|
|
213
|
+
npx knex migrate:down
|
|
214
|
+
# 或
|
|
215
|
+
flyway undo
|
|
216
|
+
\`\`\`
|
|
217
|
+
适用条件:迁移后立即发现问题,数据量小
|
|
218
|
+
|
|
219
|
+
**Level 2:备份恢复(中速,5-30 分钟)**
|
|
220
|
+
\`\`\`bash
|
|
221
|
+
# 迁移前创建备份(必须!)
|
|
222
|
+
pg_dump -h $DB_HOST -U $DB_USER -d $DB_NAME \
|
|
223
|
+
--table=users \
|
|
224
|
+
-f backup_users_$(date +%Y%m%d_%H%M%S).sql
|
|
225
|
+
|
|
226
|
+
# 恢复
|
|
227
|
+
psql -h $DB_HOST -U $DB_USER -d $DB_NAME < backup_users_20240115_020000.sql
|
|
228
|
+
\`\`\`
|
|
229
|
+
|
|
230
|
+
**Level 3:蓝绿数据库(最可靠,但成本高)**
|
|
231
|
+
\`\`\`
|
|
232
|
+
Green DB(新)→ 迁移成功 → 流量切到 Green
|
|
233
|
+
Blue DB(旧)→ 保留 72 小时 → 确认无问题后关闭
|
|
234
|
+
\`\`\`
|
|
235
|
+
|
|
236
|
+
**回滚决策树**
|
|
237
|
+
\`\`\`
|
|
238
|
+
迁移执行中...
|
|
239
|
+
├── 数据验证失败?
|
|
240
|
+
│ └── YES → 立即执行 Level 1 回滚(DOWN 脚本)
|
|
241
|
+
├── 业务 Smoke Test 失败?
|
|
242
|
+
│ └── YES → Level 1 回滚 → 分析根因
|
|
243
|
+
└── 迁移后 24 小时内发现数据异常?
|
|
244
|
+
└── YES → Level 2 回滚(备份恢复)→ 通知用户
|
|
245
|
+
\`\`\`
|
|
246
|
+
|
|
247
|
+
**输出**:多级回滚方案 + 回滚决策树 + 备份命令`,
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
title: '5. 零停机迁移四步法',
|
|
251
|
+
content: `对于无法停机的生产系统,使用"扩列→双写→切流→清旧"四步法:
|
|
252
|
+
|
|
253
|
+
**背景**:将 \`username\` 列重命名为 \`name\`,同时新增 \`email\` 列
|
|
254
|
+
|
|
255
|
+
**Step 1:扩列(向后兼容)**
|
|
256
|
+
\`\`\`sql
|
|
257
|
+
-- 新增 name 和 email 列,保留 username(双列共存)
|
|
258
|
+
ALTER TABLE users ADD COLUMN name VARCHAR(100);
|
|
259
|
+
ALTER TABLE users ADD COLUMN email VARCHAR(255);
|
|
260
|
+
-- 应用代码:只读 username,不写 name(暂不变更代码)
|
|
261
|
+
\`\`\`
|
|
262
|
+
|
|
263
|
+
**Step 2:双写 + 数据回填**
|
|
264
|
+
\`\`\`typescript
|
|
265
|
+
// 应用代码更新:同时写入 username 和 name
|
|
266
|
+
await db.users.update({
|
|
267
|
+
where: { id },
|
|
268
|
+
data: {
|
|
269
|
+
username: newName, // 旧列
|
|
270
|
+
name: newName, // 新列(同步写入)
|
|
271
|
+
email: email,
|
|
272
|
+
},
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
// 异步回填历史数据(后台任务,不影响主流程)
|
|
276
|
+
async function backfillNames() {
|
|
277
|
+
let cursor = 0;
|
|
278
|
+
while (true) {
|
|
279
|
+
const rows = await db.users.findMany({
|
|
280
|
+
where: { name: null },
|
|
281
|
+
take: 1000,
|
|
282
|
+
});
|
|
283
|
+
if (rows.length === 0) break;
|
|
284
|
+
await db.users.updateMany({
|
|
285
|
+
where: { id: { in: rows.map(r => r.id) } },
|
|
286
|
+
data: rows.map(r => ({ name: r.username })),
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
\`\`\`
|
|
291
|
+
|
|
292
|
+
**Step 3:切流(读取切换到新列)**
|
|
293
|
+
\`\`\`typescript
|
|
294
|
+
// 确认回填完成后,切换读取源
|
|
295
|
+
// 应用代码:读 name,写 name(不再写 username)
|
|
296
|
+
const user = await db.users.findUnique({
|
|
297
|
+
select: { id: true, name: true, email: true }, // 不再 select username
|
|
298
|
+
});
|
|
299
|
+
\`\`\`
|
|
300
|
+
|
|
301
|
+
**Step 4:清旧(移除废弃列)**
|
|
302
|
+
\`\`\`sql
|
|
303
|
+
-- 确认应用代码已完全切换(观察 1-2 周)
|
|
304
|
+
ALTER TABLE users DROP COLUMN username;
|
|
305
|
+
-- 观察指标:慢查询、错误日志中是否有 username 相关错误
|
|
306
|
+
\`\`\`
|
|
307
|
+
|
|
308
|
+
**关键时间线**
|
|
309
|
+
\`\`\`
|
|
310
|
+
Day 0: Step 1(扩列)→ 部署新版本(双写)
|
|
311
|
+
Day 1: Step 2(确认双写正常,后台回填完成)
|
|
312
|
+
Day 3: Step 3(切换读取到新列)→ 部署
|
|
313
|
+
Day 14: Step 4(确认无问题,删除旧列)
|
|
314
|
+
\`\`\`
|
|
315
|
+
|
|
316
|
+
**输出**:零停机迁移四步代码示例 + 时间线 + 监控指标`,
|
|
317
|
+
},
|
|
318
|
+
],
|
|
319
|
+
outputFormat: '迁移评估报告 + UP/DOWN 迁移脚本 + 数据验证 SQL 套件 + 多级回滚方案 + 零停机迁移四步代码示例',
|
|
320
|
+
examples: [],
|
|
321
|
+
notes: [
|
|
322
|
+
'数据迁移前必须备份,无论多紧急。备份是回滚的最后防线',
|
|
323
|
+
'分批处理大表(BATCH_SIZE = 1000-5000),避免长事务和表锁',
|
|
324
|
+
'生产迁移应先在测试环境全流程演练,记录实际耗时',
|
|
325
|
+
'零停机迁移每个步骤之间至少观察 24 小时,确认监控指标正常再进行下一步',
|
|
326
|
+
'DROP COLUMN 是不可逆操作,在确认切换完成前绝对不要执行',
|
|
327
|
+
],
|
|
328
|
+
category: '执行侧',
|
|
329
|
+
nextSkill: 'database-optimize',
|
|
330
|
+
};
|
|
331
|
+
//# sourceMappingURL=29-data-migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"29-data-migration.js","sourceRoot":"","sources":["../../src/skills/29-data-migration.ts"],"names":[],"mappings":";;;AAEa,QAAA,kBAAkB,GAAoB;IACjD,EAAE,EAAE,gBAAgB;IACpB,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,gBAAgB;IACxB,KAAK,EAAE,EAAE;IACT,WAAW,EAAE,qCAAqC;IAClD,aAAa,EAAE,mHAAmH;IAClI,iBAAiB,EAAE;;;sBAGC;IACpB,QAAQ,EAAE;QACR,MAAM;QACN,gBAAgB;QAChB,kBAAkB;QAClB,cAAc;QACd,OAAO;QACP,kBAAkB;QAClB,kBAAkB;QAClB,MAAM;QACN,uBAAuB;QACvB,iBAAiB;KAClB;IACD,KAAK,EAAE;QACL;YACE,KAAK,EAAE,SAAS;YAChB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qCAwCsB;SAChC;QACD;YACE,KAAK,EAAE,oBAAoB;YAC3B,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAyEU;SACpB;QACD;YACE,KAAK,EAAE,WAAW;YAClB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+BAmDgB;SAC1B;QACD;YACE,KAAK,EAAE,SAAS;YAChB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BAyCc;SACxB;QACD;YACE,KAAK,EAAE,aAAa;YACpB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAiEiB;SAC3B;KACF;IACD,YAAY,EAAE,4DAA4D;IAC1E,QAAQ,EAAE,EAAE;IACZ,KAAK,EAAE;QACL,4BAA4B;QAC5B,yCAAyC;QACzC,yBAAyB;QACzB,sCAAsC;QACtC,mCAAmC;KACpC;IACD,QAAQ,EAAE,KAAK;IACf,SAAS,EAAE,mBAAmB;CAC/B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"30-llm-feature.d.ts","sourceRoot":"","sources":["../../src/skills/30-llm-feature.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,eAAO,MAAM,eAAe,EAAE,eAmU7B,CAAC"}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.llmFeatureSkill = void 0;
|
|
4
|
+
exports.llmFeatureSkill = {
|
|
5
|
+
id: 'llm-feature',
|
|
6
|
+
name: 'LLM 功能设计助手',
|
|
7
|
+
nameEn: 'llm_feature',
|
|
8
|
+
order: 30,
|
|
9
|
+
description: '设计 RAG/Agent/生成类 LLM 功能,输出 Prompt 模板、评估框架与降级方案',
|
|
10
|
+
descriptionEn: 'Design RAG/Agent/generation LLM features with prompt templates, evaluation framework and fallback strategies',
|
|
11
|
+
detailDescription: `将 LLM 集成到产品中远不止调用 API——需要精心的架构设计、Prompt 工程和评估体系。
|
|
12
|
+
本 Skill 覆盖 LLM 功能设计全链路:从场景分类(RAG/Agent/生成/分类/提取)到 RAG 架构选型、
|
|
13
|
+
Prompt 工程规范,再到自动化评估框架和降级安全策略,
|
|
14
|
+
让 AI 功能既好用又可靠,避免幻觉、成本失控和不当内容。`,
|
|
15
|
+
triggers: [
|
|
16
|
+
'llm feature',
|
|
17
|
+
'ai feature',
|
|
18
|
+
'rag',
|
|
19
|
+
'llm 功能',
|
|
20
|
+
'ai 功能设计',
|
|
21
|
+
'prompt design',
|
|
22
|
+
'大模型功能',
|
|
23
|
+
'agent 设计',
|
|
24
|
+
'@ethan llm-feature',
|
|
25
|
+
'/llm-feature',
|
|
26
|
+
],
|
|
27
|
+
steps: [
|
|
28
|
+
{
|
|
29
|
+
title: '1. LLM 功能定位与场景分类',
|
|
30
|
+
content: `明确 LLM 功能的类型和边界,选择合适的架构模式:
|
|
31
|
+
|
|
32
|
+
**五大 LLM 场景类型**
|
|
33
|
+
|
|
34
|
+
| 场景 | 描述 | 典型案例 | 推荐架构 |
|
|
35
|
+
|------|------|---------|---------|
|
|
36
|
+
| **RAG(检索增强生成)** | 基于私有知识库回答 | 内部文档问答、客服 | 向量检索 + LLM |
|
|
37
|
+
| **Agent(自主决策)** | 多步骤工具调用 | 代码 Agent、任务自动化 | LLM + Function Calling |
|
|
38
|
+
| **生成** | 创作/摘要/翻译 | 文案生成、会议纪要 | 直接调用 + 结构化输出 |
|
|
39
|
+
| **分类** | 意图/情感/标签 | 工单分类、评论分析 | Fine-tune 或 Few-shot |
|
|
40
|
+
| **提取** | 信息抽取/NER | 合同关键信息、表单填充 | Structured Output + JSON Schema |
|
|
41
|
+
|
|
42
|
+
**功能定位问卷**
|
|
43
|
+
\`\`\`
|
|
44
|
+
1. 用户问题的答案在哪里?
|
|
45
|
+
- 模型已知知识 → 直接生成
|
|
46
|
+
- 私有文档/数据库 → RAG 架构
|
|
47
|
+
- 需要实时操作 → Agent 架构
|
|
48
|
+
|
|
49
|
+
2. 需要多步推理吗?
|
|
50
|
+
- 是 → Agent(工具调用链)
|
|
51
|
+
- 否 → 单次 Prompt
|
|
52
|
+
|
|
53
|
+
3. 输出格式是否严格?
|
|
54
|
+
- 是 → JSON Mode / Structured Output
|
|
55
|
+
- 否 → 自然语言生成
|
|
56
|
+
|
|
57
|
+
4. 延迟要求?
|
|
58
|
+
- < 500ms → 小模型 + 缓存
|
|
59
|
+
- < 3s → 标准调用
|
|
60
|
+
- 可接受流式 → 流式输出
|
|
61
|
+
\`\`\`
|
|
62
|
+
|
|
63
|
+
**输出**:LLM 功能定位文档(场景类型 + 架构选型建议)`,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
title: '2. RAG 架构设计',
|
|
67
|
+
content: `为知识库问答类功能设计高质量 RAG 架构:
|
|
68
|
+
|
|
69
|
+
**RAG 核心组件**
|
|
70
|
+
\`\`\`
|
|
71
|
+
文档摄入管道:
|
|
72
|
+
Raw Docs → Chunking → Embedding → Vector Store
|
|
73
|
+
↓
|
|
74
|
+
Metadata 过滤层(时间/来源/权限)
|
|
75
|
+
|
|
76
|
+
查询管道:
|
|
77
|
+
User Query → Query 改写/扩展 → 向量检索 → Rerank → LLM 生成
|
|
78
|
+
\`\`\`
|
|
79
|
+
|
|
80
|
+
**Chunking 策略选型**
|
|
81
|
+
\`\`\`typescript
|
|
82
|
+
// 固定大小(适合均匀文本)
|
|
83
|
+
const CHUNK_SIZE = 512; // tokens
|
|
84
|
+
const CHUNK_OVERLAP = 50; // 上下文保留
|
|
85
|
+
|
|
86
|
+
// 语义分块(适合结构化文档,推荐)
|
|
87
|
+
// 按段落/标题边界切分
|
|
88
|
+
function semanticChunk(text: string): string[] {
|
|
89
|
+
return text.split(/\n#{1,3}\s/); // Markdown 标题分块
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// 递归分块(LangChain RecursiveCharacterTextSplitter)
|
|
93
|
+
// 优先按段落 → 句子 → 词语拆分
|
|
94
|
+
\`\`\`
|
|
95
|
+
|
|
96
|
+
**向量库选型矩阵**
|
|
97
|
+
| 方案 | 适用规模 | 托管 | 特性 |
|
|
98
|
+
|------|---------|------|------|
|
|
99
|
+
| **Pinecone** | 100万+ | 云托管 | 生产级,自动扩容 |
|
|
100
|
+
| **Weaviate** | 中大型 | 自托管/云 | 混合搜索,GraphQL |
|
|
101
|
+
| **Chroma** | 开发/小型 | 本地 | 零配置,适合 PoC |
|
|
102
|
+
| **pgvector** | 中型 | PostgreSQL | 复用现有 DB |
|
|
103
|
+
|
|
104
|
+
**Rerank 优化**
|
|
105
|
+
\`\`\`typescript
|
|
106
|
+
// 两阶段检索:向量粗召回 → 精排重排序
|
|
107
|
+
const candidates = await vectorStore.search(query, { topK: 20 });
|
|
108
|
+
const reranked = await rerankModel.rank(query, candidates, { topN: 5 });
|
|
109
|
+
// 推荐:Cohere Rerank / BGE-Reranker
|
|
110
|
+
\`\`\`
|
|
111
|
+
|
|
112
|
+
**输出**:RAG 架构图 + Chunking 策略 + 向量库选型建议`,
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
title: '3. Prompt 工程规范',
|
|
116
|
+
content: `制定高质量 Prompt 的设计规范:
|
|
117
|
+
|
|
118
|
+
**System Prompt 黄金结构**
|
|
119
|
+
\`\`\`
|
|
120
|
+
[角色定义] 你是 {产品名} 的 {角色},专注于 {领域}。
|
|
121
|
+
[能力边界] 你可以 {能力列表}。你不能/不应该 {限制列表}。
|
|
122
|
+
[输出格式] 请按照以下格式回复:{格式规范}
|
|
123
|
+
[行为准则] {特定规则,如:始终用中文回复/引用来源}
|
|
124
|
+
\`\`\`
|
|
125
|
+
|
|
126
|
+
**System Prompt 模板**
|
|
127
|
+
\`\`\`typescript
|
|
128
|
+
const SYSTEM_PROMPT = \`
|
|
129
|
+
你是 Acme Corp 的智能客服助手,专注于解答产品使用和技术支持问题。
|
|
130
|
+
|
|
131
|
+
## 能力
|
|
132
|
+
- 查询订单状态、退换货政策、产品规格
|
|
133
|
+
- 引导用户完成常见操作流程
|
|
134
|
+
- 基于知识库提供准确答案
|
|
135
|
+
|
|
136
|
+
## 限制
|
|
137
|
+
- 不讨论竞争对手产品
|
|
138
|
+
- 不提供具体价格承诺(引导至销售团队)
|
|
139
|
+
- 不确定时明确说明,不猜测
|
|
140
|
+
|
|
141
|
+
## 输出规范
|
|
142
|
+
- 语言:与用户保持一致(中/英文)
|
|
143
|
+
- 长度:简洁清晰,避免超过 200 字
|
|
144
|
+
- 引用:若基于文档回答,在末尾标注 [来源:{文档名}]
|
|
145
|
+
\`.trim();
|
|
146
|
+
\`\`\`
|
|
147
|
+
|
|
148
|
+
**Few-shot 示例设计**
|
|
149
|
+
\`\`\`typescript
|
|
150
|
+
const FEW_SHOT_EXAMPLES = [
|
|
151
|
+
{
|
|
152
|
+
role: 'user',
|
|
153
|
+
content: '我的订单 #12345 什么时候发货?'
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
role: 'assistant',
|
|
157
|
+
content: '您好!根据订单信息,#12345 已于昨天完成备货,预计今日发出,3-5个工作日送达。[来源:订单管理文档]'
|
|
158
|
+
}
|
|
159
|
+
];
|
|
160
|
+
\`\`\`
|
|
161
|
+
|
|
162
|
+
**关键参数建议**
|
|
163
|
+
\`\`\`typescript
|
|
164
|
+
// 不同场景的推荐参数
|
|
165
|
+
const PARAMS = {
|
|
166
|
+
factual_qa: { temperature: 0.1, max_tokens: 500 }, // 事实问答,低随机性
|
|
167
|
+
creative: { temperature: 0.8, max_tokens: 2000 }, // 创意生成
|
|
168
|
+
classification:{ temperature: 0, max_tokens: 50 }, // 分类,确定性输出
|
|
169
|
+
code_gen: { temperature: 0.2, max_tokens: 4000 }, // 代码生成
|
|
170
|
+
};
|
|
171
|
+
\`\`\`
|
|
172
|
+
|
|
173
|
+
**Token 预算管理**
|
|
174
|
+
\`\`\`
|
|
175
|
+
System Prompt: ~500 tokens (固定)
|
|
176
|
+
RAG Context: ~2000 tokens (动态,按相关度截断)
|
|
177
|
+
Conversation: ~1000 tokens (保留最近 N 轮)
|
|
178
|
+
User Query: ~200 tokens (预留)
|
|
179
|
+
Output: ~1000 tokens (max_tokens 控制)
|
|
180
|
+
总计: ~4700 tokens < 8K context window
|
|
181
|
+
\`\`\`
|
|
182
|
+
|
|
183
|
+
**输出**:System Prompt 模板 + Few-shot 示例 + 参数配置建议`,
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
title: '4. LLM 评估方案',
|
|
187
|
+
content: `建立自动化 + 人工评估体系,持续监控 LLM 功能质量:
|
|
188
|
+
|
|
189
|
+
**三层评估框架**
|
|
190
|
+
|
|
191
|
+
**① 自动化 Evals(CI/CD 集成)**
|
|
192
|
+
\`\`\`typescript
|
|
193
|
+
// 评估维度
|
|
194
|
+
interface EvalResult {
|
|
195
|
+
accuracy: number; // 答案正确率(对比 Golden Set)
|
|
196
|
+
faithfulness: number; // 回答与上下文一致性(RAG 专用)
|
|
197
|
+
relevance: number; // 答案与问题相关度
|
|
198
|
+
latency_p95: number; // P95 响应时间(ms)
|
|
199
|
+
cost_per_query: number; // 平均 token 成本($)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// 自动评估示例(LLM-as-Judge)
|
|
203
|
+
async function evalWithLLM(question: string, answer: string, context: string) {
|
|
204
|
+
const judgePrompt = \`
|
|
205
|
+
问题:\${question}
|
|
206
|
+
检索上下文:\${context}
|
|
207
|
+
模型回答:\${answer}
|
|
208
|
+
|
|
209
|
+
请评估回答的准确性(0-1)和忠实度(0-1),返回 JSON:
|
|
210
|
+
{"accuracy": 0.x, "faithfulness": 0.x, "reason": "..."}
|
|
211
|
+
\`;
|
|
212
|
+
return await llm.json(judgePrompt);
|
|
213
|
+
}
|
|
214
|
+
\`\`\`
|
|
215
|
+
|
|
216
|
+
**② Golden Set 维护**
|
|
217
|
+
\`\`\`json
|
|
218
|
+
// evals/golden-set.json
|
|
219
|
+
[
|
|
220
|
+
{
|
|
221
|
+
"id": "Q001",
|
|
222
|
+
"question": "退货政策是什么?",
|
|
223
|
+
"expected_keywords": ["30天", "unopened", "退款"],
|
|
224
|
+
"expected_source": "return-policy.md",
|
|
225
|
+
"difficulty": "easy"
|
|
226
|
+
}
|
|
227
|
+
]
|
|
228
|
+
\`\`\`
|
|
229
|
+
|
|
230
|
+
**③ 人工评分(A/B 测试)**
|
|
231
|
+
\`\`\`
|
|
232
|
+
评分维度(1-5分):
|
|
233
|
+
- Helpful(有帮助): 回答解决了用户问题
|
|
234
|
+
- Accurate(准确): 信息与事实一致
|
|
235
|
+
- Safe(安全): 无有害/不当内容
|
|
236
|
+
- Concise(简洁): 无冗余信息
|
|
237
|
+
\`\`\`
|
|
238
|
+
|
|
239
|
+
**评估指标基准**
|
|
240
|
+
| 指标 | 可接受 | 良好 | 优秀 |
|
|
241
|
+
|------|--------|------|------|
|
|
242
|
+
| 准确率 | > 70% | > 85% | > 95% |
|
|
243
|
+
| 忠实度 | > 75% | > 90% | > 97% |
|
|
244
|
+
| P95 延迟 | < 5s | < 3s | < 1.5s |
|
|
245
|
+
| 幻觉率 | < 15% | < 5% | < 2% |
|
|
246
|
+
|
|
247
|
+
**输出**:评估脚本 + Golden Set 模板 + A/B 测试方案`,
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
title: '5. 降级与安全策略',
|
|
251
|
+
content: `为 LLM 功能设计完善的降级和安全机制:
|
|
252
|
+
|
|
253
|
+
**五大风险与对策**
|
|
254
|
+
|
|
255
|
+
**① 幻觉控制**
|
|
256
|
+
\`\`\`typescript
|
|
257
|
+
// RAG 置信度检查:若无相关文档,拒绝回答
|
|
258
|
+
const MIN_SIMILARITY = 0.75;
|
|
259
|
+
const docs = await vectorStore.search(query, { topK: 3 });
|
|
260
|
+
if (docs[0].score < MIN_SIMILARITY) {
|
|
261
|
+
return { answer: '抱歉,我没有找到相关信息,请联系人工客服。', sources: [] };
|
|
262
|
+
}
|
|
263
|
+
\`\`\`
|
|
264
|
+
|
|
265
|
+
**② Fallback 降级链**
|
|
266
|
+
\`\`\`typescript
|
|
267
|
+
async function robustLLMCall(prompt: string) {
|
|
268
|
+
try {
|
|
269
|
+
// 主模型(高质量)
|
|
270
|
+
return await gpt4o.complete(prompt, { timeout: 5000 });
|
|
271
|
+
} catch (primaryError) {
|
|
272
|
+
try {
|
|
273
|
+
// 降级到备用模型(更快更便宜)
|
|
274
|
+
return await gpt4oMini.complete(prompt, { timeout: 3000 });
|
|
275
|
+
} catch (fallbackError) {
|
|
276
|
+
// 最终降级:静态规则/人工兜底
|
|
277
|
+
return { answer: FALLBACK_MESSAGES[detectIntent(prompt)], fallback: true };
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
\`\`\`
|
|
282
|
+
|
|
283
|
+
**③ 内容过滤**
|
|
284
|
+
\`\`\`typescript
|
|
285
|
+
// 输入/输出双向过滤
|
|
286
|
+
const BLOCKED_PATTERNS = [/如何.*伤害/, /制作.*武器/];
|
|
287
|
+
function isSafe(text: string): boolean {
|
|
288
|
+
return !BLOCKED_PATTERNS.some(p => p.test(text));
|
|
289
|
+
}
|
|
290
|
+
// 推荐:使用 OpenAI Moderation API / Azure Content Safety
|
|
291
|
+
\`\`\`
|
|
292
|
+
|
|
293
|
+
**④ 成本限制**
|
|
294
|
+
\`\`\`typescript
|
|
295
|
+
// 每用户每日 Token 限额
|
|
296
|
+
const DAILY_TOKEN_LIMIT = 50000;
|
|
297
|
+
// 请求频率限制
|
|
298
|
+
const RATE_LIMIT = { requests: 10, window: '1m' };
|
|
299
|
+
// 输出截断
|
|
300
|
+
const MAX_OUTPUT_TOKENS = 1000;
|
|
301
|
+
\`\`\`
|
|
302
|
+
|
|
303
|
+
**⑤ 可观测性**
|
|
304
|
+
\`\`\`typescript
|
|
305
|
+
// 每次 LLM 调用必须记录
|
|
306
|
+
logger.info('llm_call', {
|
|
307
|
+
model, prompt_tokens, completion_tokens, latency_ms,
|
|
308
|
+
user_id, session_id, feature_flag,
|
|
309
|
+
is_fallback, safety_triggered,
|
|
310
|
+
});
|
|
311
|
+
\`\`\`
|
|
312
|
+
|
|
313
|
+
**输出**:降级策略代码模板 + 内容安全配置 + 成本控制方案 + 可观测性埋点`,
|
|
314
|
+
},
|
|
315
|
+
],
|
|
316
|
+
outputFormat: 'LLM 功能定位文档 + RAG 架构图 + System Prompt 模板 + 评估框架(Golden Set + 自动 Evals)+ 降级与安全策略代码',
|
|
317
|
+
examples: [],
|
|
318
|
+
notes: [
|
|
319
|
+
'先从小模型(GPT-4o mini/Claude Haiku)开始验证,确认方案可行再升级到大模型降低成本',
|
|
320
|
+
'RAG 的质量 80% 取决于 Chunking 策略和 Embedding 质量,而非 LLM 本身',
|
|
321
|
+
'Golden Set 至少需要 100 条覆盖核心场景的问答对,建立前先做 10 条快速验证',
|
|
322
|
+
'幻觉是 RAG 的最大风险,必须设置相似度阈值,宁可说"不知道"也不要胡编',
|
|
323
|
+
'生产环境必须监控 Token 消耗和每次调用成本,防止费用失控',
|
|
324
|
+
],
|
|
325
|
+
category: '需求侧',
|
|
326
|
+
nextSkill: 'system-design',
|
|
327
|
+
};
|
|
328
|
+
//# sourceMappingURL=30-llm-feature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"30-llm-feature.js","sourceRoot":"","sources":["../../src/skills/30-llm-feature.ts"],"names":[],"mappings":";;;AAEa,QAAA,eAAe,GAAoB;IAC9C,EAAE,EAAE,aAAa;IACjB,IAAI,EAAE,YAAY;IAClB,MAAM,EAAE,aAAa;IACrB,KAAK,EAAE,EAAE;IACT,WAAW,EAAE,gDAAgD;IAC7D,aAAa,EAAE,8GAA8G;IAC7H,iBAAiB,EAAE;;;8BAGS;IAC5B,QAAQ,EAAE;QACR,aAAa;QACb,YAAY;QACZ,KAAK;QACL,QAAQ;QACR,SAAS;QACT,eAAe;QACf,OAAO;QACP,UAAU;QACV,oBAAoB;QACpB,cAAc;KACf;IACD,KAAK,EAAE;QACL;YACE,KAAK,EAAE,kBAAkB;YACzB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iCAiCkB;SAC5B;QACD;YACE,KAAK,EAAE,aAAa;YACpB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uCA6CwB;SAClC;QACD;YACE,KAAK,EAAE,gBAAgB;YACvB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+CAmEgC;SAC1C;QACD;YACE,KAAK,EAAE,aAAa;YACpB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uCA4DwB;SAClC;QACD;YACE,KAAK,EAAE,YAAY;YACnB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2CA8D4B;SACtC;KACF;IACD,YAAY,EAAE,kFAAkF;IAChG,QAAQ,EAAE,EAAE;IACZ,KAAK,EAAE;QACL,uDAAuD;QACvD,qDAAqD;QACrD,gDAAgD;QAChD,uCAAuC;QACvC,iCAAiC;KAClC;IACD,QAAQ,EAAE,KAAK;IACf,SAAS,EAAE,eAAe;CAC3B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"31-threat-model.d.ts","sourceRoot":"","sources":["../../src/skills/31-threat-model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,eAAO,MAAM,gBAAgB,EAAE,eA2O9B,CAAC"}
|