cc-proficiency 0.1.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/.claude-plugin/plugin.json +11 -0
- package/LICENSE +201 -0
- package/README.md +345 -0
- package/README.zh-CN.md +284 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +543 -0
- package/dist/cli.js.map +1 -0
- package/dist/gist/uploader.d.ts +26 -0
- package/dist/gist/uploader.d.ts.map +1 -0
- package/dist/gist/uploader.js +99 -0
- package/dist/gist/uploader.js.map +1 -0
- package/dist/hooks/session-end.js +64 -0
- package/dist/i18n/locales.d.ts +30 -0
- package/dist/i18n/locales.d.ts.map +1 -0
- package/dist/i18n/locales.js +64 -0
- package/dist/i18n/locales.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/parsers/config-parser.d.ts +25 -0
- package/dist/parsers/config-parser.d.ts.map +1 -0
- package/dist/parsers/config-parser.js +262 -0
- package/dist/parsers/config-parser.js.map +1 -0
- package/dist/parsers/history-parser.d.ts +13 -0
- package/dist/parsers/history-parser.d.ts.map +1 -0
- package/dist/parsers/history-parser.js +50 -0
- package/dist/parsers/history-parser.js.map +1 -0
- package/dist/parsers/normalizer.d.ts +8 -0
- package/dist/parsers/normalizer.d.ts.map +1 -0
- package/dist/parsers/normalizer.js +105 -0
- package/dist/parsers/normalizer.js.map +1 -0
- package/dist/parsers/transcript-parser.d.ts +23 -0
- package/dist/parsers/transcript-parser.d.ts.map +1 -0
- package/dist/parsers/transcript-parser.js +112 -0
- package/dist/parsers/transcript-parser.js.map +1 -0
- package/dist/renderer/svg.d.ts +10 -0
- package/dist/renderer/svg.d.ts.map +1 -0
- package/dist/renderer/svg.js +209 -0
- package/dist/renderer/svg.js.map +1 -0
- package/dist/scoring/curves.d.ts +34 -0
- package/dist/scoring/curves.d.ts.map +1 -0
- package/dist/scoring/curves.js +60 -0
- package/dist/scoring/curves.js.map +1 -0
- package/dist/scoring/engine.d.ts +16 -0
- package/dist/scoring/engine.d.ts.map +1 -0
- package/dist/scoring/engine.js +137 -0
- package/dist/scoring/engine.js.map +1 -0
- package/dist/scoring/rule-engine.d.ts +30 -0
- package/dist/scoring/rule-engine.d.ts.map +1 -0
- package/dist/scoring/rule-engine.js +151 -0
- package/dist/scoring/rule-engine.js.map +1 -0
- package/dist/scoring/rules.d.ts +32 -0
- package/dist/scoring/rules.d.ts.map +1 -0
- package/dist/scoring/rules.js +443 -0
- package/dist/scoring/rules.js.map +1 -0
- package/dist/scoring/signals.d.ts +7 -0
- package/dist/scoring/signals.d.ts.map +1 -0
- package/dist/scoring/signals.js +245 -0
- package/dist/scoring/signals.js.map +1 -0
- package/dist/store/local-store.d.ts +12 -0
- package/dist/store/local-store.d.ts.map +1 -0
- package/dist/store/local-store.js +107 -0
- package/dist/store/local-store.js.map +1 -0
- package/dist/store/queue.d.ts +24 -0
- package/dist/store/queue.d.ts.map +1 -0
- package/dist/store/queue.js +105 -0
- package/dist/store/queue.js.map +1 -0
- package/dist/types.d.ts +264 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/ci-detect.d.ts +6 -0
- package/dist/utils/ci-detect.d.ts.map +1 -0
- package/dist/utils/ci-detect.js +19 -0
- package/dist/utils/ci-detect.js.map +1 -0
- package/hooks/hooks.json +15 -0
- package/hooks/session-end.ts +71 -0
- package/hooks/tsconfig.json +13 -0
- package/package.json +43 -0
- package/skills/proficiency/SKILL.md +15 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface HistorySignals {
|
|
2
|
+
totalEntries: number;
|
|
3
|
+
uniqueProjects: Set<string>;
|
|
4
|
+
uniqueCommands: Set<string>;
|
|
5
|
+
pastedContentCount: number;
|
|
6
|
+
sessionIds: Set<string>;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Parse ~/.claude/history.jsonl to extract usage signals.
|
|
10
|
+
* Streaming line-by-line with per-line error handling.
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseHistory(filePath: string): Promise<HistorySignals>;
|
|
13
|
+
//# sourceMappingURL=history-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-parser.d.ts","sourceRoot":"","sources":["../../src/parsers/history-parser.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5B,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CA4C5E"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseHistory = parseHistory;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const node_readline_1 = require("node:readline");
|
|
6
|
+
/**
|
|
7
|
+
* Parse ~/.claude/history.jsonl to extract usage signals.
|
|
8
|
+
* Streaming line-by-line with per-line error handling.
|
|
9
|
+
*/
|
|
10
|
+
async function parseHistory(filePath) {
|
|
11
|
+
const result = {
|
|
12
|
+
totalEntries: 0,
|
|
13
|
+
uniqueProjects: new Set(),
|
|
14
|
+
uniqueCommands: new Set(),
|
|
15
|
+
pastedContentCount: 0,
|
|
16
|
+
sessionIds: new Set(),
|
|
17
|
+
};
|
|
18
|
+
const rl = (0, node_readline_1.createInterface)({
|
|
19
|
+
input: (0, node_fs_1.createReadStream)(filePath, { encoding: "utf-8" }),
|
|
20
|
+
crlfDelay: Infinity,
|
|
21
|
+
});
|
|
22
|
+
for await (const line of rl) {
|
|
23
|
+
if (!line.trim())
|
|
24
|
+
continue;
|
|
25
|
+
try {
|
|
26
|
+
const entry = JSON.parse(line);
|
|
27
|
+
result.totalEntries++;
|
|
28
|
+
if (entry.project) {
|
|
29
|
+
result.uniqueProjects.add(entry.project);
|
|
30
|
+
}
|
|
31
|
+
if (entry.sessionId) {
|
|
32
|
+
result.sessionIds.add(entry.sessionId);
|
|
33
|
+
}
|
|
34
|
+
// Slash commands (display starts with /)
|
|
35
|
+
if (entry.display && entry.display.startsWith("/")) {
|
|
36
|
+
const command = entry.display.split(" ")[0];
|
|
37
|
+
result.uniqueCommands.add(command);
|
|
38
|
+
}
|
|
39
|
+
// Pasted content
|
|
40
|
+
if (entry.pastedContents && Object.keys(entry.pastedContents).length > 0) {
|
|
41
|
+
result.pastedContentCount++;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// Malformed line — skip
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=history-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-parser.js","sourceRoot":"","sources":["../../src/parsers/history-parser.ts"],"names":[],"mappings":";;AAgBA,oCA4CC;AA5DD,qCAA2C;AAC3C,iDAAgD;AAWhD;;;GAGG;AACI,KAAK,UAAU,YAAY,CAAC,QAAgB;IACjD,MAAM,MAAM,GAAmB;QAC7B,YAAY,EAAE,CAAC;QACf,cAAc,EAAE,IAAI,GAAG,EAAE;QACzB,cAAc,EAAE,IAAI,GAAG,EAAE;QACzB,kBAAkB,EAAE,CAAC;QACrB,UAAU,EAAE,IAAI,GAAG,EAAE;KACtB,CAAC;IAEF,MAAM,EAAE,GAAG,IAAA,+BAAe,EAAC;QACzB,KAAK,EAAE,IAAA,0BAAgB,EAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;QACxD,SAAS,EAAE,QAAQ;KACpB,CAAC,CAAC;IAEH,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,EAAE,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YAAE,SAAS;QAE3B,IAAI,CAAC;YACH,MAAM,KAAK,GAAiB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC7C,MAAM,CAAC,YAAY,EAAE,CAAC;YAEtB,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;gBAClB,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC3C,CAAC;YACD,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;gBACpB,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YACzC,CAAC;YAED,yCAAyC;YACzC,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACnD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;gBAC7C,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACrC,CAAC;YAED,iBAAiB;YACjB,IAAI,KAAK,CAAC,cAAc,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzE,MAAM,CAAC,kBAAkB,EAAE,CAAC;YAC9B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,wBAAwB;QAC1B,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RawTranscriptEntry, NormalizedEvent } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Normalize a raw JSONL transcript entry into an internal NormalizedEvent.
|
|
4
|
+
* Unknown types → UnknownEvent (logged, not crashed).
|
|
5
|
+
* Missing fields → undefined (signal extractors handle gracefully).
|
|
6
|
+
*/
|
|
7
|
+
export declare function normalizeEntry(raw: RawTranscriptEntry): NormalizedEvent[];
|
|
8
|
+
//# sourceMappingURL=normalizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalizer.d.ts","sourceRoot":"","sources":["../../src/parsers/normalizer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,eAAe,EAEhB,MAAM,aAAa,CAAC;AAErB;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,kBAAkB,GAAG,eAAe,EAAE,CAoBzE"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeEntry = normalizeEntry;
|
|
4
|
+
/**
|
|
5
|
+
* Normalize a raw JSONL transcript entry into an internal NormalizedEvent.
|
|
6
|
+
* Unknown types → UnknownEvent (logged, not crashed).
|
|
7
|
+
* Missing fields → undefined (signal extractors handle gracefully).
|
|
8
|
+
*/
|
|
9
|
+
function normalizeEntry(raw) {
|
|
10
|
+
const base = {
|
|
11
|
+
sessionId: raw.sessionId ?? "",
|
|
12
|
+
timestamp: raw.timestamp ?? "",
|
|
13
|
+
};
|
|
14
|
+
switch (raw.type) {
|
|
15
|
+
case "user":
|
|
16
|
+
return normalizeUserEntry(raw, base);
|
|
17
|
+
case "assistant":
|
|
18
|
+
return normalizeAssistantEntry(raw, base);
|
|
19
|
+
case "progress":
|
|
20
|
+
return normalizeProgressEntry(raw, base);
|
|
21
|
+
case "system":
|
|
22
|
+
return normalizeSystemEntry(raw, base);
|
|
23
|
+
case "file-history-snapshot":
|
|
24
|
+
return [{ kind: "file_snapshot", ...base }];
|
|
25
|
+
default:
|
|
26
|
+
return [{ kind: "unknown", ...base, rawType: raw.type ?? "undefined" }];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function normalizeUserEntry(raw, base) {
|
|
30
|
+
const events = [];
|
|
31
|
+
const msg = raw.message;
|
|
32
|
+
if (!msg)
|
|
33
|
+
return events;
|
|
34
|
+
// User prompt (string content = actual user message)
|
|
35
|
+
if (typeof msg.content === "string") {
|
|
36
|
+
events.push({
|
|
37
|
+
kind: "user_prompt",
|
|
38
|
+
...base,
|
|
39
|
+
content: msg.content,
|
|
40
|
+
permissionMode: raw.permissionMode,
|
|
41
|
+
});
|
|
42
|
+
return events;
|
|
43
|
+
}
|
|
44
|
+
// Tool results (array content)
|
|
45
|
+
if (Array.isArray(msg.content)) {
|
|
46
|
+
for (const block of msg.content) {
|
|
47
|
+
if (block.type === "tool_result") {
|
|
48
|
+
events.push({
|
|
49
|
+
kind: "tool_result",
|
|
50
|
+
...base,
|
|
51
|
+
toolId: block.tool_use_id ?? "",
|
|
52
|
+
isError: block.is_error === true,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return events;
|
|
58
|
+
}
|
|
59
|
+
function normalizeAssistantEntry(raw, base) {
|
|
60
|
+
const events = [];
|
|
61
|
+
const msg = raw.message;
|
|
62
|
+
if (!msg || !Array.isArray(msg.content))
|
|
63
|
+
return events;
|
|
64
|
+
for (const block of msg.content) {
|
|
65
|
+
if (block.type === "tool_use" && block.name) {
|
|
66
|
+
events.push({
|
|
67
|
+
kind: "tool_call",
|
|
68
|
+
...base,
|
|
69
|
+
toolName: block.name,
|
|
70
|
+
toolId: block.id ?? "",
|
|
71
|
+
input: block.input ?? {},
|
|
72
|
+
callerType: block.caller?.type,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return events;
|
|
77
|
+
}
|
|
78
|
+
function normalizeProgressEntry(raw, base) {
|
|
79
|
+
if (raw.data?.type === "hook_progress") {
|
|
80
|
+
return [
|
|
81
|
+
{
|
|
82
|
+
kind: "hook_progress",
|
|
83
|
+
...base,
|
|
84
|
+
hookEvent: raw.data.hookEvent ?? "",
|
|
85
|
+
hookName: raw.data.hookName ?? "",
|
|
86
|
+
command: raw.data.command ?? "",
|
|
87
|
+
},
|
|
88
|
+
];
|
|
89
|
+
}
|
|
90
|
+
return [{ kind: "unknown", ...base, rawType: `progress:${raw.data?.type ?? "unknown"}` }];
|
|
91
|
+
}
|
|
92
|
+
function normalizeSystemEntry(raw, base) {
|
|
93
|
+
if (raw.subtype === "stop_hook_summary") {
|
|
94
|
+
return [
|
|
95
|
+
{
|
|
96
|
+
kind: "system_stop",
|
|
97
|
+
...base,
|
|
98
|
+
hookCount: raw.hookCount ?? 0,
|
|
99
|
+
preventedContinuation: raw.preventedContinuation ?? false,
|
|
100
|
+
},
|
|
101
|
+
];
|
|
102
|
+
}
|
|
103
|
+
return [{ kind: "unknown", ...base, rawType: `system:${raw.subtype ?? "unknown"}` }];
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=normalizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalizer.js","sourceRoot":"","sources":["../../src/parsers/normalizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { NormalizedEvent, ParsedSession } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Parse a session transcript JSONL file using streaming (handles 10MB+ files).
|
|
4
|
+
* Per-line try/catch: malformed lines are skipped with warning.
|
|
5
|
+
*/
|
|
6
|
+
export declare function parseTranscript(filePath: string): Promise<ParsedSession>;
|
|
7
|
+
/**
|
|
8
|
+
* Sanitize a cwd path into a project slug.
|
|
9
|
+
* "/app/my-project" → "my-project"
|
|
10
|
+
* Strips leading path components, keeps only the last segment.
|
|
11
|
+
*/
|
|
12
|
+
export declare function sanitizeProjectSlug(cwd: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Count parallel tool calls in a session.
|
|
15
|
+
* Multiple tool_call events with the same timestamp in a single assistant turn.
|
|
16
|
+
*/
|
|
17
|
+
export declare function countParallelToolCalls(events: NormalizedEvent[]): number;
|
|
18
|
+
/**
|
|
19
|
+
* Detect deliberate tool chaining workflows.
|
|
20
|
+
* E.g., Grep → Read → Edit sequences.
|
|
21
|
+
*/
|
|
22
|
+
export declare function countDeliberateWorkflows(events: NormalizedEvent[]): number;
|
|
23
|
+
//# sourceMappingURL=transcript-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcript-parser.d.ts","sourceRoot":"","sources":["../../src/parsers/transcript-parser.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAsB,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGtF;;;GAGG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAmD9E;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGvD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,CAmBxE;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,CAoB1E"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseTranscript = parseTranscript;
|
|
4
|
+
exports.sanitizeProjectSlug = sanitizeProjectSlug;
|
|
5
|
+
exports.countParallelToolCalls = countParallelToolCalls;
|
|
6
|
+
exports.countDeliberateWorkflows = countDeliberateWorkflows;
|
|
7
|
+
const node_fs_1 = require("node:fs");
|
|
8
|
+
const node_readline_1 = require("node:readline");
|
|
9
|
+
const normalizer_js_1 = require("./normalizer.js");
|
|
10
|
+
/**
|
|
11
|
+
* Parse a session transcript JSONL file using streaming (handles 10MB+ files).
|
|
12
|
+
* Per-line try/catch: malformed lines are skipped with warning.
|
|
13
|
+
*/
|
|
14
|
+
async function parseTranscript(filePath) {
|
|
15
|
+
const events = [];
|
|
16
|
+
let sessionId = "";
|
|
17
|
+
let version = "";
|
|
18
|
+
let project = "";
|
|
19
|
+
let firstTimestamp = "";
|
|
20
|
+
let lastTimestamp = "";
|
|
21
|
+
const rl = (0, node_readline_1.createInterface)({
|
|
22
|
+
input: (0, node_fs_1.createReadStream)(filePath, { encoding: "utf-8" }),
|
|
23
|
+
crlfDelay: Infinity,
|
|
24
|
+
});
|
|
25
|
+
for await (const line of rl) {
|
|
26
|
+
if (!line.trim())
|
|
27
|
+
continue;
|
|
28
|
+
try {
|
|
29
|
+
const raw = JSON.parse(line);
|
|
30
|
+
// Extract session metadata from first entry
|
|
31
|
+
if (!sessionId && raw.sessionId) {
|
|
32
|
+
sessionId = raw.sessionId;
|
|
33
|
+
}
|
|
34
|
+
if (!version && raw.version) {
|
|
35
|
+
version = raw.version;
|
|
36
|
+
}
|
|
37
|
+
if (!project && raw.cwd) {
|
|
38
|
+
project = sanitizeProjectSlug(raw.cwd);
|
|
39
|
+
}
|
|
40
|
+
if (!firstTimestamp && raw.timestamp) {
|
|
41
|
+
firstTimestamp = raw.timestamp;
|
|
42
|
+
}
|
|
43
|
+
if (raw.timestamp) {
|
|
44
|
+
lastTimestamp = raw.timestamp;
|
|
45
|
+
}
|
|
46
|
+
const normalized = (0, normalizer_js_1.normalizeEntry)(raw);
|
|
47
|
+
events.push(...normalized);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// Malformed line — skip silently (could log to error.log in production)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
sessionId,
|
|
55
|
+
startTime: firstTimestamp,
|
|
56
|
+
endTime: lastTimestamp,
|
|
57
|
+
project,
|
|
58
|
+
events,
|
|
59
|
+
version,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Sanitize a cwd path into a project slug.
|
|
64
|
+
* "/app/my-project" → "my-project"
|
|
65
|
+
* Strips leading path components, keeps only the last segment.
|
|
66
|
+
*/
|
|
67
|
+
function sanitizeProjectSlug(cwd) {
|
|
68
|
+
const parts = cwd.replace(/\\/g, "/").split("/").filter(Boolean);
|
|
69
|
+
return parts[parts.length - 1] ?? "unknown";
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Count parallel tool calls in a session.
|
|
73
|
+
* Multiple tool_call events with the same timestamp in a single assistant turn.
|
|
74
|
+
*/
|
|
75
|
+
function countParallelToolCalls(events) {
|
|
76
|
+
const toolCalls = events.filter((e) => e.kind === "tool_call");
|
|
77
|
+
if (toolCalls.length < 2)
|
|
78
|
+
return 0;
|
|
79
|
+
let parallelCount = 0;
|
|
80
|
+
const byTimestamp = new Map();
|
|
81
|
+
for (const tc of toolCalls) {
|
|
82
|
+
const count = (byTimestamp.get(tc.timestamp) ?? 0) + 1;
|
|
83
|
+
byTimestamp.set(tc.timestamp, count);
|
|
84
|
+
}
|
|
85
|
+
for (const count of byTimestamp.values()) {
|
|
86
|
+
if (count > 1) {
|
|
87
|
+
parallelCount += count;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return parallelCount;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Detect deliberate tool chaining workflows.
|
|
94
|
+
* E.g., Grep → Read → Edit sequences.
|
|
95
|
+
*/
|
|
96
|
+
function countDeliberateWorkflows(events) {
|
|
97
|
+
const toolCalls = events.filter((e) => e.kind === "tool_call");
|
|
98
|
+
let workflowCount = 0;
|
|
99
|
+
for (let i = 0; i < toolCalls.length - 2; i++) {
|
|
100
|
+
const a = toolCalls[i];
|
|
101
|
+
const b = toolCalls[i + 1];
|
|
102
|
+
const c = toolCalls[i + 2];
|
|
103
|
+
// Grep/Glob → Read → Edit/Write
|
|
104
|
+
if ((a.toolName === "Grep" || a.toolName === "Glob") &&
|
|
105
|
+
b.toolName === "Read" &&
|
|
106
|
+
(c.toolName === "Edit" || c.toolName === "Write")) {
|
|
107
|
+
workflowCount++;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return workflowCount;
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=transcript-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcript-parser.js","sourceRoot":"","sources":["../../src/parsers/transcript-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ProficiencyResult } from "../types.js";
|
|
2
|
+
import { type Locale } from "../i18n/locales.js";
|
|
3
|
+
export declare function renderCalibratingBadge(result: ProficiencyResult, locale?: Locale): string;
|
|
4
|
+
export declare function renderFullBadge(result: ProficiencyResult, locale?: Locale): string;
|
|
5
|
+
export declare function renderBadge(result: ProficiencyResult, locale?: Locale): string;
|
|
6
|
+
export declare function getInsights(result: ProficiencyResult): {
|
|
7
|
+
topStrength: string;
|
|
8
|
+
nextAction: string;
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=svg.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"svg.d.ts","sourceRoot":"","sources":["../../src/renderer/svg.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAkE,MAAM,aAAa,CAAC;AACrH,OAAO,EAAa,KAAK,MAAM,EAAsB,MAAM,oBAAoB,CAAC;AAgIhF,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAE,MAAa,GAAG,MAAM,CA6B/F;AAGD,wBAAgB,eAAe,CAAC,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAE,MAAa,GAAG,MAAM,CAkCxF;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,iBAAiB,EAAE,MAAM,GAAE,MAAa,GAAG,MAAM,CAGpF;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAqBlG"}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.renderCalibratingBadge = renderCalibratingBadge;
|
|
4
|
+
exports.renderFullBadge = renderFullBadge;
|
|
5
|
+
exports.renderBadge = renderBadge;
|
|
6
|
+
exports.getInsights = getInsights;
|
|
7
|
+
const locales_js_1 = require("../i18n/locales.js");
|
|
8
|
+
const C = {
|
|
9
|
+
bg: "#0d1117",
|
|
10
|
+
card: "#161b22",
|
|
11
|
+
border: "#30363d",
|
|
12
|
+
text: "#e6edf3",
|
|
13
|
+
textDim: "#8b949e",
|
|
14
|
+
textMuted: "#484f58",
|
|
15
|
+
barBg: "#21262d",
|
|
16
|
+
red: "#f85149",
|
|
17
|
+
green: "#3fb950",
|
|
18
|
+
blue: "#58a6ff",
|
|
19
|
+
};
|
|
20
|
+
const DOMAIN_COLORS = {
|
|
21
|
+
"cc-mastery": "#a371f7", // purple
|
|
22
|
+
"tool-mcp": "#58a6ff", // blue
|
|
23
|
+
"agentic": "#3fb950", // green
|
|
24
|
+
"prompt-craft": "#f0883e", // orange
|
|
25
|
+
"context-mgmt": "#d29922", // gold
|
|
26
|
+
};
|
|
27
|
+
const SANS = `'Segoe UI', system-ui, -apple-system, sans-serif`;
|
|
28
|
+
const MONO = `ui-monospace, 'SF Mono', SFMono-Regular, monospace`;
|
|
29
|
+
function escapeXml(str) {
|
|
30
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
31
|
+
}
|
|
32
|
+
function confidenceSymbol(c) {
|
|
33
|
+
switch (c) {
|
|
34
|
+
case "low": return "\u25CB";
|
|
35
|
+
case "medium": return "\u25D0";
|
|
36
|
+
case "high": return "\u25CF";
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function defs() {
|
|
40
|
+
return `<defs>
|
|
41
|
+
<filter id="glow"><feGaussianBlur stdDeviation="1.5" result="blur"/><feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge></filter>
|
|
42
|
+
</defs>`;
|
|
43
|
+
}
|
|
44
|
+
function domainLabel(id, t) {
|
|
45
|
+
const map = {
|
|
46
|
+
"cc-mastery": "ccMastery", "tool-mcp": "toolMcp", "agentic": "agentic",
|
|
47
|
+
"prompt-craft": "promptCraft", "context-mgmt": "contextMgmt",
|
|
48
|
+
};
|
|
49
|
+
const key = map[id];
|
|
50
|
+
return key ? String(t[key]) : id;
|
|
51
|
+
}
|
|
52
|
+
function renderDomainRow(d, y, t) {
|
|
53
|
+
const label = escapeXml(domainLabel(d.id, t));
|
|
54
|
+
const color = DOMAIN_COLORS[d.id] ?? C.textDim;
|
|
55
|
+
const barWidth = 160;
|
|
56
|
+
const filledWidth = Math.round((d.score / 100) * barWidth);
|
|
57
|
+
return `<g transform="translate(20, ${y})">
|
|
58
|
+
<text x="0" y="11" fill="${C.textDim}" font-size="11" font-family="${SANS}" font-weight="500">${label}</text>
|
|
59
|
+
<g transform="translate(100, 2)"><rect width="${barWidth}" height="10" rx="5" fill="${C.barBg}" opacity="0.5"/><rect width="${filledWidth}" height="10" rx="5" fill="${color}" filter="url(#glow)"/></g>
|
|
60
|
+
<text x="${100 + barWidth + 8}" y="11" fill="${C.text}" font-size="12" font-family="${MONO}" font-weight="700">${d.score}</text>
|
|
61
|
+
<text x="${100 + barWidth + 34}" y="11" fill="${color}" font-size="10" font-family="${MONO}">${confidenceSymbol(d.confidence)}</text>
|
|
62
|
+
</g>`;
|
|
63
|
+
}
|
|
64
|
+
function formatCount(n) {
|
|
65
|
+
if (n >= 1000)
|
|
66
|
+
return (n / 1000).toFixed(1) + "k";
|
|
67
|
+
return String(n);
|
|
68
|
+
}
|
|
69
|
+
// ── 8 Feature Mini-Bars (heatmap row) ──
|
|
70
|
+
const MINI_BAR_KEYS = [
|
|
71
|
+
{ key: "hooks", localeKey: "hooks", color: "#a371f7" },
|
|
72
|
+
{ key: "plugins", localeKey: "plugins", color: "#a371f7" },
|
|
73
|
+
{ key: "skills", localeKey: "skills", color: "#58a6ff" },
|
|
74
|
+
{ key: "mcp", localeKey: "mcp", color: "#58a6ff" },
|
|
75
|
+
{ key: "agents", localeKey: "agents", color: "#3fb950" },
|
|
76
|
+
{ key: "plan", localeKey: "plan", color: "#3fb950" },
|
|
77
|
+
{ key: "memory", localeKey: "memory", color: "#d29922" },
|
|
78
|
+
{ key: "rules", localeKey: "rules", color: "#d29922" },
|
|
79
|
+
];
|
|
80
|
+
function miniBarColor(score, baseColor) {
|
|
81
|
+
if (score === 0)
|
|
82
|
+
return C.barBg;
|
|
83
|
+
return baseColor;
|
|
84
|
+
}
|
|
85
|
+
function miniBarOpacity(score) {
|
|
86
|
+
if (score === 0)
|
|
87
|
+
return "0.3";
|
|
88
|
+
if (score < 30)
|
|
89
|
+
return "0.4";
|
|
90
|
+
if (score < 70)
|
|
91
|
+
return "0.7";
|
|
92
|
+
return "1.0";
|
|
93
|
+
}
|
|
94
|
+
function renderMiniBarGrid(featureScores, y, t) {
|
|
95
|
+
const scores = featureScores ?? {};
|
|
96
|
+
const totalFeatures = MINI_BAR_KEYS.length;
|
|
97
|
+
const gap = 3;
|
|
98
|
+
const startX = 20;
|
|
99
|
+
const availableWidth = 340;
|
|
100
|
+
const colWidth = Math.floor((availableWidth - gap * (totalFeatures - 1)) / totalFeatures);
|
|
101
|
+
const barHeight = 20;
|
|
102
|
+
const lines = [];
|
|
103
|
+
for (let i = 0; i < totalFeatures; i++) {
|
|
104
|
+
const feat = MINI_BAR_KEYS[i];
|
|
105
|
+
const score = scores[feat.key] ?? 0;
|
|
106
|
+
const label = escapeXml(String(t[feat.localeKey]));
|
|
107
|
+
const x = startX + i * (colWidth + gap);
|
|
108
|
+
const fillColor = miniBarColor(score, feat.color);
|
|
109
|
+
const opacity = miniBarOpacity(score);
|
|
110
|
+
lines.push(`<g transform="translate(${x}, ${y})">`);
|
|
111
|
+
lines.push(` <rect width="${colWidth}" height="${barHeight}" rx="4" fill="${fillColor}" opacity="${opacity}"/>`);
|
|
112
|
+
lines.push(` <text x="${colWidth / 2}" y="${barHeight / 2 + 1}" fill="${score > 0 ? '#fff' : C.textMuted}" font-size="8" font-family="${MONO}" font-weight="600" text-anchor="middle" dominant-baseline="middle">${score}</text>`);
|
|
113
|
+
lines.push(` <text x="${colWidth / 2}" y="${barHeight + 11}" fill="${C.textMuted}" font-size="7" font-family="${SANS}" text-anchor="middle">${label}</text>`);
|
|
114
|
+
lines.push(`</g>`);
|
|
115
|
+
}
|
|
116
|
+
return lines.join("\n");
|
|
117
|
+
}
|
|
118
|
+
const MINI_BAR_SECTION_HEIGHT = 36; // single row of mini-bars + labels
|
|
119
|
+
// ── Calibrating Badge ──
|
|
120
|
+
function renderCalibratingBadge(result, locale = "en") {
|
|
121
|
+
const t = (0, locales_js_1.getLocale)(locale);
|
|
122
|
+
const width = 380;
|
|
123
|
+
const height = 180;
|
|
124
|
+
const cl = result.setupChecklist;
|
|
125
|
+
const needed = Math.max(0, 3 - result.sessionCount);
|
|
126
|
+
const u = escapeXml(result.username);
|
|
127
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" role="img" aria-labelledby="cc-title cc-desc">
|
|
128
|
+
<title id="cc-title">${escapeXml(t.title)} \u2014 @${u}</title>
|
|
129
|
+
<desc id="cc-desc">${escapeXml(t.calibrating)}: ${result.sessionCount} ${escapeXml(t.sessions)}</desc>
|
|
130
|
+
${defs()}
|
|
131
|
+
<rect width="${width}" height="${height}" rx="10" fill="${C.bg}"/>
|
|
132
|
+
<rect x="0.5" y="0.5" width="${width - 1}" height="${height - 1}" rx="9.5" fill="${C.card}" stroke="${C.border}"/>
|
|
133
|
+
<text x="20" y="28" fill="${C.text}" font-size="15" font-family="${SANS}" font-weight="600">${escapeXml(t.title)}</text>
|
|
134
|
+
<text x="${width - 20}" y="28" fill="${C.textDim}" font-size="11" font-family="${MONO}" text-anchor="end">@${u}</text>
|
|
135
|
+
<line x1="20" y1="40" x2="${width - 20}" y2="40" stroke="${C.border}"/>
|
|
136
|
+
<text x="20" y="64" fill="#d29922" font-size="12" font-family="${SANS}">\u23F3 ${escapeXml(t.calibrating)}</text>
|
|
137
|
+
<text x="20" y="82" fill="${C.textDim}" font-size="11" font-family="${MONO}">${result.sessionCount} ${escapeXml(t.sessions)} \u00B7 ${escapeXml(t.needMore(needed))}</text>
|
|
138
|
+
<line x1="20" y1="96" x2="${width - 20}" y2="96" stroke="${C.border}"/>
|
|
139
|
+
<text x="20" y="114" fill="${C.textDim}" font-size="10" font-family="${SANS}" font-weight="500">${escapeXml(t.setup)}</text>
|
|
140
|
+
<text x="20" y="132" fill="${cl.hasClaudeMd ? C.green : C.textMuted}" font-size="10" font-family="${SANS}">${cl.hasClaudeMd ? "\u2713" : "\u2717"} ${escapeXml(t.claudeMd)}</text>
|
|
141
|
+
<text x="110" y="132" fill="${cl.hasHooks ? C.green : C.textMuted}" font-size="10" font-family="${SANS}">${cl.hasHooks ? "\u2713" : "\u2717"} ${escapeXml(t.hooks)}</text>
|
|
142
|
+
<text x="180" y="132" fill="${cl.hasPlugins ? C.green : C.textMuted}" font-size="10" font-family="${SANS}">${cl.hasPlugins ? "\u2713" : "\u2717"} ${escapeXml(t.plugins)}</text>
|
|
143
|
+
<text x="20" y="148" fill="${cl.hasMcpServers ? C.green : C.textMuted}" font-size="10" font-family="${SANS}">${cl.hasMcpServers ? "\u2713" : "\u2717"} ${escapeXml(t.mcp)}</text>
|
|
144
|
+
<text x="110" y="148" fill="${cl.hasMemory ? C.green : C.textMuted}" font-size="10" font-family="${SANS}">${cl.hasMemory ? "\u2713" : "\u2717"} ${escapeXml(t.memory)}</text>
|
|
145
|
+
<text x="180" y="148" fill="${cl.hasRules ? C.green : C.textMuted}" font-size="10" font-family="${SANS}">${cl.hasRules ? "\u2713" : "\u2717"} ${escapeXml(t.rules)}</text>
|
|
146
|
+
<text x="${width - 20}" y="${height - 12}" fill="${C.textMuted}" font-size="9" font-family="${MONO}" text-anchor="end">${result.timestamp.slice(0, 10)}</text>
|
|
147
|
+
</svg>`;
|
|
148
|
+
}
|
|
149
|
+
// ── Full Badge (also used for early) ──
|
|
150
|
+
function renderFullBadge(result, locale = "en") {
|
|
151
|
+
const t = (0, locales_js_1.getLocale)(locale);
|
|
152
|
+
const width = 380;
|
|
153
|
+
const rows = result.domains.length;
|
|
154
|
+
const separatorY = 50 + rows * 22 + 4;
|
|
155
|
+
const miniBarY = separatorY + 12;
|
|
156
|
+
const footerY = miniBarY + MINI_BAR_SECTION_HEIGHT + 4;
|
|
157
|
+
const height = footerY + 22;
|
|
158
|
+
const u = escapeXml(result.username);
|
|
159
|
+
const domainSvg = result.domains.map((d, i) => renderDomainRow(d, 50 + i * 22, t)).join("\n");
|
|
160
|
+
const phaseLabel = result.phase === "early" ? `<text x="${width - 20}" y="${footerY + 14}" fill="#d29922" font-size="9" font-family="${MONO}" text-anchor="end">${escapeXml(t.earlyResults)}</text>` : "";
|
|
161
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" role="img" aria-labelledby="cc-title cc-desc">
|
|
162
|
+
<title id="cc-title">${escapeXml(t.title)} \u2014 @${u}</title>
|
|
163
|
+
<desc id="cc-desc">${result.sessionCount} ${escapeXml(t.sessions)}, ${result.projectCount} ${escapeXml(t.projects)}</desc>
|
|
164
|
+
${defs()}
|
|
165
|
+
<rect width="${width}" height="${height}" rx="10" fill="${C.bg}"/>
|
|
166
|
+
<rect x="0.5" y="0.5" width="${width - 1}" height="${height - 1}" rx="9.5" fill="${C.card}" stroke="${C.border}"/>
|
|
167
|
+
<text x="20" y="28" fill="${C.text}" font-size="15" font-family="${SANS}" font-weight="600">${escapeXml(t.title)}</text>
|
|
168
|
+
<text x="${width - 20}" y="28" fill="${C.textDim}" font-size="11" font-family="${MONO}" text-anchor="end">@${u}</text>
|
|
169
|
+
<line x1="20" y1="40" x2="${width - 20}" y2="40" stroke="${C.border}"/>
|
|
170
|
+
|
|
171
|
+
${domainSvg}
|
|
172
|
+
|
|
173
|
+
<line x1="20" y1="${separatorY}" x2="${width - 20}" y2="${separatorY}" stroke="${C.border}"/>
|
|
174
|
+
|
|
175
|
+
${renderMiniBarGrid(result.features.featureScores, miniBarY, t)}
|
|
176
|
+
|
|
177
|
+
<line x1="20" y1="${footerY}" x2="${width - 20}" y2="${footerY}" stroke="${C.border}"/>
|
|
178
|
+
<text x="20" y="${footerY + 14}" fill="${C.textMuted}" font-size="10" font-family="${MONO}">${result.sessionCount} ${escapeXml(t.sessions)} \u00B7 ${result.projectCount} ${escapeXml(t.projects)} \u00B7 ${result.timestamp.slice(0, 10)}</text>
|
|
179
|
+
${phaseLabel}
|
|
180
|
+
</svg>`;
|
|
181
|
+
}
|
|
182
|
+
function renderBadge(result, locale = "en") {
|
|
183
|
+
if (result.phase === "calibrating")
|
|
184
|
+
return renderCalibratingBadge(result, locale);
|
|
185
|
+
return renderFullBadge(result, locale);
|
|
186
|
+
}
|
|
187
|
+
function getInsights(result) {
|
|
188
|
+
const sorted = [...result.domains].sort((a, b) => b.score - a.score);
|
|
189
|
+
const weakest = [...result.domains].sort((a, b) => a.score - b.score);
|
|
190
|
+
const labels = {
|
|
191
|
+
"cc-mastery": "CC configuration mastery",
|
|
192
|
+
"tool-mcp": "tool & MCP integration",
|
|
193
|
+
"agentic": "agentic workflows",
|
|
194
|
+
"prompt-craft": "prompt engineering",
|
|
195
|
+
"context-mgmt": "context management",
|
|
196
|
+
};
|
|
197
|
+
const actions = {
|
|
198
|
+
"cc-mastery": "enhance CLAUDE.md, add hooks with matchers",
|
|
199
|
+
"tool-mcp": "chain tools deliberately (Grep\u2192Read\u2192Edit)",
|
|
200
|
+
"agentic": "use subagents with different types",
|
|
201
|
+
"prompt-craft": "structure prompts with markdown and code blocks",
|
|
202
|
+
"context-mgmt": "use cross-session memory files",
|
|
203
|
+
};
|
|
204
|
+
return {
|
|
205
|
+
topStrength: labels[sorted[0].id] ?? sorted[0].label,
|
|
206
|
+
nextAction: actions[weakest[0].id] ?? `improve ${weakest[0].label}`,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=svg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"svg.js","sourceRoot":"","sources":["../../src/renderer/svg.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Saturating score curves for anti-gaming.
|
|
3
|
+
* All return 0-100.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Logarithmic saturating curve.
|
|
7
|
+
* score = min(100, k * log(1 + value / scale))
|
|
8
|
+
*
|
|
9
|
+
* @param value - raw signal value
|
|
10
|
+
* @param scale - divisor that controls how quickly the curve saturates
|
|
11
|
+
* @param k - multiplier (typically calibrated so k * log(1 + maxExpected/scale) ≈ 100)
|
|
12
|
+
*/
|
|
13
|
+
export declare function logCurve(value: number, scale: number, k: number): number;
|
|
14
|
+
/**
|
|
15
|
+
* Capped ratio curve.
|
|
16
|
+
* score = min(100, (value / cap) * 100)
|
|
17
|
+
*/
|
|
18
|
+
export declare function cappedRatio(value: number, cap: number): number;
|
|
19
|
+
/**
|
|
20
|
+
* Binary score — either 0 or the specified value.
|
|
21
|
+
*/
|
|
22
|
+
export declare function binary(present: boolean, score: number): number;
|
|
23
|
+
/**
|
|
24
|
+
* Ratio to score — converts a 0-1 ratio to 0-100.
|
|
25
|
+
*/
|
|
26
|
+
export declare function ratioToScore(ratio: number): number;
|
|
27
|
+
/**
|
|
28
|
+
* Weighted sum of sub-signals, clamped to 0-100.
|
|
29
|
+
*/
|
|
30
|
+
export declare function weightedSum(components: Array<{
|
|
31
|
+
score: number;
|
|
32
|
+
weight: number;
|
|
33
|
+
}>): number;
|
|
34
|
+
//# sourceMappingURL=curves.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"curves.d.ts","sourceRoot":"","sources":["../../src/scoring/curves.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAGxE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAG9D;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,UAAU,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,GACnD,MAAM,CASR"}
|