vibepro 0.1.0-alpha.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/LICENSE +201 -0
- package/NOTICE +9 -0
- package/README.ja.md +448 -0
- package/README.md +520 -0
- package/agent-instructions/codex/AGENTS.vibepro.md +45 -0
- package/bin/vibepro.js +9 -0
- package/docs/assets/vibepro-header.png +0 -0
- package/package.json +51 -0
- package/skills/vibepro-diagnosis-packages/SKILL.md +133 -0
- package/skills/vibepro-human-review/SKILL.md +73 -0
- package/skills/vibepro-story-refactor/SKILL.md +89 -0
- package/skills/vibepro-workflow/SKILL.md +139 -0
- package/src/agent-harness-map.js +230 -0
- package/src/agent-harness-scanner.js +337 -0
- package/src/agent-review.js +2180 -0
- package/src/api-boundary-scanner.js +452 -0
- package/src/architecture-profiler.js +423 -0
- package/src/authorization-scoring.js +149 -0
- package/src/brainbase-importer.js +534 -0
- package/src/change-risk-classifier.js +195 -0
- package/src/check-packs.js +605 -0
- package/src/checkpoint-manager.js +233 -0
- package/src/cli.js +2213 -0
- package/src/code-quality-scanner.js +310 -0
- package/src/codex-manager.js +143 -0
- package/src/component-style-scanner.js +336 -0
- package/src/coverage-report.js +99 -0
- package/src/database-access-scanner.js +163 -0
- package/src/decision-records.js +315 -0
- package/src/design-modernize.js +1435 -0
- package/src/design-system.js +1732 -0
- package/src/diagnostic-engine.js +1945 -0
- package/src/diagram-requirement-resolver.js +194 -0
- package/src/doctor.js +677 -0
- package/src/environment-graph.js +424 -0
- package/src/execution-state.js +849 -0
- package/src/explore-evidence.js +425 -0
- package/src/flow-design-scanner.js +896 -0
- package/src/flow-verifier.js +887 -0
- package/src/gesture-interaction-scanner.js +330 -0
- package/src/graph-context.js +263 -0
- package/src/graphify-adapter.js +189 -0
- package/src/html-report.js +1035 -0
- package/src/journey-map.js +1299 -0
- package/src/language.js +48 -0
- package/src/lazy-pattern-detector.js +182 -0
- package/src/local-dev-scanner.js +135 -0
- package/src/managed-worktree-gate.js +187 -0
- package/src/managed-worktree.js +766 -0
- package/src/merge-manager.js +501 -0
- package/src/network-contract-scanner.js +442 -0
- package/src/nocodb-story-sync.js +386 -0
- package/src/oss-readiness-scanner.js +417 -0
- package/src/performance-evidence.js +756 -0
- package/src/performance-measurer.js +591 -0
- package/src/pr-manager.js +8220 -0
- package/src/presets.js +682 -0
- package/src/public-discovery-scanner.js +519 -0
- package/src/refactoring-delta-reporter.js +367 -0
- package/src/refactoring-opportunity-generator.js +797 -0
- package/src/regression-risk-scanner.js +146 -0
- package/src/repo-status.js +266 -0
- package/src/report-fingerprint.js +188 -0
- package/src/report-pr-body-prompt-template.md +108 -0
- package/src/report-pr-body-schema.json +95 -0
- package/src/report-store.js +135 -0
- package/src/report-validator.js +192 -0
- package/src/requirement-consistency.js +1066 -0
- package/src/runtime-info.js +134 -0
- package/src/self-dogfood-scanner.js +476 -0
- package/src/session-learning.js +164 -0
- package/src/skills-manager.js +157 -0
- package/src/spec-drift.js +378 -0
- package/src/spec-fingerprint.js +445 -0
- package/src/spec-prompt-template.md +155 -0
- package/src/spec-schema.json +219 -0
- package/src/spec-store.js +258 -0
- package/src/spec-validator.js +459 -0
- package/src/static-site-scanner.js +316 -0
- package/src/story-candidate-generator.js +85 -0
- package/src/story-catalog-generator.js +2813 -0
- package/src/story-html.js +156 -0
- package/src/story-manager.js +2144 -0
- package/src/story-task-generator.js +522 -0
- package/src/task-manager.js +1029 -0
- package/src/terminal-link-scanner.js +238 -0
- package/src/usage-report.js +417 -0
- package/src/verification-evidence.js +284 -0
- package/src/workspace.js +126 -0
package/src/presets.js
ADDED
|
@@ -0,0 +1,682 @@
|
|
|
1
|
+
const NEXT_APP_RELEVANT_PATTERNS = [
|
|
2
|
+
/^src\/app\/.+\/(page|route|client)\.[jt]sx?$/,
|
|
3
|
+
/^src\/app\/.+\/_components\/.+\.[jt]sx?$/,
|
|
4
|
+
/^src\/components\/.+\.[jt]sx?$/,
|
|
5
|
+
/^src\/lib\/actions\/.+\.[jt]s$/,
|
|
6
|
+
/^src\/lib\/auth\/.+\.[jt]s$/,
|
|
7
|
+
/^src\/lib\/article\/.+\.[jt]s$/,
|
|
8
|
+
/^src\/lib\/services\/.+\.[jt]s$/,
|
|
9
|
+
/^src\/lib\/api\/.+\.[jt]s$/
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
function classifyNextApp(filePath) {
|
|
13
|
+
if (/^src\/app\/.+\/route\.[jt]s$/.test(filePath)) return 'api_route';
|
|
14
|
+
if (/^src\/app\//.test(filePath)) return 'app_route';
|
|
15
|
+
if (/^src\/components\//.test(filePath)) return 'component';
|
|
16
|
+
if (/^src\/lib\/actions\//.test(filePath)) return 'server_action';
|
|
17
|
+
if (/^src\/lib\/crawlers\//.test(filePath)) return 'crawler';
|
|
18
|
+
if (/^src\/lib\/auth\//.test(filePath)) return 'auth';
|
|
19
|
+
if (/^src\/lib\/article\//.test(filePath)) return 'article_logic';
|
|
20
|
+
if (/^src\/lib\/api\//.test(filePath)) return 'api_client';
|
|
21
|
+
return 'domain_code';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const COMMON_DOCUMENT_SIGNAL_GROUPS = [
|
|
25
|
+
{ key: 'architecture', pattern: /^docs\/architecture\// },
|
|
26
|
+
{ key: 'managementStories', pattern: /^docs\/management\/stories\// },
|
|
27
|
+
{ key: 'requirements', pattern: /^docs\/requirements\// },
|
|
28
|
+
{ key: 'userStories', pattern: /^docs\/user_stories\// },
|
|
29
|
+
{ key: 'features', pattern: /^docs\/features\// }
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
const NEXT_APP_DOCUMENT_SIGNAL_GROUPS = [
|
|
33
|
+
{ key: 'authAccountAccess', pattern: /(auth|account|login|sign[-_ ]?in|sso|oauth|session)/i },
|
|
34
|
+
{ key: 'premiumBilling', pattern: /(stripe|premium|subscription|billing|webhook-secret)/i },
|
|
35
|
+
{ key: 'contentCms', pattern: /(article|cms|sanity)/i },
|
|
36
|
+
{ key: 'onboarding', pattern: /(onboarding|profile|preferences)/i },
|
|
37
|
+
{ key: 'notification', pattern: /notification/i },
|
|
38
|
+
...COMMON_DOCUMENT_SIGNAL_GROUPS
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
const NEXT_APP_PRODUCT_SURFACE_SIGNALS = [
|
|
42
|
+
{
|
|
43
|
+
id: 'story-product-auth-account-access',
|
|
44
|
+
title: '認証とアカウント利用開始を成立させる',
|
|
45
|
+
category: 'product',
|
|
46
|
+
codePattern: /(^src\/components\/auth\/|^src\/app\/api\/auth\/|^src\/lib\/auth|login|sign[-_]?in|nextauth|session)/i,
|
|
47
|
+
docKey: 'authAccountAccess',
|
|
48
|
+
evidenceTokens: ['auth', 'account', 'session']
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: 'story-product-premium-billing',
|
|
52
|
+
title: 'プレミアム課金導線を安定化する',
|
|
53
|
+
category: 'product',
|
|
54
|
+
codePattern: /stripe|premium|subscription/,
|
|
55
|
+
docKey: 'premiumBilling',
|
|
56
|
+
evidenceTokens: ['stripe', 'premium', 'subscription']
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: 'story-product-content-cms',
|
|
60
|
+
title: '記事とCMS運用を整理する',
|
|
61
|
+
category: 'product',
|
|
62
|
+
codePattern: /articles|sanity|cms/,
|
|
63
|
+
docKey: 'contentCms',
|
|
64
|
+
evidenceTokens: ['articles', 'sanity', 'cms']
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
id: 'story-product-onboarding',
|
|
68
|
+
title: 'オンボーディング体験を安定化する',
|
|
69
|
+
category: 'product',
|
|
70
|
+
codePattern: /onboarding|profile-step|preferences-step/,
|
|
71
|
+
docKey: 'onboarding',
|
|
72
|
+
evidenceTokens: ['onboarding', 'profile', 'preferences']
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
id: 'story-product-notification',
|
|
76
|
+
title: '通知体験を安定化する',
|
|
77
|
+
category: 'product',
|
|
78
|
+
codePattern: /notification/,
|
|
79
|
+
docKey: 'notification',
|
|
80
|
+
evidenceTokens: ['notification']
|
|
81
|
+
}
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
const NEXT_APP_COVERAGE_PATTERNS = {
|
|
85
|
+
'story-product-premium-billing': [
|
|
86
|
+
/^src\/app\/\(public\)\/premium\//,
|
|
87
|
+
/^src\/app\/api\/stripe\//,
|
|
88
|
+
/^src\/app\/api\/webhook\/stripe\/route\.ts$/,
|
|
89
|
+
/^src\/components\/ui\/button\/ButtonCheckout\.tsx$/,
|
|
90
|
+
/^src\/components\/ui\/button\/CheckoutErrorModal\.tsx$/,
|
|
91
|
+
/^src\/components\/ui\/modal\/PremiumRequiredModal\.tsx$/,
|
|
92
|
+
/^src\/lib\/constants\/stripe\.ts$/
|
|
93
|
+
],
|
|
94
|
+
'story-product-content-cms': [
|
|
95
|
+
/^src\/app\/\(public\)\/articles\//,
|
|
96
|
+
/^src\/app\/api\/articles\//,
|
|
97
|
+
/^src\/lib\/article/,
|
|
98
|
+
/^src\/lib\/article-utils\.ts$/
|
|
99
|
+
],
|
|
100
|
+
'story-product-onboarding': [
|
|
101
|
+
/^src\/app\/onboarding\//,
|
|
102
|
+
/^src\/app\/api\/onboarding\//,
|
|
103
|
+
/^src\/lib\/auth\/onboarding\.ts$/
|
|
104
|
+
],
|
|
105
|
+
'story-product-notification': [
|
|
106
|
+
/^src\/app\/\(app\)\/notification\//,
|
|
107
|
+
/^src\/components\/ui\/UpdateNotification\.tsx$/
|
|
108
|
+
],
|
|
109
|
+
'story-product-auth-account-access': [
|
|
110
|
+
/^src\/app\/\(auth\)\//,
|
|
111
|
+
/^src\/app\/\(app\)\/auth\//,
|
|
112
|
+
/^src\/components\/auth\//,
|
|
113
|
+
/^src\/app\/api\/auth\//,
|
|
114
|
+
/^src\/app\/api\/user\//,
|
|
115
|
+
/^src\/app\/api\/users\//,
|
|
116
|
+
/^src\/lib\/auth/,
|
|
117
|
+
/^src\/lib\/services\/user\//,
|
|
118
|
+
/^src\/lib\/actions\/user_actions\.ts$/
|
|
119
|
+
],
|
|
120
|
+
'story-product-profile-personalization': [
|
|
121
|
+
/^src\/app\/\(app\)\/profile\//,
|
|
122
|
+
/^src\/lib\/services\/profile\//,
|
|
123
|
+
/^src\/lib\/services\/user\/user(Read|Write|Entry)Service\.ts$/,
|
|
124
|
+
/^src\/lib\/actions\/profile_action\.ts$/
|
|
125
|
+
],
|
|
126
|
+
'story-product-public-discovery-seo': [
|
|
127
|
+
/^src\/app\/\(public\)\/articles\//,
|
|
128
|
+
/^src\/app\/\(public\)\/_components\/landing\//,
|
|
129
|
+
/^src\/app\/\(public\)\/sitemap/,
|
|
130
|
+
/^src\/app\/robots\.ts$/,
|
|
131
|
+
/^src\/app\/sitemap\.ts$/,
|
|
132
|
+
/^src\/lib\/services\/analytics\//,
|
|
133
|
+
/^src\/components\/common\/StructuredData\.tsx$/
|
|
134
|
+
],
|
|
135
|
+
'story-product-waiting-list-contact': [
|
|
136
|
+
/^src\/app\/\(public\)\/contact\//,
|
|
137
|
+
/^src\/app\/\(public\)\/waiting-list\//
|
|
138
|
+
],
|
|
139
|
+
'story-product-qr-offline-access': [
|
|
140
|
+
/^src\/app\/\(app\)\/_components\/QRCodeScanner\.tsx$/,
|
|
141
|
+
/^src\/app\/\(public\)\/offline\//,
|
|
142
|
+
/^src\/components\/common\/ModernServiceWorkerManager\.tsx$/,
|
|
143
|
+
/^src\/components\/ui\/UpdateNotification\.tsx$/
|
|
144
|
+
],
|
|
145
|
+
'story-product-app-navigation-shell': [
|
|
146
|
+
/^src\/app\/\(app\)\/home\//,
|
|
147
|
+
/^src\/components\/layout\//
|
|
148
|
+
],
|
|
149
|
+
'story-ops-observability-health': [
|
|
150
|
+
/^src\/app\/api\/health\//,
|
|
151
|
+
/^src\/app\/api\/heartbeat\//,
|
|
152
|
+
/^src\/app\/api\/vercel\//,
|
|
153
|
+
/^src\/app\/log_viewer\//,
|
|
154
|
+
/^src\/components\/common\/ConsoleLogger\.tsx$/
|
|
155
|
+
],
|
|
156
|
+
'story-product-legal-trust-pages': [
|
|
157
|
+
/^src\/app\/\(public\)\/privacy/,
|
|
158
|
+
/^src\/app\/\(public\)\/terms\//,
|
|
159
|
+
/^src\/app\/\(public\)\/tos\//,
|
|
160
|
+
/^src\/app\/\(public\)\/tokusho\//,
|
|
161
|
+
/^src\/app\/\(public\)\/guidelines\//
|
|
162
|
+
],
|
|
163
|
+
'story-security-api-trust-boundary': [
|
|
164
|
+
/^src\/app\/api\/debug\//,
|
|
165
|
+
/^src\/app\/api\/test\//,
|
|
166
|
+
/^src\/app\/api\/admin\//
|
|
167
|
+
]
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const NEXT_APP_PRESET = {
|
|
171
|
+
id: 'next-app',
|
|
172
|
+
isCodePath: (filePath) => typeof filePath === 'string' && filePath.startsWith('src/'),
|
|
173
|
+
storyRelevantPatterns: NEXT_APP_RELEVANT_PATTERNS,
|
|
174
|
+
classifyRole: classifyNextApp,
|
|
175
|
+
codeSurfaceSignatures: null,
|
|
176
|
+
productSurfaceSignals: NEXT_APP_PRODUCT_SURFACE_SIGNALS,
|
|
177
|
+
documentSignalGroups: NEXT_APP_DOCUMENT_SIGNAL_GROUPS,
|
|
178
|
+
coveragePatterns: NEXT_APP_COVERAGE_PATTERNS
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const MODULAR_WEB_RELEVANT_PATTERNS = [
|
|
182
|
+
/^cli\/.+\.[jt]sx?$/,
|
|
183
|
+
/^lib\/services\/.+\.[jt]s$/,
|
|
184
|
+
/^lib\/auth\/.+\.[jt]s$/,
|
|
185
|
+
/^lib\/[^/]+\.[jt]s$/,
|
|
186
|
+
/^lib\/[^/]+\/[^/]+\.[jt]s$/,
|
|
187
|
+
/^mcp\/.+\.[jt]sx?$/,
|
|
188
|
+
/^public\/modules\/core\/.+\.[jt]s$/,
|
|
189
|
+
/^public\/modules\/domain\/.+\.[jt]s$/,
|
|
190
|
+
/^public\/modules\/.+\.[jt]s$/,
|
|
191
|
+
/^server\/routes\/.+\.[jt]s$/,
|
|
192
|
+
/^server\/.+\.[jt]s$/
|
|
193
|
+
];
|
|
194
|
+
|
|
195
|
+
function classifyModularWeb(filePath) {
|
|
196
|
+
if (/^cli\//.test(filePath)) return 'cli';
|
|
197
|
+
if (/^mcp\//.test(filePath)) return 'mcp_server';
|
|
198
|
+
if (/^public\/modules\/core\//.test(filePath)) return 'web_core';
|
|
199
|
+
if (/^public\/modules\/domain\//.test(filePath)) return 'domain_service';
|
|
200
|
+
if (/^public\/modules\//.test(filePath)) return 'web_module';
|
|
201
|
+
if (/^server\/routes\//.test(filePath)) return 'server_route';
|
|
202
|
+
if (/^server\//.test(filePath)) return 'server_module';
|
|
203
|
+
if (/^lib\/services\//.test(filePath)) return 'service';
|
|
204
|
+
if (/^lib\/auth\//.test(filePath)) return 'auth';
|
|
205
|
+
if (/^lib\//.test(filePath)) return 'lib_module';
|
|
206
|
+
return 'domain_code';
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const MODULAR_WEB_CODE_SURFACE_SIGNATURES = [
|
|
210
|
+
{
|
|
211
|
+
id: 'story-code-cli-tooling',
|
|
212
|
+
title: 'CLIツールと配布インターフェースを整える',
|
|
213
|
+
category: 'product',
|
|
214
|
+
patterns: [/^cli\//]
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
id: 'story-code-mcp-server',
|
|
218
|
+
title: 'MCPサーバ境界と実行ライフサイクルを整える',
|
|
219
|
+
category: 'architecture',
|
|
220
|
+
patterns: [/^mcp\//]
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
id: 'story-code-web-core',
|
|
224
|
+
title: 'Webクライアントのコア基盤を整える',
|
|
225
|
+
category: 'architecture',
|
|
226
|
+
patterns: [
|
|
227
|
+
/^public\/modules\/core\//,
|
|
228
|
+
/^public\/modules\/components\//,
|
|
229
|
+
/^public\/modules\/utils\//,
|
|
230
|
+
/^public\/modules\/[^/]+\.[jt]sx?$/
|
|
231
|
+
]
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
id: 'story-code-domain-services',
|
|
235
|
+
title: 'ドメインサービスの責務と契約を整える',
|
|
236
|
+
category: 'product',
|
|
237
|
+
patterns: [
|
|
238
|
+
/^public\/modules\/domain\//,
|
|
239
|
+
/^public\/modules\/(app|settings|auth|device|setup|terminal|ui)\//,
|
|
240
|
+
/^lib\/services\//,
|
|
241
|
+
/^server\/services\//
|
|
242
|
+
]
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
id: 'story-code-server-routes',
|
|
246
|
+
title: 'サーバ側ルートとAPI境界を整える',
|
|
247
|
+
category: 'architecture',
|
|
248
|
+
patterns: [
|
|
249
|
+
/^server\/routes\//,
|
|
250
|
+
/^server\/api\//,
|
|
251
|
+
/^server\/controllers\//,
|
|
252
|
+
/^server\/(middleware|lib|utils|bootstrap|mesh)\//,
|
|
253
|
+
/^lib\/[^/]+\.[jt]s$/
|
|
254
|
+
]
|
|
255
|
+
}
|
|
256
|
+
];
|
|
257
|
+
|
|
258
|
+
const MODULAR_WEB_COVERAGE_PATTERNS = {
|
|
259
|
+
'story-code-cli-tooling': [
|
|
260
|
+
/^cli\//
|
|
261
|
+
],
|
|
262
|
+
'story-code-mcp-server': [
|
|
263
|
+
/^mcp\//
|
|
264
|
+
],
|
|
265
|
+
'story-code-web-core': [
|
|
266
|
+
/^public\/modules\/core\//,
|
|
267
|
+
/^public\/modules\/components\//,
|
|
268
|
+
/^public\/modules\/utils\//,
|
|
269
|
+
/^public\/modules\/[^/]+\.[jt]sx?$/
|
|
270
|
+
],
|
|
271
|
+
'story-code-domain-services': [
|
|
272
|
+
/^public\/modules\/domain\//,
|
|
273
|
+
/^public\/modules\/(app|settings|auth|device|setup|terminal|ui)\//,
|
|
274
|
+
/^lib\/services\//,
|
|
275
|
+
/^server\/services\//
|
|
276
|
+
],
|
|
277
|
+
'story-code-server-routes': [
|
|
278
|
+
/^server\/routes\//,
|
|
279
|
+
/^server\/api\//,
|
|
280
|
+
/^server\/controllers\//,
|
|
281
|
+
/^server\/(middleware|lib|utils|bootstrap|mesh)\//,
|
|
282
|
+
/^lib\/[^/]+\.[jt]s$/
|
|
283
|
+
]
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
const MODULAR_WEB_PRESET = {
|
|
287
|
+
id: 'modular-web',
|
|
288
|
+
isCodePath: (filePath) =>
|
|
289
|
+
typeof filePath === 'string' &&
|
|
290
|
+
/^(cli\/|lib\/|mcp\/|public\/modules\/|server\/|src\/)/.test(filePath),
|
|
291
|
+
storyRelevantPatterns: MODULAR_WEB_RELEVANT_PATTERNS,
|
|
292
|
+
classifyRole: classifyModularWeb,
|
|
293
|
+
codeSurfaceSignatures: MODULAR_WEB_CODE_SURFACE_SIGNATURES,
|
|
294
|
+
productSurfaceSignals: [],
|
|
295
|
+
documentSignalGroups: [...COMMON_DOCUMENT_SIGNAL_GROUPS],
|
|
296
|
+
coveragePatterns: MODULAR_WEB_COVERAGE_PATTERNS
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
const SALES_TAILOR_CODE_SURFACE_SIGNATURES = [
|
|
300
|
+
{
|
|
301
|
+
id: 'story-salestailor-project-planning',
|
|
302
|
+
title: '営業プロジェクトとターゲット戦略を設計する',
|
|
303
|
+
category: 'product',
|
|
304
|
+
patterns: [
|
|
305
|
+
/^src\/app\/projects\//,
|
|
306
|
+
/^src\/app\/api\/projects\//,
|
|
307
|
+
/^src\/app\/api\/plans\//,
|
|
308
|
+
/^src\/lib\/services\/.*project/i,
|
|
309
|
+
/^src\/lib\/services\/.*plan/i
|
|
310
|
+
]
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
id: 'story-salestailor-letter-generation-review',
|
|
314
|
+
title: '営業レター生成とレビューを成立させる',
|
|
315
|
+
category: 'product',
|
|
316
|
+
patterns: [
|
|
317
|
+
/sample-review/i,
|
|
318
|
+
/sample-generation/i,
|
|
319
|
+
/letter/i,
|
|
320
|
+
/prompt-generation/i,
|
|
321
|
+
/^src\/app\/api\/.*generate/i
|
|
322
|
+
]
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
id: 'story-salestailor-prompt-improvement-loop',
|
|
326
|
+
title: 'プロンプト改善フィードバックを運用する',
|
|
327
|
+
category: 'product',
|
|
328
|
+
patterns: [
|
|
329
|
+
/prompt-improvement/i,
|
|
330
|
+
/improvement/i,
|
|
331
|
+
/feedback/i
|
|
332
|
+
]
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
id: 'story-salestailor-contact-form-automation',
|
|
336
|
+
title: '問い合わせフォーム送信を自動化する',
|
|
337
|
+
category: 'product',
|
|
338
|
+
patterns: [
|
|
339
|
+
/formSubmission/i,
|
|
340
|
+
/form-automation/i,
|
|
341
|
+
/contactForm/i,
|
|
342
|
+
/captcha/i
|
|
343
|
+
]
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
id: 'story-salestailor-company-product-data',
|
|
347
|
+
title: '企業・商材データを営業文脈で管理する',
|
|
348
|
+
category: 'product',
|
|
349
|
+
patterns: [
|
|
350
|
+
/^src\/app\/companies\//,
|
|
351
|
+
/^src\/app\/products\//,
|
|
352
|
+
/^src\/app\/api\/companies\//,
|
|
353
|
+
/^src\/app\/api\/products\//,
|
|
354
|
+
/companyService/i,
|
|
355
|
+
/product/i
|
|
356
|
+
]
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
id: 'story-salestailor-delivery-tracking',
|
|
360
|
+
title: '送信結果と反応を追跡する',
|
|
361
|
+
category: 'product',
|
|
362
|
+
patterns: [
|
|
363
|
+
/email-tracking/i,
|
|
364
|
+
/click-tracking/i,
|
|
365
|
+
/tracking/i,
|
|
366
|
+
/^src\/app\/api\/webhooks\/resend\//
|
|
367
|
+
]
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
id: 'story-salestailor-admin-operations',
|
|
371
|
+
title: '管理者がテンプレート・ユーザー・LLM運用を管理する',
|
|
372
|
+
category: 'ops',
|
|
373
|
+
patterns: [
|
|
374
|
+
/^src\/app\/admin\//,
|
|
375
|
+
/^src\/app\/api\/admin\//,
|
|
376
|
+
/^src\/app\/api\/templates\//,
|
|
377
|
+
/^src\/lib\/services\/admin\//,
|
|
378
|
+
/template/i,
|
|
379
|
+
/llmJudge/i
|
|
380
|
+
]
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
id: 'story-salestailor-integrations-scheduling',
|
|
384
|
+
title: '外部連携と面談日程を接続する',
|
|
385
|
+
category: 'product',
|
|
386
|
+
patterns: [
|
|
387
|
+
/timerex/i,
|
|
388
|
+
/^src\/app\/api\/integrations\//,
|
|
389
|
+
/^src\/app\/api\/webhooks\/timerex\//
|
|
390
|
+
]
|
|
391
|
+
}
|
|
392
|
+
];
|
|
393
|
+
|
|
394
|
+
const SALES_TAILOR_STORY_DEFINITIONS = {
|
|
395
|
+
'story-salestailor-project-planning': {
|
|
396
|
+
who: '営業施策を設計するユーザー',
|
|
397
|
+
problem: 'ターゲット、商材、訴求、実行条件が分散すると、営業プロジェクトごとの狙いと実行単位が曖昧になる。',
|
|
398
|
+
want: 'プロジェクト単位でターゲット戦略と実行条件を整理し、生成・送信・分析へつなげたい。',
|
|
399
|
+
outcome: '営業プロジェクトの目的、対象、進め方が一貫して管理される。',
|
|
400
|
+
business_value: '営業施策の立ち上げ速度と再現性を高める。案件化率やプロジェクト作成から実行までの時間は未確認。',
|
|
401
|
+
acceptance_focus: ['プロジェクトの対象企業と条件が追跡できる', 'ターゲット戦略が生成や送信に反映される', '状態遷移と権限が破綻しない']
|
|
402
|
+
},
|
|
403
|
+
'story-salestailor-letter-generation-review': {
|
|
404
|
+
who: '営業レターを作成・確認するユーザー',
|
|
405
|
+
problem: '生成結果、レビュー、再生成、承認が一貫しないと、送信前の品質担保と改善が属人的になる。',
|
|
406
|
+
want: '対象企業ごとの文脈を踏まえたレターを生成し、レビューで修正してから送信に進めたい。',
|
|
407
|
+
outcome: 'レター生成から承認までの品質管理がStoryとして追跡できる。',
|
|
408
|
+
business_value: '商談化につながる文面品質と運用速度を支える。承認率、再生成率、返信率は未確認。',
|
|
409
|
+
acceptance_focus: ['生成結果と対象企業の対応が崩れない', 'レビュー・再生成・承認の状態が追跡できる', '改善フィードバックが次の生成に接続できる']
|
|
410
|
+
},
|
|
411
|
+
'story-salestailor-prompt-improvement-loop': {
|
|
412
|
+
who: '営業レター品質を改善する運用者',
|
|
413
|
+
problem: '改善フィードバックが1件単位や全体単位に閉じると、対象パートごとの改善やプロンプト版管理に接続しづらい。',
|
|
414
|
+
want: 'レビューで得た改善点をパート、重要度、適用範囲ごとに蓄積し、プロンプト改善へ反映したい。',
|
|
415
|
+
outcome: 'レター品質改善が単発修正ではなく、検証可能な改善ループとして残る。',
|
|
416
|
+
business_value: '生成品質の継続改善と運用品質の平準化に効く。改善反映後の品質指標は未確認。',
|
|
417
|
+
acceptance_focus: ['複数改善点を同一レターに紐づけられる', '対象パートと適用範囲で分類できる', 'プロンプト版と改善結果の対応が追跡できる']
|
|
418
|
+
},
|
|
419
|
+
'story-salestailor-contact-form-automation': {
|
|
420
|
+
who: '問い合わせフォーム送信を自動化したい営業担当者',
|
|
421
|
+
problem: 'フォーム探索、入力、CAPTCHA、送信結果の扱いが不安定だと、手作業削減と送信品質を両立できない。',
|
|
422
|
+
want: '企業サイトのフォームを検出し、必要項目を安全に入力して、結果を確認できる形で送信したい。',
|
|
423
|
+
outcome: 'フォーム送信の自動化が運用可能な業務フローになる。',
|
|
424
|
+
business_value: '営業接触数の拡張と作業時間削減につながる。成功率、失敗分類、再試行基準は未確認。',
|
|
425
|
+
acceptance_focus: ['フォーム検出から送信までの状態が追跡できる', '失敗理由と再試行可否が分かる', 'CAPTCHAや外部ブラウザ依存の扱いが明確である']
|
|
426
|
+
},
|
|
427
|
+
'story-salestailor-company-product-data': {
|
|
428
|
+
who: '営業対象企業と商材情報を管理するユーザー',
|
|
429
|
+
problem: '企業情報、商材情報、インポート、更新が散らばると、生成文面やターゲティングの根拠が弱くなる。',
|
|
430
|
+
want: '企業と商材の情報を営業文脈で整え、プロジェクトやレター生成に利用したい。',
|
|
431
|
+
outcome: '営業文面の根拠になる企業・商材データが管理される。',
|
|
432
|
+
business_value: 'パーソナライズ精度と運用効率を支える。データ鮮度と利用率は未確認。',
|
|
433
|
+
acceptance_focus: ['企業・商材情報の作成、更新、取り込みが成立する', 'プロジェクトや生成処理から参照できる', '重複や不足情報の扱いが決まる']
|
|
434
|
+
},
|
|
435
|
+
'story-salestailor-delivery-tracking': {
|
|
436
|
+
who: '送信後の反応を確認したい営業担当者と運用者',
|
|
437
|
+
problem: '送信結果、開封、クリック、返信などの反応が追えないと、施策改善と次アクションにつながらない。',
|
|
438
|
+
want: '送信後の状態と反応を確認し、プロジェクトや改善判断へ戻したい。',
|
|
439
|
+
outcome: '営業接触の結果が可視化され、次の改善に使える。',
|
|
440
|
+
business_value: '営業施策の学習速度を高める。返信率、クリック率、商談化率は未確認。',
|
|
441
|
+
acceptance_focus: ['送信結果と反応イベントが保存される', '対象企業・レター・プロジェクトへ紐づく', 'webhookや外部イベントの信頼境界が明確である']
|
|
442
|
+
},
|
|
443
|
+
'story-salestailor-admin-operations': {
|
|
444
|
+
who: 'OutreachSuiteを運用する管理者',
|
|
445
|
+
problem: 'テンプレート、ユーザー、LLM判定、利用状況の管理が弱いと、プロダクト全体の品質と安全な運用を保てない。',
|
|
446
|
+
want: '管理者がテンプレート、ユーザー、評価、利用状況を確認・調整できるようにしたい。',
|
|
447
|
+
outcome: '営業生成システムを管理者が継続運用できる。',
|
|
448
|
+
business_value: '運用品質、権限管理、生成品質の統制に効く。管理者作業の頻度と基準は未確認。',
|
|
449
|
+
acceptance_focus: ['管理画面と管理APIの責務が整理される', '管理者権限が一貫している', 'テンプレートやLLM評価の変更履歴を追える']
|
|
450
|
+
},
|
|
451
|
+
'story-salestailor-integrations-scheduling': {
|
|
452
|
+
who: '営業接点を面談や外部ツールへつなげたいユーザー',
|
|
453
|
+
problem: '日程調整や外部連携が営業フローと分断されると、返信後の面談化や結果追跡が弱くなる。',
|
|
454
|
+
want: 'Timerexなどの外部連携を通じて、営業接触から日程調整・結果確認までつなげたい。',
|
|
455
|
+
outcome: '営業接触後の次アクションが外部サービスと連携して管理される。',
|
|
456
|
+
business_value: '商談化までの摩擦を減らす。面談設定率や連携失敗率は未確認。',
|
|
457
|
+
acceptance_focus: ['外部認証とcallbackが安全に処理される', 'tracking URLやwebhookがプロジェクトに紐づく', '失敗時の再接続や通知が決まる']
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
|
|
461
|
+
const SALES_TAILOR_WORKFLOW_POSITIONS = {
|
|
462
|
+
'story-salestailor-company-product-data': {
|
|
463
|
+
stage: 'foundation',
|
|
464
|
+
before: [],
|
|
465
|
+
after: ['story-salestailor-project-planning', 'story-salestailor-letter-generation-review'],
|
|
466
|
+
confidence: 'medium',
|
|
467
|
+
rationale: '企業・商材情報はターゲット設計とレター生成の根拠になるため'
|
|
468
|
+
},
|
|
469
|
+
'story-salestailor-project-planning': {
|
|
470
|
+
stage: 'planning',
|
|
471
|
+
before: ['story-salestailor-company-product-data'],
|
|
472
|
+
after: ['story-salestailor-letter-generation-review', 'story-salestailor-contact-form-automation'],
|
|
473
|
+
confidence: 'medium',
|
|
474
|
+
rationale: 'プロジェクト設計は生成・送信の実行単位になるため'
|
|
475
|
+
},
|
|
476
|
+
'story-salestailor-letter-generation-review': {
|
|
477
|
+
stage: 'creation',
|
|
478
|
+
before: ['story-salestailor-project-planning'],
|
|
479
|
+
after: ['story-salestailor-prompt-improvement-loop', 'story-salestailor-contact-form-automation'],
|
|
480
|
+
confidence: 'medium',
|
|
481
|
+
rationale: '送信前に文面生成とレビューで品質を担保するため'
|
|
482
|
+
},
|
|
483
|
+
'story-salestailor-prompt-improvement-loop': {
|
|
484
|
+
stage: 'quality_improvement',
|
|
485
|
+
before: ['story-salestailor-letter-generation-review'],
|
|
486
|
+
after: ['story-salestailor-letter-generation-review'],
|
|
487
|
+
confidence: 'medium',
|
|
488
|
+
rationale: 'レビュー結果を次の生成品質へ戻す改善ループのため'
|
|
489
|
+
},
|
|
490
|
+
'story-salestailor-contact-form-automation': {
|
|
491
|
+
stage: 'execution',
|
|
492
|
+
before: ['story-salestailor-project-planning', 'story-salestailor-letter-generation-review'],
|
|
493
|
+
after: ['story-salestailor-delivery-tracking', 'story-salestailor-integrations-scheduling'],
|
|
494
|
+
confidence: 'medium',
|
|
495
|
+
rationale: '生成した文面を企業接点へ届ける実行段階のため'
|
|
496
|
+
},
|
|
497
|
+
'story-salestailor-delivery-tracking': {
|
|
498
|
+
stage: 'measurement',
|
|
499
|
+
before: ['story-salestailor-contact-form-automation'],
|
|
500
|
+
after: ['story-salestailor-prompt-improvement-loop'],
|
|
501
|
+
confidence: 'medium',
|
|
502
|
+
rationale: '送信結果と反応が改善判断に戻るため'
|
|
503
|
+
},
|
|
504
|
+
'story-salestailor-admin-operations': {
|
|
505
|
+
stage: 'operations',
|
|
506
|
+
before: [],
|
|
507
|
+
after: [],
|
|
508
|
+
confidence: 'medium',
|
|
509
|
+
rationale: '管理者運用は全体の品質と権限を支える横断機能のため'
|
|
510
|
+
},
|
|
511
|
+
'story-salestailor-integrations-scheduling': {
|
|
512
|
+
stage: 'conversion_support',
|
|
513
|
+
before: ['story-salestailor-contact-form-automation'],
|
|
514
|
+
after: ['story-salestailor-delivery-tracking'],
|
|
515
|
+
confidence: 'medium',
|
|
516
|
+
rationale: '営業接触後の面談化や外部結果を追跡するため'
|
|
517
|
+
}
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
const SALES_TAILOR_COVERAGE_PATTERNS = Object.fromEntries(
|
|
521
|
+
SALES_TAILOR_CODE_SURFACE_SIGNATURES.map((signature) => [signature.id, signature.patterns])
|
|
522
|
+
);
|
|
523
|
+
|
|
524
|
+
const SALES_TAILOR_PRESET = {
|
|
525
|
+
id: 'salestailor',
|
|
526
|
+
isCodePath: (filePath) => typeof filePath === 'string' && filePath.startsWith('src/'),
|
|
527
|
+
storyRelevantPatterns: NEXT_APP_RELEVANT_PATTERNS,
|
|
528
|
+
classifyRole: classifyNextApp,
|
|
529
|
+
codeSurfaceSignatures: SALES_TAILOR_CODE_SURFACE_SIGNATURES,
|
|
530
|
+
productSurfaceSignals: [],
|
|
531
|
+
documentSignalGroups: [...COMMON_DOCUMENT_SIGNAL_GROUPS],
|
|
532
|
+
coveragePatterns: SALES_TAILOR_COVERAGE_PATTERNS,
|
|
533
|
+
storyDefinitions: SALES_TAILOR_STORY_DEFINITIONS,
|
|
534
|
+
workflowPositions: SALES_TAILOR_WORKFLOW_POSITIONS
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
const BRAINBASE_CODE_SURFACE_SIGNATURES = [
|
|
538
|
+
{
|
|
539
|
+
id: 'story-code-cli-tooling',
|
|
540
|
+
title: 'CLIツールと配布インターフェースを整える',
|
|
541
|
+
category: 'product',
|
|
542
|
+
patterns: [/^cli\//]
|
|
543
|
+
},
|
|
544
|
+
{
|
|
545
|
+
id: 'story-code-mcp-ssot',
|
|
546
|
+
title: 'MCP経由のSSOT入出力を整える',
|
|
547
|
+
category: 'architecture',
|
|
548
|
+
patterns: [/^mcp\/brainbase\//]
|
|
549
|
+
},
|
|
550
|
+
{
|
|
551
|
+
id: 'story-code-mcp-external',
|
|
552
|
+
title: 'MCP経由の外部連携を整理する',
|
|
553
|
+
category: 'product',
|
|
554
|
+
patterns: [/^mcp\/(?!brainbase\/)[^/]+\//]
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
id: 'story-code-portal-views',
|
|
558
|
+
title: '役割別ポータル・ビューを成立させる',
|
|
559
|
+
category: 'product',
|
|
560
|
+
patterns: [
|
|
561
|
+
/^public\/modules\/(app|settings|auth|device|setup|ui)\//,
|
|
562
|
+
/^public\/modules\/(dashboard|session-list-renderer|session-handlers|session-manager|session-ui-state|session-indicators|task-manager|state|state-api|project-mapping)\.[jt]sx?$/,
|
|
563
|
+
/^server\/routes\/brainbase\//,
|
|
564
|
+
/^server\/routes\/vibepro\//,
|
|
565
|
+
/^server\/routes\/(setup|state|inbox|schedule|tasks|timeline|wiki|info-ssot)\.js$/,
|
|
566
|
+
/^server\/controllers\/(brainbase-action|info-ssot|inbox|schedule|task|timeline|wiki|setup|state)-controller\.js$/
|
|
567
|
+
]
|
|
568
|
+
},
|
|
569
|
+
{
|
|
570
|
+
id: 'story-code-domain-data',
|
|
571
|
+
title: 'SSOTドメインデータと取り込みパイプラインを整える',
|
|
572
|
+
category: 'product',
|
|
573
|
+
patterns: [
|
|
574
|
+
/^public\/modules\/domain\/(nocodb-issue|nocodb-task)\//,
|
|
575
|
+
/^server\/services\/(info-ssot|nocodb|conversation-linker)/,
|
|
576
|
+
/^server\/controllers\/(info-ssot|nocodb)-controller\.js$/,
|
|
577
|
+
/^server\/routes\/(nocodb|info-ssot)\.js$/,
|
|
578
|
+
/^lib\/(config-parser|inbox-parser|kiro-schedule-parser|kiro-task-parser|schedule-parser|task-parser|task-directory-scanner|task-file-manager)\.js$/
|
|
579
|
+
]
|
|
580
|
+
},
|
|
581
|
+
{
|
|
582
|
+
id: 'story-code-mana-detection',
|
|
583
|
+
title: 'mana 観測対象とセッション健全性を整える',
|
|
584
|
+
category: 'product',
|
|
585
|
+
patterns: [
|
|
586
|
+
/^server\/services\/(session-runtime|session-core)\//,
|
|
587
|
+
/^server\/services\/(session-activity-ws|session-health-monitor|learning-service|learning-health)/,
|
|
588
|
+
/^server\/controllers\/session\//,
|
|
589
|
+
/^server\/routes\/(sessions|learning|usage)\.js$/,
|
|
590
|
+
/^public\/modules\/domain\/timeline\//,
|
|
591
|
+
/^lib\/timeline-storage\.js$/
|
|
592
|
+
]
|
|
593
|
+
},
|
|
594
|
+
{
|
|
595
|
+
id: 'story-code-terminal-runtime',
|
|
596
|
+
title: 'terminal/tmux 実行基盤を整える',
|
|
597
|
+
category: 'architecture',
|
|
598
|
+
patterns: [
|
|
599
|
+
/^server\/services\/(terminal-|tmux-|cli-pattern-detector|pasted-text-detector|terminal-output-parser)/,
|
|
600
|
+
/^server\/routes\/terminal\.js$/,
|
|
601
|
+
/^public\/modules\/terminal\//,
|
|
602
|
+
/^public\/modules\/xterm-/
|
|
603
|
+
]
|
|
604
|
+
},
|
|
605
|
+
{
|
|
606
|
+
id: 'story-code-mesh-network',
|
|
607
|
+
title: 'mesh 通信境界とセキュリティを整える',
|
|
608
|
+
category: 'architecture',
|
|
609
|
+
patterns: [
|
|
610
|
+
/^server\/mesh\//,
|
|
611
|
+
/^server\/routes\/mesh\.js$/
|
|
612
|
+
]
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
id: 'story-code-external-integrations',
|
|
616
|
+
title: '外部システム連携を整理する',
|
|
617
|
+
category: 'product',
|
|
618
|
+
patterns: [
|
|
619
|
+
/^server\/services\/(github-service|google-calendar-service|honcho-service|wiki-service)\.js$/,
|
|
620
|
+
/^server\/routes\/wiki\.js$/,
|
|
621
|
+
/^server\/controllers\/wiki-controller\.js$/,
|
|
622
|
+
/^lib\/(calendar-event-converter|google-calendar-utils)\.js$/
|
|
623
|
+
]
|
|
624
|
+
},
|
|
625
|
+
{
|
|
626
|
+
id: 'story-code-core-platform',
|
|
627
|
+
title: 'コア基盤の責務分離(EventBus / DI / Store)',
|
|
628
|
+
category: 'architecture',
|
|
629
|
+
patterns: [
|
|
630
|
+
/^public\/modules\/core\//,
|
|
631
|
+
/^public\/modules\/(components|utils)\//,
|
|
632
|
+
/^public\/modules\/(confirm-modal|file-opener|file-preview-config|file-upload|iframe-contextmenu|mobile-keyboard|toast|ui-helpers)/,
|
|
633
|
+
/^server\/(middleware|lib|utils|bootstrap)\//,
|
|
634
|
+
/^lib\/(atomic-mutex|runtime-paths|sqlite-store|state-store)\.js$/,
|
|
635
|
+
/^server\/services\/(auth-service|config-service|env-sanitizer|storage-service|system-service|token-usage-service|worktree-service|archive-finalizer-service|create-session-services)\.js$/
|
|
636
|
+
]
|
|
637
|
+
},
|
|
638
|
+
{
|
|
639
|
+
id: 'story-code-health-ops',
|
|
640
|
+
title: '稼働状態と運用確認を見える化する',
|
|
641
|
+
category: 'ops',
|
|
642
|
+
patterns: [
|
|
643
|
+
/^server\/controllers\/(health|misc)-controller\.js$/,
|
|
644
|
+
/^server\/routes\/(health|misc)\.js$/
|
|
645
|
+
]
|
|
646
|
+
}
|
|
647
|
+
];
|
|
648
|
+
|
|
649
|
+
const BRAINBASE_COVERAGE_PATTERNS = Object.fromEntries(
|
|
650
|
+
BRAINBASE_CODE_SURFACE_SIGNATURES.map((sig) => [sig.id, sig.patterns])
|
|
651
|
+
);
|
|
652
|
+
|
|
653
|
+
const BRAINBASE_PRESET = {
|
|
654
|
+
id: 'brainbase',
|
|
655
|
+
isCodePath: (filePath) =>
|
|
656
|
+
typeof filePath === 'string' &&
|
|
657
|
+
/^(cli\/|lib\/|mcp\/|public\/modules\/|server\/|src\/)/.test(filePath),
|
|
658
|
+
storyRelevantPatterns: MODULAR_WEB_RELEVANT_PATTERNS,
|
|
659
|
+
classifyRole: classifyModularWeb,
|
|
660
|
+
codeSurfaceSignatures: BRAINBASE_CODE_SURFACE_SIGNATURES,
|
|
661
|
+
productSurfaceSignals: [],
|
|
662
|
+
documentSignalGroups: [...COMMON_DOCUMENT_SIGNAL_GROUPS],
|
|
663
|
+
coveragePatterns: BRAINBASE_COVERAGE_PATTERNS
|
|
664
|
+
};
|
|
665
|
+
|
|
666
|
+
const PRESETS = {
|
|
667
|
+
'next-app': NEXT_APP_PRESET,
|
|
668
|
+
'modular-web': MODULAR_WEB_PRESET,
|
|
669
|
+
salestailor: SALES_TAILOR_PRESET,
|
|
670
|
+
brainbase: BRAINBASE_PRESET
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
export const DEFAULT_PRESET_ID = 'next-app';
|
|
674
|
+
|
|
675
|
+
export function getPreset(name) {
|
|
676
|
+
if (name && PRESETS[name]) return PRESETS[name];
|
|
677
|
+
return PRESETS[DEFAULT_PRESET_ID];
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
export function resolvePresetId(config, explicitPreset = null) {
|
|
681
|
+
return explicitPreset ?? config?.story_catalog?.preset ?? DEFAULT_PRESET_ID;
|
|
682
|
+
}
|