cmp-standards 3.5.0 → 3.7.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/README.md +399 -633
- package/dist/analytics/CrossProjectAnalytics.js +65 -65
- package/dist/cli/index.js +255 -12
- package/dist/cli/index.js.map +1 -1
- package/dist/dashboard/tokens.js +173 -173
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +2 -0
- package/dist/db/client.js.map +1 -1
- package/dist/db/cloud.d.ts +1 -0
- package/dist/db/cloud.d.ts.map +1 -1
- package/dist/db/drizzle-client.d.ts +2 -2
- package/dist/db/drizzle-client.d.ts.map +1 -1
- package/dist/db/drizzle-client.js +0 -1
- package/dist/db/drizzle-client.js.map +1 -1
- package/dist/db/migrations.js +256 -256
- package/dist/db/turso-client.js +2 -2
- package/dist/db/upstash-client.d.ts +9 -0
- package/dist/db/upstash-client.d.ts.map +1 -1
- package/dist/db/upstash-client.js +11 -0
- package/dist/db/upstash-client.js.map +1 -1
- package/dist/eslint/rules/no-async-useeffect.js +6 -6
- package/dist/experts/ExpertVotePersistence.js +9 -9
- package/dist/feedback/collector.d.ts.map +1 -1
- package/dist/feedback/collector.js +6 -2
- package/dist/feedback/collector.js.map +1 -1
- package/dist/hooks/cloud-post-tool-use.d.ts.map +1 -1
- package/dist/hooks/cloud-post-tool-use.js +72 -10
- package/dist/hooks/cloud-post-tool-use.js.map +1 -1
- package/dist/hooks/cloud-pre-tool-use.d.ts +12 -9
- package/dist/hooks/cloud-pre-tool-use.d.ts.map +1 -1
- package/dist/hooks/cloud-pre-tool-use.js +227 -99
- package/dist/hooks/cloud-pre-tool-use.js.map +1 -1
- package/dist/hooks/cloud-session-start.d.ts.map +1 -1
- package/dist/hooks/cloud-session-start.js +19 -16
- package/dist/hooks/cloud-session-start.js.map +1 -1
- package/dist/hooks/resilient-hook-runner.d.ts +78 -0
- package/dist/hooks/resilient-hook-runner.d.ts.map +1 -0
- package/dist/hooks/resilient-hook-runner.js +201 -0
- package/dist/hooks/resilient-hook-runner.js.map +1 -0
- package/dist/hooks/session-end.js +14 -14
- package/dist/patterns/registry.js +90 -90
- package/dist/registry/generator.d.ts.map +1 -1
- package/dist/registry/generator.js +31 -21
- package/dist/registry/generator.js.map +1 -1
- package/dist/schema/codewiki-types.d.ts +10 -10
- package/dist/schema/docs-types.d.ts +8 -8
- package/dist/schema/ecosystem-types.d.ts +12 -12
- package/dist/schema/expert-types.d.ts +2 -2
- package/dist/schema/opportunity-types.d.ts +6 -6
- package/dist/schema/tracking.d.ts +2 -2
- package/dist/services/BootstrapService.d.ts +123 -0
- package/dist/services/BootstrapService.d.ts.map +1 -0
- package/dist/services/BootstrapService.js +309 -0
- package/dist/services/BootstrapService.js.map +1 -0
- package/dist/services/CodeWikiIndexer.js +3 -3
- package/dist/services/ContextGenerator.js +7 -7
- package/dist/services/FeedbackCollector.js +11 -11
- package/dist/services/GitIntegration.d.ts.map +1 -1
- package/dist/services/GitIntegration.js +27 -23
- package/dist/services/GitIntegration.js.map +1 -1
- package/dist/services/HookVerifier.js +70 -70
- package/dist/services/KnowledgeGapDetector.d.ts +122 -0
- package/dist/services/KnowledgeGapDetector.d.ts.map +1 -0
- package/dist/services/KnowledgeGapDetector.js +530 -0
- package/dist/services/KnowledgeGapDetector.js.map +1 -0
- package/dist/services/ProjectScaffold.d.ts.map +1 -1
- package/dist/services/ProjectScaffold.js +79 -78
- package/dist/services/ProjectScaffold.js.map +1 -1
- package/dist/services/index.d.ts +4 -0
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +6 -0
- package/dist/services/index.js.map +1 -1
- package/dist/services/knowledge-graph.d.ts +121 -0
- package/dist/services/knowledge-graph.d.ts.map +1 -0
- package/dist/services/knowledge-graph.js +446 -0
- package/dist/services/knowledge-graph.js.map +1 -0
- package/dist/services/memory-router.d.ts +25 -0
- package/dist/services/memory-router.d.ts.map +1 -1
- package/dist/services/memory-router.js +236 -98
- package/dist/services/memory-router.js.map +1 -1
- package/dist/services/pattern-learning.d.ts +79 -0
- package/dist/services/pattern-learning.d.ts.map +1 -0
- package/dist/services/pattern-learning.js +312 -0
- package/dist/services/pattern-learning.js.map +1 -0
- package/dist/services/pattern-tracker.js +95 -95
- package/dist/services/semantic-search.d.ts.map +1 -1
- package/dist/services/semantic-search.js +12 -8
- package/dist/services/semantic-search.js.map +1 -1
- package/package.json +124 -116
- package/standards/README.md +94 -50
- package/standards/experts/expert-routing.md +215 -215
- package/standards/general/code-quality.md +86 -86
- package/standards/general/ecosystem.md +243 -0
- package/standards/general/learning-loop.md +192 -0
- package/standards/general/memory-usage.md +205 -205
- package/standards/general/project-onboarding.md +339 -0
- package/standards/general/sync-workflow.md +235 -235
- package/standards/general/workflow.md +82 -82
- package/standards/hooks/mandatory-tracking.md +446 -446
- package/standards/infrastructure/cloud-database.md +287 -287
- package/standards/mcp/server-design.md +243 -243
- package/standards/mcp/tool-patterns.md +354 -354
- package/standards/skills/skill-structure.md +286 -286
- package/standards/skills/workflow-design.md +323 -323
- package/standards/tools/tool-design.md +297 -297
- package/templates/agents/architecture-expert.md +61 -61
- package/templates/agents/database-expert.md +62 -62
- package/templates/agents/documentation-expert.md +57 -57
- package/templates/agents/ecosystem-expert.md +104 -0
- package/templates/agents/memory-expert.md +88 -88
- package/templates/agents/performance-expert.md +61 -61
- package/templates/agents/security-expert.md +59 -59
- package/templates/agents/ux-expert.md +63 -63
- package/templates/agents/worker.md +75 -75
- package/templates/ai-skills/SKILL_TEMPLATE.md +55 -55
- package/templates/claude-settings.json +72 -72
- package/templates/commands/experts.md +138 -138
- package/templates/hooks/README.md +158 -158
- package/templates/hooks/project.config.json.template +77 -77
- package/templates/hooks/settings.local.json.template +57 -57
- package/templates/hooks.config.json +21 -0
- package/templates/memory-config.json +56 -56
- package/templates/memory-config.schema.json +212 -212
- package/templates/settings.json +58 -58
- package/templates/skills/continue.md +205 -205
- package/templates/workflows/business-improvement.md +264 -264
- package/templates/workflows/expert-review.md +153 -153
- package/templates/workflows/internal-app.md +245 -245
- package/templates/workflows/sync-docs.md +187 -187
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resilient-hook-runner.d.ts","sourceRoot":"","sources":["../../src/hooks/resilient-hook-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,OAAO,CAAA;IACnB,QAAQ,EAAE;QACR,eAAe,EAAE,OAAO,CAAA;QACxB,YAAY,EAAE,OAAO,CAAA;QACrB,YAAY,EAAE,OAAO,CAAA;QACrB,kBAAkB,EAAE,OAAO,CAAA;KAC5B,CAAA;CACF;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,MAAM,QAAQ,GAAG,YAAY,GAAG,aAAa,GAAG,cAAc,GAAG,YAAY,CAAA;AAsBnF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,UAAU,CAiC9D;AAMD;;GAEG;AACH,wBAAsB,WAAW,CAAC,CAAC,EACjC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,GACV,OAAO,CAAC;IAAE,MAAM,EAAE,CAAC,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC,CAoB3C;AAMD,UAAU,YAAY;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,GAAG,EAAE,MAAM,CAAA;CACZ;AAID,wBAAgB,gBAAgB,IAAI,YAAY,GAAG,IAAI,CAUtD;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI,CAQrE;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAMD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,WAAW,CAAQ;gBAEf,WAAW,EAAE,MAAM;IAK/B;;OAEG;IACG,OAAO,CACX,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,EACjC,QAAQ,GAAE,UAAuD,GAChE,OAAO,CAAC,UAAU,CAAC;IAyBtB;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,UAAU,CAAC,UAAU,CAAC,GAAG,OAAO;IAIhE;;OAEG;IACH,SAAS,IAAI,UAAU;CAGxB;AAMD;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,SAAS,OAAO,EAAE,EAC9C,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,UAAU,CAAC,EAC/C,OAAO,CAAC,EAAE;IACR,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAA;CACpB,GACA,CAAC,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,UAAU,CAAC,CAiCzC;AAiBD,eAAe,mBAAmB,CAAA"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Resilient Hook Runner
|
|
3
|
+
* @description A fault-tolerant hook execution system that:
|
|
4
|
+
* - Fails silently (never blocks tool execution)
|
|
5
|
+
* - Uses timeouts to prevent hanging
|
|
6
|
+
* - Caches state to avoid repeated network calls
|
|
7
|
+
* - Supports per-project enable/disable
|
|
8
|
+
* - Provides graceful degradation
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync, readFileSync } from 'fs';
|
|
11
|
+
import { join } from 'path';
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// Default Configuration
|
|
14
|
+
// =============================================================================
|
|
15
|
+
const DEFAULT_CONFIG = {
|
|
16
|
+
enabled: true,
|
|
17
|
+
timeout: 2000, // 2 second max
|
|
18
|
+
silentFail: true, // Never block on errors
|
|
19
|
+
features: {
|
|
20
|
+
sessionTracking: false, // Disable by default - causes network calls
|
|
21
|
+
taskTracking: false, // Disable by default - causes network calls
|
|
22
|
+
fileTracking: true, // Local only - fast
|
|
23
|
+
knowledgeInjection: true // Local + optional network
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
// =============================================================================
|
|
27
|
+
// Configuration Loading
|
|
28
|
+
// =============================================================================
|
|
29
|
+
/**
|
|
30
|
+
* Load hook configuration from project
|
|
31
|
+
* Checks: .claude/hooks.config.json > .claude/memory-config.json > defaults
|
|
32
|
+
*/
|
|
33
|
+
export function loadHookConfig(projectRoot) {
|
|
34
|
+
// Priority 1: Dedicated hook config
|
|
35
|
+
const hookConfigPath = join(projectRoot, '.claude', 'hooks.config.json');
|
|
36
|
+
if (existsSync(hookConfigPath)) {
|
|
37
|
+
try {
|
|
38
|
+
const content = readFileSync(hookConfigPath, 'utf-8');
|
|
39
|
+
const parsed = JSON.parse(content);
|
|
40
|
+
return { ...DEFAULT_CONFIG, ...parsed };
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// Invalid JSON, use defaults
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Priority 2: Memory config with hooks section
|
|
47
|
+
const memoryConfigPath = join(projectRoot, '.claude', 'memory-config.json');
|
|
48
|
+
if (existsSync(memoryConfigPath)) {
|
|
49
|
+
try {
|
|
50
|
+
const content = readFileSync(memoryConfigPath, 'utf-8');
|
|
51
|
+
const parsed = JSON.parse(content);
|
|
52
|
+
if (parsed.hooks) {
|
|
53
|
+
return { ...DEFAULT_CONFIG, ...parsed.hooks };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Invalid JSON, use defaults
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Priority 3: Environment variable override
|
|
61
|
+
if (process.env.CMP_HOOKS_DISABLED === 'true') {
|
|
62
|
+
return { ...DEFAULT_CONFIG, enabled: false };
|
|
63
|
+
}
|
|
64
|
+
return DEFAULT_CONFIG;
|
|
65
|
+
}
|
|
66
|
+
// =============================================================================
|
|
67
|
+
// Timeout Wrapper
|
|
68
|
+
// =============================================================================
|
|
69
|
+
/**
|
|
70
|
+
* Execute a function with timeout protection
|
|
71
|
+
*/
|
|
72
|
+
export async function withTimeout(fn, timeoutMs, fallback) {
|
|
73
|
+
let timeoutId;
|
|
74
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
75
|
+
timeoutId = setTimeout(() => {
|
|
76
|
+
resolve({ result: fallback, timedOut: true });
|
|
77
|
+
}, timeoutMs);
|
|
78
|
+
});
|
|
79
|
+
const executionPromise = fn()
|
|
80
|
+
.then(result => {
|
|
81
|
+
clearTimeout(timeoutId);
|
|
82
|
+
return { result, timedOut: false };
|
|
83
|
+
})
|
|
84
|
+
.catch(() => {
|
|
85
|
+
clearTimeout(timeoutId);
|
|
86
|
+
return { result: fallback, timedOut: false };
|
|
87
|
+
});
|
|
88
|
+
return Promise.race([executionPromise, timeoutPromise]);
|
|
89
|
+
}
|
|
90
|
+
let sessionCache = null;
|
|
91
|
+
export function getCachedSession() {
|
|
92
|
+
if (!sessionCache)
|
|
93
|
+
return null;
|
|
94
|
+
// Check if expired
|
|
95
|
+
if (Date.now() - sessionCache.lastUpdated > sessionCache.ttl) {
|
|
96
|
+
sessionCache = null;
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
return sessionCache;
|
|
100
|
+
}
|
|
101
|
+
export function setCachedSession(session) {
|
|
102
|
+
sessionCache = {
|
|
103
|
+
sessionId: session.sessionId || `session_${Date.now()}`,
|
|
104
|
+
system: session.system || 'UNKNOWN',
|
|
105
|
+
activeTaskId: session.activeTaskId,
|
|
106
|
+
lastUpdated: Date.now(),
|
|
107
|
+
ttl: session.ttl || 30 * 60 * 1000 // 30 minutes default
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
export function clearSessionCache() {
|
|
111
|
+
sessionCache = null;
|
|
112
|
+
}
|
|
113
|
+
// =============================================================================
|
|
114
|
+
// Resilient Hook Executor
|
|
115
|
+
// =============================================================================
|
|
116
|
+
export class ResilientHookRunner {
|
|
117
|
+
config;
|
|
118
|
+
projectRoot;
|
|
119
|
+
constructor(projectRoot) {
|
|
120
|
+
this.projectRoot = projectRoot;
|
|
121
|
+
this.config = loadHookConfig(projectRoot);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Execute a hook with full protection
|
|
125
|
+
*/
|
|
126
|
+
async execute(hookType, hookFn, fallback = { success: false, proceed: true, took: 0 }) {
|
|
127
|
+
const start = Date.now();
|
|
128
|
+
// Check if hooks are enabled
|
|
129
|
+
if (!this.config.enabled) {
|
|
130
|
+
return { ...fallback, success: true, took: Date.now() - start };
|
|
131
|
+
}
|
|
132
|
+
// Execute with timeout protection
|
|
133
|
+
const { result, timedOut } = await withTimeout(hookFn, this.config.timeout, fallback);
|
|
134
|
+
if (timedOut) {
|
|
135
|
+
console.warn(`[Hook:${hookType}] Timed out after ${this.config.timeout}ms`);
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
...result,
|
|
139
|
+
took: Date.now() - start
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Check if a specific feature is enabled
|
|
144
|
+
*/
|
|
145
|
+
isFeatureEnabled(feature) {
|
|
146
|
+
return this.config.enabled && this.config.features[feature];
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Get current configuration
|
|
150
|
+
*/
|
|
151
|
+
getConfig() {
|
|
152
|
+
return { ...this.config };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// =============================================================================
|
|
156
|
+
// Safe Hook Wrapper
|
|
157
|
+
// =============================================================================
|
|
158
|
+
/**
|
|
159
|
+
* Wrap any hook function to make it resilient
|
|
160
|
+
*/
|
|
161
|
+
export function safeHook(hookFn, options) {
|
|
162
|
+
const timeout = options?.timeout || DEFAULT_CONFIG.timeout;
|
|
163
|
+
return async (...args) => {
|
|
164
|
+
const start = Date.now();
|
|
165
|
+
try {
|
|
166
|
+
const { result, timedOut } = await withTimeout(() => hookFn(...args), timeout, { success: false, proceed: true, took: 0 });
|
|
167
|
+
if (timedOut) {
|
|
168
|
+
return {
|
|
169
|
+
success: false,
|
|
170
|
+
proceed: true,
|
|
171
|
+
warning: `Hook timed out after ${timeout}ms`,
|
|
172
|
+
took: Date.now() - start
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
return { ...result, took: Date.now() - start };
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
// Never throw - always return proceed: true
|
|
179
|
+
return {
|
|
180
|
+
success: false,
|
|
181
|
+
proceed: true,
|
|
182
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
183
|
+
took: Date.now() - start
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
// =============================================================================
|
|
189
|
+
// CLI Entry Point
|
|
190
|
+
// =============================================================================
|
|
191
|
+
if (process.argv[1]?.includes('resilient-hook-runner')) {
|
|
192
|
+
const projectRoot = process.cwd();
|
|
193
|
+
const config = loadHookConfig(projectRoot);
|
|
194
|
+
console.log(JSON.stringify({
|
|
195
|
+
projectRoot,
|
|
196
|
+
config,
|
|
197
|
+
cacheStatus: getCachedSession() ? 'active' : 'empty'
|
|
198
|
+
}, null, 2));
|
|
199
|
+
}
|
|
200
|
+
export default ResilientHookRunner;
|
|
201
|
+
//# sourceMappingURL=resilient-hook-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resilient-hook-runner.js","sourceRoot":"","sources":["../../src/hooks/resilient-hook-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -63,34 +63,34 @@ export async function onSessionEnd(event) {
|
|
|
63
63
|
const duration = new Date(endedAt).getTime() - new Date(startedAt).getTime();
|
|
64
64
|
// 2. Get task counts for this session
|
|
65
65
|
const taskCounts = await db.execute({
|
|
66
|
-
sql: `SELECT
|
|
67
|
-
SUM(CASE WHEN json_extract(content, '$.sessionId') = ? AND status = 'active' THEN 1 ELSE 0 END) as started,
|
|
68
|
-
SUM(CASE WHEN json_extract(content, '$.sessionId') = ? AND status = 'done' THEN 1 ELSE 0 END) as completed
|
|
69
|
-
FROM items
|
|
66
|
+
sql: `SELECT
|
|
67
|
+
SUM(CASE WHEN json_extract(content, '$.sessionId') = ? AND status = 'active' THEN 1 ELSE 0 END) as started,
|
|
68
|
+
SUM(CASE WHEN json_extract(content, '$.sessionId') = ? AND status = 'done' THEN 1 ELSE 0 END) as completed
|
|
69
|
+
FROM items
|
|
70
70
|
WHERE system = ? AND type = 'task'`,
|
|
71
71
|
args: [event.sessionId, event.sessionId, system]
|
|
72
72
|
});
|
|
73
73
|
const taskRow = taskCounts.rows[0] || { started: 0, completed: 0 };
|
|
74
74
|
// 3. Get memory counts for this session
|
|
75
75
|
const memoryCounts = await db.execute({
|
|
76
|
-
sql: `SELECT COUNT(*) as created FROM items
|
|
77
|
-
WHERE system = ? AND type = 'memory'
|
|
76
|
+
sql: `SELECT COUNT(*) as created FROM items
|
|
77
|
+
WHERE system = ? AND type = 'memory'
|
|
78
78
|
AND json_extract(content, '$.sessionId') = ?`,
|
|
79
79
|
args: [system, event.sessionId]
|
|
80
80
|
});
|
|
81
81
|
const memoryRow = memoryCounts.rows[0] || { created: 0 };
|
|
82
82
|
// 4. Get pattern counts for this session
|
|
83
83
|
const patternCounts = await db.execute({
|
|
84
|
-
sql: `SELECT COUNT(*) as detected FROM items
|
|
85
|
-
WHERE system = ? AND type = 'pattern'
|
|
84
|
+
sql: `SELECT COUNT(*) as detected FROM items
|
|
85
|
+
WHERE system = ? AND type = 'pattern'
|
|
86
86
|
AND date(created_at) = date('now')`,
|
|
87
87
|
args: [system]
|
|
88
88
|
});
|
|
89
89
|
const patternRow = patternCounts.rows[0] || { detected: 0 };
|
|
90
90
|
// 5. Get improvement counts
|
|
91
91
|
const improvementCounts = await db.execute({
|
|
92
|
-
sql: `SELECT COUNT(*) as generated FROM items
|
|
93
|
-
WHERE system = ? AND type = 'auto_improvement'
|
|
92
|
+
sql: `SELECT COUNT(*) as generated FROM items
|
|
93
|
+
WHERE system = ? AND type = 'auto_improvement'
|
|
94
94
|
AND date(created_at) = date('now')`,
|
|
95
95
|
args: [system]
|
|
96
96
|
});
|
|
@@ -127,7 +127,7 @@ export async function onSessionEnd(event) {
|
|
|
127
127
|
};
|
|
128
128
|
// 9. Persist summary
|
|
129
129
|
await db.execute({
|
|
130
|
-
sql: `INSERT INTO items (id, type, system, status, content, created_at, updated_at)
|
|
130
|
+
sql: `INSERT INTO items (id, type, system, status, content, created_at, updated_at)
|
|
131
131
|
VALUES (?, 'session_summary', ?, 'active', ?, ?, ?)`,
|
|
132
132
|
args: [
|
|
133
133
|
summary.id,
|
|
@@ -175,9 +175,9 @@ export async function getSessionSummaries(system, limit = 20) {
|
|
|
175
175
|
try {
|
|
176
176
|
const db = turso.getClient();
|
|
177
177
|
const result = await db.execute({
|
|
178
|
-
sql: `SELECT content FROM items
|
|
179
|
-
WHERE system = ? AND type = 'session_summary' AND status = 'active'
|
|
180
|
-
ORDER BY created_at DESC
|
|
178
|
+
sql: `SELECT content FROM items
|
|
179
|
+
WHERE system = ? AND type = 'session_summary' AND status = 'active'
|
|
180
|
+
ORDER BY created_at DESC
|
|
181
181
|
LIMIT ?`,
|
|
182
182
|
args: [system, limit]
|
|
183
183
|
});
|
|
@@ -54,10 +54,10 @@ export const BUILTIN_PATTERNS = [
|
|
|
54
54
|
filePatterns: ['*.ts', '*.tsx'],
|
|
55
55
|
excludePatterns: ['*.test.ts', '*.spec.ts'],
|
|
56
56
|
eslintRuleName: 'charter/no-any-type',
|
|
57
|
-
astVisitorTemplate: `return {
|
|
58
|
-
TSAnyKeyword(node) {
|
|
59
|
-
context.report({ node, messageId: 'violation' });
|
|
60
|
-
}
|
|
57
|
+
astVisitorTemplate: `return {
|
|
58
|
+
TSAnyKeyword(node) {
|
|
59
|
+
context.report({ node, messageId: 'violation' });
|
|
60
|
+
}
|
|
61
61
|
};`,
|
|
62
62
|
status: 'active',
|
|
63
63
|
threshold: 3,
|
|
@@ -73,14 +73,14 @@ export const BUILTIN_PATTERNS = [
|
|
|
73
73
|
filePatterns: ['*.ts', '*.tsx', '*.js', '*.jsx'],
|
|
74
74
|
excludePatterns: ['*.test.ts', '*.spec.ts', '*.test.js'],
|
|
75
75
|
eslintRuleName: 'no-console',
|
|
76
|
-
astVisitorTemplate: `return {
|
|
77
|
-
CallExpression(node) {
|
|
78
|
-
if (node.callee.type === 'MemberExpression' &&
|
|
79
|
-
node.callee.object.name === 'console' &&
|
|
80
|
-
node.callee.property.name === 'log') {
|
|
81
|
-
context.report({ node, messageId: 'violation' });
|
|
82
|
-
}
|
|
83
|
-
}
|
|
76
|
+
astVisitorTemplate: `return {
|
|
77
|
+
CallExpression(node) {
|
|
78
|
+
if (node.callee.type === 'MemberExpression' &&
|
|
79
|
+
node.callee.object.name === 'console' &&
|
|
80
|
+
node.callee.property.name === 'log') {
|
|
81
|
+
context.report({ node, messageId: 'violation' });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
84
|
};`,
|
|
85
85
|
status: 'active',
|
|
86
86
|
threshold: 3,
|
|
@@ -95,16 +95,16 @@ export const BUILTIN_PATTERNS = [
|
|
|
95
95
|
regex: 'eslint-disable',
|
|
96
96
|
filePatterns: ['*.ts', '*.tsx', '*.js', '*.jsx'],
|
|
97
97
|
eslintRuleName: 'charter/no-eslint-disable',
|
|
98
|
-
astVisitorTemplate: `const sourceCode = context.getSourceCode();
|
|
99
|
-
return {
|
|
100
|
-
Program() {
|
|
101
|
-
const comments = sourceCode.getAllComments();
|
|
102
|
-
for (const comment of comments) {
|
|
103
|
-
if (comment.value.includes('eslint-disable')) {
|
|
104
|
-
context.report({ loc: comment.loc, messageId: 'violation' });
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
98
|
+
astVisitorTemplate: `const sourceCode = context.getSourceCode();
|
|
99
|
+
return {
|
|
100
|
+
Program() {
|
|
101
|
+
const comments = sourceCode.getAllComments();
|
|
102
|
+
for (const comment of comments) {
|
|
103
|
+
if (comment.value.includes('eslint-disable')) {
|
|
104
|
+
context.report({ loc: comment.loc, messageId: 'violation' });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
108
|
};`,
|
|
109
109
|
status: 'active',
|
|
110
110
|
threshold: 3,
|
|
@@ -120,14 +120,14 @@ export const BUILTIN_PATTERNS = [
|
|
|
120
120
|
filePatterns: ['*.ts'],
|
|
121
121
|
excludePatterns: ['**/migrations/**', '**/db/**'],
|
|
122
122
|
eslintRuleName: 'charter/no-raw-sql',
|
|
123
|
-
astVisitorTemplate: `return {
|
|
124
|
-
CallExpression(node) {
|
|
125
|
-
if (node.callee.type === 'MemberExpression' &&
|
|
126
|
-
node.callee.property.name === 'execute' &&
|
|
127
|
-
node.arguments[0]?.type === 'TemplateLiteral') {
|
|
128
|
-
context.report({ node, messageId: 'violation' });
|
|
129
|
-
}
|
|
130
|
-
}
|
|
123
|
+
astVisitorTemplate: `return {
|
|
124
|
+
CallExpression(node) {
|
|
125
|
+
if (node.callee.type === 'MemberExpression' &&
|
|
126
|
+
node.callee.property.name === 'execute' &&
|
|
127
|
+
node.arguments[0]?.type === 'TemplateLiteral') {
|
|
128
|
+
context.report({ node, messageId: 'violation' });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
131
|
};`,
|
|
132
132
|
status: 'active',
|
|
133
133
|
threshold: 2,
|
|
@@ -143,15 +143,15 @@ export const BUILTIN_PATTERNS = [
|
|
|
143
143
|
filePatterns: ['*.ts'],
|
|
144
144
|
excludePatterns: [],
|
|
145
145
|
eslintRuleName: 'charter/require-zod-validation',
|
|
146
|
-
astVisitorTemplate: `return {
|
|
147
|
-
CallExpression(node) {
|
|
148
|
-
// Check for publicProcedure.mutation without .input()
|
|
149
|
-
if (node.callee.type === 'MemberExpression' &&
|
|
150
|
-
node.callee.property.name === 'mutation') {
|
|
151
|
-
// Implementation details
|
|
152
|
-
context.report({ node, messageId: 'violation' });
|
|
153
|
-
}
|
|
154
|
-
}
|
|
146
|
+
astVisitorTemplate: `return {
|
|
147
|
+
CallExpression(node) {
|
|
148
|
+
// Check for publicProcedure.mutation without .input()
|
|
149
|
+
if (node.callee.type === 'MemberExpression' &&
|
|
150
|
+
node.callee.property.name === 'mutation') {
|
|
151
|
+
// Implementation details
|
|
152
|
+
context.report({ node, messageId: 'violation' });
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
155
|
};`,
|
|
156
156
|
status: 'active',
|
|
157
157
|
threshold: 3,
|
|
@@ -166,14 +166,14 @@ export const BUILTIN_PATTERNS = [
|
|
|
166
166
|
regex: 'useEffect\\(async',
|
|
167
167
|
filePatterns: ['*.tsx', '*.jsx'],
|
|
168
168
|
eslintRuleName: 'charter/no-async-useeffect',
|
|
169
|
-
astVisitorTemplate: `return {
|
|
170
|
-
CallExpression(node) {
|
|
171
|
-
if (node.callee.type === 'Identifier' &&
|
|
172
|
-
node.callee.name === 'useEffect' &&
|
|
173
|
-
node.arguments[0]?.async) {
|
|
174
|
-
context.report({ node, messageId: 'violation' });
|
|
175
|
-
}
|
|
176
|
-
}
|
|
169
|
+
astVisitorTemplate: `return {
|
|
170
|
+
CallExpression(node) {
|
|
171
|
+
if (node.callee.type === 'Identifier' &&
|
|
172
|
+
node.callee.name === 'useEffect' &&
|
|
173
|
+
node.arguments[0]?.async) {
|
|
174
|
+
context.report({ node, messageId: 'violation' });
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
177
|
};`,
|
|
178
178
|
status: 'active',
|
|
179
179
|
threshold: 3,
|
|
@@ -189,12 +189,12 @@ export const BUILTIN_PATTERNS = [
|
|
|
189
189
|
filePatterns: ['*.tsx', '*.jsx', '*.css'],
|
|
190
190
|
excludePatterns: ['**/tailwind.config.*'],
|
|
191
191
|
eslintRuleName: 'charter/use-semantic-tokens',
|
|
192
|
-
astVisitorTemplate: `return {
|
|
193
|
-
Literal(node) {
|
|
194
|
-
if (typeof node.value === 'string' && /#[0-9a-fA-F]{3,8}/.test(node.value)) {
|
|
195
|
-
context.report({ node, messageId: 'violation' });
|
|
196
|
-
}
|
|
197
|
-
}
|
|
192
|
+
astVisitorTemplate: `return {
|
|
193
|
+
Literal(node) {
|
|
194
|
+
if (typeof node.value === 'string' && /#[0-9a-fA-F]{3,8}/.test(node.value)) {
|
|
195
|
+
context.report({ node, messageId: 'violation' });
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
198
|
};`,
|
|
199
199
|
status: 'active',
|
|
200
200
|
threshold: 5,
|
|
@@ -209,19 +209,19 @@ export const BUILTIN_PATTERNS = [
|
|
|
209
209
|
regex: 'insert\\(finance\\)(?!.*LedgerService)',
|
|
210
210
|
filePatterns: ['*.ts'],
|
|
211
211
|
eslintRuleName: 'charter/finance-ledger-sync',
|
|
212
|
-
astVisitorTemplate: `let hasFinanceInsert = false;
|
|
213
|
-
let hasLedgerCall = false;
|
|
214
|
-
return {
|
|
215
|
-
CallExpression(node) {
|
|
216
|
-
const callee = node.callee;
|
|
217
|
-
if (callee.property?.name === 'insert') hasFinanceInsert = true;
|
|
218
|
-
if (callee.object?.name === 'LedgerService') hasLedgerCall = true;
|
|
219
|
-
},
|
|
220
|
-
'Program:exit'(node) {
|
|
221
|
-
if (hasFinanceInsert && !hasLedgerCall) {
|
|
222
|
-
context.report({ node, messageId: 'violation' });
|
|
223
|
-
}
|
|
224
|
-
}
|
|
212
|
+
astVisitorTemplate: `let hasFinanceInsert = false;
|
|
213
|
+
let hasLedgerCall = false;
|
|
214
|
+
return {
|
|
215
|
+
CallExpression(node) {
|
|
216
|
+
const callee = node.callee;
|
|
217
|
+
if (callee.property?.name === 'insert') hasFinanceInsert = true;
|
|
218
|
+
if (callee.object?.name === 'LedgerService') hasLedgerCall = true;
|
|
219
|
+
},
|
|
220
|
+
'Program:exit'(node) {
|
|
221
|
+
if (hasFinanceInsert && !hasLedgerCall) {
|
|
222
|
+
context.report({ node, messageId: 'violation' });
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
225
|
};`,
|
|
226
226
|
status: 'active',
|
|
227
227
|
threshold: 1,
|
|
@@ -379,30 +379,30 @@ export class PatternRegistry {
|
|
|
379
379
|
if (!pattern || !pattern.eslintRuleName || !pattern.astVisitorTemplate) {
|
|
380
380
|
return null;
|
|
381
381
|
}
|
|
382
|
-
return `/**
|
|
383
|
-
* @file ${pattern.eslintRuleName}
|
|
384
|
-
* @description ${pattern.description}
|
|
385
|
-
* Auto-generated by cmp-standards pattern detection
|
|
386
|
-
* @version 1.0.0
|
|
387
|
-
*/
|
|
388
|
-
|
|
389
|
-
module.exports = {
|
|
390
|
-
meta: {
|
|
391
|
-
type: 'problem',
|
|
392
|
-
docs: {
|
|
393
|
-
description: '${pattern.description}',
|
|
394
|
-
category: 'Best Practices',
|
|
395
|
-
recommended: true
|
|
396
|
-
},
|
|
397
|
-
schema: [],
|
|
398
|
-
messages: {
|
|
399
|
-
violation: '${pattern.description}'
|
|
400
|
-
}
|
|
401
|
-
},
|
|
402
|
-
create(context) {
|
|
403
|
-
${pattern.astVisitorTemplate}
|
|
404
|
-
}
|
|
405
|
-
}
|
|
382
|
+
return `/**
|
|
383
|
+
* @file ${pattern.eslintRuleName}
|
|
384
|
+
* @description ${pattern.description}
|
|
385
|
+
* Auto-generated by cmp-standards pattern detection
|
|
386
|
+
* @version 1.0.0
|
|
387
|
+
*/
|
|
388
|
+
|
|
389
|
+
module.exports = {
|
|
390
|
+
meta: {
|
|
391
|
+
type: 'problem',
|
|
392
|
+
docs: {
|
|
393
|
+
description: '${pattern.description}',
|
|
394
|
+
category: 'Best Practices',
|
|
395
|
+
recommended: true
|
|
396
|
+
},
|
|
397
|
+
schema: [],
|
|
398
|
+
messages: {
|
|
399
|
+
violation: '${pattern.description}'
|
|
400
|
+
}
|
|
401
|
+
},
|
|
402
|
+
create(context) {
|
|
403
|
+
${pattern.astVisitorTemplate}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
406
|
`;
|
|
407
407
|
}
|
|
408
408
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/registry/generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAoB,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAQ5E,MAAM,WAAW,uBAAuB;IACtC,4CAA4C;IAC5C,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAA;IAClB,wCAAwC;IACxC,gBAAgB,EAAE,MAAM,CAAA;IACxB,8CAA8C;IAC9C,gBAAgB,EAAE,MAAM,CAAA;CACzB;AAoMD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,gBAAgB,CAAkB;IAC1C,OAAO,CAAC,WAAW,CAAsB;gBAE7B,MAAM,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC;IAKrD;;OAEG;IACG,IAAI,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/C;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/registry/generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAoB,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAQ5E,MAAM,WAAW,uBAAuB;IACtC,4CAA4C;IAC5C,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAA;IAClB,wCAAwC;IACxC,gBAAgB,EAAE,MAAM,CAAA;IACxB,8CAA8C;IAC9C,gBAAgB,EAAE,MAAM,CAAA;CACzB;AAoMD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,gBAAgB,CAAkB;IAC1C,OAAO,CAAC,WAAW,CAAsB;gBAE7B,MAAM,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC;IAKrD;;OAEG;IACG,IAAI,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/C;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAmG5C;;OAEG;YACW,eAAe;IAgB7B;;OAEG;IACG,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC;CA4DjE;AAMD,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CAG1D"}
|
|
@@ -182,45 +182,55 @@ export class RegistryGenerator {
|
|
|
182
182
|
// 1. Find all source files
|
|
183
183
|
const files = await this.findSourceFiles(projectRoot);
|
|
184
184
|
console.log(` Found ${files.length} source files`);
|
|
185
|
-
// 2. Parse sections from all files
|
|
185
|
+
// 2. Parse sections from all files (parallel)
|
|
186
|
+
const parseResults = await Promise.allSettled(files.map(async (file) => {
|
|
187
|
+
const sections = await parseMarkdownFile(file, this.config);
|
|
188
|
+
console.log(` Parsed ${sections.length} sections from ${path.basename(file)}`);
|
|
189
|
+
return sections;
|
|
190
|
+
}));
|
|
186
191
|
const allSections = [];
|
|
187
|
-
for (const
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
allSections.push(...sections);
|
|
191
|
-
console.log(` Parsed ${sections.length} sections from ${path.basename(file)}`);
|
|
192
|
+
for (const result of parseResults) {
|
|
193
|
+
if (result.status === 'fulfilled') {
|
|
194
|
+
allSections.push(...result.value);
|
|
192
195
|
}
|
|
193
|
-
|
|
194
|
-
console.warn(` Warning: Could not parse
|
|
196
|
+
else {
|
|
197
|
+
console.warn(` Warning: Could not parse file:`, result.reason);
|
|
195
198
|
}
|
|
196
199
|
}
|
|
197
200
|
console.log(` Total sections: ${allSections.length}`);
|
|
198
|
-
// 3. Generate embeddings
|
|
201
|
+
// 3. Generate embeddings (batched parallel for rate limiting)
|
|
199
202
|
console.log(' Generating embeddings...');
|
|
200
203
|
const providerInfo = this.embeddingService.getProviderInfo();
|
|
201
204
|
const embeddingSections = [];
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
const
|
|
206
|
-
|
|
205
|
+
const batchSize = 10; // Process 10 at a time to avoid rate limits
|
|
206
|
+
for (let i = 0; i < allSections.length; i += batchSize) {
|
|
207
|
+
const batch = allSections.slice(i, i + batchSize);
|
|
208
|
+
const batchResults = await Promise.allSettled(batch.map(async (section) => {
|
|
209
|
+
const textToEmbed = `${section.title}\n\n${section.description}\n\n${section.content}`;
|
|
207
210
|
const embedding = await this.embeddingService.embed(textToEmbed);
|
|
208
|
-
|
|
211
|
+
return {
|
|
209
212
|
id: section.id,
|
|
210
213
|
title: section.title,
|
|
211
214
|
description: section.description,
|
|
212
215
|
keywords: section.keywords,
|
|
213
216
|
embedding,
|
|
214
217
|
path: section.path,
|
|
215
|
-
tokens: Math.ceil(textToEmbed.length / 4),
|
|
218
|
+
tokens: Math.ceil(textToEmbed.length / 4),
|
|
216
219
|
criticality: section.criticality,
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
+
};
|
|
221
|
+
}));
|
|
222
|
+
for (const result of batchResults) {
|
|
223
|
+
if (result.status === 'fulfilled') {
|
|
224
|
+
embeddingSections.push(result.value);
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
console.warn(` Warning: Could not embed section:`, result.reason);
|
|
220
228
|
}
|
|
221
229
|
}
|
|
222
|
-
|
|
223
|
-
|
|
230
|
+
console.log(` Embedded ${Math.min(i + batchSize, allSections.length)}/${allSections.length} sections`);
|
|
231
|
+
// Small delay between batches to respect rate limits
|
|
232
|
+
if (i + batchSize < allSections.length) {
|
|
233
|
+
await new Promise(r => setTimeout(r, 100));
|
|
224
234
|
}
|
|
225
235
|
}
|
|
226
236
|
// 4. Create registry
|