@kb-labs/qa-entry 2.94.0 → 2.96.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 (112) hide show
  1. package/dist/cli/commands/baseline-diff.d.ts +14 -0
  2. package/dist/cli/commands/baseline-diff.js +40 -0
  3. package/dist/cli/commands/baseline-diff.js.map +1 -0
  4. package/dist/cli/commands/baseline-status.d.ts +10 -5
  5. package/dist/cli/commands/baseline-status.js +14 -17
  6. package/dist/cli/commands/baseline-status.js.map +1 -1
  7. package/dist/cli/commands/baseline-update.d.ts +10 -5
  8. package/dist/cli/commands/baseline-update.js +26 -18
  9. package/dist/cli/commands/baseline-update.js.map +1 -1
  10. package/dist/cli/commands/flags.d.ts +117 -132
  11. package/dist/cli/commands/flags.js +65 -79
  12. package/dist/cli/commands/flags.js.map +1 -1
  13. package/dist/cli/commands/qa-check.d.ts +13 -34
  14. package/dist/cli/commands/qa-check.js +26 -106
  15. package/dist/cli/commands/qa-check.js.map +1 -1
  16. package/dist/cli/commands/qa-gate.d.ts +19 -0
  17. package/dist/cli/commands/qa-gate.js +36 -0
  18. package/dist/cli/commands/qa-gate.js.map +1 -0
  19. package/dist/cli/commands/qa-history.d.ts +15 -5
  20. package/dist/cli/commands/qa-history.js +13 -24
  21. package/dist/cli/commands/qa-history.js.map +1 -1
  22. package/dist/cli/commands/qa-regressions.d.ts +10 -5
  23. package/dist/cli/commands/qa-regressions.js +15 -18
  24. package/dist/cli/commands/qa-regressions.js.map +1 -1
  25. package/dist/cli/commands/qa-run.d.ts +18 -11
  26. package/dist/cli/commands/qa-run.js +28 -141
  27. package/dist/cli/commands/qa-run.js.map +1 -1
  28. package/dist/cli/commands/qa-stats.d.ts +19 -0
  29. package/dist/cli/commands/qa-stats.js +43 -0
  30. package/dist/cli/commands/qa-stats.js.map +1 -0
  31. package/dist/cli/commands/qa-trends.d.ts +15 -5
  32. package/dist/cli/commands/qa-trends.js +15 -18
  33. package/dist/cli/commands/qa-trends.js.map +1 -1
  34. package/dist/index.d.ts +1 -1
  35. package/dist/index.js +143 -291
  36. package/dist/index.js.map +1 -1
  37. package/dist/manifest.d.ts +74 -106
  38. package/dist/manifest.js +143 -291
  39. package/dist/manifest.js.map +1 -1
  40. package/dist/rest/handlers/baseline-diff-handler.d.ts +7 -27
  41. package/dist/rest/handlers/baseline-diff-handler.js +15 -41
  42. package/dist/rest/handlers/baseline-diff-handler.js.map +1 -1
  43. package/dist/rest/handlers/baseline-handler.d.ts +3 -13
  44. package/dist/rest/handlers/baseline-handler.js +10 -5
  45. package/dist/rest/handlers/baseline-handler.js.map +1 -1
  46. package/dist/rest/handlers/baseline-update-handler.d.ts +4 -14
  47. package/dist/rest/handlers/baseline-update-handler.js +15 -13
  48. package/dist/rest/handlers/baseline-update-handler.js.map +1 -1
  49. package/dist/rest/handlers/check-handler.d.ts +15 -0
  50. package/dist/rest/handlers/check-handler.js +28 -0
  51. package/dist/rest/handlers/check-handler.js.map +1 -0
  52. package/dist/rest/handlers/gate-handler.d.ts +13 -0
  53. package/dist/rest/handlers/gate-handler.js +28 -0
  54. package/dist/rest/handlers/gate-handler.js.map +1 -0
  55. package/dist/rest/handlers/history-handler.d.ts +3 -16
  56. package/dist/rest/handlers/history-handler.js +10 -11
  57. package/dist/rest/handlers/history-handler.js.map +1 -1
  58. package/dist/rest/handlers/package-timeline-handler.d.ts +5 -20
  59. package/dist/rest/handlers/package-timeline-handler.js +11 -7
  60. package/dist/rest/handlers/package-timeline-handler.js.map +1 -1
  61. package/dist/rest/handlers/regressions-handler.d.ts +2 -11
  62. package/dist/rest/handlers/regressions-handler.js +11 -5
  63. package/dist/rest/handlers/regressions-handler.js.map +1 -1
  64. package/dist/rest/handlers/run-handler.d.ts +10 -27
  65. package/dist/rest/handlers/run-handler.js +18 -63
  66. package/dist/rest/handlers/run-handler.js.map +1 -1
  67. package/dist/rest/handlers/{error-groups-handler.d.ts → stats-handler.d.ts} +5 -9
  68. package/dist/rest/handlers/stats-handler.js +21 -0
  69. package/dist/rest/handlers/stats-handler.js.map +1 -0
  70. package/dist/rest/handlers/summary-handler.d.ts +7 -20
  71. package/dist/rest/handlers/summary-handler.js +16 -26
  72. package/dist/rest/handlers/summary-handler.js.map +1 -1
  73. package/dist/rest/handlers/tasks-handler.d.ts +9 -0
  74. package/dist/rest/handlers/tasks-handler.js +38 -0
  75. package/dist/rest/handlers/tasks-handler.js.map +1 -0
  76. package/dist/rest/handlers/trends-handler.d.ts +4 -43
  77. package/dist/rest/handlers/trends-handler.js +11 -18
  78. package/dist/rest/handlers/trends-handler.js.map +1 -1
  79. package/dist/widgets/117.js +24 -1
  80. package/dist/widgets/{919.js → 215.js} +1 -1
  81. package/dist/widgets/370.js +1 -1
  82. package/dist/widgets/{805.js → 46.js} +92 -92
  83. package/dist/widgets/50.js +1 -1
  84. package/dist/widgets/62.js +96 -0
  85. package/dist/widgets/648.js +1 -0
  86. package/dist/widgets/669.js +1 -1
  87. package/dist/widgets/775.js +1 -1
  88. package/dist/widgets/78.js +1 -0
  89. package/dist/widgets/823.js +1 -0
  90. package/dist/widgets/968.js +2 -2
  91. package/dist/widgets/__federation_expose_QADashboard.js +1 -1
  92. package/dist/widgets/mf-manifest.json +32 -31
  93. package/dist/widgets/mf-stats.json +32 -31
  94. package/dist/widgets/remoteEntry.js +2 -2
  95. package/package.json +11 -8
  96. package/dist/cli/commands/qa-save.d.ts +0 -10
  97. package/dist/cli/commands/qa-save.js +0 -69
  98. package/dist/cli/commands/qa-save.js.map +0 -1
  99. package/dist/rest/handlers/details-handler.d.ts +0 -61
  100. package/dist/rest/handlers/details-handler.js +0 -70
  101. package/dist/rest/handlers/details-handler.js.map +0 -1
  102. package/dist/rest/handlers/error-groups-handler.js +0 -17
  103. package/dist/rest/handlers/error-groups-handler.js.map +0 -1
  104. package/dist/rest/handlers/latest-handler.d.ts +0 -22
  105. package/dist/rest/handlers/latest-handler.js +0 -17
  106. package/dist/rest/handlers/latest-handler.js.map +0 -1
  107. package/dist/rest/handlers/run-check-handler.d.ts +0 -20
  108. package/dist/rest/handlers/run-check-handler.js +0 -58
  109. package/dist/rest/handlers/run-check-handler.js.map +0 -1
  110. package/dist/widgets/418.js +0 -38
  111. package/dist/widgets/451.js +0 -1
  112. package/dist/widgets/694.js +0 -1
