@decibelsystems/tools 2.0.2 → 2.1.1
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 +115 -233
- package/dist/config/queueableActions.d.ts +11 -0
- package/dist/config/queueableActions.d.ts.map +1 -0
- package/dist/config/queueableActions.js +22 -0
- package/dist/config/queueableActions.js.map +1 -0
- package/dist/daemon.d.ts +29 -0
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +64 -0
- package/dist/daemon.js.map +1 -1
- package/dist/daemonConfig.d.ts +7 -0
- package/dist/daemonConfig.d.ts.map +1 -1
- package/dist/daemonConfig.js +9 -0
- package/dist/daemonConfig.js.map +1 -1
- package/dist/facades/definitions.d.ts.map +1 -1
- package/dist/facades/definitions.js +130 -33
- package/dist/facades/definitions.js.map +1 -1
- package/dist/httpQueueDetection.d.ts +16 -0
- package/dist/httpQueueDetection.d.ts.map +1 -0
- package/dist/httpQueueDetection.js +36 -0
- package/dist/httpQueueDetection.js.map +1 -0
- package/dist/httpServer.d.ts +4 -0
- package/dist/httpServer.d.ts.map +1 -1
- package/dist/httpServer.js +224 -97
- package/dist/httpServer.js.map +1 -1
- package/dist/kernel.d.ts +2 -0
- package/dist/kernel.d.ts.map +1 -1
- package/dist/kernel.js +1 -0
- package/dist/kernel.js.map +1 -1
- package/dist/server.js +30 -1
- package/dist/server.js.map +1 -1
- package/dist/tools/agentic/agentQueue.d.ts +50 -0
- package/dist/tools/agentic/agentQueue.d.ts.map +1 -0
- package/dist/tools/agentic/agentQueue.js +226 -0
- package/dist/tools/agentic/agentQueue.js.map +1 -0
- package/dist/tools/agentic/index.d.ts +2 -0
- package/dist/tools/agentic/index.d.ts.map +1 -1
- package/dist/tools/agentic/index.js +84 -0
- package/dist/tools/agentic/index.js.map +1 -1
- package/dist/tools/coordinator/coordinator.d.ts +14 -0
- package/dist/tools/coordinator/coordinator.d.ts.map +1 -1
- package/dist/tools/coordinator/coordinator.js +101 -0
- package/dist/tools/coordinator/coordinator.js.map +1 -1
- package/dist/tools/coordinator/index.d.ts +2 -0
- package/dist/tools/coordinator/index.d.ts.map +1 -1
- package/dist/tools/coordinator/index.js +2 -0
- package/dist/tools/coordinator/index.js.map +1 -1
- package/dist/tools/decibel/index.d.ts +3 -0
- package/dist/tools/decibel/index.d.ts.map +1 -0
- package/dist/tools/decibel/index.js +150 -0
- package/dist/tools/decibel/index.js.map +1 -0
- package/dist/tools/decibel.d.ts +13 -0
- package/dist/tools/decibel.d.ts.map +1 -0
- package/dist/tools/decibel.js +156 -0
- package/dist/tools/decibel.js.map +1 -0
- package/dist/tools/deck.d.ts +4 -4
- package/dist/tools/deck.d.ts.map +1 -1
- package/dist/tools/deck.js +1546 -78
- package/dist/tools/deck.js.map +1 -1
- package/dist/tools/designer/index.d.ts +6 -0
- package/dist/tools/designer/index.d.ts.map +1 -1
- package/dist/tools/designer/index.js +344 -1
- package/dist/tools/designer/index.js.map +1 -1
- package/dist/tools/designer.d.ts +143 -0
- package/dist/tools/designer.d.ts.map +1 -1
- package/dist/tools/designer.js +457 -0
- package/dist/tools/designer.js.map +1 -1
- package/dist/tools/guardian/index.d.ts +1 -0
- package/dist/tools/guardian/index.d.ts.map +1 -1
- package/dist/tools/guardian/index.js +40 -1
- package/dist/tools/guardian/index.js.map +1 -1
- package/dist/tools/guardian.d.ts +30 -0
- package/dist/tools/guardian.d.ts.map +1 -1
- package/dist/tools/guardian.js +96 -0
- package/dist/tools/guardian.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +7 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/mother.d.ts +11 -0
- package/dist/tools/mother.d.ts.map +1 -0
- package/dist/tools/mother.js +503 -0
- package/dist/tools/mother.js.map +1 -0
- package/dist/tools/swarm.d.ts +11 -0
- package/dist/tools/swarm.d.ts.map +1 -0
- package/dist/tools/swarm.js +701 -0
- package/dist/tools/swarm.js.map +1 -0
- package/dist/tools/terminal.d.ts +17 -0
- package/dist/tools/terminal.d.ts.map +1 -0
- package/dist/tools/terminal.js +968 -0
- package/dist/tools/terminal.js.map +1 -0
- package/dist/transports/http.d.ts.map +1 -1
- package/dist/transports/http.js +2 -0
- package/dist/transports/http.js.map +1 -1
- package/dist/transports/types.d.ts +4 -0
- package/dist/transports/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/templates/docs.html +1084 -0
package/dist/tools/designer.d.ts
CHANGED
|
@@ -117,6 +117,149 @@ export interface CheckParityOutput {
|
|
|
117
117
|
source: string;
|
|
118
118
|
}
|
|
119
119
|
export declare function checkParity(input: CheckParityInput): Promise<CheckParityOutput | DesignerError>;
|
|
120
|
+
export interface TokensLookupInput {
|
|
121
|
+
projectId?: string;
|
|
122
|
+
category?: string;
|
|
123
|
+
}
|
|
124
|
+
export interface TokensLookupOutput {
|
|
125
|
+
tokens: DesignToken[];
|
|
126
|
+
total: number;
|
|
127
|
+
categories: string[];
|
|
128
|
+
source: string | null;
|
|
129
|
+
synced_at: string | null;
|
|
130
|
+
path: string;
|
|
131
|
+
}
|
|
132
|
+
export declare function tokensLookup(input: TokensLookupInput): Promise<TokensLookupOutput | DesignerError>;
|
|
133
|
+
export interface DriftDetectionInput {
|
|
134
|
+
projectId?: string;
|
|
135
|
+
}
|
|
136
|
+
export interface DriftEntry {
|
|
137
|
+
token_name: string;
|
|
138
|
+
expected: string;
|
|
139
|
+
actual: string;
|
|
140
|
+
file: string;
|
|
141
|
+
format: 'css' | 'tailwind' | 'swift' | 'json';
|
|
142
|
+
}
|
|
143
|
+
export interface DriftDetectionOutput {
|
|
144
|
+
drifted: DriftEntry[];
|
|
145
|
+
scanned_files: number;
|
|
146
|
+
total_tokens_checked: number;
|
|
147
|
+
drift_detected: boolean;
|
|
148
|
+
timestamp: string;
|
|
149
|
+
}
|
|
150
|
+
export declare function driftDetection(input: DriftDetectionInput): Promise<DriftDetectionOutput | DesignerError>;
|
|
151
|
+
export interface FigmaParityInput {
|
|
152
|
+
projectId?: string;
|
|
153
|
+
component: string;
|
|
154
|
+
figma_node_id?: string;
|
|
155
|
+
}
|
|
156
|
+
export interface FigmaParityOutput {
|
|
157
|
+
component: string;
|
|
158
|
+
status: 'pending_figma_integration' | 'compared';
|
|
159
|
+
figma_node_id: string | null;
|
|
160
|
+
message: string;
|
|
161
|
+
timestamp: string;
|
|
162
|
+
}
|
|
163
|
+
export declare function figmaParity(input: FigmaParityInput): Promise<FigmaParityOutput | DesignerError>;
|
|
120
164
|
export declare function listPrinciples(input: ListPrinciplesInput): Promise<ListPrinciplesOutput | DesignerError>;
|
|
165
|
+
export type EvalType = 'token-drift' | 'component-parity' | 'motion-review' | 'design-compliance' | 'visual-review' | 'accessibility';
|
|
166
|
+
export type EvalScope = 'component' | 'page' | 'project';
|
|
167
|
+
export type FindingSeverity = 'critical' | 'warning' | 'info';
|
|
168
|
+
export interface EvalFinding {
|
|
169
|
+
severity: FindingSeverity;
|
|
170
|
+
category: string;
|
|
171
|
+
message: string;
|
|
172
|
+
location?: string;
|
|
173
|
+
expected?: string;
|
|
174
|
+
actual?: string;
|
|
175
|
+
suggestion?: string;
|
|
176
|
+
}
|
|
177
|
+
export interface LogEvalInput {
|
|
178
|
+
projectId?: string;
|
|
179
|
+
evalType: EvalType;
|
|
180
|
+
scope: EvalScope;
|
|
181
|
+
target: string;
|
|
182
|
+
score: number;
|
|
183
|
+
summary: string;
|
|
184
|
+
findings: EvalFinding[];
|
|
185
|
+
platform?: string;
|
|
186
|
+
branch?: string;
|
|
187
|
+
commit?: string;
|
|
188
|
+
evaluator?: string;
|
|
189
|
+
requestedBy?: string;
|
|
190
|
+
tags?: string[];
|
|
191
|
+
}
|
|
192
|
+
export interface LogEvalOutput {
|
|
193
|
+
id: string;
|
|
194
|
+
grade: string;
|
|
195
|
+
score: number;
|
|
196
|
+
findingCounts: {
|
|
197
|
+
critical: number;
|
|
198
|
+
warning: number;
|
|
199
|
+
info: number;
|
|
200
|
+
};
|
|
201
|
+
previousEvalId: string | null;
|
|
202
|
+
path: string;
|
|
203
|
+
timestamp: string;
|
|
204
|
+
}
|
|
205
|
+
export declare function logEval(input: LogEvalInput): Promise<LogEvalOutput | DesignerError>;
|
|
206
|
+
export interface ListEvalsInput {
|
|
207
|
+
projectId?: string;
|
|
208
|
+
evalType?: EvalType;
|
|
209
|
+
scope?: EvalScope;
|
|
210
|
+
target?: string;
|
|
211
|
+
minScore?: number;
|
|
212
|
+
maxScore?: number;
|
|
213
|
+
tags?: string[];
|
|
214
|
+
limit?: number;
|
|
215
|
+
}
|
|
216
|
+
export interface EvalSummary {
|
|
217
|
+
id: string;
|
|
218
|
+
eval_type: EvalType;
|
|
219
|
+
scope: EvalScope;
|
|
220
|
+
target: string;
|
|
221
|
+
score: number;
|
|
222
|
+
grade: string;
|
|
223
|
+
summary: string;
|
|
224
|
+
finding_counts: {
|
|
225
|
+
critical: number;
|
|
226
|
+
warning: number;
|
|
227
|
+
info: number;
|
|
228
|
+
};
|
|
229
|
+
tags: string[];
|
|
230
|
+
timestamp: string;
|
|
231
|
+
}
|
|
232
|
+
export interface ListEvalsOutput {
|
|
233
|
+
evals: EvalSummary[];
|
|
234
|
+
total: number;
|
|
235
|
+
path: string;
|
|
236
|
+
}
|
|
237
|
+
export declare function listEvals(input: ListEvalsInput): Promise<ListEvalsOutput | DesignerError>;
|
|
238
|
+
export interface EvalHistoryInput {
|
|
239
|
+
projectId?: string;
|
|
240
|
+
evalType: EvalType;
|
|
241
|
+
target?: string;
|
|
242
|
+
}
|
|
243
|
+
export interface EvalHistoryPoint {
|
|
244
|
+
id: string;
|
|
245
|
+
score: number;
|
|
246
|
+
grade: string;
|
|
247
|
+
finding_counts: {
|
|
248
|
+
critical: number;
|
|
249
|
+
warning: number;
|
|
250
|
+
info: number;
|
|
251
|
+
};
|
|
252
|
+
timestamp: string;
|
|
253
|
+
summary: string;
|
|
254
|
+
}
|
|
255
|
+
export interface EvalHistoryOutput {
|
|
256
|
+
eval_type: EvalType;
|
|
257
|
+
target: string;
|
|
258
|
+
history: EvalHistoryPoint[];
|
|
259
|
+
trend: 'improving' | 'declining' | 'stable' | 'insufficient_data';
|
|
260
|
+
delta: number | null;
|
|
261
|
+
path: string;
|
|
262
|
+
}
|
|
263
|
+
export declare function evalHistory(input: EvalHistoryInput): Promise<EvalHistoryOutput | DesignerError>;
|
|
121
264
|
export {};
|
|
122
265
|
//# sourceMappingURL=designer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"designer.d.ts","sourceRoot":"","sources":["../../src/tools/designer.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"designer.d.ts","sourceRoot":"","sources":["../../src/tools/designer.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAUD,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,aAAa,CAOxE;AAED,MAAM,WAAW,yBAAyB;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,0BAA0B;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,CAAC;CACrB;AAkBD,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,yBAAyB,GAC/B,OAAO,CAAC,0BAA0B,GAAG,aAAa,CAAC,CAoDrD;AAMD,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;IAC1D,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE;QACN,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAiBD,wBAAsB,UAAU,CAC9B,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,gBAAgB,GAAG,aAAa,CAAC,CAsF3C;AAMD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,aAAa,CAAC;CAClD;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,EAAE,EAAE,MAAM,CAAC;KACZ,CAAC;IACF,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,eAAe;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AA6BD,wBAAsB,WAAW,CAC/B,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,iBAAiB,GAAG,aAAa,CAAC,CAmI5C;AAMD,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,eAAe,CACnC,KAAK,EAAE,oBAAoB,GAC1B,OAAO,CAAC,qBAAqB,GAAG,aAAa,CAAC,CAgDhD;AAMD,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAMD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,WAAW,CAC/B,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,iBAAiB,GAAG,aAAa,CAAC,CAyH5C;AAUD,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,YAAY,CAChC,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC,kBAAkB,GAAG,aAAa,CAAC,CAqD7C;AAMD,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,KAAK,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;CAC/C;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;CACnB;AA+ED,wBAAsB,cAAc,CAClC,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,oBAAoB,GAAG,aAAa,CAAC,CAqF/C;AAMD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,2BAA2B,GAAG,UAAU,CAAC;IACjD,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,WAAW,CAC/B,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,iBAAiB,GAAG,aAAa,CAAC,CA6B5C;AAMD,wBAAsB,cAAc,CAClC,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAAC,oBAAoB,GAAG,aAAa,CAAC,CAsB/C;AAMD,MAAM,MAAM,QAAQ,GAChB,aAAa,GACb,kBAAkB,GAClB,eAAe,GACf,mBAAmB,GACnB,eAAe,GACf,eAAe,CAAC;AAEpB,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG,MAAM,GAAG,SAAS,CAAC;AAEzD,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;AAE9D,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,eAAe,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAUD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,OAAO,CAC3B,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,aAAa,GAAG,aAAa,CAAC,CA+FxC;AAMD,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,QAAQ,CAAC;IACpB,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACpE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,SAAS,CAC7B,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,eAAe,GAAG,aAAa,CAAC,CAiF1C;AAMD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,QAAQ,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,KAAK,EAAE,WAAW,GAAG,WAAW,GAAG,QAAQ,GAAG,mBAAmB,CAAC;IAClE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,WAAW,CAC/B,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,iBAAiB,GAAG,aAAa,CAAC,CAyD5C"}
|
package/dist/tools/designer.js
CHANGED
|
@@ -470,6 +470,242 @@ export async function checkParity(input) {
|
|
|
470
470
|
source: `figma:${input.fileKey}`,
|
|
471
471
|
};
|
|
472
472
|
}
|
|
473
|
+
export async function tokensLookup(input) {
|
|
474
|
+
let resolved;
|
|
475
|
+
try {
|
|
476
|
+
resolved = resolveProjectPaths(input.projectId);
|
|
477
|
+
}
|
|
478
|
+
catch {
|
|
479
|
+
return makeProjectError('look up tokens');
|
|
480
|
+
}
|
|
481
|
+
const tokensFile = path.join(resolved.subPath('designer', 'tokens'), 'tokens.yaml');
|
|
482
|
+
let tokens;
|
|
483
|
+
let source = null;
|
|
484
|
+
let synced_at = null;
|
|
485
|
+
try {
|
|
486
|
+
const content = await fs.readFile(tokensFile, 'utf-8');
|
|
487
|
+
const data = YAML.parse(content);
|
|
488
|
+
tokens = data?.tokens || [];
|
|
489
|
+
source = data?.source || null;
|
|
490
|
+
synced_at = data?.synced_at || null;
|
|
491
|
+
}
|
|
492
|
+
catch {
|
|
493
|
+
return {
|
|
494
|
+
error: 'NO_TOKENS',
|
|
495
|
+
message: 'No tokens.yaml found. Sync tokens from Figma first or create a tokens file manually.',
|
|
496
|
+
hint: 'Use designer sync_tokens with a Figma fileKey, or place a tokens.yaml in .decibel/designer/tokens/',
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
// Derive categories from token types + collections
|
|
500
|
+
const categorySet = new Set();
|
|
501
|
+
for (const t of tokens) {
|
|
502
|
+
if (t.type)
|
|
503
|
+
categorySet.add(t.type);
|
|
504
|
+
if (t.collection)
|
|
505
|
+
categorySet.add(t.collection.toLowerCase());
|
|
506
|
+
}
|
|
507
|
+
// Filter by category if specified
|
|
508
|
+
if (input.category) {
|
|
509
|
+
const cat = input.category.toLowerCase();
|
|
510
|
+
tokens = tokens.filter(t => t.type === cat ||
|
|
511
|
+
(t.collection && t.collection.toLowerCase() === cat));
|
|
512
|
+
}
|
|
513
|
+
log(`Designer: Tokens lookup — ${tokens.length} tokens${input.category ? ` (category: ${input.category})` : ''}`);
|
|
514
|
+
return {
|
|
515
|
+
tokens,
|
|
516
|
+
total: tokens.length,
|
|
517
|
+
categories: Array.from(categorySet).sort(),
|
|
518
|
+
source,
|
|
519
|
+
synced_at,
|
|
520
|
+
path: tokensFile,
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
// Format-aware value normalizer: convert various color/value formats to comparable form
|
|
524
|
+
function normalizeColorValue(value) {
|
|
525
|
+
if (typeof value === 'string')
|
|
526
|
+
return value.toLowerCase().replace(/\s/g, '');
|
|
527
|
+
// Figma RGBA object → hex
|
|
528
|
+
if (typeof value === 'object' && value !== null && 'r' in value) {
|
|
529
|
+
const v = value;
|
|
530
|
+
const toHex = (n) => Math.round(n * 255).toString(16).padStart(2, '0');
|
|
531
|
+
return `#${toHex(v.r)}${toHex(v.g)}${toHex(v.b)}`.toLowerCase();
|
|
532
|
+
}
|
|
533
|
+
if (typeof value === 'number')
|
|
534
|
+
return String(value);
|
|
535
|
+
return null;
|
|
536
|
+
}
|
|
537
|
+
// Parsers for different source file formats
|
|
538
|
+
const FORMAT_PARSERS = {
|
|
539
|
+
css: {
|
|
540
|
+
glob: '**/*.css',
|
|
541
|
+
extract(content) {
|
|
542
|
+
const map = new Map();
|
|
543
|
+
const re = /--([a-zA-Z0-9_-]+)\s*:\s*([^;]+)/g;
|
|
544
|
+
let m;
|
|
545
|
+
while ((m = re.exec(content)) !== null) {
|
|
546
|
+
map.set(m[1].toLowerCase(), m[2].trim().toLowerCase());
|
|
547
|
+
}
|
|
548
|
+
return map;
|
|
549
|
+
},
|
|
550
|
+
},
|
|
551
|
+
tailwind: {
|
|
552
|
+
glob: '**/tailwind.config.{js,ts,cjs,mjs}',
|
|
553
|
+
extract(content) {
|
|
554
|
+
const map = new Map();
|
|
555
|
+
// Match hex/rgb values in tailwind config
|
|
556
|
+
const re = /['"]([a-zA-Z0-9_-]+)['"]\s*:\s*['"](#[0-9a-fA-F]{3,8}|rgb[a]?\([^)]+\))['"]/g;
|
|
557
|
+
let m;
|
|
558
|
+
while ((m = re.exec(content)) !== null) {
|
|
559
|
+
map.set(m[1].toLowerCase(), m[2].toLowerCase());
|
|
560
|
+
}
|
|
561
|
+
return map;
|
|
562
|
+
},
|
|
563
|
+
},
|
|
564
|
+
swift: {
|
|
565
|
+
glob: '**/*.swift',
|
|
566
|
+
extract(content) {
|
|
567
|
+
const map = new Map();
|
|
568
|
+
// Match Color(hex: 0xRRGGBB) or Color(hex: "RRGGBB")
|
|
569
|
+
const re = /(?:let|var|static)\s+(\w+)\s*.*?Color\(\s*hex\s*:\s*(?:0x|"|')([0-9a-fA-F]{6,8})/g;
|
|
570
|
+
let m;
|
|
571
|
+
while ((m = re.exec(content)) !== null) {
|
|
572
|
+
map.set(m[1].toLowerCase(), `#${m[2].toLowerCase()}`);
|
|
573
|
+
}
|
|
574
|
+
return map;
|
|
575
|
+
},
|
|
576
|
+
},
|
|
577
|
+
json: {
|
|
578
|
+
glob: '**/tokens.json',
|
|
579
|
+
extract(content) {
|
|
580
|
+
const map = new Map();
|
|
581
|
+
try {
|
|
582
|
+
const data = JSON.parse(content);
|
|
583
|
+
// Flatten nested token objects
|
|
584
|
+
function walk(obj, prefix) {
|
|
585
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
586
|
+
const key = prefix ? `${prefix}/${k}` : k;
|
|
587
|
+
if (typeof v === 'object' && v !== null && 'value' in v) {
|
|
588
|
+
map.set(key.toLowerCase(), String(v.value).toLowerCase());
|
|
589
|
+
}
|
|
590
|
+
else if (typeof v === 'object' && v !== null) {
|
|
591
|
+
walk(v, key);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
walk(data, '');
|
|
596
|
+
}
|
|
597
|
+
catch { /* not valid JSON, skip */ }
|
|
598
|
+
return map;
|
|
599
|
+
},
|
|
600
|
+
},
|
|
601
|
+
};
|
|
602
|
+
export async function driftDetection(input) {
|
|
603
|
+
let resolved;
|
|
604
|
+
try {
|
|
605
|
+
resolved = resolveProjectPaths(input.projectId);
|
|
606
|
+
}
|
|
607
|
+
catch {
|
|
608
|
+
return makeProjectError('detect drift');
|
|
609
|
+
}
|
|
610
|
+
const now = new Date();
|
|
611
|
+
// Load token registry
|
|
612
|
+
const tokensFile = path.join(resolved.subPath('designer', 'tokens'), 'tokens.yaml');
|
|
613
|
+
let registryTokens;
|
|
614
|
+
try {
|
|
615
|
+
const content = await fs.readFile(tokensFile, 'utf-8');
|
|
616
|
+
const data = YAML.parse(content);
|
|
617
|
+
registryTokens = data?.tokens || [];
|
|
618
|
+
}
|
|
619
|
+
catch {
|
|
620
|
+
return {
|
|
621
|
+
error: 'NO_TOKENS',
|
|
622
|
+
message: 'No tokens.yaml found. Sync or create tokens first.',
|
|
623
|
+
hint: 'Use designer sync_tokens or manually place tokens.yaml in .decibel/designer/tokens/',
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
// Build a lookup from token name → normalized expected value
|
|
627
|
+
const expectedMap = new Map();
|
|
628
|
+
for (const t of registryTokens) {
|
|
629
|
+
const norm = normalizeColorValue(t.value);
|
|
630
|
+
if (norm) {
|
|
631
|
+
// Use the last segment of slash-separated names for matching
|
|
632
|
+
const shortName = t.name.split('/').pop().toLowerCase();
|
|
633
|
+
expectedMap.set(shortName, norm);
|
|
634
|
+
expectedMap.set(t.name.toLowerCase(), norm);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
const drifted = [];
|
|
638
|
+
let scannedFiles = 0;
|
|
639
|
+
// Scan source files using each format parser
|
|
640
|
+
for (const [format, parser] of Object.entries(FORMAT_PARSERS)) {
|
|
641
|
+
// Use the project root to find source files
|
|
642
|
+
const projectRoot = resolved.projectPath.replace(/\/.decibel$/, '');
|
|
643
|
+
let files;
|
|
644
|
+
try {
|
|
645
|
+
const { glob } = await import('glob');
|
|
646
|
+
files = await glob(parser.glob, {
|
|
647
|
+
cwd: projectRoot,
|
|
648
|
+
absolute: true,
|
|
649
|
+
ignore: ['**/node_modules/**', '**/dist/**', '**/.decibel/**'],
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
catch {
|
|
653
|
+
continue; // glob not available or no matches
|
|
654
|
+
}
|
|
655
|
+
for (const file of files) {
|
|
656
|
+
scannedFiles++;
|
|
657
|
+
const content = await fs.readFile(file, 'utf-8');
|
|
658
|
+
const sourceValues = parser.extract(content);
|
|
659
|
+
for (const [name, actual] of sourceValues) {
|
|
660
|
+
const expected = expectedMap.get(name);
|
|
661
|
+
if (expected && expected !== actual.replace(/\s/g, '')) {
|
|
662
|
+
drifted.push({
|
|
663
|
+
token_name: name,
|
|
664
|
+
expected,
|
|
665
|
+
actual,
|
|
666
|
+
file: path.relative(projectRoot, file),
|
|
667
|
+
format: format,
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
log(`Designer: Drift detection — ${drifted.length} drifted tokens across ${scannedFiles} files`);
|
|
674
|
+
return {
|
|
675
|
+
drifted,
|
|
676
|
+
scanned_files: scannedFiles,
|
|
677
|
+
total_tokens_checked: expectedMap.size,
|
|
678
|
+
drift_detected: drifted.length > 0,
|
|
679
|
+
timestamp: now.toISOString(),
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
export async function figmaParity(input) {
|
|
683
|
+
let resolved;
|
|
684
|
+
try {
|
|
685
|
+
resolved = resolveProjectPaths(input.projectId);
|
|
686
|
+
}
|
|
687
|
+
catch {
|
|
688
|
+
return makeProjectError('check Figma parity');
|
|
689
|
+
}
|
|
690
|
+
// Input validation
|
|
691
|
+
if (!input.component || input.component.trim().length === 0) {
|
|
692
|
+
return {
|
|
693
|
+
error: 'INVALID_INPUT',
|
|
694
|
+
message: 'component parameter is required and must be non-empty.',
|
|
695
|
+
hint: 'Provide the component name or file path (e.g., "Button", "src/components/Button.tsx").',
|
|
696
|
+
};
|
|
697
|
+
}
|
|
698
|
+
const now = new Date();
|
|
699
|
+
// Phase 1: skeleton — real Figma MCP integration is pending
|
|
700
|
+
log(`Designer: Figma parity check requested for component "${input.component}" (Phase 2 integration pending)`);
|
|
701
|
+
return {
|
|
702
|
+
component: input.component,
|
|
703
|
+
status: 'pending_figma_integration',
|
|
704
|
+
figma_node_id: input.figma_node_id || null,
|
|
705
|
+
message: `Figma parity diff for "${input.component}" is registered. Real comparison requires Phase 2 Figma MCP integration. Node ID ${input.figma_node_id ? `"${input.figma_node_id}" saved for` : 'not provided — will need it for'} automated comparison.`,
|
|
706
|
+
timestamp: now.toISOString(),
|
|
707
|
+
};
|
|
708
|
+
}
|
|
473
709
|
// ============================================================================
|
|
474
710
|
// List Design Principles
|
|
475
711
|
// ============================================================================
|
|
@@ -492,4 +728,225 @@ export async function listPrinciples(input) {
|
|
|
492
728
|
path: principlesDir,
|
|
493
729
|
};
|
|
494
730
|
}
|
|
731
|
+
function deriveGrade(score) {
|
|
732
|
+
if (score >= 90)
|
|
733
|
+
return 'A';
|
|
734
|
+
if (score >= 80)
|
|
735
|
+
return 'B';
|
|
736
|
+
if (score >= 70)
|
|
737
|
+
return 'C';
|
|
738
|
+
if (score >= 60)
|
|
739
|
+
return 'D';
|
|
740
|
+
return 'F';
|
|
741
|
+
}
|
|
742
|
+
export async function logEval(input) {
|
|
743
|
+
let resolved;
|
|
744
|
+
try {
|
|
745
|
+
resolved = resolveProjectPaths(input.projectId);
|
|
746
|
+
}
|
|
747
|
+
catch {
|
|
748
|
+
return makeProjectError('log eval');
|
|
749
|
+
}
|
|
750
|
+
// Validate score range
|
|
751
|
+
if (input.score < 0 || input.score > 100) {
|
|
752
|
+
return {
|
|
753
|
+
error: 'INVALID_INPUT',
|
|
754
|
+
message: 'score must be between 0 and 100.',
|
|
755
|
+
};
|
|
756
|
+
}
|
|
757
|
+
const now = new Date();
|
|
758
|
+
const timestamp = now.toISOString();
|
|
759
|
+
const fileTimestamp = formatTimestampForFilename(now);
|
|
760
|
+
const grade = deriveGrade(input.score);
|
|
761
|
+
const id = `EVAL-${fileTimestamp}-${slugify(input.target)}`;
|
|
762
|
+
const evalsDir = resolved.subPath('designer', 'evals');
|
|
763
|
+
ensureDir(evalsDir);
|
|
764
|
+
// Auto-link to most recent eval with same evalType + target
|
|
765
|
+
let previousEvalId = null;
|
|
766
|
+
try {
|
|
767
|
+
const existingFiles = await fs.readdir(evalsDir);
|
|
768
|
+
const candidates = [];
|
|
769
|
+
for (const f of existingFiles) {
|
|
770
|
+
if (!f.endsWith('.yaml') && !f.endsWith('.yml'))
|
|
771
|
+
continue;
|
|
772
|
+
try {
|
|
773
|
+
const content = await fs.readFile(path.join(evalsDir, f), 'utf-8');
|
|
774
|
+
const data = YAML.parse(content);
|
|
775
|
+
if (data?.eval_type === input.evalType && data?.target === input.target && data?.id) {
|
|
776
|
+
candidates.push({ id: data.id, timestamp: data.timestamp });
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
catch { /* skip malformed */ }
|
|
780
|
+
}
|
|
781
|
+
if (candidates.length > 0) {
|
|
782
|
+
candidates.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
783
|
+
previousEvalId = candidates[0].id;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
catch { /* no evals dir yet */ }
|
|
787
|
+
const findingCounts = {
|
|
788
|
+
critical: input.findings.filter(f => f.severity === 'critical').length,
|
|
789
|
+
warning: input.findings.filter(f => f.severity === 'warning').length,
|
|
790
|
+
info: input.findings.filter(f => f.severity === 'info').length,
|
|
791
|
+
};
|
|
792
|
+
const evalData = {
|
|
793
|
+
id,
|
|
794
|
+
project: resolved.id,
|
|
795
|
+
eval_type: input.evalType,
|
|
796
|
+
scope: input.scope,
|
|
797
|
+
target: input.target,
|
|
798
|
+
score: input.score,
|
|
799
|
+
grade,
|
|
800
|
+
summary: input.summary,
|
|
801
|
+
findings: input.findings,
|
|
802
|
+
finding_counts: findingCounts,
|
|
803
|
+
previous_eval_id: previousEvalId,
|
|
804
|
+
platform: input.platform || null,
|
|
805
|
+
branch: input.branch || null,
|
|
806
|
+
commit: input.commit || null,
|
|
807
|
+
evaluator: input.evaluator || 'decibel-designer',
|
|
808
|
+
requested_by: input.requestedBy || null,
|
|
809
|
+
tags: input.tags || [],
|
|
810
|
+
timestamp,
|
|
811
|
+
};
|
|
812
|
+
const filePath = path.join(evalsDir, `${id}.yaml`);
|
|
813
|
+
validateWritePath(filePath, resolved);
|
|
814
|
+
await fs.writeFile(filePath, YAML.stringify(evalData), 'utf-8');
|
|
815
|
+
log(`Designer: Logged eval ${id} — ${input.evalType} ${input.scope} "${input.target}" → ${grade} (${input.score}/100, ${input.findings.length} findings)`);
|
|
816
|
+
await emitCreateProvenance(`designer:eval:${id}`, YAML.stringify(evalData), `Design eval: ${input.evalType} on "${input.target}" — ${grade} (${input.score}/100)`, input.projectId);
|
|
817
|
+
return {
|
|
818
|
+
id,
|
|
819
|
+
grade,
|
|
820
|
+
score: input.score,
|
|
821
|
+
findingCounts,
|
|
822
|
+
previousEvalId,
|
|
823
|
+
path: filePath,
|
|
824
|
+
timestamp,
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
export async function listEvals(input) {
|
|
828
|
+
let resolved;
|
|
829
|
+
try {
|
|
830
|
+
resolved = resolveProjectPaths(input.projectId);
|
|
831
|
+
}
|
|
832
|
+
catch {
|
|
833
|
+
return makeProjectError('list evals');
|
|
834
|
+
}
|
|
835
|
+
const evalsDir = resolved.subPath('designer', 'evals');
|
|
836
|
+
let files;
|
|
837
|
+
try {
|
|
838
|
+
files = await fs.readdir(evalsDir);
|
|
839
|
+
}
|
|
840
|
+
catch {
|
|
841
|
+
return { evals: [], total: 0, path: evalsDir };
|
|
842
|
+
}
|
|
843
|
+
const evals = [];
|
|
844
|
+
for (const file of files) {
|
|
845
|
+
if (!file.endsWith('.yaml') && !file.endsWith('.yml'))
|
|
846
|
+
continue;
|
|
847
|
+
try {
|
|
848
|
+
const content = await fs.readFile(path.join(evalsDir, file), 'utf-8');
|
|
849
|
+
const data = YAML.parse(content);
|
|
850
|
+
if (!data?.id)
|
|
851
|
+
continue;
|
|
852
|
+
evals.push({
|
|
853
|
+
id: data.id,
|
|
854
|
+
eval_type: data.eval_type,
|
|
855
|
+
scope: data.scope,
|
|
856
|
+
target: data.target,
|
|
857
|
+
score: data.score,
|
|
858
|
+
grade: data.grade,
|
|
859
|
+
summary: data.summary,
|
|
860
|
+
finding_counts: data.finding_counts || { critical: 0, warning: 0, info: 0 },
|
|
861
|
+
tags: data.tags || [],
|
|
862
|
+
timestamp: data.timestamp,
|
|
863
|
+
});
|
|
864
|
+
}
|
|
865
|
+
catch {
|
|
866
|
+
// Skip malformed files
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
// Apply filters
|
|
870
|
+
let filtered = evals;
|
|
871
|
+
if (input.evalType) {
|
|
872
|
+
filtered = filtered.filter(e => e.eval_type === input.evalType);
|
|
873
|
+
}
|
|
874
|
+
if (input.scope) {
|
|
875
|
+
filtered = filtered.filter(e => e.scope === input.scope);
|
|
876
|
+
}
|
|
877
|
+
if (input.target) {
|
|
878
|
+
const t = input.target.toLowerCase();
|
|
879
|
+
filtered = filtered.filter(e => e.target.toLowerCase().includes(t));
|
|
880
|
+
}
|
|
881
|
+
if (input.minScore !== undefined) {
|
|
882
|
+
filtered = filtered.filter(e => e.score >= input.minScore);
|
|
883
|
+
}
|
|
884
|
+
if (input.maxScore !== undefined) {
|
|
885
|
+
filtered = filtered.filter(e => e.score <= input.maxScore);
|
|
886
|
+
}
|
|
887
|
+
if (input.tags && input.tags.length > 0) {
|
|
888
|
+
filtered = filtered.filter(e => input.tags.some(tag => e.tags.includes(tag)));
|
|
889
|
+
}
|
|
890
|
+
// Sort by timestamp descending (most recent first)
|
|
891
|
+
filtered.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
892
|
+
if (input.limit) {
|
|
893
|
+
filtered = filtered.slice(0, input.limit);
|
|
894
|
+
}
|
|
895
|
+
return {
|
|
896
|
+
evals: filtered,
|
|
897
|
+
total: filtered.length,
|
|
898
|
+
path: evalsDir,
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
export async function evalHistory(input) {
|
|
902
|
+
let resolved;
|
|
903
|
+
try {
|
|
904
|
+
resolved = resolveProjectPaths(input.projectId);
|
|
905
|
+
}
|
|
906
|
+
catch {
|
|
907
|
+
return makeProjectError('get eval history');
|
|
908
|
+
}
|
|
909
|
+
const target = input.target || 'full-project';
|
|
910
|
+
// Reuse listEvals to get all matching evals
|
|
911
|
+
const result = await listEvals({
|
|
912
|
+
projectId: input.projectId,
|
|
913
|
+
evalType: input.evalType,
|
|
914
|
+
target,
|
|
915
|
+
});
|
|
916
|
+
if ('error' in result)
|
|
917
|
+
return result;
|
|
918
|
+
// Sort chronologically (oldest first) for trend analysis
|
|
919
|
+
const sorted = [...result.evals].sort((a, b) => a.timestamp.localeCompare(b.timestamp));
|
|
920
|
+
const history = sorted.map(e => ({
|
|
921
|
+
id: e.id,
|
|
922
|
+
score: e.score,
|
|
923
|
+
grade: e.grade,
|
|
924
|
+
finding_counts: e.finding_counts,
|
|
925
|
+
timestamp: e.timestamp,
|
|
926
|
+
summary: e.summary,
|
|
927
|
+
}));
|
|
928
|
+
// Compute trend
|
|
929
|
+
let trend = 'insufficient_data';
|
|
930
|
+
let delta = null;
|
|
931
|
+
if (history.length >= 2) {
|
|
932
|
+
const first = history[0].score;
|
|
933
|
+
const last = history[history.length - 1].score;
|
|
934
|
+
delta = last - first;
|
|
935
|
+
if (delta > 5)
|
|
936
|
+
trend = 'improving';
|
|
937
|
+
else if (delta < -5)
|
|
938
|
+
trend = 'declining';
|
|
939
|
+
else
|
|
940
|
+
trend = 'stable';
|
|
941
|
+
}
|
|
942
|
+
log(`Designer: Eval history for ${input.evalType} "${target}" — ${history.length} data points, trend: ${trend}`);
|
|
943
|
+
return {
|
|
944
|
+
eval_type: input.evalType,
|
|
945
|
+
target,
|
|
946
|
+
history,
|
|
947
|
+
trend,
|
|
948
|
+
delta,
|
|
949
|
+
path: resolved.subPath('designer', 'evals'),
|
|
950
|
+
};
|
|
951
|
+
}
|
|
495
952
|
//# sourceMappingURL=designer.js.map
|