codetrap 0.1.6 → 0.1.8

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.
Files changed (60) hide show
  1. package/README.md +159 -51
  2. package/docs/installation.md +113 -29
  3. package/package.json +4 -3
  4. package/plugins/codetrap-agent/.codex-plugin/plugin.json +1 -2
  5. package/plugins/codetrap-agent/hooks/post-flight-capture.example.md +19 -17
  6. package/plugins/codetrap-agent/hooks.json +2 -2
  7. package/{skills → plugins/codetrap-agent/skills}/codetrap-add/SKILL.md +10 -4
  8. package/plugins/codetrap-agent/skills/codetrap-capture/SKILL.md +14 -3
  9. package/plugins/codetrap-agent/skills/codetrap-capture-external/SKILL.md +52 -9
  10. package/plugins/codetrap-agent/skills/codetrap-check/SKILL.md +74 -6
  11. package/{skills → plugins/codetrap-agent/skills}/codetrap-search/SKILL.md +6 -5
  12. package/plugins/codetrap-agent/templates/AGENTS.codetrap.md +31 -5
  13. package/scripts/search-policy-sweep.ts +131 -0
  14. package/src/commands/workflow.ts +186 -68
  15. package/src/db/connection.ts +6 -6
  16. package/src/db/embedding-queries.ts +230 -48
  17. package/src/db/queries.ts +0 -25
  18. package/src/db/repository.ts +32 -21
  19. package/src/db/schema.ts +80 -0
  20. package/src/index.ts +32 -7
  21. package/src/lib/command-requests.ts +134 -1
  22. package/src/lib/config.ts +57 -7
  23. package/src/lib/constants.ts +1 -1
  24. package/src/lib/doctor.ts +96 -6
  25. package/src/lib/embed-output.ts +26 -0
  26. package/src/lib/embedder.ts +118 -3
  27. package/src/lib/embedding-health.ts +3 -1
  28. package/src/lib/embedding-job.ts +3 -0
  29. package/src/lib/embedding-management.ts +65 -0
  30. package/src/lib/embedding-runtime.ts +177 -0
  31. package/src/lib/output-json.ts +0 -2
  32. package/src/lib/scope-context.ts +17 -11
  33. package/src/lib/scope-migration.ts +2 -1
  34. package/src/lib/scope.ts +4 -6
  35. package/src/lib/search-eval.ts +136 -23
  36. package/src/lib/search-policy-sweep.ts +563 -0
  37. package/src/lib/search-policy.ts +0 -4
  38. package/src/lib/search-service.ts +14 -15
  39. package/src/lib/session-candidate-document.ts +175 -0
  40. package/src/lib/session-candidate-scope.ts +6 -0
  41. package/src/lib/session-capture.ts +298 -32
  42. package/src/lib/session-codec.ts +1 -8
  43. package/src/lib/session-operations.ts +111 -51
  44. package/src/lib/session-review.ts +327 -0
  45. package/src/lib/session-store.ts +177 -55
  46. package/src/lib/store.ts +79 -11
  47. package/src/lib/string-list.ts +3 -0
  48. package/src/lib/text-lines.ts +7 -0
  49. package/src/lib/trap-search-document.ts +2 -1
  50. package/src/lib/value-types.ts +3 -0
  51. package/src/web/client-review.ts +171 -0
  52. package/src/web/client-script.ts +1543 -0
  53. package/src/web/client-shell.ts +414 -0
  54. package/src/web/client-text.ts +447 -0
  55. package/src/web/project-registry.ts +3 -5
  56. package/src/web/server.ts +184 -111
  57. package/src/web/static.ts +581 -484
  58. package/skills/codetrap-capture-external/SKILL.md +0 -62
  59. package/skills/codetrap-check/SKILL.md +0 -69
  60. package/src/lib/embedding-index.ts +0 -53
