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.
Files changed (82) hide show
  1. package/.claude-plugin/plugin.json +11 -0
  2. package/LICENSE +201 -0
  3. package/README.md +345 -0
  4. package/README.zh-CN.md +284 -0
  5. package/dist/cli.d.ts +3 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +543 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/gist/uploader.d.ts +26 -0
  10. package/dist/gist/uploader.d.ts.map +1 -0
  11. package/dist/gist/uploader.js +99 -0
  12. package/dist/gist/uploader.js.map +1 -0
  13. package/dist/hooks/session-end.js +64 -0
  14. package/dist/i18n/locales.d.ts +30 -0
  15. package/dist/i18n/locales.d.ts.map +1 -0
  16. package/dist/i18n/locales.js +64 -0
  17. package/dist/i18n/locales.js.map +1 -0
  18. package/dist/index.d.ts +12 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +38 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/parsers/config-parser.d.ts +25 -0
  23. package/dist/parsers/config-parser.d.ts.map +1 -0
  24. package/dist/parsers/config-parser.js +262 -0
  25. package/dist/parsers/config-parser.js.map +1 -0
  26. package/dist/parsers/history-parser.d.ts +13 -0
  27. package/dist/parsers/history-parser.d.ts.map +1 -0
  28. package/dist/parsers/history-parser.js +50 -0
  29. package/dist/parsers/history-parser.js.map +1 -0
  30. package/dist/parsers/normalizer.d.ts +8 -0
  31. package/dist/parsers/normalizer.d.ts.map +1 -0
  32. package/dist/parsers/normalizer.js +105 -0
  33. package/dist/parsers/normalizer.js.map +1 -0
  34. package/dist/parsers/transcript-parser.d.ts +23 -0
  35. package/dist/parsers/transcript-parser.d.ts.map +1 -0
  36. package/dist/parsers/transcript-parser.js +112 -0
  37. package/dist/parsers/transcript-parser.js.map +1 -0
  38. package/dist/renderer/svg.d.ts +10 -0
  39. package/dist/renderer/svg.d.ts.map +1 -0
  40. package/dist/renderer/svg.js +209 -0
  41. package/dist/renderer/svg.js.map +1 -0
  42. package/dist/scoring/curves.d.ts +34 -0
  43. package/dist/scoring/curves.d.ts.map +1 -0
  44. package/dist/scoring/curves.js +60 -0
  45. package/dist/scoring/curves.js.map +1 -0
  46. package/dist/scoring/engine.d.ts +16 -0
  47. package/dist/scoring/engine.d.ts.map +1 -0
  48. package/dist/scoring/engine.js +137 -0
  49. package/dist/scoring/engine.js.map +1 -0
  50. package/dist/scoring/rule-engine.d.ts +30 -0
  51. package/dist/scoring/rule-engine.d.ts.map +1 -0
  52. package/dist/scoring/rule-engine.js +151 -0
  53. package/dist/scoring/rule-engine.js.map +1 -0
  54. package/dist/scoring/rules.d.ts +32 -0
  55. package/dist/scoring/rules.d.ts.map +1 -0
  56. package/dist/scoring/rules.js +443 -0
  57. package/dist/scoring/rules.js.map +1 -0
  58. package/dist/scoring/signals.d.ts +7 -0
  59. package/dist/scoring/signals.d.ts.map +1 -0
  60. package/dist/scoring/signals.js +245 -0
  61. package/dist/scoring/signals.js.map +1 -0
  62. package/dist/store/local-store.d.ts +12 -0
  63. package/dist/store/local-store.d.ts.map +1 -0
  64. package/dist/store/local-store.js +107 -0
  65. package/dist/store/local-store.js.map +1 -0
  66. package/dist/store/queue.d.ts +24 -0
  67. package/dist/store/queue.d.ts.map +1 -0
  68. package/dist/store/queue.js +105 -0
  69. package/dist/store/queue.js.map +1 -0
  70. package/dist/types.d.ts +264 -0
  71. package/dist/types.d.ts.map +1 -0
  72. package/dist/types.js +4 -0
  73. package/dist/types.js.map +1 -0
  74. package/dist/utils/ci-detect.d.ts +6 -0
  75. package/dist/utils/ci-detect.d.ts.map +1 -0
  76. package/dist/utils/ci-detect.js +19 -0
  77. package/dist/utils/ci-detect.js.map +1 -0
  78. package/hooks/hooks.json +15 -0
  79. package/hooks/session-end.ts +71 -0
  80. package/hooks/tsconfig.json +13 -0
  81. package/package.json +43 -0
  82. package/skills/proficiency/SKILL.md +15 -0
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ /**
3
+ * Saturating score curves for anti-gaming.
4
+ * All return 0-100.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.logCurve = logCurve;
8
+ exports.cappedRatio = cappedRatio;
9
+ exports.binary = binary;
10
+ exports.ratioToScore = ratioToScore;
11
+ exports.weightedSum = weightedSum;
12
+ /**
13
+ * Logarithmic saturating curve.
14
+ * score = min(100, k * log(1 + value / scale))
15
+ *
16
+ * @param value - raw signal value
17
+ * @param scale - divisor that controls how quickly the curve saturates
18
+ * @param k - multiplier (typically calibrated so k * log(1 + maxExpected/scale) ≈ 100)
19
+ */
20
+ function logCurve(value, scale, k) {
21
+ if (value <= 0)
22
+ return 0;
23
+ return Math.min(100, k * Math.log(1 + value / scale));
24
+ }
25
+ /**
26
+ * Capped ratio curve.
27
+ * score = min(100, (value / cap) * 100)
28
+ */
29
+ function cappedRatio(value, cap) {
30
+ if (value <= 0 || cap <= 0)
31
+ return 0;
32
+ return Math.min(100, (value / cap) * 100);
33
+ }
34
+ /**
35
+ * Binary score — either 0 or the specified value.
36
+ */
37
+ function binary(present, score) {
38
+ return present ? score : 0;
39
+ }
40
+ /**
41
+ * Ratio to score — converts a 0-1 ratio to 0-100.
42
+ */
43
+ function ratioToScore(ratio) {
44
+ return Math.min(100, Math.max(0, ratio * 100));
45
+ }
46
+ /**
47
+ * Weighted sum of sub-signals, clamped to 0-100.
48
+ */
49
+ function weightedSum(components) {
50
+ let total = 0;
51
+ let totalWeight = 0;
52
+ for (const { score, weight } of components) {
53
+ total += score * weight;
54
+ totalWeight += weight;
55
+ }
56
+ if (totalWeight === 0)
57
+ return 0;
58
+ return Math.min(100, Math.max(0, total / totalWeight));
59
+ }
60
+ //# sourceMappingURL=curves.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"curves.js","sourceRoot":"","sources":["../../src/scoring/curves.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAUH,4BAGC;AAMD,kCAGC;AAKD,wBAEC;AAKD,oCAEC;AAKD,kCAWC;AAlDD;;;;;;;GAOG;AACH,SAAgB,QAAQ,CAAC,KAAa,EAAE,KAAa,EAAE,CAAS;IAC9D,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IACzB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC;AACxD,CAAC;AAED;;;GAGG;AACH,SAAgB,WAAW,CAAC,KAAa,EAAE,GAAW;IACpD,IAAI,KAAK,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IACrC,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,SAAgB,MAAM,CAAC,OAAgB,EAAE,KAAa;IACpD,OAAO,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,SAAgB,YAAY,CAAC,KAAa;IACxC,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,SAAgB,WAAW,CACzB,UAAoD;IAEpD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,KAAK,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,UAAU,EAAE,CAAC;QAC3C,KAAK,IAAI,KAAK,GAAG,MAAM,CAAC;QACxB,WAAW,IAAI,MAAM,CAAC;IACxB,CAAC;IACD,IAAI,WAAW,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAChC,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC;AACzD,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { ProficiencyResult, ConfidenceLevel, SetupChecklist, FeatureInventory, ParsedSession } from "../types.js";
2
+ import type { ConfigSignals } from "../parsers/config-parser.js";
3
+ import type { RuleFire } from "./rules.js";
4
+ export declare const SCORING_VERSION = "3.0.0";
5
+ export declare function getConfidence(dataPoints: number): ConfidenceLevel;
6
+ export declare function getPhase(sessionCount: number): "calibrating" | "early" | "full";
7
+ export declare function getRecencyWeight(sessionTimestamp: string, now?: number): number;
8
+ /**
9
+ * Extract feature inventory from sessions (hooks, skills, MCP, tools used).
10
+ */
11
+ export declare function extractFeatureInventory(sessions: ParsedSession[], fires: RuleFire[]): FeatureInventory;
12
+ /**
13
+ * Main compute: fire rules, aggregate, produce result.
14
+ */
15
+ export declare function computeProficiency(sessions: ParsedSession[], config: ConfigSignals, username: string, setupChecklist: SetupChecklist): ProficiencyResult;
16
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/scoring/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EAEjB,eAAe,EACf,cAAc,EACd,gBAAgB,EAGhB,aAAa,EACd,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAEjE,OAAO,KAAK,EAAc,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEvD,eAAO,MAAM,eAAe,UAAU,CAAC;AAYvC,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,CAIjE;AAED,wBAAgB,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,GAAG,OAAO,GAAG,MAAM,CAI/E;AAED,wBAAgB,gBAAgB,CAAC,gBAAgB,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,MAAM,CAQ3F;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,aAAa,EAAE,EACzB,KAAK,EAAE,QAAQ,EAAE,GAChB,gBAAgB,CAoElB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,aAAa,EAAE,EACzB,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,cAAc,GAC7B,iBAAiB,CA4BnB"}
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SCORING_VERSION = void 0;
4
+ exports.getConfidence = getConfidence;
5
+ exports.getPhase = getPhase;
6
+ exports.getRecencyWeight = getRecencyWeight;
7
+ exports.extractFeatureInventory = extractFeatureInventory;
8
+ exports.computeProficiency = computeProficiency;
9
+ const rule_engine_js_1 = require("./rule-engine.js");
10
+ exports.SCORING_VERSION = "3.0.0";
11
+ const CALIBRATION_THRESHOLD = 3;
12
+ const FULL_CONFIDENCE_THRESHOLD = 10;
13
+ const RECENCY_WINDOWS = [
14
+ { maxDays: 7, weight: 1.0 },
15
+ { maxDays: 30, weight: 0.7 },
16
+ { maxDays: 90, weight: 0.4 },
17
+ { maxDays: Infinity, weight: 0.2 },
18
+ ];
19
+ function getConfidence(dataPoints) {
20
+ if (dataPoints >= 50)
21
+ return "high";
22
+ if (dataPoints >= 10)
23
+ return "medium";
24
+ return "low";
25
+ }
26
+ function getPhase(sessionCount) {
27
+ if (sessionCount < CALIBRATION_THRESHOLD)
28
+ return "calibrating";
29
+ if (sessionCount < FULL_CONFIDENCE_THRESHOLD)
30
+ return "early";
31
+ return "full";
32
+ }
33
+ function getRecencyWeight(sessionTimestamp, now = Date.now()) {
34
+ const sessionTime = new Date(sessionTimestamp).getTime();
35
+ if (isNaN(sessionTime))
36
+ return RECENCY_WINDOWS[RECENCY_WINDOWS.length - 1].weight;
37
+ const daysSince = (now - sessionTime) / (24 * 60 * 60 * 1000);
38
+ for (const window of RECENCY_WINDOWS) {
39
+ if (daysSince <= window.maxDays)
40
+ return window.weight;
41
+ }
42
+ return 0.2;
43
+ }
44
+ /**
45
+ * Extract feature inventory from sessions (hooks, skills, MCP, tools used).
46
+ */
47
+ function extractFeatureInventory(sessions, fires) {
48
+ const allEvents = sessions.flatMap((s) => s.events);
49
+ const tcs = allEvents.filter((e) => e.kind === "tool_call");
50
+ // Hooks from hook_progress events
51
+ const hookCounts = new Map();
52
+ for (const e of allEvents) {
53
+ if (e.kind === "hook_progress") {
54
+ const name = e.hookName.split(":").pop() ?? e.hookName;
55
+ if (name === "callback" || name === "startup")
56
+ continue;
57
+ hookCounts.set(name, (hookCounts.get(name) ?? 0) + 1);
58
+ }
59
+ }
60
+ // Skills
61
+ const skillCounts = new Map();
62
+ for (const tc of tcs) {
63
+ if (tc.toolName === "Skill") {
64
+ const skill = String(tc.input?.skill ?? "unknown");
65
+ skillCounts.set(skill, (skillCounts.get(skill) ?? 0) + 1);
66
+ }
67
+ }
68
+ // MCP servers
69
+ const mcpServers = new Set();
70
+ for (const tc of tcs) {
71
+ if (tc.toolName.startsWith("mcp__")) {
72
+ const parts = tc.toolName.split("__");
73
+ if (parts.length >= 2) {
74
+ const segments = parts.slice(1, -1).join("_").split("_").filter(Boolean);
75
+ mcpServers.add(segments[segments.length - 1] ?? parts[1]);
76
+ }
77
+ }
78
+ }
79
+ // Top tools
80
+ const toolFreq = new Map();
81
+ for (const tc of tcs) {
82
+ if (!tc.toolName.startsWith("mcp__")) {
83
+ toolFreq.set(tc.toolName, (toolFreq.get(tc.toolName) ?? 0) + 1);
84
+ }
85
+ }
86
+ const topTools = [...toolFreq.entries()]
87
+ .sort((a, b) => b[1] - a[1])
88
+ .slice(0, 5)
89
+ .map(([name, count]) => ({ name, count }));
90
+ // Feature scores from rule fires
91
+ const featureScoreMap = (0, rule_engine_js_1.extractFeatureScores)(fires);
92
+ const featureScores = {};
93
+ for (const [tag, data] of featureScoreMap) {
94
+ featureScores[tag] = data.score;
95
+ }
96
+ const prompts = allEvents.filter((e) => e.kind === "user_prompt");
97
+ return {
98
+ hooks: [...hookCounts.entries()].sort((a, b) => b[1] - a[1]).map(([name, count]) => ({ name, count })),
99
+ skills: [...skillCounts.entries()].sort((a, b) => b[1] - a[1]).map(([name, count]) => ({ name, count })),
100
+ mcpServers: [...mcpServers],
101
+ topTools,
102
+ totalToolCalls: tcs.length,
103
+ uniqueToolCount: new Set(tcs.map((tc) => tc.toolName)).size,
104
+ usedPlanMode: prompts.some((p) => p.kind === "user_prompt" && p.permissionMode === "plan"),
105
+ hasMemory: fires.some((f) => f.featureTags.includes("memory") && f.points > 0),
106
+ hasRules: fires.some((f) => f.featureTags.includes("rules") && f.points > 0),
107
+ featureScores,
108
+ };
109
+ }
110
+ /**
111
+ * Main compute: fire rules, aggregate, produce result.
112
+ */
113
+ function computeProficiency(sessions, config, username, setupChecklist) {
114
+ const allEvents = sessions.flatMap((s) => s.events);
115
+ const sessionCount = sessions.length;
116
+ const projectCount = new Set(sessions.map((s) => s.project)).size;
117
+ const phase = getPhase(sessionCount);
118
+ // Fire all rules
119
+ const fires = (0, rule_engine_js_1.fireRules)(allEvents, config, sessionCount);
120
+ // Aggregate into domain buckets with caps
121
+ const buckets = (0, rule_engine_js_1.aggregateToBuckets)(fires);
122
+ // Convert to domain scores (phase-aware)
123
+ const domains = (0, rule_engine_js_1.bucketsToScores)(buckets, phase);
124
+ // Extract feature inventory
125
+ const features = extractFeatureInventory(sessions, fires);
126
+ return {
127
+ username,
128
+ timestamp: new Date().toISOString(),
129
+ domains,
130
+ features,
131
+ sessionCount,
132
+ projectCount,
133
+ phase,
134
+ setupChecklist,
135
+ };
136
+ }
137
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/scoring/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { DomainId, DomainScore, NormalizedEvent } from "../types.js";
2
+ import type { ConfigSignals } from "../parsers/config-parser.js";
3
+ import { type RuleFire, type FeatureTag } from "./rules.js";
4
+ export interface DomainBucket {
5
+ configPoints: number;
6
+ behaviorPoints: number;
7
+ penaltyPoints: number;
8
+ firedRules: RuleFire[];
9
+ }
10
+ /**
11
+ * Fire all rules against session events and config.
12
+ * Returns per-rule fire results.
13
+ */
14
+ export declare function fireRules(events: NormalizedEvent[], config: ConfigSignals, sessionCount: number): RuleFire[];
15
+ /**
16
+ * Aggregate rule fires into domain buckets with caps.
17
+ */
18
+ export declare function aggregateToBuckets(fires: RuleFire[]): Map<DomainId, DomainBucket>;
19
+ /**
20
+ * Convert buckets to domain scores.
21
+ */
22
+ export declare function bucketsToScores(buckets: Map<DomainId, DomainBucket>, phase: "calibrating" | "early" | "full"): DomainScore[];
23
+ /**
24
+ * Extract feature tag scores from rule fires (for mini-bar heatmap).
25
+ */
26
+ export declare function extractFeatureScores(fires: RuleFire[]): Map<FeatureTag, {
27
+ score: number;
28
+ maxPossible: number;
29
+ }>;
30
+ //# sourceMappingURL=rule-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-engine.d.ts","sourceRoot":"","sources":["../../src/scoring/rule-engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAkC,eAAe,EAAoB,MAAM,aAAa,CAAC;AAC5H,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAA2B,KAAK,QAAQ,EAAoB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAQvG,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,QAAQ,EAAE,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,MAAM,EAAE,eAAe,EAAE,EACzB,MAAM,EAAE,aAAa,EACrB,YAAY,EAAE,MAAM,GACnB,QAAQ,EAAE,CAqBZ;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,CA+BjF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,EACpC,KAAK,EAAE,aAAa,GAAG,OAAO,GAAG,MAAM,GACtC,WAAW,EAAE,CA4Cf;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,UAAU,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAmC/G"}
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fireRules = fireRules;
4
+ exports.aggregateToBuckets = aggregateToBuckets;
5
+ exports.bucketsToScores = bucketsToScores;
6
+ exports.extractFeatureScores = extractFeatureScores;
7
+ const rules_js_1 = require("./rules.js");
8
+ // ── Bucket Caps ──
9
+ // Per GPT-5.4: config max 25, behavior max 75, penalty max -15
10
+ const CONFIG_CAP = 25;
11
+ const BEHAVIOR_CAP = 75;
12
+ const PENALTY_CAP = -15;
13
+ /**
14
+ * Fire all rules against session events and config.
15
+ * Returns per-rule fire results.
16
+ */
17
+ function fireRules(events, config, sessionCount) {
18
+ const ctx = { events, config, sessionCount };
19
+ const fires = [];
20
+ for (const rule of rules_js_1.RULES) {
21
+ const rawCount = rule.detect(ctx);
22
+ if (rawCount <= 0)
23
+ continue;
24
+ const count = Math.min(rawCount, rule.maxPerSession);
25
+ fires.push({
26
+ ruleId: rule.id,
27
+ domain: rule.domain,
28
+ tier: rule.tier,
29
+ points: rule.points * count,
30
+ featureTags: rule.featureTags,
31
+ evidenceType: rule.evidenceType,
32
+ count,
33
+ });
34
+ }
35
+ return fires;
36
+ }
37
+ /**
38
+ * Aggregate rule fires into domain buckets with caps.
39
+ */
40
+ function aggregateToBuckets(fires) {
41
+ const buckets = new Map();
42
+ const domains = ["cc-mastery", "tool-mcp", "agentic", "prompt-craft", "context-mgmt"];
43
+ for (const d of domains) {
44
+ buckets.set(d, { configPoints: 0, behaviorPoints: 0, penaltyPoints: 0, firedRules: [] });
45
+ }
46
+ for (const fire of fires) {
47
+ const bucket = buckets.get(fire.domain);
48
+ if (!bucket)
49
+ continue;
50
+ bucket.firedRules.push(fire);
51
+ if (fire.tier === "anti-pattern") {
52
+ bucket.penaltyPoints += fire.points; // already negative
53
+ }
54
+ else if (fire.evidenceType === "config") {
55
+ bucket.configPoints += fire.points;
56
+ }
57
+ else {
58
+ bucket.behaviorPoints += fire.points;
59
+ }
60
+ }
61
+ // Apply caps
62
+ for (const bucket of buckets.values()) {
63
+ bucket.configPoints = Math.min(bucket.configPoints, CONFIG_CAP);
64
+ bucket.behaviorPoints = Math.min(bucket.behaviorPoints, BEHAVIOR_CAP);
65
+ bucket.penaltyPoints = Math.max(bucket.penaltyPoints, PENALTY_CAP);
66
+ }
67
+ return buckets;
68
+ }
69
+ /**
70
+ * Convert buckets to domain scores.
71
+ */
72
+ function bucketsToScores(buckets, phase) {
73
+ // Phase-aware config weighting (GPT-5.4: calibrating 40/60, early 25/75, full 15/85)
74
+ const configScale = phase === "calibrating" ? 2.0 : phase === "early" ? 1.5 : 1.0;
75
+ const behaviorScale = phase === "calibrating" ? 0.8 : phase === "early" ? 1.0 : 1.15;
76
+ const labels = {
77
+ "cc-mastery": "CC Mastery",
78
+ "tool-mcp": "Tool & MCP",
79
+ "agentic": "Agentic",
80
+ "prompt-craft": "Prompt Craft",
81
+ "context-mgmt": "Context Mgmt",
82
+ };
83
+ const weights = {
84
+ "cc-mastery": 0.2,
85
+ "tool-mcp": 0.2,
86
+ "agentic": 0.2,
87
+ "prompt-craft": 0.2,
88
+ "context-mgmt": 0.2,
89
+ };
90
+ const domains = ["cc-mastery", "tool-mcp", "agentic", "prompt-craft", "context-mgmt"];
91
+ const scores = [];
92
+ for (const id of domains) {
93
+ const bucket = buckets.get(id);
94
+ const rawScore = bucket.configPoints * configScale +
95
+ bucket.behaviorPoints * behaviorScale +
96
+ bucket.penaltyPoints;
97
+ const score = Math.round(Math.min(100, Math.max(0, rawScore)));
98
+ const dataPoints = bucket.firedRules.length;
99
+ scores.push({
100
+ id,
101
+ label: labels[id],
102
+ score,
103
+ weight: weights[id],
104
+ confidence: getConfidence(dataPoints),
105
+ dataPoints,
106
+ });
107
+ }
108
+ return scores;
109
+ }
110
+ /**
111
+ * Extract feature tag scores from rule fires (for mini-bar heatmap).
112
+ */
113
+ function extractFeatureScores(fires) {
114
+ const featureScores = new Map();
115
+ const allTags = ["hooks", "plugins", "skills", "mcp", "agents", "plan", "memory", "rules"];
116
+ for (const tag of allTags) {
117
+ featureScores.set(tag, { points: 0, maxPossible: 0 });
118
+ }
119
+ // Calculate max possible per feature tag from all rules
120
+ for (const rule of rules_js_1.RULES) {
121
+ for (const tag of rule.featureTags) {
122
+ const entry = featureScores.get(tag);
123
+ if (rule.points > 0) {
124
+ entry.maxPossible += rule.points;
125
+ }
126
+ }
127
+ }
128
+ // Add actual points from fired rules
129
+ for (const fire of fires) {
130
+ for (const tag of fire.featureTags) {
131
+ const entry = featureScores.get(tag);
132
+ if (fire.points > 0) {
133
+ entry.points += fire.points;
134
+ }
135
+ }
136
+ }
137
+ const result = new Map();
138
+ for (const [tag, data] of featureScores) {
139
+ const score = data.maxPossible > 0 ? Math.round((data.points / data.maxPossible) * 100) : 0;
140
+ result.set(tag, { score, maxPossible: data.maxPossible });
141
+ }
142
+ return result;
143
+ }
144
+ function getConfidence(dataPoints) {
145
+ if (dataPoints >= 8)
146
+ return "high";
147
+ if (dataPoints >= 4)
148
+ return "medium";
149
+ return "low";
150
+ }
151
+ //# sourceMappingURL=rule-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-engine.js","sourceRoot":"","sources":["../../src/scoring/rule-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import type { DomainId, NormalizedEvent } from "../types.js";
2
+ import type { ConfigSignals } from "../parsers/config-parser.js";
3
+ export type FeatureTag = "hooks" | "plugins" | "skills" | "mcp" | "agents" | "plan" | "memory" | "rules";
4
+ export type EvidenceType = "config" | "behavior";
5
+ export type RuleTier = "beginner" | "intermediate" | "advanced" | "anti-pattern";
6
+ export interface ScoringRule {
7
+ id: string;
8
+ domain: DomainId;
9
+ tier: RuleTier;
10
+ points: number;
11
+ featureTags: FeatureTag[];
12
+ evidenceType: EvidenceType;
13
+ maxPerSession: number;
14
+ reason: string;
15
+ detect: (ctx: RuleContext) => number;
16
+ }
17
+ export interface RuleContext {
18
+ events: NormalizedEvent[];
19
+ config: ConfigSignals;
20
+ sessionCount: number;
21
+ }
22
+ export interface RuleFire {
23
+ ruleId: string;
24
+ domain: DomainId;
25
+ tier: RuleTier;
26
+ points: number;
27
+ featureTags: FeatureTag[];
28
+ evidenceType: EvidenceType;
29
+ count: number;
30
+ }
31
+ export declare const RULES: ScoringRule[];
32
+ //# sourceMappingURL=rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/scoring/rules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAkC,MAAM,aAAa,CAAC;AAC7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAIjE,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AACzG,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,UAAU,CAAC;AACjD,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,cAAc,GAAG,UAAU,GAAG,cAAc,CAAC;AAEjF,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,QAAQ,CAAC;IACjB,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,YAAY,EAAE,YAAY,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,CAAC,GAAG,EAAE,WAAW,KAAK,MAAM,CAAC;CACtC;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,QAAQ,CAAC;IACjB,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,YAAY,EAAE,YAAY,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;CACf;AAaD,eAAO,MAAM,KAAK,EAAE,WAAW,EA4b9B,CAAC"}