quackscore 0.2.5 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -1
- package/dist/commands/create.d.ts +1 -0
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +28 -12
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +19 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/leaderboard.d.ts +5 -1
- package/dist/commands/leaderboard.d.ts.map +1 -1
- package/dist/commands/leaderboard.js +57 -29
- package/dist/commands/leaderboard.js.map +1 -1
- package/dist/commands/mock-report.js +21 -21
- package/dist/commands/mock-report.js.map +1 -1
- package/dist/commands/profile-options.d.ts +24 -0
- package/dist/commands/profile-options.d.ts.map +1 -0
- package/dist/commands/profile-options.js +38 -0
- package/dist/commands/profile-options.js.map +1 -0
- package/dist/commands/remove.d.ts +5 -1
- package/dist/commands/remove.d.ts.map +1 -1
- package/dist/commands/remove.js +14 -5
- package/dist/commands/remove.js.map +1 -1
- package/dist/commands/show.d.ts +5 -1
- package/dist/commands/show.d.ts.map +1 -1
- package/dist/commands/show.js +12 -3
- package/dist/commands/show.js.map +1 -1
- package/dist/commands/stats.d.ts +7 -0
- package/dist/commands/stats.d.ts.map +1 -0
- package/dist/commands/stats.js +59 -0
- package/dist/commands/stats.js.map +1 -0
- package/dist/commands/update-summary.d.ts +2 -0
- package/dist/commands/update-summary.d.ts.map +1 -1
- package/dist/commands/update-summary.js +12 -3
- package/dist/commands/update-summary.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +148 -68
- package/dist/commands/update.js.map +1 -1
- package/dist/config/types.d.ts +1 -1
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +14 -0
- package/dist/config/types.js.map +1 -1
- package/dist/github/client.d.ts +5 -5
- package/dist/github/client.d.ts.map +1 -1
- package/dist/github/client.js +157 -57
- package/dist/github/client.js.map +1 -1
- package/dist/github/index.d.ts +2 -0
- package/dist/github/index.d.ts.map +1 -1
- package/dist/github/index.js +1 -0
- package/dist/github/index.js.map +1 -1
- package/dist/github/repository-stats.d.ts +8 -0
- package/dist/github/repository-stats.d.ts.map +1 -0
- package/dist/github/repository-stats.js +96 -0
- package/dist/github/repository-stats.js.map +1 -0
- package/dist/index.js +48 -7
- package/dist/index.js.map +1 -1
- package/dist/llm/analyzer.d.ts +3 -3
- package/dist/llm/analyzer.d.ts.map +1 -1
- package/dist/llm/analyzer.js +5 -5
- package/dist/llm/analyzer.js.map +1 -1
- package/dist/llm/character.d.ts +2 -2
- package/dist/llm/character.d.ts.map +1 -1
- package/dist/llm/character.js +3 -3
- package/dist/llm/character.js.map +1 -1
- package/dist/llm/client.d.ts +2 -2
- package/dist/llm/client.d.ts.map +1 -1
- package/dist/llm/client.js +1 -1
- package/dist/llm/client.js.map +1 -1
- package/dist/llm/prompts.d.ts.map +1 -1
- package/dist/llm/prompts.js +13 -1
- package/dist/llm/prompts.js.map +1 -1
- package/dist/llm/providers.d.ts +3 -3
- package/dist/llm/providers.d.ts.map +1 -1
- package/dist/llm/providers.js +25 -6
- package/dist/llm/providers.js.map +1 -1
- package/dist/report/generate.d.ts.map +1 -1
- package/dist/report/generate.js +9 -7
- package/dist/report/generate.js.map +1 -1
- package/dist/report/index.d.ts +1 -0
- package/dist/report/index.d.ts.map +1 -1
- package/dist/report/index.js +1 -0
- package/dist/report/index.js.map +1 -1
- package/dist/report/leaderboard.d.ts +5 -1
- package/dist/report/leaderboard.d.ts.map +1 -1
- package/dist/report/leaderboard.js +611 -865
- package/dist/report/leaderboard.js.map +1 -1
- package/dist/report/repository-stats.d.ts +3 -0
- package/dist/report/repository-stats.d.ts.map +1 -0
- package/dist/report/repository-stats.js +650 -0
- package/dist/report/repository-stats.js.map +1 -0
- package/dist/scoring/index.d.ts +1 -0
- package/dist/scoring/index.d.ts.map +1 -1
- package/dist/scoring/index.js +1 -0
- package/dist/scoring/index.js.map +1 -1
- package/dist/scoring/points.d.ts.map +1 -1
- package/dist/scoring/points.js +5 -10
- package/dist/scoring/points.js.map +1 -1
- package/dist/scoring/repository-stats.d.ts +7 -0
- package/dist/scoring/repository-stats.d.ts.map +1 -0
- package/dist/scoring/repository-stats.js +120 -0
- package/dist/scoring/repository-stats.js.map +1 -0
- package/dist/shared/profile-scope.d.ts +19 -0
- package/dist/shared/profile-scope.d.ts.map +1 -0
- package/dist/shared/profile-scope.js +101 -0
- package/dist/shared/profile-scope.js.map +1 -0
- package/dist/shared/profile-summary.js +6 -6
- package/dist/shared/profile-summary.js.map +1 -1
- package/dist/shared/repository-stats.d.ts +51 -0
- package/dist/shared/repository-stats.d.ts.map +1 -0
- package/dist/shared/repository-stats.js +2 -0
- package/dist/shared/repository-stats.js.map +1 -0
- package/dist/shared/types.d.ts +29 -1
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/shared/ui.d.ts +1 -0
- package/dist/shared/ui.d.ts.map +1 -1
- package/dist/shared/ui.js +3 -0
- package/dist/shared/ui.js.map +1 -1
- package/dist/storage/index.d.ts +2 -2
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +2 -2
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/leaderboard.d.ts +3 -2
- package/dist/storage/leaderboard.d.ts.map +1 -1
- package/dist/storage/leaderboard.js +80 -9
- package/dist/storage/leaderboard.js.map +1 -1
- package/dist/storage/paths.d.ts +6 -0
- package/dist/storage/paths.d.ts.map +1 -1
- package/dist/storage/paths.js +21 -0
- package/dist/storage/paths.js.map +1 -1
- package/dist/storage/report.d.ts +5 -2
- package/dist/storage/report.d.ts.map +1 -1
- package/dist/storage/report.js +38 -8
- package/dist/storage/report.js.map +1 -1
- package/dist/storage/user.d.ts +2 -1
- package/dist/storage/user.d.ts.map +1 -1
- package/dist/storage/user.js +27 -10
- package/dist/storage/user.js.map +1 -1
- package/package.json +13 -6
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ProfileSelector } from '../shared/profile-scope.js';
|
|
2
|
+
import type { ProfileScope } from '../shared/types.js';
|
|
3
|
+
export interface ScopedProfileOptions {
|
|
4
|
+
org?: string;
|
|
5
|
+
repository?: string;
|
|
6
|
+
weeks?: number;
|
|
7
|
+
teams?: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface ScopeTargetOptions {
|
|
10
|
+
org?: string;
|
|
11
|
+
repository?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ResolvedScopedProfileOptions {
|
|
14
|
+
org?: string;
|
|
15
|
+
repository?: string;
|
|
16
|
+
weeks?: number;
|
|
17
|
+
teams?: string[];
|
|
18
|
+
selector: ProfileSelector;
|
|
19
|
+
scope: ProfileScope;
|
|
20
|
+
}
|
|
21
|
+
export declare function weeksToSinceISO(weeks: number): string;
|
|
22
|
+
export declare function resolveScopeTarget(username: string, options?: ScopeTargetOptions): ProfileSelector;
|
|
23
|
+
export declare function resolveScopedProfileOptions(username: string, options: ScopedProfileOptions): ResolvedScopedProfileOptions;
|
|
24
|
+
//# sourceMappingURL=profile-options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-options.d.ts","sourceRoot":"","sources":["../../src/commands/profile-options.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,4BAA4B;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,eAAe,CAAC;IAC1B,KAAK,EAAE,YAAY,CAAC;CACrB;AAOD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,eAAe,CAYtG;AAED,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,4BAA4B,CAqBzH"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { normalizeTeams, profileSelector, scopeFromSelector } from '../shared/profile-scope.js';
|
|
2
|
+
function cleanOption(value) {
|
|
3
|
+
const trimmed = value?.trim();
|
|
4
|
+
return trimmed ? trimmed : undefined;
|
|
5
|
+
}
|
|
6
|
+
export function weeksToSinceISO(weeks) {
|
|
7
|
+
return new Date(Date.now() - weeks * 7 * 24 * 60 * 60 * 1000).toISOString();
|
|
8
|
+
}
|
|
9
|
+
export function resolveScopeTarget(username, options = {}) {
|
|
10
|
+
const org = cleanOption(options.org);
|
|
11
|
+
const repository = cleanOption(options.repository);
|
|
12
|
+
if (repository && !org) {
|
|
13
|
+
throw new Error('--repository requires --organisation.');
|
|
14
|
+
}
|
|
15
|
+
return profileSelector(username, {
|
|
16
|
+
organisation: org,
|
|
17
|
+
repository,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
export function resolveScopedProfileOptions(username, options) {
|
|
21
|
+
if (options.weeks != null && (!Number.isInteger(options.weeks) || options.weeks <= 0)) {
|
|
22
|
+
throw new Error('--weeks must be a positive integer.');
|
|
23
|
+
}
|
|
24
|
+
const selector = resolveScopeTarget(username, options);
|
|
25
|
+
if ((options.teams ?? []).some((team) => team.trim().length === 0)) {
|
|
26
|
+
throw new Error('--team cannot be empty.');
|
|
27
|
+
}
|
|
28
|
+
const teams = options.teams == null ? undefined : normalizeTeams(options.teams);
|
|
29
|
+
return {
|
|
30
|
+
org: selector.organisation,
|
|
31
|
+
repository: selector.repository,
|
|
32
|
+
weeks: options.weeks,
|
|
33
|
+
teams,
|
|
34
|
+
selector,
|
|
35
|
+
scope: scopeFromSelector(selector, options.weeks),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=profile-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-options.js","sourceRoot":"","sources":["../../src/commands/profile-options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAyBhG,SAAS,WAAW,CAAC,KAAc;IACjC,MAAM,OAAO,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC;IAC9B,OAAO,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAAgB,EAAE,UAA8B,EAAE;IACnF,MAAM,GAAG,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACrC,MAAM,UAAU,GAAG,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAEnD,IAAI,UAAU,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,eAAe,CAAC,QAAQ,EAAE;QAC/B,YAAY,EAAE,GAAG;QACjB,UAAU;KACX,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,QAAgB,EAAE,OAA6B;IACzF,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC;QACtF,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,QAAQ,GAAG,kBAAkB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAEvD,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;QACnE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAEhF,OAAO;QACL,GAAG,EAAE,QAAQ,CAAC,YAAY;QAC1B,UAAU,EAAE,QAAQ,CAAC,UAAU;QAC/B,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,KAAK;QACL,QAAQ;QACR,KAAK,EAAE,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC;KAClD,CAAC;AACJ,CAAC"}
|
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface RemoveOptions {
|
|
2
|
+
org?: string;
|
|
3
|
+
repository?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function runRemove(username: string, options?: RemoveOptions): Promise<void>;
|
|
2
6
|
//# sourceMappingURL=remove.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remove.d.ts","sourceRoot":"","sources":["../../src/commands/remove.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"remove.d.ts","sourceRoot":"","sources":["../../src/commands/remove.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwC5F"}
|
package/dist/commands/remove.js
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
|
-
import {
|
|
2
|
+
import { profileFilePath, profileReportPath } from '../storage/paths.js';
|
|
3
3
|
import { rpgHeader, rpgSuccess, rpgInfo, rpgError } from '../shared/ui.js';
|
|
4
4
|
import { diagLog } from '../shared/diagnostics.js';
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import { resolveScopeTarget } from './profile-options.js';
|
|
6
|
+
export async function runRemove(username, options = {}) {
|
|
7
|
+
let selector;
|
|
8
|
+
try {
|
|
9
|
+
selector = resolveScopeTarget(username, options);
|
|
10
|
+
}
|
|
11
|
+
catch (err) {
|
|
12
|
+
rpgError(err.message);
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
diagLog('Starting remove command', { username, selector });
|
|
7
16
|
rpgHeader(`Quackscore Remove — ${username}`);
|
|
8
|
-
const dataPath =
|
|
9
|
-
const reportPath =
|
|
17
|
+
const dataPath = profileFilePath(selector);
|
|
18
|
+
const reportPath = profileReportPath(selector);
|
|
10
19
|
let removed = 0;
|
|
11
20
|
if (fs.existsSync(dataPath)) {
|
|
12
21
|
fs.unlinkSync(dataPath);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remove.js","sourceRoot":"","sources":["../../src/commands/remove.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"remove.js","sourceRoot":"","sources":["../../src/commands/remove.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAO1D,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAgB,EAAE,UAAyB,EAAE;IAC3E,IAAI,QAAQ,CAAC;IACb,IAAI,CAAC;QACH,QAAQ,GAAG,kBAAkB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,QAAQ,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,yBAAyB,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC3D,SAAS,CAAC,uBAAuB,QAAQ,EAAE,CAAC,CAAC;IAE7C,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC/C,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QACxB,UAAU,CAAC,sBAAsB,QAAQ,EAAE,CAAC,CAAC;QAC7C,OAAO,CAAC,wBAAwB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACtD,OAAO,EAAE,CAAC;IACZ,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,uBAAuB,QAAQ,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAC1B,UAAU,CAAC,wBAAwB,UAAU,EAAE,CAAC,CAAC;QACjD,OAAO,CAAC,0BAA0B,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;QAC1D,OAAO,EAAE,CAAC;IACZ,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,yBAAyB,UAAU,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;QAClB,QAAQ,CAAC,uBAAuB,QAAQ,uBAAuB,CAAC,CAAC;QACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,WAAW,OAAO,iBAAiB,QAAQ,IAAI,CAAC,CAAC;AAC3D,CAAC"}
|
package/dist/commands/show.d.ts
CHANGED
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface ShowOptions {
|
|
2
|
+
org?: string;
|
|
3
|
+
repository?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function runShow(username: string, options?: ShowOptions): Promise<void>;
|
|
2
6
|
//# sourceMappingURL=show.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../../src/commands/show.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../../src/commands/show.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBxF"}
|
package/dist/commands/show.js
CHANGED
|
@@ -3,9 +3,18 @@ import { rpgError, rpgLog } from '../shared/ui.js';
|
|
|
3
3
|
import { diagLog } from '../shared/diagnostics.js';
|
|
4
4
|
import open from 'open';
|
|
5
5
|
import fs from 'fs';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
import { resolveScopeTarget } from './profile-options.js';
|
|
7
|
+
export async function runShow(username, options = {}) {
|
|
8
|
+
let selector;
|
|
9
|
+
try {
|
|
10
|
+
selector = resolveScopeTarget(username, options);
|
|
11
|
+
}
|
|
12
|
+
catch (err) {
|
|
13
|
+
rpgError(err.message);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
const reportPath = getUserReportPath(selector);
|
|
17
|
+
diagLog('Resolved report path for show command', { username, selector, reportPath });
|
|
9
18
|
if (!fs.existsSync(reportPath)) {
|
|
10
19
|
rpgError(`No report found for ${username}. Run 'quackscore create ${username}' first.`);
|
|
11
20
|
process.exit(1);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"show.js","sourceRoot":"","sources":["../../src/commands/show.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"show.js","sourceRoot":"","sources":["../../src/commands/show.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAO1D,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,QAAgB,EAAE,UAAuB,EAAE;IACvE,IAAI,QAAQ,CAAC;IACb,IAAI,CAAC;QACH,QAAQ,GAAG,kBAAkB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,QAAQ,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC;QACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,UAAU,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC/C,OAAO,CAAC,uCAAuC,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;IACrF,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,QAAQ,CAAC,uBAAuB,QAAQ,4BAA4B,QAAQ,UAAU,CAAC,CAAC;QACxF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,CAAC,sBAAsB,QAAQ,KAAK,CAAC,CAAC;IAC5C,OAAO,CAAC,4CAA4C,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC;IAChF,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/commands/stats.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,YAAY;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAwDjF"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import open from 'open';
|
|
2
|
+
import { fetchRepositoryStatsPRs } from '../github/index.js';
|
|
3
|
+
import { aggregateRepositoryStats, formatDuration } from '../scoring/index.js';
|
|
4
|
+
import { generateRepositoryStatsHTML } from '../report/index.js';
|
|
5
|
+
import { saveRepositoryStatsReport } from '../storage/index.js';
|
|
6
|
+
import { rpgError, rpgHeader, rpgInfo, rpgLog, rpgSuccess } from '../shared/ui.js';
|
|
7
|
+
import { diagError, diagLog } from '../shared/diagnostics.js';
|
|
8
|
+
export async function runStats(repo, options) {
|
|
9
|
+
const org = options.organisation;
|
|
10
|
+
if (!org) {
|
|
11
|
+
rpgError('Organisation is required. Use: quackscore stats <repo> --organisation <org>');
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
const token = options.githubToken ?? process.env['QUACKSCORE_GH_TOKEN'];
|
|
15
|
+
if (!token) {
|
|
16
|
+
rpgError('GitHub token not set. Use --github-token or set QUACKSCORE_GH_TOKEN.');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
diagLog('Starting repository stats command', {
|
|
20
|
+
org,
|
|
21
|
+
repo,
|
|
22
|
+
team: options.team,
|
|
23
|
+
githubTokenPresent: Boolean(token),
|
|
24
|
+
});
|
|
25
|
+
rpgHeader(`Quackscore Stats - ${org}/${repo}`);
|
|
26
|
+
if (options.team) {
|
|
27
|
+
rpgInfo(`Filtering to PRs authored by team "${options.team}"...`);
|
|
28
|
+
}
|
|
29
|
+
rpgLog('Fetching repository pull requests and review activity...');
|
|
30
|
+
let prs;
|
|
31
|
+
try {
|
|
32
|
+
prs = await fetchRepositoryStatsPRs(token, {
|
|
33
|
+
org,
|
|
34
|
+
repo,
|
|
35
|
+
team: options.team,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
diagError('Repository stats command failed while fetching GitHub data', err, {
|
|
40
|
+
org,
|
|
41
|
+
repo,
|
|
42
|
+
team: options.team,
|
|
43
|
+
});
|
|
44
|
+
rpgError(`Failed to fetch repository stats: ${err.message}`);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
rpgSuccess(`Found ${prs.length} merged PR${prs.length === 1 ? '' : 's'}`);
|
|
48
|
+
rpgLog('Computing repository stats...');
|
|
49
|
+
const reportData = aggregateRepositoryStats(org, repo, prs, { team: options.team });
|
|
50
|
+
const html = generateRepositoryStatsHTML(reportData);
|
|
51
|
+
const reportPath = saveRepositoryStatsReport(org, repo, options.team, html);
|
|
52
|
+
rpgSuccess(`Repository stats saved: ${reportPath}`);
|
|
53
|
+
rpgInfo(`Average approval: ${formatDuration(reportData.summary.averageApprovalHours)}`);
|
|
54
|
+
rpgInfo(`Average merge: ${formatDuration(reportData.summary.averageMergeHours)}`);
|
|
55
|
+
rpgInfo(`Average comments: ${reportData.summary.averageComments.toFixed(1)}`);
|
|
56
|
+
rpgLog('Opening repository stats report...');
|
|
57
|
+
await open(reportPath);
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/commands/stats.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-summary.d.ts","sourceRoot":"","sources":["../../src/commands/update-summary.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"update-summary.d.ts","sourceRoot":"","sources":["../../src/commands/update-summary.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyE1G"}
|
|
@@ -5,8 +5,17 @@ import { loadConfig } from '../config/index.js';
|
|
|
5
5
|
import { rpgHeader, rpgLog, rpgSuccess, rpgError } from '../shared/ui.js';
|
|
6
6
|
import { diagError, diagLog } from '../shared/diagnostics.js';
|
|
7
7
|
import open from 'open';
|
|
8
|
+
import { resolveScopeTarget } from './profile-options.js';
|
|
8
9
|
export async function runUpdateSummary(username, options = {}) {
|
|
9
|
-
|
|
10
|
+
let selector;
|
|
11
|
+
try {
|
|
12
|
+
selector = resolveScopeTarget(username, options);
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
rpgError(err.message);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
diagLog('Starting update-summary command', { username, selector });
|
|
10
19
|
let model;
|
|
11
20
|
try {
|
|
12
21
|
const config = loadConfig();
|
|
@@ -20,7 +29,7 @@ export async function runUpdateSummary(username, options = {}) {
|
|
|
20
29
|
process.exit(1);
|
|
21
30
|
}
|
|
22
31
|
rpgHeader(`Quackscore Update Summary — ${username}`);
|
|
23
|
-
const existing = loadUserData(
|
|
32
|
+
const existing = loadUserData(selector);
|
|
24
33
|
if (!existing) {
|
|
25
34
|
rpgError(`No existing profile found for "${username}". Run quackscore create first.`);
|
|
26
35
|
process.exit(1);
|
|
@@ -52,7 +61,7 @@ export async function runUpdateSummary(username, options = {}) {
|
|
|
52
61
|
rpgLog('Forging updated Quack-Card...');
|
|
53
62
|
const reportStartedAt = Date.now();
|
|
54
63
|
const html = generateHTML(userData);
|
|
55
|
-
const reportPath = saveReport(
|
|
64
|
+
const reportPath = saveReport(selector, html);
|
|
56
65
|
diagLog('Generated and saved report for update-summary', {
|
|
57
66
|
durationMs: Date.now() - reportStartedAt,
|
|
58
67
|
reportPath,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-summary.js","sourceRoot":"","sources":["../../src/commands/update-summary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,IAAI,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"update-summary.js","sourceRoot":"","sources":["../../src/commands/update-summary.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAyBjD,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA+PvF"}
|
package/dist/commands/update.js
CHANGED
|
@@ -4,14 +4,49 @@ import { calculatePRPoints, aggregateStats } from '../scoring/index.js';
|
|
|
4
4
|
import { loadUserData, saveUserData, saveReport } from '../storage/index.js';
|
|
5
5
|
import { generateHTML } from '../report/index.js';
|
|
6
6
|
import { loadConfig } from '../config/index.js';
|
|
7
|
+
import { mergeTeamDisplay, prIdentity, teamKey } from '../shared/profile-scope.js';
|
|
7
8
|
import { rpgHeader, rpgLog, rpgInfo, rpgProgress, rpgSuccess, rpgError } from '../shared/ui.js';
|
|
8
9
|
import { diagError, diagLog } from '../shared/diagnostics.js';
|
|
9
10
|
import { setupEscCancel } from '../shared/cancel.js';
|
|
10
11
|
import open from 'open';
|
|
12
|
+
import { resolveScopedProfileOptions, weeksToSinceISO } from './profile-options.js';
|
|
13
|
+
function sameTeamSet(left = [], right = []) {
|
|
14
|
+
return left.length === right.length && left.every((team, index) => teamKey(team) === teamKey(right[index] ?? ''));
|
|
15
|
+
}
|
|
16
|
+
function samePRSet(left, right) {
|
|
17
|
+
if (left.length !== right.length)
|
|
18
|
+
return false;
|
|
19
|
+
const rightKeys = new Set(right.map(prIdentity));
|
|
20
|
+
return left.every((pr) => rightKeys.has(prIdentity(pr)));
|
|
21
|
+
}
|
|
22
|
+
function mergeWithCachedAnalysis(freshPR, cachedPR) {
|
|
23
|
+
if (!cachedPR)
|
|
24
|
+
return freshPR;
|
|
25
|
+
return {
|
|
26
|
+
...freshPR,
|
|
27
|
+
analysis: cachedPR.analysis,
|
|
28
|
+
points: cachedPR.points,
|
|
29
|
+
diff: freshPR.diff ?? cachedPR.diff,
|
|
30
|
+
rawFileStats: freshPR.rawFileStats ?? cachedPR.rawFileStats,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
11
33
|
export async function runUpdate(username, options) {
|
|
34
|
+
let resolvedOptions;
|
|
35
|
+
try {
|
|
36
|
+
resolvedOptions = resolveScopedProfileOptions(username, options);
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
rpgError(err.message);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
12
42
|
diagLog('Starting update command', {
|
|
13
43
|
username,
|
|
14
|
-
options: {
|
|
44
|
+
options: {
|
|
45
|
+
org: resolvedOptions.org,
|
|
46
|
+
repository: resolvedOptions.repository,
|
|
47
|
+
weeks: resolvedOptions.weeks,
|
|
48
|
+
teams: resolvedOptions.teams,
|
|
49
|
+
},
|
|
15
50
|
githubTokenPresent: Boolean(options.githubToken ?? process.env['QUACKSCORE_GH_TOKEN']),
|
|
16
51
|
});
|
|
17
52
|
const token = options.githubToken ?? process.env['QUACKSCORE_GH_TOKEN'];
|
|
@@ -32,41 +67,54 @@ export async function runUpdate(username, options) {
|
|
|
32
67
|
process.exit(1);
|
|
33
68
|
}
|
|
34
69
|
rpgHeader(`Quackscore Update — ${username}`);
|
|
35
|
-
const existing = loadUserData(
|
|
70
|
+
const existing = loadUserData(resolvedOptions.selector);
|
|
36
71
|
if (!existing) {
|
|
37
|
-
diagLog('No existing user data found during update; delegating to create', {
|
|
72
|
+
diagLog('No existing user data found during update; delegating to create', {
|
|
73
|
+
username,
|
|
74
|
+
selector: resolvedOptions.selector,
|
|
75
|
+
});
|
|
38
76
|
rpgInfo('No existing data found. Running full analysis...');
|
|
39
77
|
const { runCreate } = await import('./create.js');
|
|
40
78
|
await runCreate(username, options);
|
|
41
79
|
return;
|
|
42
80
|
}
|
|
81
|
+
const effectiveWeeks = resolvedOptions.weeks ?? existing.scope?.windowWeeks;
|
|
82
|
+
const effectiveTeams = resolvedOptions.teams == null
|
|
83
|
+
? existing.teams ?? []
|
|
84
|
+
: mergeTeamDisplay(existing.teams, resolvedOptions.teams);
|
|
43
85
|
diagLog('Loaded existing user data for update', {
|
|
44
86
|
username,
|
|
45
87
|
lastUpdated: existing.lastUpdated,
|
|
46
88
|
existingPRs: existing.prs.length,
|
|
47
89
|
totalPoints: existing.stats.totalPoints,
|
|
48
90
|
level: existing.stats.level,
|
|
91
|
+
effectiveWeeks,
|
|
92
|
+
effectiveTeams,
|
|
49
93
|
});
|
|
50
94
|
rpgLog(`Last updated: ${existing.lastUpdated}`);
|
|
51
|
-
rpgInfo('Fetching
|
|
52
|
-
const since =
|
|
53
|
-
?
|
|
95
|
+
rpgInfo('Fetching PR scrolls...');
|
|
96
|
+
const since = effectiveWeeks != null
|
|
97
|
+
? weeksToSinceISO(effectiveWeeks)
|
|
54
98
|
: existing.lastUpdated;
|
|
55
|
-
if (
|
|
56
|
-
rpgInfo(`
|
|
99
|
+
if (effectiveWeeks != null) {
|
|
100
|
+
rpgInfo(`Synchronizing the last ${effectiveWeeks} week${effectiveWeeks === 1 ? '' : 's'} of PRs (since ${new Date(since).toLocaleDateString()})...`);
|
|
57
101
|
}
|
|
58
|
-
|
|
102
|
+
if (resolvedOptions.teams != null) {
|
|
103
|
+
const teamText = effectiveTeams.length > 0 ? effectiveTeams.join(', ') : 'none';
|
|
104
|
+
rpgInfo(`Updating team tags: ${teamText}`);
|
|
105
|
+
}
|
|
106
|
+
let fetchedPRs;
|
|
59
107
|
try {
|
|
60
108
|
const fetchStartedAt = Date.now();
|
|
61
|
-
|
|
62
|
-
org:
|
|
63
|
-
repo:
|
|
109
|
+
fetchedPRs = await fetchUserPRs(username, token, {
|
|
110
|
+
org: resolvedOptions.org,
|
|
111
|
+
repo: resolvedOptions.repository,
|
|
64
112
|
since,
|
|
65
113
|
});
|
|
66
114
|
diagLog('Fetched candidate PRs for update', {
|
|
67
115
|
username,
|
|
68
116
|
durationMs: Date.now() - fetchStartedAt,
|
|
69
|
-
candidateCount:
|
|
117
|
+
candidateCount: fetchedPRs.length,
|
|
70
118
|
since,
|
|
71
119
|
});
|
|
72
120
|
}
|
|
@@ -74,73 +122,93 @@ export async function runUpdate(username, options) {
|
|
|
74
122
|
diagError('Update command failed while fetching PRs', err, {
|
|
75
123
|
username,
|
|
76
124
|
options,
|
|
77
|
-
since
|
|
125
|
+
since,
|
|
78
126
|
});
|
|
79
127
|
rpgError(`Failed to fetch PRs: ${err.message}`);
|
|
80
128
|
process.exit(1);
|
|
81
129
|
}
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
130
|
+
const existingByIdentity = new Map(existing.prs.map((pr) => [prIdentity(pr), pr]));
|
|
131
|
+
let allPRs;
|
|
132
|
+
let freshPRs;
|
|
133
|
+
let agedOutCount = 0;
|
|
134
|
+
if (effectiveWeeks != null) {
|
|
135
|
+
allPRs = fetchedPRs.map((pr) => mergeWithCachedAnalysis(pr, existingByIdentity.get(prIdentity(pr))));
|
|
136
|
+
freshPRs = allPRs.filter((pr) => {
|
|
137
|
+
const cached = existingByIdentity.get(prIdentity(pr));
|
|
138
|
+
return !cached || !cached.analysis || cached.points == null;
|
|
139
|
+
});
|
|
140
|
+
const fetchedKeys = new Set(allPRs.map(prIdentity));
|
|
141
|
+
agedOutCount = existing.prs.filter((pr) => !fetchedKeys.has(prIdentity(pr))).length;
|
|
142
|
+
rpgSuccess(`Window contains ${allPRs.length} PRs${freshPRs.length > 0 ? `, ${freshPRs.length} new to analyze` : ''}${agedOutCount > 0 ? `, ${agedOutCount} aged out` : ''}.`);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
freshPRs = fetchedPRs.filter((pr) => !existingByIdentity.has(prIdentity(pr)));
|
|
146
|
+
allPRs = [...existing.prs, ...freshPRs];
|
|
147
|
+
rpgSuccess(`Found ${freshPRs.length} new PRs since last update`);
|
|
148
|
+
}
|
|
149
|
+
const teamsChanged = !sameTeamSet(existing.teams ?? [], effectiveTeams);
|
|
150
|
+
const windowChanged = existing.scope?.windowWeeks !== effectiveWeeks;
|
|
151
|
+
const prSetChanged = effectiveWeeks != null ? !samePRSet(allPRs, existing.prs) : freshPRs.length > 0;
|
|
152
|
+
if (freshPRs.length === 0 && !teamsChanged && !windowChanged && !prSetChanged) {
|
|
92
153
|
rpgInfo('Nothing new to analyze. Your card is up to date.');
|
|
93
154
|
return;
|
|
94
155
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
additions: pr.additions,
|
|
114
|
-
deletions: pr.deletions,
|
|
115
|
-
diffPresent: Boolean(pr.diff),
|
|
116
|
-
diffLength: pr.diff?.length ?? 0,
|
|
117
|
-
});
|
|
118
|
-
try {
|
|
119
|
-
const analysisStartedAt = Date.now();
|
|
120
|
-
pr.analysis = await analyzePR(pr, model);
|
|
121
|
-
pr.points = calculatePRPoints(pr);
|
|
122
|
-
diagLog('Completed fresh PR analysis during update', {
|
|
123
|
-
prNumber: pr.number,
|
|
124
|
-
durationMs: Date.now() - analysisStartedAt,
|
|
125
|
-
skipped: pr.analysis.skipped,
|
|
126
|
-
complexity: pr.analysis.complexity,
|
|
127
|
-
areas: pr.analysis.areas,
|
|
128
|
-
types: pr.analysis.types,
|
|
129
|
-
technologies: pr.analysis.technologies,
|
|
130
|
-
points: pr.points,
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
catch (err) {
|
|
134
|
-
diagError('PR analysis failed during update', err, {
|
|
156
|
+
if (freshPRs.length > 0) {
|
|
157
|
+
rpgLog('Evaluating effort and complexity...');
|
|
158
|
+
rpgInfo('Press ESC to stop scanning and save partial results.');
|
|
159
|
+
const { isCancelled, cleanup } = setupEscCancel();
|
|
160
|
+
for (let i = 0; i < freshPRs.length; i++) {
|
|
161
|
+
if (isCancelled()) {
|
|
162
|
+
rpgInfo(`Scan stopped early after ${i} PR${i === 1 ? '' : 's'}. Saving partial results...`);
|
|
163
|
+
freshPRs.splice(i);
|
|
164
|
+
allPRs = effectiveWeeks != null
|
|
165
|
+
? allPRs.filter((pr) => pr.analysis || pr.points != null || freshPRs.includes(pr))
|
|
166
|
+
: [...existing.prs, ...freshPRs];
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
const pr = freshPRs[i];
|
|
170
|
+
rpgProgress(i + 1, freshPRs.length, pr.title);
|
|
171
|
+
diagLog('Analyzing fresh PR during update', {
|
|
172
|
+
index: i + 1,
|
|
173
|
+
total: freshPRs.length,
|
|
135
174
|
prNumber: pr.number,
|
|
136
175
|
repo: pr.repo,
|
|
137
176
|
title: pr.title,
|
|
177
|
+
mergedAt: pr.mergedAt,
|
|
178
|
+
additions: pr.additions,
|
|
179
|
+
deletions: pr.deletions,
|
|
180
|
+
diffPresent: Boolean(pr.diff),
|
|
181
|
+
diffLength: pr.diff?.length ?? 0,
|
|
138
182
|
});
|
|
139
|
-
|
|
183
|
+
try {
|
|
184
|
+
const analysisStartedAt = Date.now();
|
|
185
|
+
pr.analysis = await analyzePR(pr, model);
|
|
186
|
+
pr.points = calculatePRPoints(pr);
|
|
187
|
+
diagLog('Completed fresh PR analysis during update', {
|
|
188
|
+
prNumber: pr.number,
|
|
189
|
+
durationMs: Date.now() - analysisStartedAt,
|
|
190
|
+
skipped: pr.analysis.skipped,
|
|
191
|
+
effortScore: pr.analysis.effortScore,
|
|
192
|
+
areas: pr.analysis.areas,
|
|
193
|
+
types: pr.analysis.types,
|
|
194
|
+
technologies: pr.analysis.technologies,
|
|
195
|
+
points: pr.points,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
catch (err) {
|
|
199
|
+
diagError('PR analysis failed during update', err, {
|
|
200
|
+
prNumber: pr.number,
|
|
201
|
+
repo: pr.repo,
|
|
202
|
+
title: pr.title,
|
|
203
|
+
});
|
|
204
|
+
rpgError(`Skipping PR #${pr.number}: ${err.message}`);
|
|
205
|
+
}
|
|
140
206
|
}
|
|
207
|
+
cleanup();
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
rpgInfo('No new PRs required analysis. Rebuilding the scoped profile from cached results.');
|
|
141
211
|
}
|
|
142
|
-
cleanup();
|
|
143
|
-
const allPRs = [...existing.prs, ...freshPRs];
|
|
144
212
|
const stats = aggregateStats(allPRs);
|
|
145
213
|
diagLog('Aggregated stats for update', {
|
|
146
214
|
totalPRsAfterMerge: allPRs.length,
|
|
@@ -151,17 +219,27 @@ export async function runUpdate(username, options) {
|
|
|
151
219
|
areaCount: Object.keys(stats.areas).length,
|
|
152
220
|
technologyCount: Object.keys(stats.technologies).length,
|
|
153
221
|
typeCount: Object.keys(stats.types).length,
|
|
222
|
+
teamsChanged,
|
|
223
|
+
windowChanged,
|
|
224
|
+
agedOutCount,
|
|
154
225
|
});
|
|
155
226
|
diagLog('Preserving existing character profile during update (use update-summary to regenerate)', {
|
|
156
227
|
username,
|
|
157
228
|
hasCharacter: Boolean(existing.character),
|
|
158
229
|
});
|
|
159
230
|
const userData = {
|
|
231
|
+
...existing,
|
|
160
232
|
username,
|
|
161
233
|
lastUpdated: new Date().toISOString(),
|
|
162
234
|
prs: allPRs,
|
|
163
235
|
stats,
|
|
164
236
|
character: existing.character,
|
|
237
|
+
scope: {
|
|
238
|
+
organisation: resolvedOptions.org,
|
|
239
|
+
repository: resolvedOptions.repository,
|
|
240
|
+
windowWeeks: effectiveWeeks,
|
|
241
|
+
},
|
|
242
|
+
teams: effectiveTeams,
|
|
165
243
|
};
|
|
166
244
|
saveUserData(userData);
|
|
167
245
|
diagLog('Persisted user data for update', {
|
|
@@ -171,11 +249,13 @@ export async function runUpdate(username, options) {
|
|
|
171
249
|
totalPoints: userData.stats.totalPoints,
|
|
172
250
|
level: userData.stats.level,
|
|
173
251
|
},
|
|
252
|
+
teams: userData.teams,
|
|
253
|
+
scope: userData.scope,
|
|
174
254
|
});
|
|
175
255
|
rpgLog('Forging updated Quack-Card...');
|
|
176
256
|
const reportStartedAt = Date.now();
|
|
177
257
|
const html = generateHTML(userData);
|
|
178
|
-
const reportPath = saveReport(
|
|
258
|
+
const reportPath = saveReport(resolvedOptions.selector, html);
|
|
179
259
|
diagLog('Generated and saved report for update', {
|
|
180
260
|
durationMs: Date.now() - reportStartedAt,
|
|
181
261
|
reportPath,
|