@kb-labs/quality-entry 2.109.0 → 2.110.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 (51) hide show
  1. package/dist/cli/commands/build-order.d.ts +1 -3
  2. package/dist/cli/commands/build-order.js +4 -4
  3. package/dist/cli/commands/build-order.js.map +1 -1
  4. package/dist/cli/commands/check-builds.js +2 -5
  5. package/dist/cli/commands/check-builds.js.map +1 -1
  6. package/dist/cli/commands/check-layers.d.ts +1 -3
  7. package/dist/cli/commands/check-layers.js +3 -3
  8. package/dist/cli/commands/check-layers.js.map +1 -1
  9. package/dist/cli/commands/check-tests.js +2 -6
  10. package/dist/cli/commands/check-tests.js.map +1 -1
  11. package/dist/cli/commands/check-types.js +2 -6
  12. package/dist/cli/commands/check-types.js.map +1 -1
  13. package/dist/cli/commands/context.d.ts +1 -3
  14. package/dist/cli/commands/context.js +5 -5
  15. package/dist/cli/commands/context.js.map +1 -1
  16. package/dist/cli/commands/coupling.d.ts +1 -3
  17. package/dist/cli/commands/coupling.js +2 -2
  18. package/dist/cli/commands/coupling.js.map +1 -1
  19. package/dist/cli/commands/cycles.d.ts +3 -1
  20. package/dist/cli/commands/cycles.js +1 -4
  21. package/dist/cli/commands/cycles.js.map +1 -1
  22. package/dist/cli/commands/dead-code.d.ts +1 -3
  23. package/dist/cli/commands/dead-code.js +4 -4
  24. package/dist/cli/commands/dead-code.js.map +1 -1
  25. package/dist/cli/commands/fix-deps.js +3 -3
  26. package/dist/cli/commands/fix-deps.js.map +1 -1
  27. package/dist/cli/commands/gate.d.ts +1 -3
  28. package/dist/cli/commands/gate.js +3 -3
  29. package/dist/cli/commands/gate.js.map +1 -1
  30. package/dist/cli/commands/health.d.ts +1 -3
  31. package/dist/cli/commands/health.js +2 -2
  32. package/dist/cli/commands/health.js.map +1 -1
  33. package/dist/cli/commands/history.d.ts +1 -3
  34. package/dist/cli/commands/history.js +3 -3
  35. package/dist/cli/commands/history.js.map +1 -1
  36. package/dist/cli/commands/index.d.ts +1 -0
  37. package/dist/cli/commands/index.js +32 -46
  38. package/dist/cli/commands/index.js.map +1 -1
  39. package/dist/cli/commands/snapshot.d.ts +1 -3
  40. package/dist/cli/commands/snapshot.js +1 -1
  41. package/dist/cli/commands/snapshot.js.map +1 -1
  42. package/dist/cli/commands/stats.d.ts +1 -3
  43. package/dist/cli/commands/stats.js +2 -2
  44. package/dist/cli/commands/stats.js.map +1 -1
  45. package/dist/cli/commands/visualize.d.ts +4 -9
  46. package/dist/cli/commands/visualize.js +1 -1
  47. package/dist/cli/commands/visualize.js.map +1 -1
  48. package/dist/widgets/mf-manifest.json +5 -5
  49. package/dist/widgets/mf-stats.json +5 -5
  50. package/dist/widgets/remoteEntry.js +2 -2
  51. package/package.json +4 -4
@@ -81,7 +81,7 @@ var snapshot_default = defineCommand({
81
81
  }]
82
82
  });
83
83
  }
84
- return { exitCode: 0 };
84
+ return { ok: true };
85
85
  }
86
86
  }