@@ -0,0 +1,447 @@
1
+ export const WEB_TEXT = {
2
+ en: {
3
+ "app.subtitle": "review console",
4
+ "nav.review": "Review",
5
+ "nav.library": "Library",
6
+ "nav.insights": "Insights",
7
+ "nav.embeddings": "Embeddings",
8
+ "action.refresh": "Refresh",
9
+ "action.add": "Add",
10
+ "action.hideSidebar": "Hide sidebar",
11
+ "action.showSidebar": "Show sidebar",
12
+ "action.hideQueue": "Hide queue pane",
13
+ "action.showQueue": "Show queue pane",
14
+ "action.deleteSession": "Delete",
15
+ "action.cleanDeletedCandidates": "Clear deleted candidates",
16
+ "action.useProvider": "Use provider",
17
+ "action.reindexProject": "Reindex project",
18
+ "action.reindexGlobal": "Reindex global",
19
+ "section.sessions": "sessions",
20
+ "placeholder.projectPath": "/path/to/project",
21
+ "placeholder.endpoint": "http://127.0.0.1:11434",
22
+ "placeholder.model": "qwen3-embedding:0.6b",
23
+ "title.candidateInbox": "candidate inbox",
24
+ "title.candidateDetail": "candidate detail",
25
+ "title.trapLibrary": "trap library",
26
+ "title.trapDetail": "trap detail",
27
+ "title.growthInsights": "growth insights",
28
+ "title.insightDetail": "insight detail",
29
+ "title.embeddings": "embeddings",
30
+ "title.embeddingDetail": "semantic search detail",
31
+ "title.currentProfile": "current profile",
32
+ "title.projectEmbeddings": "project embeddings",
33
+ "title.globalEmbeddings": "global embeddings",
34
+ "title.storedProfiles": "stored profiles",
35
+ "title.providerSetup": "provider setup",
36
+ "title.reindex": "reindex",
37
+ "title.recentTraps": "recent traps",
38
+ "title.mostViewed": "most viewed",
39
+ "title.recentHighSeverity": "recent high severity",
40
+ "title.evidence": "evidence",
41
+ "title.possibleConflicts": "possible conflicts",
42
+ "title.before": "Before",
43
+ "title.after": "After",
44
+ "tab.inbox": "Inbox {count}",
45
+ "tab.reviewed": "Reviewed {count}",
46
+ "meta.noProject": "no project selected",
47
+ "meta.noSession": "no session selected",
48
+ "meta.sessionCounts": "{goal} / {pending} pending, {reviewed} reviewed",
49
+ "meta.libraryCounts": "{shown} shown / {loaded} loaded / {sort}",
50
+ "meta.insightCounts": "{count} traps / {status} status",
51
+ "meta.embeddingCounts": "{provider} / project {projectFresh}/{projectTotal} fresh / global {globalFresh}/{globalTotal} fresh",
52
+ "meta.embeddingDetail": "{profile} / {state}",
53
+ "meta.selectCandidate": "select a candidate",
54
+ "meta.selectTrap": "select a trap",
55
+ "meta.selectProject": "select a project",
56
+ "empty.noProjects": "No projects",
57
+ "empty.noSessions": "No sessions",
58
+ "empty.noPending": "No pending candidates",
59
+ "empty.noReviewed": "No reviewed candidates",
60
+ "empty.noTrapMatches": "No traps match this view",
61
+ "empty.noTrapSelected": "No trap selected",
62
+ "empty.loadingTrapDetails": "Loading trap details",
63
+ "empty.noCandidateSelected": "No candidate selected",
64
+ "empty.noEvidence": "No evidence",
65
+ "empty.noData": "No data",
66
+ "empty.noTraps": "No traps",
67
+ "empty.noProfiles": "No stored profiles",
68
+ "action.viewTrap": "View trap",
69
+ "action.clearFilters": "Clear filters",
70
+ "action.save": "Save",
71
+ "action.accept": "Accept",
72
+ "action.reject": "Reject",
73
+ "action.acceptAnyway": "Accept anyway",
74
+ "action.supersede": "Supersede",
75
+ "placeholder.searchTraps": "Search title, context, mistake, fix, tags",
76
+ "placeholder.anyModule": "any module",
77
+ "placeholder.anyOwner": "any owner",
78
+ "placeholder.supersedesId": "supersedes id",
79
+ "label.scope": "Scope",
80
+ "label.status": "Status",
81
+ "label.category": "Category",
82
+ "label.sort": "Sort",
83
+ "label.module": "Module",
84
+ "label.owner": "Owner",
85
+ "label.provider": "Provider",
86
+ "label.endpoint": "Endpoint",
87
+ "label.model": "Model",
88
+ "label.dimensions": "Dimensions",
89
+ "label.profileId": "Profile id",
90
+ "label.available": "Available",
91
+ "label.setupAction": "Next action",
92
+ "label.fresh": "Fresh",
93
+ "label.stale": "Stale",
94
+ "label.missing": "Missing",
95
+ "label.total": "Total",
96
+ "label.count": "Count",
97
+ "label.title": "Title",
98
+ "label.severity": "Severity",
99
+ "label.tags": "Tags",
100
+ "label.pathGlobs": "Path globs",
101
+ "label.context": "Context",
102
+ "label.mistake": "Mistake",
103
+ "label.fix": "Fix",
104
+ "label.created": "Created",
105
+ "label.updated": "Updated",
106
+ "label.stateKey": "State key",
107
+ "label.supersedes": "Supersedes",
108
+ "label.validFrom": "Valid from",
109
+ "label.validUntil": "Valid until",
110
+ "metric.loadedTraps": "Loaded traps",
111
+ "metric.confirmedTraps": "Confirmed traps",
112
+ "metric.highSeverity": "High severity",
113
+ "metric.topCategory": "Top category",
114
+ "metric.focusArea": "Focus area",
115
+ "metric.mostViewed": "Most viewed",
116
+ "metric.activeProvider": "Active provider",
117
+ "metric.activeProfile": "Active profile",
118
+ "metric.projectFresh": "Project fresh",
119
+ "metric.globalFresh": "Global fresh",
120
+ "metric.currentFilters": "current filters",
121
+ "metric.selectedScope": "selected scope",
122
+ "metric.errorCritical": "error + critical",
123
+ "metric.repeatedPattern": "repeated pattern",
124
+ "metric.largestPattern": "largest pattern",
125
+ "metric.module": "module",
126
+ "metric.tag": "tag",
127
+ "metric.noHits": "no hits yet",
128
+ "insight.categories": "categories",
129
+ "insight.modules": "modules",
130
+ "insight.tags": "tags",
131
+ "insight.severityMix": "severity mix",
132
+ "option.projectGlobal": "project + global",
133
+ "option.allCategories": "all categories",
134
+ "sort.updated": "recently updated",
135
+ "sort.severity": "severity",
136
+ "sort.hits": "hit count",
137
+ "sort.category": "category",
138
+ "sort.title": "title",
139
+ "sortLabel.updated": "recent first",
140
+ "sortLabel.severity": "severity first",
141
+ "sortLabel.hits": "hits first",
142
+ "sortLabel.category": "category sort",
143
+ "sortLabel.title": "title sort",
144
+ "pill.hits": "{count} hits",
145
+ "pill.pending": "{count} pending",
146
+ "pill.candidates": "{count} candidates",
147
+ "pill.accepted": "{count} accepted",
148
+ "pill.warnings": "{count} warnings",
149
+ "pill.quality": "quality {score}",
150
+ "pill.conflict": "conflict {status}",
151
+ "pill.action": "action {action}",
152
+ "review.pending": "pending review",
153
+ "reviewSummary.pending": "{count} pending candidate(s)",
154
+ "reviewSummary.sessions": "{count} session(s)",
155
+ "reviewSummary.quality": "{high} high quality / {edit} need edit",
156
+ "review.rejected": "rejected",
157
+ "review.accepted": "accepted -> trap #{id}",
158
+ "review.acceptedDeleted": "accepted -> trap #{id} deleted",
159
+ "review.acceptedLinkMissing": "accepted -> trap link missing",
160
+ "embedding.available": "available",
161
+ "embedding.unavailable": "unavailable",
162
+ "embedding.notConfigured": "not configured",
163
+ "embedding.noProfile": "no active profile",
164
+ "embedding.activeProfile": "active profile",
165
+ "embedding.profileNeedsReindex": "profile needs reindex",
166
+ "status.refreshed": "Refreshed",
167
+ "status.candidateSaved": "Candidate saved",
168
+ "status.candidateRejected": "Candidate rejected",
169
+ "status.candidateAccepted": "Candidate accepted",
170
+ "status.possibleConflict": "Possible conflict found",
171
+ "status.supersedesRequired": "Supersedes id is required",
172
+ "status.openedTrap": "Opened trap #{id}",
173
+ "status.trapNotInLibrary": "Trap #{id} is not in the current library",
174
+ "status.sessionDeleted": "Session deleted",
175
+ "status.deletedCandidatesCleaned": "Deleted candidate links cleared",
176
+ "status.embeddingProviderSaved": "Embedding provider saved",
177
+ "status.embeddingsReindexed": "Embeddings reindexed: {generated} generated, {skipped} skipped",
178
+ "status.invalidDimensions": "Dimensions must be a positive integer",
179
+ "hint.acceptUsesCurrentDraft": "Accept uses the current draft.",
180
+ "hint.unsavedDraftAccepted": "Unsaved edits will be accepted.",
181
+ "hint.jinaEnv": "Jina uses JINA_API_KEY from the environment; the web console does not save API keys.",
182
+ "hint.reindexAfterSwitch": "Reindex project or global embeddings before semantic/hybrid search can use the active profile.",
183
+ "prompt.rejectReason": "Reject reason",
184
+ "prompt.deleteSession": "Delete session {id}?",
185
+ "value.project": "project",
186
+ "value.global": "global",
187
+ "value.ollama": "Ollama",
188
+ "value.jina": "Jina",
189
+ "value.active": "active",
190
+ "value.all": "all",
191
+ "value.archived": "archived",
192
+ "value.superseded": "superseded",
193
+ "value.proposed": "proposed",
194
+ "value.accepted": "accepted",
195
+ "value.rejected": "rejected",
196
+ "value.accepted_missing": "accepted missing",
197
+ "value.warning": "warning",
198
+ "value.error": "error",
199
+ "value.critical": "critical",
200
+ "value.api": "api",
201
+ "value.database": "database",
202
+ "value.auth": "auth",
203
+ "value.convention": "convention",
204
+ "value.security": "security",
205
+ "value.performance": "performance",
206
+ "value.bug": "bug",
207
+ "value.other": "other",
208
+ "value.none": "none",
209
+ "value.possible": "possible",
210
+ "value.confirmed": "confirmed",
211
+ "value.accept": "accept",
212
+ "value.edit": "edit",
213
+ "value.supersede": "supersede",
214
+ "value.archive_old": "archive old",
215
+ "value.manual": "manual",
216
+ "value.conversation": "conversation",
217
+ "value.commit": "commit",
218
+ "value.issue": "issue",
219
+ "value.test_failure": "test failure",
220
+ "value.article": "article",
221
+ },
222
+ zh: {
223
+ "app.subtitle": "复盘控制台",
224
+ "nav.review": "审核",
225
+ "nav.library": "库",
226
+ "nav.insights": "洞察",
227
+ "nav.embeddings": "嵌入",
228
+ "action.refresh": "刷新",
229
+ "action.add": "添加",
230
+ "action.hideSidebar": "隐藏侧边栏",
231
+ "action.showSidebar": "显示侧边栏",
232
+ "action.hideQueue": "隐藏队列栏",
233
+ "action.showQueue": "显示队列栏",
234
+ "action.deleteSession": "删除",
235
+ "action.cleanDeletedCandidates": "清除已删除候选",
236
+ "action.useProvider": "使用提供方",
237
+ "action.reindexProject": "重建项目索引",
238
+ "action.reindexGlobal": "重建全局索引",
239
+ "section.sessions": "会话",
240
+ "placeholder.projectPath": "/项目/路径",
241
+ "placeholder.endpoint": "http://127.0.0.1:11434",
242
+ "placeholder.model": "qwen3-embedding:0.6b",
243
+ "title.candidateInbox": "候选收件箱",
244
+ "title.candidateDetail": "候选详情",
245
+ "title.trapLibrary": "陷阱库",
246
+ "title.trapDetail": "陷阱详情",
247
+ "title.growthInsights": "成长洞察",
248
+ "title.insightDetail": "洞察详情",
249
+ "title.embeddings": "嵌入",
250
+ "title.embeddingDetail": "语义搜索详情",
251
+ "title.currentProfile": "当前 profile",
252
+ "title.projectEmbeddings": "项目嵌入",
253
+ "title.globalEmbeddings": "全局嵌入",
254
+ "title.storedProfiles": "已存 profile",
255
+ "title.providerSetup": "提供方设置",
256
+ "title.reindex": "重建索引",
257
+ "title.recentTraps": "最近陷阱",
258
+ "title.mostViewed": "查看最多",
259
+ "title.recentHighSeverity": "最近高严重度",
260
+ "title.evidence": "证据",
261
+ "title.possibleConflicts": "可能冲突",
262
+ "title.before": "修改前",
263
+ "title.after": "修改后",
264
+ "tab.inbox": "待审 {count}",
265
+ "tab.reviewed": "已审 {count}",
266
+ "meta.noProject": "未选择项目",
267
+ "meta.noSession": "未选择会话",
268
+ "meta.sessionCounts": "{goal} / {pending} 个待审,{reviewed} 个已审",
269
+ "meta.libraryCounts": "显示 {shown} / 已加载 {loaded} / {sort}",
270
+ "meta.insightCounts": "{count} 条陷阱 / 状态 {status}",
271
+ "meta.embeddingCounts": "{provider} / 项目 {projectFresh}/{projectTotal} fresh / 全局 {globalFresh}/{globalTotal} fresh",
272
+ "meta.embeddingDetail": "{profile} / {state}",
273
+ "meta.selectCandidate": "选择一个候选",
274
+ "meta.selectTrap": "选择一个陷阱",
275
+ "meta.selectProject": "选择一个项目",
276
+ "empty.noProjects": "没有项目",
277
+ "empty.noSessions": "没有会话",
278
+ "empty.noPending": "没有待审候选",
279
+ "empty.noReviewed": "没有已审候选",
280
+ "empty.noTrapMatches": "没有匹配的陷阱",
281
+ "empty.noTrapSelected": "未选择陷阱",
282
+ "empty.loadingTrapDetails": "正在加载陷阱详情",
283
+ "empty.noCandidateSelected": "未选择候选",
284
+ "empty.noEvidence": "没有证据",
285
+ "empty.noData": "没有数据",
286
+ "empty.noTraps": "没有陷阱",
287
+ "empty.noProfiles": "没有已存 profile",
288
+ "action.viewTrap": "查看陷阱",
289
+ "action.clearFilters": "清除筛选",
290
+ "action.save": "保存",
291
+ "action.accept": "接受",
292
+ "action.reject": "拒绝",
293
+ "action.acceptAnyway": "仍然接受",
294
+ "action.supersede": "标记取代",
295
+ "placeholder.searchTraps": "搜索标题、上下文、错误、修复、标签",
296
+ "placeholder.anyModule": "任意模块",
297
+ "placeholder.anyOwner": "任意负责人",
298
+ "placeholder.supersedesId": "被取代的 id",
299
+ "label.scope": "范围",
300
+ "label.status": "状态",
301
+ "label.category": "分类",
302
+ "label.sort": "排序",
303
+ "label.module": "模块",
304
+ "label.owner": "负责人",
305
+ "label.provider": "提供方",
306
+ "label.endpoint": "端点",
307
+ "label.model": "模型",
308
+ "label.dimensions": "维度",
309
+ "label.profileId": "Profile id",
310
+ "label.available": "可用",
311
+ "label.setupAction": "下一步",
312
+ "label.fresh": "Fresh",
313
+ "label.stale": "Stale",
314
+ "label.missing": "Missing",
315
+ "label.total": "总数",
316
+ "label.count": "数量",
317
+ "label.title": "标题",
318
+ "label.severity": "严重度",
319
+ "label.tags": "标签",
320
+ "label.pathGlobs": "路径规则",
321
+ "label.context": "上下文",
322
+ "label.mistake": "错误",
323
+ "label.fix": "修复",
324
+ "label.created": "创建时间",
325
+ "label.updated": "更新时间",
326
+ "label.stateKey": "状态键",
327
+ "label.supersedes": "取代",
328
+ "label.validFrom": "生效开始",
329
+ "label.validUntil": "生效结束",
330
+ "metric.loadedTraps": "已加载陷阱",
331
+ "metric.confirmedTraps": "确认陷阱",
332
+ "metric.highSeverity": "高严重度",
333
+ "metric.topCategory": "最高分类",
334
+ "metric.focusArea": "关注区域",
335
+ "metric.mostViewed": "查看最多",
336
+ "metric.activeProvider": "当前提供方",
337
+ "metric.activeProfile": "当前 profile",
338
+ "metric.projectFresh": "项目 fresh",
339
+ "metric.globalFresh": "全局 fresh",
340
+ "metric.currentFilters": "当前筛选",
341
+ "metric.selectedScope": "选中范围",
342
+ "metric.errorCritical": "error + critical",
343
+ "metric.repeatedPattern": "重复模式",
344
+ "metric.largestPattern": "最大模式",
345
+ "metric.module": "模块",
346
+ "metric.tag": "标签",
347
+ "metric.noHits": "还没有查看记录",
348
+ "insight.categories": "分类",
349
+ "insight.modules": "模块",
350
+ "insight.tags": "标签",
351
+ "insight.severityMix": "严重度分布",
352
+ "option.projectGlobal": "项目 + 全局",
353
+ "option.allCategories": "全部分类",
354
+ "sort.updated": "最近更新",
355
+ "sort.severity": "严重度",
356
+ "sort.hits": "查看次数",
357
+ "sort.category": "分类",
358
+ "sort.title": "标题",
359
+ "sortLabel.updated": "最近优先",
360
+ "sortLabel.severity": "严重度优先",
361
+ "sortLabel.hits": "查看次数优先",
362
+ "sortLabel.category": "按分类排序",
363
+ "sortLabel.title": "按标题排序",
364
+ "pill.hits": "{count} 次查看",
365
+ "pill.pending": "{count} 个待审",
366
+ "pill.candidates": "{count} 个候选",
367
+ "pill.accepted": "{count} 个已接受",
368
+ "pill.warnings": "{count} 个警告",
369
+ "pill.quality": "质量 {score}",
370
+ "pill.conflict": "冲突 {status}",
371
+ "pill.action": "建议 {action}",
372
+ "review.pending": "待审核",
373
+ "reviewSummary.pending": "{count} 个待审候选",
374
+ "reviewSummary.sessions": "{count} 个会话",
375
+ "reviewSummary.quality": "{high} 个高质量 / {edit} 个需编辑",
376
+ "review.rejected": "已拒绝",
377
+ "review.accepted": "已接受 -> 陷阱 #{id}",
378
+ "review.acceptedDeleted": "已接受 -> 陷阱 #{id} 已删除",
379
+ "review.acceptedLinkMissing": "已接受 -> 缺少陷阱链接",
380
+ "embedding.available": "可用",
381
+ "embedding.unavailable": "不可用",
382
+ "embedding.notConfigured": "未配置",
383
+ "embedding.noProfile": "没有当前 profile",
384
+ "embedding.activeProfile": "当前 profile",
385
+ "embedding.profileNeedsReindex": "profile 需要重建索引",
386
+ "status.refreshed": "已刷新",
387
+ "status.candidateSaved": "候选已保存",
388
+ "status.candidateRejected": "候选已拒绝",
389
+ "status.candidateAccepted": "候选已接受",
390
+ "status.possibleConflict": "发现可能冲突",
391
+ "status.supersedesRequired": "需要填写被取代的 id",
392
+ "status.openedTrap": "已打开陷阱 #{id}",
393
+ "status.trapNotInLibrary": "当前陷阱库里没有陷阱 #{id}",
394
+ "status.sessionDeleted": "会话已删除",
395
+ "status.deletedCandidatesCleaned": "已清除删除候选链接",
396
+ "status.embeddingProviderSaved": "嵌入提供方已保存",
397
+ "status.embeddingsReindexed": "嵌入索引已重建:生成 {generated},跳过 {skipped}",
398
+ "status.invalidDimensions": "维度必须是正整数",
399
+ "hint.acceptUsesCurrentDraft": "接受时会使用当前草稿。",
400
+ "hint.unsavedDraftAccepted": "未保存编辑也会随接受生效。",
401
+ "hint.jinaEnv": "Jina 使用环境变量 JINA_API_KEY;网页控制台不会保存 API key。",
402
+ "hint.reindexAfterSwitch": "重建项目或全局嵌入后,语义/混合搜索才能使用当前 profile。",
403
+ "prompt.rejectReason": "拒绝原因",
404
+ "prompt.deleteSession": "删除会话 {id}?",
405
+ "value.project": "项目",
406
+ "value.global": "全局",
407
+ "value.ollama": "Ollama",
408
+ "value.jina": "Jina",
409
+ "value.active": "有效",
410
+ "value.all": "全部",
411
+ "value.archived": "已归档",
412
+ "value.superseded": "已取代",
413
+ "value.proposed": "待提议",
414
+ "value.accepted": "已接受",
415
+ "value.rejected": "已拒绝",
416
+ "value.accepted_missing": "接受记录缺失",
417
+ "value.warning": "警告",
418
+ "value.error": "错误",
419
+ "value.critical": "严重",
420
+ "value.api": "API",
421
+ "value.database": "数据库",
422
+ "value.auth": "认证",
423
+ "value.convention": "约定",
424
+ "value.security": "安全",
425
+ "value.performance": "性能",
426
+ "value.bug": "缺陷",
427
+ "value.other": "其他",
428
+ "value.none": "无",
429
+ "value.possible": "可能",
430
+ "value.confirmed": "确认",
431
+ "value.accept": "接受",
432
+ "value.edit": "编辑",
433
+ "value.supersede": "取代",
434
+ "value.archive_old": "归档旧项",
435
+ "value.manual": "手动",
436
+ "value.conversation": "对话",
437
+ "value.commit": "提交",
438
+ "value.issue": "Issue",
439
+ "value.test_failure": "测试失败",
440
+ "value.article": "文章",
441
+ }
442
+ } as const;
443
+
444
+ export type WebLocale = keyof typeof WEB_TEXT;
445
+ export type WebTextKey = keyof typeof WEB_TEXT["en"];
446
+
447
+ export const WEB_TEXT_JSON = JSON.stringify(WEB_TEXT);
@@ -2,7 +2,9 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
2
  import { homedir } from "node:os";
3
3
  import { basename, join } from "node:path";
4
4
  import { CODETRAP_DIR } from "../lib/constants";
5
- import { findProjectRoot, resolveScopePath } from "../lib/scope";
5
+ import { findProjectRoot } from "../lib/scope";
6
+ import { resolveScopePath } from "../lib/scope-path";
7
+ import { isRecord } from "../lib/value-types";
6
8
 
7
9
  export const WEB_PROJECTS_FILE = "web-projects.json";
8
10
  export const WEB_PROJECTS_VERSION = 1;
@@ -100,7 +102,3 @@ function uniqueProjects(projects: WebProject[]): WebProject[] {
100
102
  }
101
103
  return out;
102
104
  }
103
-
104
- function isRecord(value: unknown): value is Record<string, unknown> {
105
- return typeof value === "object" && value !== null && !Array.isArray(value);
106
- }