@@ -1,9 +1,14 @@
1
1
  import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
2
- import { QARegressionsFlags } from './flags.js';
2
+ import { CLIInput } from '@kb-labs/sdk';
3
3
 
4
- type QARegressionsInput = QARegressionsFlags & {
5
- argv?: string[];
6
- };
7
- declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, QARegressionsInput, unknown>;
4
+ declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, CLIInput<_kb_labs_shared_command_kit.InferFlags<{
5
+ json: {
6
+ type: "boolean";
7
+ description: string;
8
+ default: false;
9
+ };
10
+ }>>, {
11
+ exitCode: number;
12
+ }>;
8
13
 
9
14
  export { _default as default };
@@ -1,29 +1,26 @@
1
- import { defineCommand } from '@kb-labs/sdk';
2
- import { loadHistory, detectRegressions, buildRegressionsReport } from '@kb-labs/qa-core';
1
+ import { defineCommand, useConfig } from '@kb-labs/sdk';
2
+ import { SnapshotStore, detectRegressions, buildRegressionsReport } from '@kb-labs/qa-core';
3
3
 
4
4
  // src/cli/commands/qa-regressions.ts
5
5
  var qa_regressions_default = defineCommand({
6
6
  id: "qa:regressions",
7
- description: "Detect regressions since last QA save",
7
+ description: "Detect regressions since last run",
8
8
  handler: {
9
9
  async execute(ctx, input) {
10
- const { ui } = ctx;
11
- const flags = "flags" in input && typeof input.flags === "object" && input.flags !== null ? input.flags : input;
12
- const rootDir = ctx.cwd;
13
- const history = loadHistory(rootDir);
14
- const result = detectRegressions(history);
10
+ const { flags } = input;
11
+ const config = await useConfig();
12
+ const cwd = ctx.cwd ?? process.cwd();
13
+ const store = new SnapshotStore(cwd, config?.historyMaxEntries);
14
+ const history = store.loadRunHistory();
15
+ const detection = detectRegressions(history);
15
16
  if (flags.json) {
16
- ui?.json?.(result);
17
- return { exitCode: result.hasRegressions ? 1 : 0 };
17
+ ctx.ui?.json?.(detection);
18
+ } else {
19
+ for (const section of buildRegressionsReport(detection)) {
20
+ ctx.ui?.success?.(`${section.header}`, { sections: [{ items: section.lines }] });
21
+ }
18
22
  }
19
- const sections = buildRegressionsReport(result, history);
20
- for (const section of sections) {
21
- ui?.success?.(section.header, {
22
- title: section.header,
23
- sections: [{ header: "", items: section.lines }]
24
- });
25
- }
26
- return { exitCode: result.hasRegressions ? 1 : 0 };
23
+ return { exitCode: detection.hasRegressions ? 1 : 0 };
27
24
  }
28
25
  }
29
26
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/qa-regressions.ts"],"names":[],"mappings":";;;;AAMA,IAAO,yBAAQ,aAAA,CAAc;AAAA,EAC3B,EAAA,EAAI,gBAAA;AAAA,EACJ,WAAA,EAAa,uCAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAA2B;AAC7D,MAAA,MAAM,EAAE,IAAG,GAAI,GAAA;AACf,MAAA,MAAM,KAAA,GAAS,OAAA,IAAW,KAAA,IAAS,OAAQ,KAAA,CAA8B,KAAA,KAAU,QAAA,IAAa,KAAA,CAA8B,KAAA,KAAU,IAAA,GACnI,KAAA,CAAwC,KAAA,GACzC,KAAA;AACJ,MAAA,MAAM,UAAU,GAAA,CAAI,GAAA;AAEpB,MAAA,MAAM,OAAA,GAAU,YAAY,OAAO,CAAA;AACnC,MAAA,MAAM,MAAA,GAAS,kBAAkB,OAAO,CAAA;AAExC,MAAA,IAAI,MAAM,IAAA,EAAM;AACd,QAAA,EAAA,EAAI,OAAO,MAAM,CAAA;AACjB,QAAA,OAAO,EAAE,QAAA,EAAU,MAAA,CAAO,cAAA,GAAiB,IAAI,CAAA,EAAE;AAAA,MACnD;AAEA,MAAA,MAAM,QAAA,GAAW,sBAAA,CAAuB,MAAA,EAAQ,OAAO,CAAA;AACvD,MAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,QAAA,EAAA,EAAI,OAAA,GAAU,QAAQ,MAAA,EAAQ;AAAA,UAC5B,OAAO,OAAA,CAAQ,MAAA;AAAA,UACf,QAAA,EAAU,CAAC,EAAE,MAAA,EAAQ,IAAI,KAAA,EAAO,OAAA,CAAQ,OAAO;AAAA,SAChD,CAAA;AAAA,MACH;AAEA,MAAA,OAAO,EAAE,QAAA,EAAU,MAAA,CAAO,cAAA,GAAiB,IAAI,CAAA,EAAE;AAAA,IACnD;AAAA;AAEJ,CAAC","file":"qa-regressions.js","sourcesContent":["import { defineCommand, type PluginContextV3 } from '@kb-labs/sdk';\nimport { loadHistory, detectRegressions, buildRegressionsReport } from '@kb-labs/qa-core';\nimport type { QARegressionsFlags } from './flags.js';\n\ntype QARegressionsInput = QARegressionsFlags & { argv?: string[] };\n\nexport default defineCommand({\n id: 'qa:regressions',\n description: 'Detect regressions since last QA save',\n\n handler: {\n async execute(ctx: PluginContextV3, input: QARegressionsInput) {\n const { ui } = ctx;\n const flags = ('flags' in input && typeof (input as { flags?: unknown }).flags === 'object' && (input as { flags?: unknown }).flags !== null)\n ? (input as { flags: QARegressionsInput }).flags\n : input;\n const rootDir = ctx.cwd;\n\n const history = loadHistory(rootDir);\n const result = detectRegressions(history);\n\n if (flags.json) {\n ui?.json?.(result);\n return { exitCode: result.hasRegressions ? 1 : 0 };\n }\n\n const sections = buildRegressionsReport(result, history);\n for (const section of sections) {\n ui?.success?.(section.header, {\n title: section.header,\n sections: [{ header: '', items: section.lines }],\n });\n }\n\n return { exitCode: result.hasRegressions ? 1 : 0 };\n },\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../src/cli/commands/qa-regressions.ts"],"names":[],"mappings":";;;;AAcA,IAAO,yBAAQ,aAAA,CAA2E;AAAA,EACxF,EAAA,EAAI,gBAAA;AAAA,EACJ,WAAA,EAAa,mCAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAAoE;AACtG,MAAA,MAAM,EAAE,OAAM,GAAI,KAAA;AAClB,MAAA,MAAM,MAAA,GAAS,MAAM,SAAA,EAA0B;AAC/C,MAAA,MAAM,GAAA,GAAM,GAAA,CAAI,GAAA,IAAO,OAAA,CAAQ,GAAA,EAAI;AAEnC,MAAA,MAAM,KAAA,GAAQ,IAAI,aAAA,CAAc,GAAA,EAAK,QAAQ,iBAAiB,CAAA;AAC9D,MAAA,MAAM,OAAA,GAAU,MAAM,cAAA,EAAe;AACrC,MAAA,MAAM,SAAA,GAAY,kBAAkB,OAAO,CAAA;AAE3C,MAAA,IAAI,MAAM,IAAA,EAAM;AACd,QAAA,GAAA,CAAI,EAAA,EAAI,OAAO,SAAS,CAAA;AAAA,MAC1B,CAAA,MAAO;AACL,QAAA,KAAA,MAAW,OAAA,IAAW,sBAAA,CAAuB,SAAS,CAAA,EAAG;AACvD,UAAA,GAAA,CAAI,EAAA,EAAI,OAAA,GAAU,CAAA,EAAG,OAAA,CAAQ,MAAM,CAAA,CAAA,EAAI,EAAE,QAAA,EAAU,CAAC,EAAE,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA;AAAA,QACjF;AAAA,MACF;AAEA,MAAA,OAAO,EAAE,QAAA,EAAU,SAAA,CAAU,cAAA,GAAiB,IAAI,CAAA,EAAE;AAAA,IACtD;AAAA;AAEJ,CAAC","file":"qa-regressions.js","sourcesContent":["import {\n defineCommand,\n useConfig,\n type CLIInput,\n type PluginContextV3,\n} from '@kb-labs/sdk';\nimport {\n SnapshotStore,\n detectRegressions,\n buildRegressionsReport,\n} from '@kb-labs/qa-core';\nimport { type QAPluginConfig } from '@kb-labs/qa-contracts';\nimport type { QaRegressionsFlags } from './flags.js';\n\nexport default defineCommand<unknown, CLIInput<QaRegressionsFlags>, { exitCode: number }>({\n id: 'qa:regressions',\n description: 'Detect regressions since last run',\n\n handler: {\n async execute(ctx: PluginContextV3, input: CLIInput<QaRegressionsFlags>): Promise<{ exitCode: number }> {\n const { flags } = input;\n const config = await useConfig<QAPluginConfig>();\n const cwd = ctx.cwd ?? process.cwd();\n\n const store = new SnapshotStore(cwd, config?.historyMaxEntries);\n const history = store.loadRunHistory();\n const detection = detectRegressions(history);\n\n if (flags.json) {\n ctx.ui?.json?.(detection);\n } else {\n for (const section of buildRegressionsReport(detection)) {\n ctx.ui?.success?.(`${section.header}`, { sections: [{ items: section.lines }] });\n }\n }\n\n return { exitCode: detection.hasRegressions ? 1 : 0 };\n },\n },\n});\n"]}
@@ -1,16 +1,23 @@
1
1
  import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
2
2
  import { CLIInput } from '@kb-labs/sdk';
3
3
 
4
- interface QARunFlags {
5
- json?: boolean;
6
- 'skip-check'?: string | string[];
7
- 'no-cache'?: boolean;
8
- all?: boolean;
9
- package?: string;
10
- repo?: string;
11
- scope?: string;
12
- summary?: boolean;
13
- }
14
- declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, CLIInput<QARunFlags>, unknown>;
4
+ declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, CLIInput<_kb_labs_shared_command_kit.InferFlags<{
5
+ tasks: {
6
+ type: "string";
7
+ description: string;
8
+ };
9
+ save: {
10
+ type: "boolean";
11
+ description: string;
12
+ default: true;
13
+ };
14
+ json: {
15
+ type: "boolean";
16
+ description: string;
17
+ default: false;
18
+ };
19
+ }>>, {
20
+ exitCode: number;
21
+ }>;
15
22
 
16
23
  export { _default as default };
@@ -1,155 +1,42 @@
1
1
  import { defineCommand, useConfig } from '@kb-labs/sdk';
2
- import { getWorkspacePackages, runQA, loadBaseline, compareWithBaseline, resolveCategories, groupResults, buildDetailedJsonReport, buildRunReport, buildDetailedRunReport } from '@kb-labs/qa-core';
2
+ import { resolveDevkitBin, DevkitAdapter, SnapshotStore, captureGit, buildRunJsonReport, buildRunReport } from '@kb-labs/qa-core';
3
+ import { DEFAULT_TASKS } from '@kb-labs/qa-contracts';
3
4
 
4
5
  // src/cli/commands/qa-run.ts
5
- var CHECK_ICONS = {
6
- build: "\u{1F528}",
7
- lint: "\u{1F50D}",
8
- typeCheck: "\u{1F4D8}",
9
- test: "\u{1F9EA}"
10
- };
11
- var STATUS_MARKS = {
12
- pass: "\u2713",
13
- fail: "\u2717",
14
- skip: "\u2212"
15
- };
16
6
  var qa_run_default = defineCommand({
17
7
  id: "qa:run",
18
- description: "Run all QA checks (build, lint, types, tests)",
8
+ description: "Run devkit tasks and record results",
19
9
  handler: {
20
10
  async execute(ctx, input) {
21
- const { ui } = ctx;
22
11
  const { flags } = input;
23
- const rootDir = ctx.cwd;
24
- let config;
25
- try {
26
- config = await Promise.race([
27
- useConfig(),
28
- new Promise((resolve) => {
29
- setTimeout(() => resolve(void 0), 3e3);
30
- })
31
- ]);
32
- } catch {
33
- }
34
- const scopeKey = flags.scope;
35
- const checks = (scopeKey ? config?.scopes?.[scopeKey]?.checks : void 0) ?? config?.checks;
36
- const rawSkip = flags["skip-check"];
37
- const skipChecks = Array.isArray(rawSkip) ? rawSkip : rawSkip ? [rawSkip] : [];
38
- const isJson = !!flags.json;
39
- let totalPkgs = 0;
40
- if (!isJson) {
41
- try {
42
- const pkgs = getWorkspacePackages(rootDir, {
43
- package: flags.package,
44
- repo: flags.repo,
45
- scope: scopeKey
46
- }, config?.packages);
47
- totalPkgs = pkgs.length;
48
- } catch {
49
- }
50
- }
51
- const counters = {};
52
- let currentPhase = "";
53
- const startTime = Date.now();
54
- const { results, packages } = await runQA({
55
- rootDir,
56
- skipChecks,
57
- noCache: !!flags["no-cache"],
58
- package: flags.package,
59
- repo: flags.repo,
60
- scope: scopeKey,
61
- packagesConfig: config?.packages,
62
- checks,
63
- onProgress: (phase, pkg, status, durationMs2) => {
64
- if (isJson) {
65
- return;
66
- }
67
- if (phase !== currentPhase) {
68
- currentPhase = phase;
69
- counters[phase] = 0;
70
- const phaseIcon = CHECK_ICONS[phase] ?? "\u25B8";
71
- const elapsed = ((Date.now() - startTime) / 1e3).toFixed(0);
72
- process.stdout.write(`
73
- ${phaseIcon} ${phase} (${elapsed}s elapsed)
74
- `);
75
- }
76
- counters[phase] = (counters[phase] ?? 0) + 1;
77
- const count = counters[phase];
78
- const total = totalPkgs || "?";
79
- const mark = STATUS_MARKS[status] ?? status;
80
- const time = durationMs2 != null ? ` (${(durationMs2 / 1e3).toFixed(1)}s)` : "";
81
- process.stdout.write(` [${count}/${total}] ${pkg} ${mark}${time}
82
- `);
83
- }
84
- });
85
- const durationMs = Date.now() - startTime;
86
- if (!isJson) {
87
- const elapsed = (durationMs / 1e3).toFixed(1);
88
- process.stdout.write(`
89
- Completed in ${elapsed}s
90
-
91
- `);
92
- }
93
- const analytics = ctx.platform.analytics;
94
- if (analytics) {
95
- const hasFails2 = Object.values(results).some((r) => r.failed.length > 0);
96
- for (const ct of Object.keys(results)) {
97
- const r = results[ct];
98
- await analytics.track("qa.check.completed", {
99
- checkType: ct,
100
- status: r.failed.length > 0 ? "failed" : "passed",
101
- passed: r.passed.length,
102
- failed: r.failed.length,
103
- skipped: r.skipped.length
104
- });
105
- }
106
- const checkKeys = Object.keys(results);
107
- await analytics.track("qa.run.completed", {
108
- status: hasFails2 ? "failed" : "passed",
109
- ...Object.fromEntries(checkKeys.flatMap((ct) => [
110
- [`${ct}Passed`, results[ct].passed.length],
111
- [`${ct}Failed`, results[ct].failed.length]
112
- ])),
113
- totalPassed: checkKeys.reduce((s, ct) => s + results[ct].passed.length, 0),
114
- totalFailed: checkKeys.reduce((s, ct) => s + results[ct].failed.length, 0),
115
- totalSkipped: checkKeys.reduce((s, ct) => s + results[ct].skipped.length, 0),
116
- durationMs
117
- });
118
- }
119
- const baseline = loadBaseline(rootDir);
120
- const diff = baseline ? compareWithBaseline(results, baseline) : null;
121
- const categoryMap = resolveCategories(packages, config);
122
- const grouped = groupResults(results, packages, categoryMap, config);
123
- if (isJson) {
124
- const report = buildDetailedJsonReport(results, grouped, diff);
125
- ui?.json?.({ ...report, skippedChecks: skipChecks });
126
- return { exitCode: report.status === "failed" ? 1 : 0 };
127
- }
128
- if (skipChecks.length > 0) {
129
- ui?.success?.("Skipped checks", {
130
- title: "Skipped checks",
131
- sections: [{ header: "", items: skipChecks.map((c) => ` - ${c}`) }]
132
- });
133
- }
134
- if (flags.summary) {
135
- const sections = buildRunReport(results, diff);
136
- for (const section of sections) {
137
- ui?.success?.(section.header, {
138
- title: section.header,
139
- sections: [{ header: "", items: section.lines }]
140
- });
141
- }
12
+ const config = await useConfig();
13
+ const cwd = ctx.cwd ?? process.cwd();
14
+ const binaryPath = resolveDevkitBin(cwd, config?.devkitPath);
15
+ const adapter = new DevkitAdapter({ binaryPath, cwd, shell: ctx.api.shell });
16
+ const store = new SnapshotStore(cwd, config?.historyMaxEntries);
17
+ const tasks = flags.tasks ? flags.tasks.split(",").map((s) => s.trim()).filter(Boolean) : config?.defaultTasks?.slice() ?? [...DEFAULT_TASKS];
18
+ const save = flags.save !== false;
19
+ const git = await captureGit(ctx.api.shell, cwd);
20
+ const start = Date.now();
21
+ const raw = await adapter.run(tasks);
22
+ const durationMs = Date.now() - start;
23
+ const snap = save ? store.saveRun(raw, tasks, durationMs, git) : null;
24
+ const effective = snap ?? {
25
+ kind: "run",
26
+ id: "",
27
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
28
+ durationMs,
29
+ tasks,
30
+ raw
31
+ };
32
+ if (flags.json) {
33
+ ctx.ui?.json?.(buildRunJsonReport(effective));
142
34
  } else {
143
- const sections = buildDetailedRunReport(grouped, diff);
144
- for (const section of sections) {
145
- ui?.success?.(section.header, {
146
- title: section.header,
147
- sections: [{ header: "", items: section.lines }]
148
- });
35
+ for (const section of buildRunReport(effective)) {
36
+ ctx.ui?.success?.(`${section.header}`, { sections: [{ items: section.lines }] });
149
37
  }
150
38
  }
151
- const hasFails = Object.values(results).some((r) => r.failed.length > 0);
152
- return { exitCode: hasFails ? 1 : 0 };
39
+ return { exitCode: raw.ok ? 0 : 1 };
153
40
  }
154
41
  }
155
42
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/qa-run.ts"],"names":["durationMs","hasFails"],"mappings":"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","file":"qa-run.js","sourcesContent":["import { defineCommand, type CLIInput, useConfig, type PluginContextV3 } from '@kb-labs/sdk';\nimport type { QAPluginConfig } from '@kb-labs/qa-contracts';\nimport {\n runQA,\n getWorkspacePackages,\n compareWithBaseline,\n loadBaseline,\n buildDetailedJsonReport,\n buildRunReport,\n buildDetailedRunReport,\n resolveCategories,\n groupResults,\n} from '@kb-labs/qa-core';\n\ninterface QARunFlags {\n json?: boolean;\n 'skip-check'?: string | string[];\n 'no-cache'?: boolean;\n all?: boolean;\n package?: string;\n repo?: string;\n scope?: string;\n summary?: boolean;\n}\n\nconst CHECK_ICONS: Record<string, string> = {\n build: '🔨',\n lint: '🔍',\n typeCheck: '📘',\n test: '🧪',\n};\n\nconst STATUS_MARKS: Record<string, string> = {\n pass: '✓',\n fail: '✗',\n skip: '−',\n};\n\nexport default defineCommand({\n id: 'qa:run',\n description: 'Run all QA checks (build, lint, types, tests)',\n\n handler: {\n async execute(ctx: PluginContextV3, input: CLIInput<QARunFlags>) {\n const { ui } = ctx;\n const { flags } = input;\n const rootDir = ctx.cwd;\n\n // Load plugin config — needed for package discovery and checks.\n // useConfig() can hang if platform IPC is unavailable, so race with a timeout.\n let config: QAPluginConfig | undefined;\n try {\n config = await Promise.race([\n useConfig<QAPluginConfig>(),\n new Promise<undefined>((resolve) => { setTimeout(() => resolve(undefined), 3000); }),\n ]);\n } catch {\n // Config not available (no platform context) — proceed without config\n }\n\n // Select checks: per-scope override → global checks → built-in runners\n const scopeKey = flags.scope as string | undefined;\n const checks = (scopeKey ? config?.scopes?.[scopeKey]?.checks : undefined)\n ?? config?.checks;\n\n const rawSkip = flags['skip-check'];\n const skipChecks: string[] = Array.isArray(rawSkip)\n ? rawSkip as string[]\n : rawSkip ? [rawSkip as string] : [];\n\n const isJson = !!flags.json;\n\n // Pre-discover packages to get total count for progress display\n let totalPkgs = 0;\n if (!isJson) {\n try {\n const pkgs = getWorkspacePackages(rootDir, {\n package: flags.package as string | undefined,\n repo: flags.repo as string | undefined,\n scope: scopeKey,\n }, config?.packages);\n totalPkgs = pkgs.length;\n } catch {\n // Will be discovered again inside runQA\n }\n }\n\n // Progress tracking for live UI\n const counters: Record<string, number> = {};\n let currentPhase = '';\n\n const startTime = Date.now();\n const { results, packages } = await runQA({\n rootDir,\n skipChecks,\n noCache: !!flags['no-cache'],\n package: flags.package as string | undefined,\n repo: flags.repo as string | undefined,\n scope: scopeKey,\n packagesConfig: config?.packages,\n checks,\n onProgress: (phase, pkg, status, durationMs) => {\n if (isJson) {return;}\n\n // Print phase header on phase change\n if (phase !== currentPhase) {\n currentPhase = phase;\n counters[phase] = 0;\n const phaseIcon = CHECK_ICONS[phase] ?? '▸';\n const elapsed = ((Date.now() - startTime) / 1000).toFixed(0);\n process.stdout.write(`\\n${phaseIcon} ${phase} (${elapsed}s elapsed)\\n`);\n }\n\n counters[phase] = (counters[phase] ?? 0) + 1;\n const count = counters[phase];\n const total = totalPkgs || '?';\n const mark = STATUS_MARKS[status] ?? status;\n const time = durationMs != null ? ` (${(durationMs / 1000).toFixed(1)}s)` : '';\n\n process.stdout.write(` [${count}/${total}] ${pkg} ${mark}${time}\\n`);\n },\n });\n const durationMs = Date.now() - startTime;\n\n if (!isJson) {\n const elapsed = (durationMs / 1000).toFixed(1);\n process.stdout.write(`\\nCompleted in ${elapsed}s\\n\\n`);\n }\n\n // Track analytics events\n const analytics = ctx.platform.analytics;\n if (analytics) {\n const hasFails = Object.values(results).some((r) => r.failed.length > 0);\n for (const ct of Object.keys(results)) {\n const r = results[ct]!;\n await analytics.track('qa.check.completed', {\n checkType: ct,\n status: r.failed.length > 0 ? 'failed' : 'passed',\n passed: r.passed.length,\n failed: r.failed.length,\n skipped: r.skipped.length,\n });\n }\n const checkKeys = Object.keys(results);\n await analytics.track('qa.run.completed', {\n status: hasFails ? 'failed' : 'passed',\n ...Object.fromEntries(checkKeys.flatMap((ct) => [\n [`${ct}Passed`, results[ct]!.passed.length],\n [`${ct}Failed`, results[ct]!.failed.length],\n ])),\n totalPassed: checkKeys.reduce((s, ct) => s + results[ct]!.passed.length, 0),\n totalFailed: checkKeys.reduce((s, ct) => s + results[ct]!.failed.length, 0),\n totalSkipped: checkKeys.reduce((s, ct) => s + results[ct]!.skipped.length, 0),\n durationMs,\n });\n }\n\n // Compare with baseline if available\n const baseline = loadBaseline(rootDir);\n const diff = baseline ? compareWithBaseline(results, baseline) : null;\n\n const categoryMap = resolveCategories(packages, config);\n const grouped = groupResults(results, packages, categoryMap, config);\n\n if (isJson) {\n const report = buildDetailedJsonReport(results, grouped, diff);\n ui?.json?.({ ...report, skippedChecks: skipChecks });\n return { exitCode: report.status === 'failed' ? 1 : 0 };\n }\n\n // Show skipped checks section for easier debugging\n if (skipChecks.length > 0) {\n ui?.success?.('Skipped checks', {\n title: 'Skipped checks',\n sections: [{ header: '', items: skipChecks.map(c => ` - ${c}`) }],\n });\n }\n\n if (flags.summary) {\n // Legacy summary format\n const sections = buildRunReport(results, diff);\n for (const section of sections) {\n ui?.success?.(section.header, {\n title: section.header,\n sections: [{ header: '', items: section.lines }],\n });\n }\n } else {\n // Detailed report grouped by category → repo\n const sections = buildDetailedRunReport(grouped, diff);\n for (const section of sections) {\n ui?.success?.(section.header, {\n title: section.header,\n sections: [{ header: '', items: section.lines }],\n });\n }\n }\n\n const hasFails = Object.values(results).some((r) => r.failed.length > 0);\n return { exitCode: hasFails ? 1 : 0 };\n },\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../src/cli/commands/qa-run.ts"],"names":[],"mappings":";;;;;AAiBA,IAAO,iBAAQ,aAAA,CAAmE;AAAA,EAChF,EAAA,EAAI,QAAA;AAAA,EACJ,WAAA,EAAa,qCAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAA4D;AAC9F,MAAA,MAAM,EAAE,OAAM,GAAI,KAAA;AAClB,MAAA,MAAM,MAAA,GAAS,MAAM,SAAA,EAA0B;AAC/C,MAAA,MAAM,GAAA,GAAM,GAAA,CAAI,GAAA,IAAO,OAAA,CAAQ,GAAA,EAAI;AAEnC,MAAA,MAAM,UAAA,GAAa,gBAAA,CAAiB,GAAA,EAAK,MAAA,EAAQ,UAAU,CAAA;AAC3D,MAAA,MAAM,OAAA,GAAU,IAAI,aAAA,CAAc,EAAE,UAAA,EAAY,KAAK,KAAA,EAAO,GAAA,CAAI,GAAA,CAAI,KAAA,EAAO,CAAA;AAC3E,MAAA,MAAM,KAAA,GAAQ,IAAI,aAAA,CAAc,GAAA,EAAK,QAAQ,iBAAiB,CAAA;AAE9D,MAAA,MAAM,KAAA,GAAkB,MAAM,KAAA,GAC1B,KAAA,CAAM,MAAM,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,MAAM,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,GACxD,MAAA,EAAQ,cAAc,KAAA,EAAM,IAAK,CAAC,GAAG,aAAa,CAAA;AACtD,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,KAAS,KAAA;AAE5B,MAAA,MAAM,MAAM,MAAM,UAAA,CAAW,GAAA,CAAI,GAAA,CAAI,OAAO,GAAG,CAAA;AAE/C,MAAA,MAAM,KAAA,GAAQ,KAAK,GAAA,EAAI;AACvB,MAAA,MAAM,GAAA,GAAM,MAAM,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA;AACnC,MAAA,MAAM,UAAA,GAAa,IAAA,CAAK,GAAA,EAAI,GAAI,KAAA;AAEhC,MAAA,MAAM,IAAA,GAAO,OAAO,KAAA,CAAM,OAAA,CAAQ,KAAK,KAAA,EAAO,UAAA,EAAY,GAAG,CAAA,GAAI,IAAA;AACjE,MAAA,MAAM,YAAyD,IAAA,IAAQ;AAAA,QACrE,IAAA,EAAM,KAAA;AAAA,QAAO,EAAA,EAAI,EAAA;AAAA,QAAI,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,QAAG,UAAA;AAAA,QAAY,KAAA;AAAA,QAAO;AAAA,OAC/E;AAEA,MAAA,IAAI,MAAM,IAAA,EAAM;AACd,QAAA,GAAA,CAAI,EAAA,EAAI,IAAA,GAAO,kBAAA,CAAmB,SAAS,CAAC,CAAA;AAAA,MAC9C,CAAA,MAAO;AACL,QAAA,KAAA,MAAW,OAAA,IAAW,cAAA,CAAe,SAAS,CAAA,EAAG;AAC/C,UAAA,GAAA,CAAI,EAAA,EAAI,OAAA,GAAU,CAAA,EAAG,OAAA,CAAQ,MAAM,CAAA,CAAA,EAAI,EAAE,QAAA,EAAU,CAAC,EAAE,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA;AAAA,QACjF;AAAA,MACF;AAEA,MAAA,OAAO,EAAE,QAAA,EAAU,GAAA,CAAI,EAAA,GAAK,IAAI,CAAA,EAAE;AAAA,IACpC;AAAA;AAEJ,CAAC","file":"qa-run.js","sourcesContent":["import {\n defineCommand,\n useConfig,\n type CLIInput,\n type PluginContextV3,\n} from '@kb-labs/sdk';\nimport {\n DevkitAdapter,\n SnapshotStore,\n resolveDevkitBin,\n captureGit,\n buildRunReport,\n buildRunJsonReport,\n} from '@kb-labs/qa-core';\nimport { DEFAULT_TASKS, type QAPluginConfig } from '@kb-labs/qa-contracts';\nimport type { QaRunFlags } from './flags.js';\n\nexport default defineCommand<unknown, CLIInput<QaRunFlags>, { exitCode: number }>({\n id: 'qa:run',\n description: 'Run devkit tasks and record results',\n\n handler: {\n async execute(ctx: PluginContextV3, input: CLIInput<QaRunFlags>): Promise<{ exitCode: number }> {\n const { flags } = input;\n const config = await useConfig<QAPluginConfig>();\n const cwd = ctx.cwd ?? process.cwd();\n\n const binaryPath = resolveDevkitBin(cwd, config?.devkitPath);\n const adapter = new DevkitAdapter({ binaryPath, cwd, shell: ctx.api.shell });\n const store = new SnapshotStore(cwd, config?.historyMaxEntries);\n\n const tasks: string[] = flags.tasks\n ? flags.tasks.split(',').map(s => s.trim()).filter(Boolean)\n : config?.defaultTasks?.slice() ?? [...DEFAULT_TASKS];\n const save = flags.save !== false;\n\n const git = await captureGit(ctx.api.shell, cwd);\n\n const start = Date.now();\n const raw = await adapter.run(tasks);\n const durationMs = Date.now() - start;\n\n const snap = save ? store.saveRun(raw, tasks, durationMs, git) : null;\n const effective: import('@kb-labs/qa-contracts').RunSnapshot = snap ?? {\n kind: 'run', id: '', timestamp: new Date().toISOString(), durationMs, tasks, raw,\n };\n\n if (flags.json) {\n ctx.ui?.json?.(buildRunJsonReport(effective));\n } else {\n for (const section of buildRunReport(effective)) {\n ctx.ui?.success?.(`${section.header}`, { sections: [{ items: section.lines }] });\n }\n }\n\n return { exitCode: raw.ok ? 0 : 1 };\n },\n },\n});\n"]}
@@ -0,0 +1,19 @@
1
+ import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
2
+ import { CLIInput } from '@kb-labs/sdk';
3
+
4
+ declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, CLIInput<_kb_labs_shared_command_kit.InferFlags<{
5
+ save: {
6
+ type: "boolean";
7
+ description: string;
8
+ default: true;
9
+ };
10
+ json: {
11
+ type: "boolean";
12
+ description: string;
13
+ default: false;
14
+ };
15
+ }>>, {
16
+ exitCode: number;
17
+ }>;
18
+
19
+ export { _default as default };
@@ -0,0 +1,43 @@
1
+ import { defineCommand, useConfig } from '@kb-labs/sdk';
2
+ import { resolveDevkitBin, DevkitAdapter, SnapshotStore, captureGit, buildStatsJsonReport, buildStatsReport } from '@kb-labs/qa-core';
3
+
4
+ // src/cli/commands/qa-stats.ts
5
+ var qa_stats_default = defineCommand({
6
+ id: "qa:stats",
7
+ description: "Show devkit health score and category breakdown",
8
+ handler: {
9
+ async execute(ctx, input) {
10
+ const { flags } = input;
11
+ const config = await useConfig();
12
+ const cwd = ctx.cwd ?? process.cwd();
13
+ const binaryPath = resolveDevkitBin(cwd, config?.devkitPath);
14
+ const adapter = new DevkitAdapter({ binaryPath, cwd, shell: ctx.api.shell });
15
+ const store = new SnapshotStore(cwd, config?.historyMaxEntries);
16
+ const save = flags.save !== false;
17
+ const git = await captureGit(ctx.api.shell, cwd);
18
+ const start = Date.now();
19
+ const raw = await adapter.stats();
20
+ const durationMs = Date.now() - start;
21
+ const snap = save ? store.saveStats(raw, durationMs, git) : null;
22
+ const effective = snap ?? {
23
+ kind: "stats",
24
+ id: "",
25
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
26
+ durationMs,
27
+ raw
28
+ };
29
+ if (flags.json) {
30
+ ctx.ui?.json?.(buildStatsJsonReport(effective));
31
+ } else {
32
+ for (const section of buildStatsReport(effective)) {
33
+ ctx.ui?.success?.(`${section.header}`, { sections: [{ items: section.lines }] });
34
+ }
35
+ }
36
+ return { exitCode: 0 };
37
+ }
38
+ }
39
+ });
40
+
41
+ export { qa_stats_default as default };
42
+ //# sourceMappingURL=qa-stats.js.map
43
+ //# sourceMappingURL=qa-stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/cli/commands/qa-stats.ts"],"names":[],"mappings":";;;;AAiBA,IAAO,mBAAQ,aAAA,CAAqE;AAAA,EAClF,EAAA,EAAI,UAAA;AAAA,EACJ,WAAA,EAAa,iDAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAA8D;AAChG,MAAA,MAAM,EAAE,OAAM,GAAI,KAAA;AAClB,MAAA,MAAM,MAAA,GAAS,MAAM,SAAA,EAA0B;AAC/C,MAAA,MAAM,GAAA,GAAM,GAAA,CAAI,GAAA,IAAO,OAAA,CAAQ,GAAA,EAAI;AAEnC,MAAA,MAAM,UAAA,GAAa,gBAAA,CAAiB,GAAA,EAAK,MAAA,EAAQ,UAAU,CAAA;AAC3D,MAAA,MAAM,OAAA,GAAU,IAAI,aAAA,CAAc,EAAE,UAAA,EAAY,KAAK,KAAA,EAAO,GAAA,CAAI,GAAA,CAAI,KAAA,EAAO,CAAA;AAC3E,MAAA,MAAM,KAAA,GAAQ,IAAI,aAAA,CAAc,GAAA,EAAK,QAAQ,iBAAiB,CAAA;AAE9D,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,KAAS,KAAA;AAC5B,MAAA,MAAM,MAAM,MAAM,UAAA,CAAW,GAAA,CAAI,GAAA,CAAI,OAAO,GAAG,CAAA;AAE/C,MAAA,MAAM,KAAA,GAAQ,KAAK,GAAA,EAAI;AACvB,MAAA,MAAM,GAAA,GAAM,MAAM,OAAA,CAAQ,KAAA,EAAM;AAChC,MAAA,MAAM,UAAA,GAAa,IAAA,CAAK,GAAA,EAAI,GAAI,KAAA;AAEhC,MAAA,MAAM,OAAO,IAAA,GAAO,KAAA,CAAM,UAAU,GAAA,EAAK,UAAA,EAAY,GAAG,CAAA,GAAI,IAAA;AAC5D,MAAA,MAAM,YAA2D,IAAA,IAAQ;AAAA,QACvE,IAAA,EAAM,OAAA;AAAA,QAAS,EAAA,EAAI,EAAA;AAAA,QAAI,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,QAAG,UAAA;AAAA,QAAY;AAAA,OAC1E;AAEA,MAAA,IAAI,MAAM,IAAA,EAAM;AACd,QAAA,GAAA,CAAI,EAAA,EAAI,IAAA,GAAO,oBAAA,CAAqB,SAAS,CAAC,CAAA;AAAA,MAChD,CAAA,MAAO;AACL,QAAA,KAAA,MAAW,OAAA,IAAW,gBAAA,CAAiB,SAAS,CAAA,EAAG;AACjD,UAAA,GAAA,CAAI,EAAA,EAAI,OAAA,GAAU,CAAA,EAAG,OAAA,CAAQ,MAAM,CAAA,CAAA,EAAI,EAAE,QAAA,EAAU,CAAC,EAAE,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA;AAAA,QACjF;AAAA,MACF;AAEA,MAAA,OAAO,EAAE,UAAU,CAAA,EAAE;AAAA,IACvB;AAAA;AAEJ,CAAC","file":"qa-stats.js","sourcesContent":["import {\n defineCommand,\n useConfig,\n type CLIInput,\n type PluginContextV3,\n} from '@kb-labs/sdk';\nimport {\n DevkitAdapter,\n SnapshotStore,\n resolveDevkitBin,\n captureGit,\n buildStatsReport,\n buildStatsJsonReport,\n} from '@kb-labs/qa-core';\nimport { type QAPluginConfig } from '@kb-labs/qa-contracts';\nimport type { QaStatsFlags } from './flags.js';\n\nexport default defineCommand<unknown, CLIInput<QaStatsFlags>, { exitCode: number }>({\n id: 'qa:stats',\n description: 'Show devkit health score and category breakdown',\n\n handler: {\n async execute(ctx: PluginContextV3, input: CLIInput<QaStatsFlags>): Promise<{ exitCode: number }> {\n const { flags } = input;\n const config = await useConfig<QAPluginConfig>();\n const cwd = ctx.cwd ?? process.cwd();\n\n const binaryPath = resolveDevkitBin(cwd, config?.devkitPath);\n const adapter = new DevkitAdapter({ binaryPath, cwd, shell: ctx.api.shell });\n const store = new SnapshotStore(cwd, config?.historyMaxEntries);\n\n const save = flags.save !== false;\n const git = await captureGit(ctx.api.shell, cwd);\n\n const start = Date.now();\n const raw = await adapter.stats();\n const durationMs = Date.now() - start;\n\n const snap = save ? store.saveStats(raw, durationMs, git) : null;\n const effective: import('@kb-labs/qa-contracts').StatsSnapshot = snap ?? {\n kind: 'stats', id: '', timestamp: new Date().toISOString(), durationMs, raw,\n };\n\n if (flags.json) {\n ctx.ui?.json?.(buildStatsJsonReport(effective));\n } else {\n for (const section of buildStatsReport(effective)) {\n ctx.ui?.success?.(`${section.header}`, { sections: [{ items: section.lines }] });\n }\n }\n\n return { exitCode: 0 };\n },\n },\n});\n"]}
@@ -1,9 +1,19 @@
1
1
  import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
2
- import { QATrendsFlags } from './flags.js';
2
+ import { CLIInput } from '@kb-labs/sdk';
3
3
 
4
- type QATrendsInput = QATrendsFlags & {
5
- argv?: string[];
6
- };
7
- declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, QATrendsInput, unknown>;
4
+ declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, CLIInput<_kb_labs_shared_command_kit.InferFlags<{
5
+ window: {
6
+ type: "number";
7
+ description: string;
8
+ default: number;
9
+ };
10
+ json: {
11
+ type: "boolean";
12
+ description: string;
13
+ default: false;
14
+ };
15
+ }>>, {
16
+ exitCode: number;
17
+ }>;
8
18
 
9
19
  export { _default as default };
@@ -1,5 +1,6 @@
1
- import { defineCommand } from '@kb-labs/sdk';
2
- import { loadHistory, analyzeTrends, analyzeEnrichedTrends, buildTrendsReport } from '@kb-labs/qa-core';
1
+ import { defineCommand, useConfig } from '@kb-labs/sdk';
2
+ import { SnapshotStore, analyzeTrends, buildTrendsReport } from '@kb-labs/qa-core';
3
+ import { TRENDS_WINDOW } from '@kb-labs/qa-contracts';
3
4
 
4
5
  // src/cli/commands/qa-trends.ts
5
6
  var qa_trends_default = defineCommand({
@@ -7,23 +8,19 @@ var qa_trends_default = defineCommand({
7
8
  description: "Show QA quality trends over time",
8
9
  handler: {
9
10
  async execute(ctx, input) {
10
- const { ui } = ctx;
11
- const flags = "flags" in input && typeof input.flags === "object" && input.flags !== null ? input.flags : input;
12
- const rootDir = ctx.cwd;
13
- const history = loadHistory(rootDir);
14
- const window = typeof flags.window === "number" ? flags.window : 10;
15
- const trends = analyzeTrends(history, window);
11
+ const { flags } = input;
12
+ const config = await useConfig();
13
+ const cwd = ctx.cwd ?? process.cwd();
14
+ const store = new SnapshotStore(cwd, config?.historyMaxEntries);
15
+ const window = flags.window ?? TRENDS_WINDOW;
16
+ const history = store.loadRunHistory();
17
+ const analysis = analyzeTrends(history, window);
16
18
  if (flags.json) {
17
- const enrichedTrends = analyzeEnrichedTrends(history, window);
18
- ui?.json?.({ trends: enrichedTrends, historyCount: history.length, window });
19
- return { exitCode: 0 };
20
- }
21
- const sections = buildTrendsReport(trends, history);
22
- for (const section of sections) {
23
- ui?.success?.(section.header, {
24
- title: section.header,
25
- sections: [{ header: "", items: section.lines }]
26
- });
19
+ ctx.ui?.json?.(analysis);
20
+ } else {
21
+ for (const section of buildTrendsReport(analysis)) {
22
+ ctx.ui?.success?.(`${section.header}`, { sections: [{ items: section.lines }] });
23
+ }
27
24
  }
28
25
  return { exitCode: 0 };
29
26
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/qa-trends.ts"],"names":[],"mappings":";;;;AAMA,IAAO,oBAAQ,aAAA,CAAc;AAAA,EAC3B,EAAA,EAAI,WAAA;AAAA,EACJ,WAAA,EAAa,kCAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAAsB;AACxD,MAAA,MAAM,EAAE,IAAG,GAAI,GAAA;AACf,MAAA,MAAM,KAAA,GAAS,OAAA,IAAW,KAAA,IAAS,OAAQ,KAAA,CAA8B,KAAA,KAAU,QAAA,IAAa,KAAA,CAA8B,KAAA,KAAU,IAAA,GACnI,KAAA,CAAmC,KAAA,GACpC,KAAA;AACJ,MAAA,MAAM,UAAU,GAAA,CAAI,GAAA;AAEpB,MAAA,MAAM,OAAA,GAAU,YAAY,OAAO,CAAA;AACnC,MAAA,MAAM,SAAS,OAAO,KAAA,CAAM,MAAA,KAAW,QAAA,GAAW,MAAM,MAAA,GAAS,EAAA;AACjE,MAAA,MAAM,MAAA,GAAS,aAAA,CAAc,OAAA,EAAS,MAAM,CAAA;AAE5C,MAAA,IAAI,MAAM,IAAA,EAAM;AACd,QAAA,MAAM,cAAA,GAAiB,qBAAA,CAAsB,OAAA,EAAS,MAAM,CAAA;AAC5D,QAAA,EAAA,EAAI,IAAA,GAAO,EAAE,MAAA,EAAQ,cAAA,EAAgB,cAAc,OAAA,CAAQ,MAAA,EAAQ,QAAQ,CAAA;AAC3E,QAAA,OAAO,EAAE,UAAU,CAAA,EAAE;AAAA,MACvB;AAEA,MAAA,MAAM,QAAA,GAAW,iBAAA,CAAkB,MAAA,EAAQ,OAAO,CAAA;AAClD,MAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,QAAA,EAAA,EAAI,OAAA,GAAU,QAAQ,MAAA,EAAQ;AAAA,UAC5B,OAAO,OAAA,CAAQ,MAAA;AAAA,UACf,QAAA,EAAU,CAAC,EAAE,MAAA,EAAQ,IAAI,KAAA,EAAO,OAAA,CAAQ,OAAO;AAAA,SAChD,CAAA;AAAA,MACH;AAEA,MAAA,OAAO,EAAE,UAAU,CAAA,EAAE;AAAA,IACvB;AAAA;AAEJ,CAAC","file":"qa-trends.js","sourcesContent":["import { defineCommand, type PluginContextV3 } from '@kb-labs/sdk';\nimport { loadHistory, analyzeTrends, analyzeEnrichedTrends, buildTrendsReport } from '@kb-labs/qa-core';\nimport type { QATrendsFlags } from './flags.js';\n\ntype QATrendsInput = QATrendsFlags & { argv?: string[] };\n\nexport default defineCommand({\n id: 'qa:trends',\n description: 'Show QA quality trends over time',\n\n handler: {\n async execute(ctx: PluginContextV3, input: QATrendsInput) {\n const { ui } = ctx;\n const flags = ('flags' in input && typeof (input as { flags?: unknown }).flags === 'object' && (input as { flags?: unknown }).flags !== null)\n ? (input as { flags: QATrendsInput }).flags\n : input;\n const rootDir = ctx.cwd;\n\n const history = loadHistory(rootDir);\n const window = typeof flags.window === 'number' ? flags.window : 10;\n const trends = analyzeTrends(history, window);\n\n if (flags.json) {\n const enrichedTrends = analyzeEnrichedTrends(history, window);\n ui?.json?.({ trends: enrichedTrends, historyCount: history.length, window });\n return { exitCode: 0 };\n }\n\n const sections = buildTrendsReport(trends, history);\n for (const section of sections) {\n ui?.success?.(section.header, {\n title: section.header,\n sections: [{ header: '', items: section.lines }],\n });\n }\n\n return { exitCode: 0 };\n },\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../src/cli/commands/qa-trends.ts"],"names":[],"mappings":";;;;;AAcA,IAAO,oBAAQ,aAAA,CAAsE;AAAA,EACnF,EAAA,EAAI,WAAA;AAAA,EACJ,WAAA,EAAa,kCAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAA+D;AACjG,MAAA,MAAM,EAAE,OAAM,GAAI,KAAA;AAClB,MAAA,MAAM,MAAA,GAAS,MAAM,SAAA,EAA0B;AAC/C,MAAA,MAAM,GAAA,GAAM,GAAA,CAAI,GAAA,IAAO,OAAA,CAAQ,GAAA,EAAI;AAEnC,MAAA,MAAM,KAAA,GAAQ,IAAI,aAAA,CAAc,GAAA,EAAK,QAAQ,iBAAiB,CAAA;AAC9D,MAAA,MAAM,MAAA,GAAS,MAAM,MAAA,IAAU,aAAA;AAC/B,MAAA,MAAM,OAAA,GAAU,MAAM,cAAA,EAAe;AACrC,MAAA,MAAM,QAAA,GAAW,aAAA,CAAc,OAAA,EAAS,MAAM,CAAA;AAE9C,MAAA,IAAI,MAAM,IAAA,EAAM;AACd,QAAA,GAAA,CAAI,EAAA,EAAI,OAAO,QAAQ,CAAA;AAAA,MACzB,CAAA,MAAO;AACL,QAAA,KAAA,MAAW,OAAA,IAAW,iBAAA,CAAkB,QAAQ,CAAA,EAAG;AACjD,UAAA,GAAA,CAAI,EAAA,EAAI,OAAA,GAAU,CAAA,EAAG,OAAA,CAAQ,MAAM,CAAA,CAAA,EAAI,EAAE,QAAA,EAAU,CAAC,EAAE,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA;AAAA,QACjF;AAAA,MACF;AAEA,MAAA,OAAO,EAAE,UAAU,CAAA,EAAE;AAAA,IACvB;AAAA;AAEJ,CAAC","file":"qa-trends.js","sourcesContent":["import {\n defineCommand,\n useConfig,\n type CLIInput,\n type PluginContextV3,\n} from '@kb-labs/sdk';\nimport {\n SnapshotStore,\n analyzeTrends,\n buildTrendsReport,\n} from '@kb-labs/qa-core';\nimport { TRENDS_WINDOW, type QAPluginConfig } from '@kb-labs/qa-contracts';\nimport type { QaTrendsFlags } from './flags.js';\n\nexport default defineCommand<unknown, CLIInput<QaTrendsFlags>, { exitCode: number }>({\n id: 'qa:trends',\n description: 'Show QA quality trends over time',\n\n handler: {\n async execute(ctx: PluginContextV3, input: CLIInput<QaTrendsFlags>): Promise<{ exitCode: number }> {\n const { flags } = input;\n const config = await useConfig<QAPluginConfig>();\n const cwd = ctx.cwd ?? process.cwd();\n\n const store = new SnapshotStore(cwd, config?.historyMaxEntries);\n const window = flags.window ?? TRENDS_WINDOW;\n const history = store.loadRunHistory();\n const analysis = analyzeTrends(history, window);\n\n if (flags.json) {\n ctx.ui?.json?.(analysis);\n } else {\n for (const section of buildTrendsReport(analysis)) {\n ctx.ui?.success?.(`${section.header}`, { sections: [{ items: section.lines }] });\n }\n }\n\n return { exitCode: 0 };\n },\n },\n});\n"]}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  export { default as manifest } from './manifest.js';
2
- import '@kb-labs/perm-presets';
2
+ import '@kb-labs/plugin-contracts';