87
87
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/snapshot.ts"],"names":[],"mappings":"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","file":"snapshot.js","sourcesContent":["import {\n defineCommand,\n useConfig,\n type CLIInput,\n type PluginContextV3,\n} from '@kb-labs/sdk';\nimport {\n analyzeLayering,\n analyzeCoupling,\n runKnip,\n analyzeTypes,\n QualitySnapshotStore,\n} from '@kb-labs/quality-core';\nimport { calculateHealth } from '@kb-labs/quality-core';\nimport { defaultQualityConfig, type QualityPluginConfig, type KnipReport } from '@kb-labs/quality-contracts';\nimport type { SnapshotFlags } from './flags.js';\nimport type { ShellAPI } from '@kb-labs/sdk';\n\nasync function captureGit(shell: ShellAPI, cwd: string) {\n try {\n const [c, b, m] = await Promise.all([\n shell.exec('git', ['rev-parse', '--short', 'HEAD'], { cwd, throwOnError: false }),\n shell.exec('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd, throwOnError: false }),\n shell.exec('git', ['log', '-1', '--format=%s'], { cwd, throwOnError: false }),\n ]);\n if (!c.ok) return undefined;\n return { commit: c.stdout.trim(), branch: b.stdout.trim() || 'HEAD', message: m.stdout.trim() };\n } catch {\n return undefined;\n }\n}\n\nexport default defineCommand<unknown, CLIInput<SnapshotFlags>, { exitCode: number }>({\n id: 'quality:snapshot',\n description: 'Collect all quality metrics and save a snapshot for trend tracking',\n\n handler: {\n async intent(_ctx: PluginContextV3, _input: CLIInput<SnapshotFlags>) {\n return {\n summary: 'Collect all quality metrics and save snapshot for trend tracking',\n operations: [\n { type: 'create' as const, resource: 'file', details: { path: '.kb/quality/snapshots/<timestamp>.json' } },\n ],\n };\n },\n\n async execute(ctx: PluginContextV3, input: CLIInput<SnapshotFlags>): Promise<{ exitCode: number }> {\n const { flags } = input;\n const config = await useConfig<QualityPluginConfig>();\n const cwd = ctx.cwd ?? process.cwd();\n const cfg = config ?? defaultQualityConfig;\n\n ctx.ui?.success?.('Collecting quality metrics…');\n\n const [layering, coupling, types, git] = await Promise.all([\n analyzeLayering({ rootDir: cwd, layerMap: cfg.layers }),\n Promise.resolve(analyzeCoupling({ rootDir: cwd, layerMap: cfg.layers })),\n analyzeTypes(cwd),\n captureGit(ctx.api.shell, cwd),\n ]);\n\n let knip: KnipReport = { unusedFiles: [], unusedExports: [], unusedDependencies: [], unlistedDependencies: [], totalIssues: 0 };\n if (cfg.knip.enabled) {\n knip = await runKnip({ shell: ctx.api.shell, rootDir: cwd });\n }\n\n const totalPackages = coupling.packages.length;\n const health = calculateHealth({\n layering,\n coupling,\n types,\n knip,\n totalPackages,\n avgTestCoverage: null,\n thresholds: cfg.thresholds,\n });\n\n const store = new QualitySnapshotStore(cwd, cfg.maxSnapshots);\n const snap = store.save({\n score: health.score,\n grade: health.grade,\n dimensions: health.dimensions,\n counters: {\n layeringViolations: layering.totalViolations,\n avgInstability: coupling.avgInstability,\n anyCount: types.packages.reduce((s: number, p: { anyCount: number }) => s + p.anyCount, 0),\n tsIgnoreCount: types.packages.reduce((s: number, p: { tsIgnoreCount: number }) => s + p.tsIgnoreCount, 0),\n unusedFiles: knip.unusedFiles.length,\n unusedDeps: knip.unusedDependencies.length,\n },\n git: git ?? { commit: '', branch: '', message: '' },\n });\n\n if (flags.json) {\n ctx.ui?.json?.(snap);\n } else {\n ctx.ui?.success?.(`Snapshot saved: score ${snap.score}/100 (${snap.grade})`, {\n sections: [{\n header: 'Dimensions',\n items: Object.entries(snap.dimensions).map(\n ([k, d]) => `${k} ${d.score}/100 (${d.grade})`\n ),\n }],\n });\n }\n\n return { exitCode: 0 };\n },\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../src/cli/commands/snapshot.ts"],"names":[],"mappings":";;;;;AAmBA,eAAe,UAAA,CAAW,OAAiB,GAAA,EAAa;AACtD,EAAA,IAAI;AACF,IAAA,MAAM,CAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,MAClC,KAAA,CAAM,IAAA,CAAK,KAAA,EAAO,CAAC,WAAA,EAAa,SAAA,EAAW,MAAM,CAAA,EAAG,EAAE,GAAA,EAAK,YAAA,EAAc,KAAA,EAAO,CAAA;AAAA,MAChF,KAAA,CAAM,IAAA,CAAK,KAAA,EAAO,CAAC,WAAA,EAAa,cAAA,EAAgB,MAAM,CAAA,EAAG,EAAE,GAAA,EAAK,YAAA,EAAc,KAAA,EAAO,CAAA;AAAA,MACrF,KAAA,CAAM,IAAA,CAAK,KAAA,EAAO,CAAC,KAAA,EAAO,IAAA,EAAM,aAAa,CAAA,EAAG,EAAE,GAAA,EAAK,YAAA,EAAc,KAAA,EAAO;AAAA,KAC7E,CAAA;AACD,IAAA,IAAI,CAAC,CAAA,CAAE,EAAA,EAAI,OAAO,KAAA,CAAA;AAClB,IAAA,OAAO,EAAE,MAAA,EAAQ,CAAA,CAAE,MAAA,CAAO,IAAA,IAAQ,MAAA,EAAQ,CAAA,CAAE,MAAA,CAAO,IAAA,MAAU,MAAA,EAAQ,OAAA,EAAS,CAAA,CAAE,MAAA,CAAO,MAAK,EAAE;AAAA,EAChG,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAEA,IAAO,mBAAQ,aAAA,CAAyD;AAAA,EACtE,EAAA,EAAI,kBAAA;AAAA,EACJ,WAAA,EAAa,oEAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,MAAA,CAAO,IAAA,EAAuB,MAAA,EAAiC;AACnE,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,kEAAA;AAAA,QACT,UAAA,EAAY;AAAA,UACV,EAAE,MAAM,QAAA,EAAmB,QAAA,EAAU,QAAQ,OAAA,EAAS,EAAE,IAAA,EAAM,wCAAA,EAAyC;AAAE;AAC3G,OACF;AAAA,IACF,CAAA;AAAA,IAEA,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAAwD;AAC1F,MAAA,MAAM,EAAE,OAAM,GAAI,KAAA;AAClB,MAAA,MAAM,MAAA,GAAS,MAAM,SAAA,EAA+B;AACpD,MAAA,MAAM,GAAA,GAAM,GAAA,CAAI,GAAA,IAAO,OAAA,CAAQ,GAAA,EAAI;AACnC,MAAA,MAAM,MAAM,MAAA,IAAU,oBAAA;AAEtB,MAAA,GAAA,CAAI,EAAA,EAAI,UAAU,kCAA6B,CAAA;AAE/C,MAAA,MAAM,CAAC,UAAU,QAAA,EAAU,KAAA,EAAO,GAAG,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,QACzD,gBAAgB,EAAE,OAAA,EAAS,KAAK,QAAA,EAAU,GAAA,CAAI,QAAQ,CAAA;AAAA,QACtD,OAAA,CAAQ,OAAA,CAAQ,eAAA,CAAgB,EAAE,OAAA,EAAS,KAAK,QAAA,EAAU,GAAA,CAAI,MAAA,EAAQ,CAAC,CAAA;AAAA,QACvE,aAAa,GAAG,CAAA;AAAA,QAChB,UAAA,CAAW,GAAA,CAAI,GAAA,CAAI,KAAA,EAAO,GAAG;AAAA,OAC9B,CAAA;AAED,MAAA,IAAI,IAAA,GAAmB,EAAE,WAAA,EAAa,IAAI,aAAA,EAAe,EAAC,EAAG,kBAAA,EAAoB,EAAC,EAAG,oBAAA,EAAsB,EAAC,EAAG,aAAa,CAAA,EAAE;AAC9H,MAAA,IAAI,GAAA,CAAI,KAAK,OAAA,EAAS;AACpB,QAAA,IAAA,GAAO,MAAM,QAAQ,EAAE,KAAA,EAAO,IAAI,GAAA,CAAI,KAAA,EAAO,OAAA,EAAS,GAAA,EAAK,CAAA;AAAA,MAC7D;AAEA,MAAA,MAAM,aAAA,GAAgB,SAAS,QAAA,CAAS,MAAA;AACxC,MAAA,MAAM,SAAS,eAAA,CAAgB;AAAA,QAC7B,QAAA;AAAA,QACA,QAAA;AAAA,QACA,KAAA;AAAA,QACA,IAAA;AAAA,QACA,aAAA;AAAA,QACA,eAAA,EAAiB,IAAA;AAAA,QACjB,YAAY,GAAA,CAAI;AAAA,OACjB,CAAA;AAED,MAAA,MAAM,KAAA,GAAQ,IAAI,oBAAA,CAAqB,GAAA,EAAK,IAAI,YAAY,CAAA;AAC5D,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK;AAAA,QACtB,OAAO,MAAA,CAAO,KAAA;AAAA,QACd,OAAO,MAAA,CAAO,KAAA;AAAA,QACd,YAAY,MAAA,CAAO,UAAA;AAAA,QACnB,QAAA,EAAU;AAAA,UACR,oBAAoB,QAAA,CAAS,eAAA;AAAA,UAC7B,gBAAgB,QAAA,CAAS,cAAA;AAAA,UACzB,QAAA,EAAU,KAAA,CAAM,QAAA,CAAS,MAAA,CAAO,CAAC,GAAW,CAAA,KAA4B,CAAA,GAAI,CAAA,CAAE,QAAA,EAAU,CAAC,CAAA;AAAA,UACzF,aAAA,EAAe,KAAA,CAAM,QAAA,CAAS,MAAA,CAAO,CAAC,GAAW,CAAA,KAAiC,CAAA,GAAI,CAAA,CAAE,aAAA,EAAe,CAAC,CAAA;AAAA,UACxG,WAAA,EAAa,KAAK,WAAA,CAAY,MAAA;AAAA,UAC9B,UAAA,EAAY,KAAK,kBAAA,CAAmB;AAAA,SACtC;AAAA,QACA,GAAA,EAAK,OAAO,EAAE,MAAA,EAAQ,IAAI,MAAA,EAAQ,EAAA,EAAI,SAAS,EAAA;AAAG,OACnD,CAAA;AAED,MAAA,IAAI,MAAM,IAAA,EAAM;AACd,QAAA,GAAA,CAAI,EAAA,EAAI,OAAO,IAAI,CAAA;AAAA,MACrB,CAAA,MAAO;AACL,QAAA,GAAA,CAAI,EAAA,EAAI,UAAU,CAAA,sBAAA,EAAyB,IAAA,CAAK,KAAK,CAAA,MAAA,EAAS,IAAA,CAAK,KAAK,CAAA,CAAA,CAAA,EAAK;AAAA,UAC3E,UAAU,CAAC;AAAA,YACT,MAAA,EAAQ,YAAA;AAAA,YACR,KAAA,EAAO,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,UAAU,CAAA,CAAE,GAAA;AAAA,cACrC,CAAC,CAAC,CAAA,EAAG,CAAC,CAAA,KAAM,CAAA,EAAG,CAAC,CAAA,EAAA,EAAK,CAAA,CAAE,KAAK,CAAA,MAAA,EAAS,CAAA,CAAE,KAAK,CAAA,CAAA;AAAA;AAC9C,WACD;AAAA,SACF,CAAA;AAAA,MACH;AAEA,MAAA,OAAO,EAAE,IAAI,IAAA,EAAK;AAAA,IACpB;AAAA;AAEJ,CAAC","file":"snapshot.js","sourcesContent":["import {\n defineCommand,\n useConfig,\n type CLIInput,\n type PluginContextV3,\n type CommandResult,\n} from '@kb-labs/sdk';\nimport {\n analyzeLayering,\n analyzeCoupling,\n runKnip,\n analyzeTypes,\n QualitySnapshotStore,\n} from '@kb-labs/quality-core';\nimport { calculateHealth } from '@kb-labs/quality-core';\nimport { defaultQualityConfig, type QualityPluginConfig, type KnipReport } from '@kb-labs/quality-contracts';\nimport type { SnapshotFlags } from './flags.js';\nimport type { ShellAPI } from '@kb-labs/sdk';\n\nasync function captureGit(shell: ShellAPI, cwd: string) {\n try {\n const [c, b, m] = await Promise.all([\n shell.exec('git', ['rev-parse', '--short', 'HEAD'], { cwd, throwOnError: false }),\n shell.exec('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd, throwOnError: false }),\n shell.exec('git', ['log', '-1', '--format=%s'], { cwd, throwOnError: false }),\n ]);\n if (!c.ok) return undefined;\n return { commit: c.stdout.trim(), branch: b.stdout.trim() || 'HEAD', message: m.stdout.trim() };\n } catch {\n return undefined;\n }\n}\n\nexport default defineCommand<unknown, CLIInput<SnapshotFlags>, unknown>({\n id: 'quality:snapshot',\n description: 'Collect all quality metrics and save a snapshot for trend tracking',\n\n handler: {\n async intent(_ctx: PluginContextV3, _input: CLIInput<SnapshotFlags>) {\n return {\n summary: 'Collect all quality metrics and save snapshot for trend tracking',\n operations: [\n { type: 'create' as const, resource: 'file', details: { path: '.kb/quality/snapshots/<timestamp>.json' } },\n ],\n };\n },\n\n async execute(ctx: PluginContextV3, input: CLIInput<SnapshotFlags>): Promise<CommandResult> {\n const { flags } = input;\n const config = await useConfig<QualityPluginConfig>();\n const cwd = ctx.cwd ?? process.cwd();\n const cfg = config ?? defaultQualityConfig;\n\n ctx.ui?.success?.('Collecting quality metrics…');\n\n const [layering, coupling, types, git] = await Promise.all([\n analyzeLayering({ rootDir: cwd, layerMap: cfg.layers }),\n Promise.resolve(analyzeCoupling({ rootDir: cwd, layerMap: cfg.layers })),\n analyzeTypes(cwd),\n captureGit(ctx.api.shell, cwd),\n ]);\n\n let knip: KnipReport = { unusedFiles: [], unusedExports: [], unusedDependencies: [], unlistedDependencies: [], totalIssues: 0 };\n if (cfg.knip.enabled) {\n knip = await runKnip({ shell: ctx.api.shell, rootDir: cwd });\n }\n\n const totalPackages = coupling.packages.length;\n const health = calculateHealth({\n layering,\n coupling,\n types,\n knip,\n totalPackages,\n avgTestCoverage: null,\n thresholds: cfg.thresholds,\n });\n\n const store = new QualitySnapshotStore(cwd, cfg.maxSnapshots);\n const snap = store.save({\n score: health.score,\n grade: health.grade,\n dimensions: health.dimensions,\n counters: {\n layeringViolations: layering.totalViolations,\n avgInstability: coupling.avgInstability,\n anyCount: types.packages.reduce((s: number, p: { anyCount: number }) => s + p.anyCount, 0),\n tsIgnoreCount: types.packages.reduce((s: number, p: { tsIgnoreCount: number }) => s + p.tsIgnoreCount, 0),\n unusedFiles: knip.unusedFiles.length,\n unusedDeps: knip.unusedDependencies.length,\n },\n git: git ?? { commit: '', branch: '', message: '' },\n });\n\n if (flags.json) {\n ctx.ui?.json?.(snap);\n } else {\n ctx.ui?.success?.(`Snapshot saved: score ${snap.score}/100 (${snap.grade})`, {\n sections: [{\n header: 'Dimensions',\n items: Object.entries(snap.dimensions).map(\n ([k, d]) => `${k} ${d.score}/100 (${d.grade})`\n ),\n }],\n });\n }\n\n return { ok: true };\n },\n },\n});\n"]}
@@ -2,8 +2,6 @@ import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
2
2
  import { CLIInput } from '@kb-labs/sdk';
3
3
  import { StatsFlags } from './flags.js';
4
4
 
5
- declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, CLIInput<StatsFlags>, {
6
- exitCode: number;
7
- }>;
5
+ declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, CLIInput<StatsFlags>, unknown>;
8
6
 
9
7
  export { _default as default };
@@ -12,7 +12,7 @@ var stats_default = defineCommand({
12
12
  const stats = await calculateStats(cwd);
13
13
  if (flags.json) {
14
14
  ctx.ui?.json?.(stats);
15
- return { exitCode: 0 };
15
+ return { ok: true };
16
16
  }
17
17
  ctx.ui?.success?.("Monorepo statistics", {
18
18
  sections: [{
@@ -24,7 +24,7 @@ var stats_default = defineCommand({
24
24
  ]
25
25
  }]
26
26
  });
27
- return { exitCode: 0 };
27
+ return { ok: true };
28
28
  }
29
29
  }
30
30
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/stats.ts"],"names":[],"mappings":";;;;AAQA,IAAO,gBAAQ,aAAA,CAAmE;AAAA,EAChF,EAAA,EAAI,eAAA;AAAA,EACJ,WAAA,EAAa,oDAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAA4D;AAC9F,MAAA,MAAM,EAAE,OAAM,GAAI,KAAA;AAClB,MAAA,MAAM,GAAA,GAAM,GAAA,CAAI,GAAA,IAAO,OAAA,CAAQ,GAAA,EAAI;AAEnC,MAAA,MAAM,KAAA,GAAQ,MAAM,cAAA,CAAe,GAAG,CAAA;AAEtC,MAAA,IAAI,MAAM,IAAA,EAAM;AACd,QAAA,GAAA,CAAI,EAAA,EAAI,OAAO,KAAK,CAAA;AACpB,QAAA,OAAO,EAAE,UAAU,CAAA,EAAE;AAAA,MACvB;AAEA,MAAA,GAAA,CAAI,EAAA,EAAI,UAAU,qBAAA,EAAuB;AAAA,QACvC,UAAU,CAAC;AAAA,UACT,MAAA,EAAQ,UAAA;AAAA,UACR,KAAA,EAAO;AAAA,YACL,CAAA,UAAA,EAAa,MAAM,QAAQ,CAAA,CAAA;AAAA,YAC3B,CAAA,eAAA,EAAkB,KAAA,CAAM,GAAA,CAAI,cAAA,EAAgB,CAAA,CAAA;AAAA,YAC5C,CAAA,MAAA,EAAS,MAAM,aAAa,CAAA;AAAA;AAC9B,SACD;AAAA,OACF,CAAA;AAED,MAAA,OAAO,EAAE,UAAU,CAAA,EAAE;AAAA,IACvB;AAAA;AAEJ,CAAC","file":"stats.js","sourcesContent":["import {\n defineCommand,\n type CLIInput,\n type PluginContextV3,\n} from '@kb-labs/sdk';\nimport { calculateStats } from '@kb-labs/quality-core';\nimport type { StatsFlags } from './flags.js';\n\nexport default defineCommand<unknown, CLIInput<StatsFlags>, { exitCode: number }>({\n id: 'quality:stats',\n description: 'Monorepo statistics: packages, lines of code, size',\n\n handler: {\n async execute(ctx: PluginContextV3, input: CLIInput<StatsFlags>): Promise<{ exitCode: number }> {\n const { flags } = input;\n const cwd = ctx.cwd ?? process.cwd();\n\n const stats = await calculateStats(cwd);\n\n if (flags.json) {\n ctx.ui?.json?.(stats);\n return { exitCode: 0 };\n }\n\n ctx.ui?.success?.('Monorepo statistics', {\n sections: [{\n header: 'Overview',\n items: [\n `Packages: ${stats.packages}`,\n `Lines of code: ${stats.loc.toLocaleString()}`,\n `Size: ${stats.sizeFormatted}`,\n ],\n }],\n });\n\n return { exitCode: 0 };\n },\n },\n});\n"]}
1
+ {"version":3,"sources":["../../../src/cli/commands/stats.ts"],"names":[],"mappings":";;;;AASA,IAAO,gBAAQ,aAAA,CAAsD;AAAA,EACnE,EAAA,EAAI,eAAA;AAAA,EACJ,WAAA,EAAa,oDAAA;AAAA,EAEb,OAAA,EAAS;AAAA,IACP,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAAqD;AACvF,MAAA,MAAM,EAAE,OAAM,GAAI,KAAA;AAClB,MAAA,MAAM,GAAA,GAAM,GAAA,CAAI,GAAA,IAAO,OAAA,CAAQ,GAAA,EAAI;AAEnC,MAAA,MAAM,KAAA,GAAQ,MAAM,cAAA,CAAe,GAAG,CAAA;AAEtC,MAAA,IAAI,MAAM,IAAA,EAAM;AACd,QAAA,GAAA,CAAI,EAAA,EAAI,OAAO,KAAK,CAAA;AACpB,QAAA,OAAO,EAAE,IAAI,IAAA,EAAK;AAAA,MACpB;AAEA,MAAA,GAAA,CAAI,EAAA,EAAI,UAAU,qBAAA,EAAuB;AAAA,QACvC,UAAU,CAAC;AAAA,UACT,MAAA,EAAQ,UAAA;AAAA,UACR,KAAA,EAAO;AAAA,YACL,CAAA,UAAA,EAAa,MAAM,QAAQ,CAAA,CAAA;AAAA,YAC3B,CAAA,eAAA,EAAkB,KAAA,CAAM,GAAA,CAAI,cAAA,EAAgB,CAAA,CAAA;AAAA,YAC5C,CAAA,MAAA,EAAS,MAAM,aAAa,CAAA;AAAA;AAC9B,SACD;AAAA,OACF,CAAA;AAED,MAAA,OAAO,EAAE,IAAI,IAAA,EAAK;AAAA,IACpB;AAAA;AAEJ,CAAC","file":"stats.js","sourcesContent":["import {\n defineCommand,\n type CLIInput,\n type PluginContextV3,\n type CommandResult,\n} from '@kb-labs/sdk';\nimport { calculateStats } from '@kb-labs/quality-core';\nimport type { StatsFlags } from './flags.js';\n\nexport default defineCommand<unknown, CLIInput<StatsFlags>, unknown>({\n id: 'quality:stats',\n description: 'Monorepo statistics: packages, lines of code, size',\n\n handler: {\n async execute(ctx: PluginContextV3, input: CLIInput<StatsFlags>): Promise<CommandResult> {\n const { flags } = input;\n const cwd = ctx.cwd ?? process.cwd();\n\n const stats = await calculateStats(cwd);\n\n if (flags.json) {\n ctx.ui?.json?.(stats);\n return { ok: true };\n }\n\n ctx.ui?.success?.('Monorepo statistics', {\n sections: [{\n header: 'Overview',\n items: [\n `Packages: ${stats.packages}`,\n `Lines of code: ${stats.loc.toLocaleString()}`,\n `Size: ${stats.sizeFormatted}`,\n ],\n }],\n });\n\n return { ok: true };\n },\n },\n});\n"]}
@@ -1,13 +1,6 @@
1
1
  import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
2
+ import { DependencyGraph } from '@kb-labs/quality-core/graph';
2
3
 
3
- /**
4
- * quality:visualize - Visualize dependency graph
5
- *
6
- * Shows dependency graph in various formats:
7
- * - Tree view for specific package
8
- * - DOT format for graphviz
9
- * - Statistics about the graph
10
- */
11
4
  type VisualizeFlags = {
12
5
  package?: string;
13
6
  tree?: boolean;
@@ -21,6 +14,8 @@ type VisualizeFlags = {
21
14
  type VisualizeInput = VisualizeFlags & {
22
15
  argv?: string[];
23
16
  };
24
- declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, VisualizeInput, unknown>;
17
+ declare const _default: _kb_labs_shared_command_kit.CommandHandlerV3<unknown, VisualizeInput, {
18
+ graph: DependencyGraph;
19
+ }>;
25
20
 
26
21
  export { _default as default };
@@ -23,7 +23,7 @@ var visualize_default = defineCommand({
23
23
  } else {
24
24
  outputStats(graph, flags, ui);
25
25
  }
26
- return { exitCode: 0 };
26
+ return { ok: true, result: { graph } };
27
27
  }
28
28
  }
29
29
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/visualize.ts"],"names":[],"mappings":"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","file":"visualize.js","sourcesContent":["/**\n * quality:visualize - Visualize dependency graph\n *\n * Shows dependency graph in various formats:\n * - Tree view for specific package\n * - DOT format for graphviz\n * - Statistics about the graph\n */\n\nimport { defineCommand, type PluginContextV3 } from '@kb-labs/sdk';\nimport type { UIFacade } from '@kb-labs/sdk';\nimport {\n buildDependencyGraph,\n getReverseDependencies,\n getImpactAnalysis,\n type DependencyGraph,\n} from '@kb-labs/quality-core/graph';\n\ntype VisualizeFlags = {\n package?: string;\n tree?: boolean;\n dot?: boolean;\n stats?: boolean;\n reverse?: boolean;\n impact?: boolean;\n json?: boolean;\n argv?: string[];\n};\n\ntype VisualizeInput = VisualizeFlags & { argv?: string[] };\n\ntype VisualizeCommandResult = {\n exitCode: number;\n graph?: DependencyGraph;\n};\n\nexport default defineCommand({\n id: 'quality:visualize',\n description: 'Visualize dependency graph',\n\n handler: {\n async execute(ctx: PluginContextV3, input: VisualizeInput): Promise<VisualizeCommandResult> {\n const { ui } = ctx;\n\n // V3: Flags may come wrapped in input.flags or passed directly\n const flags = ('flags' in input && typeof (input as { flags?: unknown }).flags === 'object' && (input as { flags?: unknown }).flags !== null)\n ? (input as { flags: VisualizeInput }).flags\n : input;\n\n // Build dependency graph\n const graph = buildDependencyGraph(ctx.cwd);\n\n // Handle different output modes\n if (flags.dot) {\n outputDot(graph, flags, ui);\n } else if (flags.tree && flags.package) {\n outputTree(graph, flags.package, flags, ui);\n } else if (flags.reverse && flags.package) {\n outputReverse(graph, flags.package, flags, ui);\n } else if (flags.impact && flags.package) {\n outputImpact(graph, flags.package, flags, ui);\n } else if (flags.stats) {\n outputStats(graph, flags, ui);\n } else {\n // Default: show stats\n outputStats(graph, flags, ui);\n }\n\n return { exitCode: 0 };\n },\n },\n});\n\n/**\n * Output dependency tree for a package\n */\nfunction outputTree(graph: DependencyGraph, packageName: string, flags: VisualizeFlags, ui: UIFacade | undefined) {\n const { nodes } = graph;\n const node = nodes.get(packageName);\n\n if (!node) {\n ui?.error?.(`Package not found: ${packageName}`);\n return;\n }\n\n const sections: Array<{ header: string; items: string[] }> = [];\n\n // Build tree recursively\n const visited = new Set<string>();\n const treeItems: string[] = [];\n\n function buildTree(pkg: string, depth: number, prefix: string) {\n if (visited.has(pkg)) {\n treeItems.push(`${prefix}${pkg} (circular)`);\n return;\n }\n visited.add(pkg);\n\n const pkgNode = nodes.get(pkg);\n if (!pkgNode) {return;}\n\n treeItems.push(`${prefix}${pkg}`);\n\n const deps = Array.from(pkgNode.deps);\n for (let i = 0; i < deps.length; i++) {\n const dep = deps[i];\n if (!dep) {continue;}\n const isLast = i === deps.length - 1;\n const newPrefix = prefix + (isLast ? ' └─ ' : ' ├─ ');\n buildTree(dep, depth + 1, newPrefix);\n }\n }\n\n buildTree(packageName, 0, '');\n\n sections.push({\n header: 'Dependency Tree',\n items: treeItems,\n });\n\n ui?.success?.('Dependency tree generated', {\n title: `📦 Dependency Tree for ${packageName}`,\n sections,\n });\n}\n\n/**\n * Output reverse dependencies (who depends on this package)\n */\nfunction outputReverse(graph: DependencyGraph, packageName: string, flags: VisualizeFlags, ui: UIFacade | undefined) {\n const reverseDeps = getReverseDependencies(graph, packageName);\n\n if (flags.json) {\n ui?.json?.({ package: packageName, reverseDependencies: Array.from(reverseDeps) });\n return;\n }\n\n const sections: Array<{ header: string; items: string[] }> = [];\n\n if (reverseDeps.size === 0) {\n sections.push({\n header: 'Result',\n items: ['No packages depend on this package'],\n });\n } else {\n sections.push({\n header: `Packages that depend on ${packageName}`,\n items: Array.from(reverseDeps).map(dep => `• ${dep}`),\n });\n }\n\n ui?.success?.('Reverse dependencies found', {\n title: `⬅️ Reverse Dependencies for ${packageName}`,\n sections,\n });\n}\n\n/**\n * Output impact analysis (all packages affected by changes)\n */\nfunction outputImpact(graph: DependencyGraph, packageName: string, flags: VisualizeFlags, ui: UIFacade | undefined) {\n const affected = getImpactAnalysis(graph, packageName);\n\n if (flags.json) {\n ui?.json?.({ package: packageName, affectedPackages: Array.from(affected) });\n return;\n }\n\n const sections: Array<{ header: string; items: string[] }> = [];\n\n if (affected.size === 0) {\n sections.push({\n header: 'Result',\n items: ['No other packages affected by changes to this package'],\n });\n } else {\n sections.push({\n header: `Impact Analysis for ${packageName}`,\n items: [\n `Changes to this package will affect ${affected.size} other packages:`,\n '',\n ...Array.from(affected).map(dep => `• ${dep}`),\n ],\n });\n\n sections.push({\n header: 'Recommendations',\n items: [\n '🧪 Run tests in affected packages',\n '🔨 Rebuild affected packages',\n '📝 Update documentation if API changed',\n ],\n });\n }\n\n ui?.success?.('Impact analysis completed', {\n title: `💥 Impact Analysis for ${packageName}`,\n sections,\n });\n}\n\n/**\n * Output dependency graph statistics\n */\nfunction outputStats(graph: DependencyGraph, flags: VisualizeFlags, ui: UIFacade | undefined) {\n const { nodes } = graph;\n\n // Calculate statistics\n let totalDeps = 0;\n let maxDeps = 0;\n let maxDepsPackage = '';\n const depCounts = new Map<number, number>();\n\n for (const [name, node] of nodes) {\n const depCount = node.deps.size;\n totalDeps += depCount;\n\n if (depCount > maxDeps) {\n maxDeps = depCount;\n maxDepsPackage = name;\n }\n\n depCounts.set(depCount, (depCounts.get(depCount) ?? 0) + 1);\n }\n\n const avgDeps = nodes.size > 0 ? (totalDeps / nodes.size).toFixed(2) : '0';\n\n if (flags.json) {\n ui?.json?.({\n totalPackages: nodes.size,\n totalDependencies: totalDeps,\n averageDependencies: Number.parseFloat(avgDeps),\n maxDependencies: maxDeps,\n maxDependenciesPackage: maxDepsPackage,\n });\n return;\n }\n\n const sections: Array<{ header: string; items: string[] }> = [];\n\n sections.push({\n header: 'Graph Statistics',\n items: [\n `Total packages: ${nodes.size}`,\n `Total dependencies: ${totalDeps}`,\n `Average dependencies per package: ${avgDeps}`,\n `Max dependencies: ${maxDeps} (${maxDepsPackage})`,\n ],\n });\n\n // Dependency distribution\n const distributionItems: string[] = [];\n const sortedCounts = Array.from(depCounts.entries()).sort((a, b) => a[0] - b[0]);\n for (const [count, packages] of sortedCounts) {\n const bar = '█'.repeat(Math.min(packages, 20));\n distributionItems.push(`${count} deps: ${bar} ${packages} packages`);\n }\n\n sections.push({\n header: 'Dependency Distribution',\n items: distributionItems,\n });\n\n ui?.success?.('Graph statistics calculated', {\n title: '📊 Dependency Graph Statistics',\n sections,\n });\n}\n\n/**\n * Output DOT format for graphviz\n */\nfunction outputDot(graph: DependencyGraph, flags: VisualizeFlags, ui: UIFacade | undefined) {\n const { nodes } = graph;\n\n const lines: string[] = [];\n lines.push('digraph dependencies {');\n lines.push(' rankdir=LR;');\n lines.push(' node [shape=box];');\n lines.push('');\n\n for (const [name, node] of nodes) {\n for (const dep of node.deps) {\n const safeName = name.replace(/[@\\/]/g, '_');\n const safeDep = dep.replace(/[@\\/]/g, '_');\n lines.push(` \"${safeName}\" -> \"${safeDep}\";`);\n }\n }\n\n lines.push('}');\n\n if (flags.json) {\n ui?.json?.({ dot: lines.join('\\n') });\n } else {\n for (const line of lines) {\n ui?.write?.(line);\n }\n ui?.write?.('');\n ui?.write?.('# Save to file and visualize with:');\n ui?.write?.('# dot -Tpng dependencies.dot -o dependencies.png');\n }\n}\n"]}
1
+ {"version":3,"sources":["../../../src/cli/commands/visualize.ts"],"names":[],"mappings":"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","file":"visualize.js","sourcesContent":["/**\n * quality:visualize - Visualize dependency graph\n *\n * Shows dependency graph in various formats:\n * - Tree view for specific package\n * - DOT format for graphviz\n * - Statistics about the graph\n */\n\nimport { defineCommand, type PluginContextV3, type CommandResult } from '@kb-labs/sdk';\nimport type { UIFacade } from '@kb-labs/sdk';\nimport {\n buildDependencyGraph,\n getReverseDependencies,\n getImpactAnalysis,\n type DependencyGraph,\n} from '@kb-labs/quality-core/graph';\n\ntype VisualizeFlags = {\n package?: string;\n tree?: boolean;\n dot?: boolean;\n stats?: boolean;\n reverse?: boolean;\n impact?: boolean;\n json?: boolean;\n argv?: string[];\n};\n\ntype VisualizeInput = VisualizeFlags & { argv?: string[] };\n\nexport default defineCommand({\n id: 'quality:visualize',\n description: 'Visualize dependency graph',\n\n handler: {\n async execute(ctx: PluginContextV3, input: VisualizeInput): Promise<CommandResult<{ graph: DependencyGraph }>> {\n const { ui } = ctx;\n\n // V3: Flags may come wrapped in input.flags or passed directly\n const flags = ('flags' in input && typeof (input as { flags?: unknown }).flags === 'object' && (input as { flags?: unknown }).flags !== null)\n ? (input as { flags: VisualizeInput }).flags\n : input;\n\n // Build dependency graph\n const graph = buildDependencyGraph(ctx.cwd);\n\n // Handle different output modes\n if (flags.dot) {\n outputDot(graph, flags, ui);\n } else if (flags.tree && flags.package) {\n outputTree(graph, flags.package, flags, ui);\n } else if (flags.reverse && flags.package) {\n outputReverse(graph, flags.package, flags, ui);\n } else if (flags.impact && flags.package) {\n outputImpact(graph, flags.package, flags, ui);\n } else if (flags.stats) {\n outputStats(graph, flags, ui);\n } else {\n // Default: show stats\n outputStats(graph, flags, ui);\n }\n\n return { ok: true, result: { graph } };\n },\n },\n});\n\n/**\n * Output dependency tree for a package\n */\nfunction outputTree(graph: DependencyGraph, packageName: string, flags: VisualizeFlags, ui: UIFacade | undefined) {\n const { nodes } = graph;\n const node = nodes.get(packageName);\n\n if (!node) {\n ui?.error?.(`Package not found: ${packageName}`);\n return;\n }\n\n const sections: Array<{ header: string; items: string[] }> = [];\n\n // Build tree recursively\n const visited = new Set<string>();\n const treeItems: string[] = [];\n\n function buildTree(pkg: string, depth: number, prefix: string) {\n if (visited.has(pkg)) {\n treeItems.push(`${prefix}${pkg} (circular)`);\n return;\n }\n visited.add(pkg);\n\n const pkgNode = nodes.get(pkg);\n if (!pkgNode) {return;}\n\n treeItems.push(`${prefix}${pkg}`);\n\n const deps = Array.from(pkgNode.deps);\n for (let i = 0; i < deps.length; i++) {\n const dep = deps[i];\n if (!dep) {continue;}\n const isLast = i === deps.length - 1;\n const newPrefix = prefix + (isLast ? ' └─ ' : ' ├─ ');\n buildTree(dep, depth + 1, newPrefix);\n }\n }\n\n buildTree(packageName, 0, '');\n\n sections.push({\n header: 'Dependency Tree',\n items: treeItems,\n });\n\n ui?.success?.('Dependency tree generated', {\n title: `📦 Dependency Tree for ${packageName}`,\n sections,\n });\n}\n\n/**\n * Output reverse dependencies (who depends on this package)\n */\nfunction outputReverse(graph: DependencyGraph, packageName: string, flags: VisualizeFlags, ui: UIFacade | undefined) {\n const reverseDeps = getReverseDependencies(graph, packageName);\n\n if (flags.json) {\n ui?.json?.({ package: packageName, reverseDependencies: Array.from(reverseDeps) });\n return;\n }\n\n const sections: Array<{ header: string; items: string[] }> = [];\n\n if (reverseDeps.size === 0) {\n sections.push({\n header: 'Result',\n items: ['No packages depend on this package'],\n });\n } else {\n sections.push({\n header: `Packages that depend on ${packageName}`,\n items: Array.from(reverseDeps).map(dep => `• ${dep}`),\n });\n }\n\n ui?.success?.('Reverse dependencies found', {\n title: `⬅️ Reverse Dependencies for ${packageName}`,\n sections,\n });\n}\n\n/**\n * Output impact analysis (all packages affected by changes)\n */\nfunction outputImpact(graph: DependencyGraph, packageName: string, flags: VisualizeFlags, ui: UIFacade | undefined) {\n const affected = getImpactAnalysis(graph, packageName);\n\n if (flags.json) {\n ui?.json?.({ package: packageName, affectedPackages: Array.from(affected) });\n return;\n }\n\n const sections: Array<{ header: string; items: string[] }> = [];\n\n if (affected.size === 0) {\n sections.push({\n header: 'Result',\n items: ['No other packages affected by changes to this package'],\n });\n } else {\n sections.push({\n header: `Impact Analysis for ${packageName}`,\n items: [\n `Changes to this package will affect ${affected.size} other packages:`,\n '',\n ...Array.from(affected).map(dep => `• ${dep}`),\n ],\n });\n\n sections.push({\n header: 'Recommendations',\n items: [\n '🧪 Run tests in affected packages',\n '🔨 Rebuild affected packages',\n '📝 Update documentation if API changed',\n ],\n });\n }\n\n ui?.success?.('Impact analysis completed', {\n title: `💥 Impact Analysis for ${packageName}`,\n sections,\n });\n}\n\n/**\n * Output dependency graph statistics\n */\nfunction outputStats(graph: DependencyGraph, flags: VisualizeFlags, ui: UIFacade | undefined) {\n const { nodes } = graph;\n\n // Calculate statistics\n let totalDeps = 0;\n let maxDeps = 0;\n let maxDepsPackage = '';\n const depCounts = new Map<number, number>();\n\n for (const [name, node] of nodes) {\n const depCount = node.deps.size;\n totalDeps += depCount;\n\n if (depCount > maxDeps) {\n maxDeps = depCount;\n maxDepsPackage = name;\n }\n\n depCounts.set(depCount, (depCounts.get(depCount) ?? 0) + 1);\n }\n\n const avgDeps = nodes.size > 0 ? (totalDeps / nodes.size).toFixed(2) : '0';\n\n if (flags.json) {\n ui?.json?.({\n totalPackages: nodes.size,\n totalDependencies: totalDeps,\n averageDependencies: Number.parseFloat(avgDeps),\n maxDependencies: maxDeps,\n maxDependenciesPackage: maxDepsPackage,\n });\n return;\n }\n\n const sections: Array<{ header: string; items: string[] }> = [];\n\n sections.push({\n header: 'Graph Statistics',\n items: [\n `Total packages: ${nodes.size}`,\n `Total dependencies: ${totalDeps}`,\n `Average dependencies per package: ${avgDeps}`,\n `Max dependencies: ${maxDeps} (${maxDepsPackage})`,\n ],\n });\n\n // Dependency distribution\n const distributionItems: string[] = [];\n const sortedCounts = Array.from(depCounts.entries()).sort((a, b) => a[0] - b[0]);\n for (const [count, packages] of sortedCounts) {\n const bar = '█'.repeat(Math.min(packages, 20));\n distributionItems.push(`${count} deps: ${bar} ${packages} packages`);\n }\n\n sections.push({\n header: 'Dependency Distribution',\n items: distributionItems,\n });\n\n ui?.success?.('Graph statistics calculated', {\n title: '📊 Dependency Graph Statistics',\n sections,\n });\n}\n\n/**\n * Output DOT format for graphviz\n */\nfunction outputDot(graph: DependencyGraph, flags: VisualizeFlags, ui: UIFacade | undefined) {\n const { nodes } = graph;\n\n const lines: string[] = [];\n lines.push('digraph dependencies {');\n lines.push(' rankdir=LR;');\n lines.push(' node [shape=box];');\n lines.push('');\n\n for (const [name, node] of nodes) {\n for (const dep of node.deps) {\n const safeName = name.replace(/[@\\/]/g, '_');\n const safeDep = dep.replace(/[@\\/]/g, '_');\n lines.push(` \"${safeName}\" -> \"${safeDep}\";`);\n }\n }\n\n lines.push('}');\n\n if (flags.json) {\n ui?.json?.({ dot: lines.join('\\n') });\n } else {\n for (const line of lines) {\n ui?.write?.(line);\n }\n ui?.write?.('');\n ui?.write?.('# Save to file and visualize with:');\n ui?.write?.('# dot -Tpng dependencies.dot -o dependencies.png');\n }\n}\n"]}
@@ -5,7 +5,7 @@
5
5
  "name": "qualityPlugin",
6
6
  "globalName": "qualityPlugin",
7
7
  "buildInfo": {
8
- "buildVersion": "2.109.0",
8
+ "buildVersion": "2.110.0",
9
9
  "buildName": "@kb-labs/quality-entry"
10
10
  },
11
11
  "publicPath": "auto",
@@ -27,7 +27,7 @@
27
27
  {
28
28
  "id": "qualityPlugin:@kb-labs/studio-event-bus",
29
29
  "name": "@kb-labs/studio-event-bus",
30
- "version": "2.109.0",
30
+ "version": "2.110.0",
31
31
  "singleton": true,
32
32
  "requiredVersion": "^2.0.0",
33
33
  "assets": {
@@ -47,7 +47,7 @@
47
47
  {
48
48
  "id": "qualityPlugin:@kb-labs/studio-ui-core",
49
49
  "name": "@kb-labs/studio-ui-core",
50
- "version": "2.109.0",
50
+ "version": "2.110.0",
51
51
  "singleton": true,
52
52
  "requiredVersion": "^2.0.0",
53
53
  "assets": {
@@ -86,7 +86,7 @@
86
86
  {
87
87
  "id": "qualityPlugin:@kb-labs/studio-hooks",
88
88
  "name": "@kb-labs/studio-hooks",
89
- "version": "2.109.0",
89
+ "version": "2.110.0",
90
90
  "singleton": true,
91
91
  "requiredVersion": "^2.0.0",
92
92
  "assets": {
@@ -106,7 +106,7 @@
106
106
  {
107
107
  "id": "qualityPlugin:@kb-labs/studio-ui-kit",
108
108
  "name": "@kb-labs/studio-ui-kit",
109
- "version": "2.109.0",
109
+ "version": "2.110.0",
110
110
  "singleton": true,
111
111
  "requiredVersion": "^2.0.0",
112
112
  "assets": {
@@ -5,7 +5,7 @@
5
5
  "name": "qualityPlugin",
6
6
  "globalName": "qualityPlugin",
7
7
  "buildInfo": {
8
- "buildVersion": "2.109.0",
8
+ "buildVersion": "2.110.0",
9
9
  "buildName": "@kb-labs/quality-entry"
10
10
  },
11
11
  "publicPath": "auto",
@@ -27,7 +27,7 @@
27
27
  {
28
28
  "id": "qualityPlugin:@kb-labs/studio-event-bus",
29
29
  "name": "@kb-labs/studio-event-bus",
30
- "version": "2.109.0",
30
+ "version": "2.110.0",
31
31
  "requiredVersion": "^2.0.0",
32
32
  "singleton": true,
33
33
  "assets": {
@@ -49,7 +49,7 @@
49
49
  {
50
50
  "id": "qualityPlugin:@kb-labs/studio-ui-core",
51
51
  "name": "@kb-labs/studio-ui-core",
52
- "version": "2.109.0",
52
+ "version": "2.110.0",
53
53
  "requiredVersion": "^2.0.0",
54
54
  "singleton": true,
55
55
  "assets": {
@@ -92,7 +92,7 @@
92
92
  {
93
93
  "id": "qualityPlugin:@kb-labs/studio-hooks",
94
94
  "name": "@kb-labs/studio-hooks",
95
- "version": "2.109.0",
95
+ "version": "2.110.0",
96
96
  "requiredVersion": "^2.0.0",
97
97
  "singleton": true,
98
98
  "assets": {
@@ -114,7 +114,7 @@
114
114
  {
115
115
  "id": "qualityPlugin:@kb-labs/studio-ui-kit",
116
116
  "name": "@kb-labs/studio-ui-kit",
117
- "version": "2.109.0",
117
+ "version": "2.110.0",
118
118
  "requiredVersion": "^2.0.0",
119
119
  "singleton": true,
120
120
  "assets": {