@industry-theme/file-city-panel 0.2.40 → 0.2.42

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.
@@ -106,7 +106,7 @@ const createLucideIcon = (iconName, iconNode) => {
106
106
  * This source code is licensed under the ISC license.
107
107
  * See the LICENSE file in the root directory of this source tree.
108
108
  */
109
- const __iconNode$h = [
109
+ const __iconNode$i = [
110
110
  [
111
111
  "path",
112
112
  {
@@ -115,14 +115,14 @@ const __iconNode$h = [
115
115
  }
116
116
  ]
117
117
  ];
118
- const Activity = createLucideIcon("activity", __iconNode$h);
118
+ const Activity = createLucideIcon("activity", __iconNode$i);
119
119
  /**
120
120
  * @license lucide-react v0.552.0 - ISC
121
121
  *
122
122
  * This source code is licensed under the ISC license.
123
123
  * See the LICENSE file in the root directory of this source tree.
124
124
  */
125
- const __iconNode$g = [
125
+ const __iconNode$h = [
126
126
  ["path", { d: "M10 12h4", key: "a56b0p" }],
127
127
  ["path", { d: "M10 8h4", key: "1sr2af" }],
128
128
  ["path", { d: "M14 21v-3a2 2 0 0 0-4 0v3", key: "1rgiei" }],
@@ -135,55 +135,55 @@ const __iconNode$g = [
135
135
  ],
136
136
  ["path", { d: "M6 21V5a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v16", key: "16ra0t" }]
137
137
  ];
138
- const Building2 = createLucideIcon("building-2", __iconNode$g);
138
+ const Building2 = createLucideIcon("building-2", __iconNode$h);
139
139
  /**
140
140
  * @license lucide-react v0.552.0 - ISC
141
141
  *
142
142
  * This source code is licensed under the ISC license.
143
143
  * See the LICENSE file in the root directory of this source tree.
144
144
  */
145
- const __iconNode$f = [
145
+ const __iconNode$g = [
146
146
  ["path", { d: "M3 3v16a2 2 0 0 0 2 2h16", key: "c24i48" }],
147
147
  ["path", { d: "M18 17V9", key: "2bz60n" }],
148
148
  ["path", { d: "M13 17V5", key: "1frdt8" }],
149
149
  ["path", { d: "M8 17v-3", key: "17ska0" }]
150
150
  ];
151
- const ChartColumn = createLucideIcon("chart-column", __iconNode$f);
151
+ const ChartColumn = createLucideIcon("chart-column", __iconNode$g);
152
152
  /**
153
153
  * @license lucide-react v0.552.0 - ISC
154
154
  *
155
155
  * This source code is licensed under the ISC license.
156
156
  * See the LICENSE file in the root directory of this source tree.
157
157
  */
158
- const __iconNode$e = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
159
- const ChevronDown = createLucideIcon("chevron-down", __iconNode$e);
158
+ const __iconNode$f = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
159
+ const ChevronDown = createLucideIcon("chevron-down", __iconNode$f);
160
160
  /**
161
161
  * @license lucide-react v0.552.0 - ISC
162
162
  *
163
163
  * This source code is licensed under the ISC license.
164
164
  * See the LICENSE file in the root directory of this source tree.
165
165
  */
166
- const __iconNode$d = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
167
- const ChevronRight = createLucideIcon("chevron-right", __iconNode$d);
166
+ const __iconNode$e = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
167
+ const ChevronRight = createLucideIcon("chevron-right", __iconNode$e);
168
168
  /**
169
169
  * @license lucide-react v0.552.0 - ISC
170
170
  *
171
171
  * This source code is licensed under the ISC license.
172
172
  * See the LICENSE file in the root directory of this source tree.
173
173
  */
174
- const __iconNode$c = [
174
+ const __iconNode$d = [
175
175
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
176
176
  ["line", { x1: "12", x2: "12", y1: "8", y2: "12", key: "1pkeuh" }],
177
177
  ["line", { x1: "12", x2: "12.01", y1: "16", y2: "16", key: "4dfq90" }]
178
178
  ];
179
- const CircleAlert = createLucideIcon("circle-alert", __iconNode$c);
179
+ const CircleAlert = createLucideIcon("circle-alert", __iconNode$d);
180
180
  /**
181
181
  * @license lucide-react v0.552.0 - ISC
182
182
  *
183
183
  * This source code is licensed under the ISC license.
184
184
  * See the LICENSE file in the root directory of this source tree.
185
185
  */
186
- const __iconNode$b = [
186
+ const __iconNode$c = [
187
187
  [
188
188
  "path",
189
189
  {
@@ -201,14 +201,14 @@ const __iconNode$b = [
201
201
  ],
202
202
  ["path", { d: "m2 2 20 20", key: "1ooewy" }]
203
203
  ];
204
- const EyeOff = createLucideIcon("eye-off", __iconNode$b);
204
+ const EyeOff = createLucideIcon("eye-off", __iconNode$c);
205
205
  /**
206
206
  * @license lucide-react v0.552.0 - ISC
207
207
  *
208
208
  * This source code is licensed under the ISC license.
209
209
  * See the LICENSE file in the root directory of this source tree.
210
210
  */
211
- const __iconNode$a = [
211
+ const __iconNode$b = [
212
212
  [
213
213
  "path",
214
214
  {
@@ -218,14 +218,14 @@ const __iconNode$a = [
218
218
  ],
219
219
  ["circle", { cx: "12", cy: "12", r: "3", key: "1v7zrd" }]
220
220
  ];
221
- const Eye = createLucideIcon("eye", __iconNode$a);
221
+ const Eye = createLucideIcon("eye", __iconNode$b);
222
222
  /**
223
223
  * @license lucide-react v0.552.0 - ISC
224
224
  *
225
225
  * This source code is licensed under the ISC license.
226
226
  * See the LICENSE file in the root directory of this source tree.
227
227
  */
228
- const __iconNode$9 = [
228
+ const __iconNode$a = [
229
229
  [
230
230
  "path",
231
231
  {
@@ -236,14 +236,14 @@ const __iconNode$9 = [
236
236
  ["path", { d: "M12 17h.01", key: "p32p05" }],
237
237
  ["path", { d: "M9.1 9a3 3 0 0 1 5.82 1c0 2-3 3-3 3", key: "mhlwft" }]
238
238
  ];
239
- const FileQuestionMark = createLucideIcon("file-question-mark", __iconNode$9);
239
+ const FileQuestionMark = createLucideIcon("file-question-mark", __iconNode$a);
240
240
  /**
241
241
  * @license lucide-react v0.552.0 - ISC
242
242
  *
243
243
  * This source code is licensed under the ISC license.
244
244
  * See the LICENSE file in the root directory of this source tree.
245
245
  */
246
- const __iconNode$8 = [
246
+ const __iconNode$9 = [
247
247
  [
248
248
  "path",
249
249
  {
@@ -256,14 +256,14 @@ const __iconNode$8 = [
256
256
  ["path", { d: "M16 13H8", key: "t4e002" }],
257
257
  ["path", { d: "M16 17H8", key: "z1uh3a" }]
258
258
  ];
259
- const FileText = createLucideIcon("file-text", __iconNode$8);
259
+ const FileText = createLucideIcon("file-text", __iconNode$9);
260
260
  /**
261
261
  * @license lucide-react v0.552.0 - ISC
262
262
  *
263
263
  * This source code is licensed under the ISC license.
264
264
  * See the LICENSE file in the root directory of this source tree.
265
265
  */
266
- const __iconNode$7 = [
266
+ const __iconNode$8 = [
267
267
  [
268
268
  "path",
269
269
  {
@@ -273,14 +273,14 @@ const __iconNode$7 = [
273
273
  ],
274
274
  ["path", { d: "M14 2v5a1 1 0 0 0 1 1h5", key: "wfsgrz" }]
275
275
  ];
276
- const File = createLucideIcon("file", __iconNode$7);
276
+ const File = createLucideIcon("file", __iconNode$8);
277
277
  /**
278
278
  * @license lucide-react v0.552.0 - ISC
279
279
  *
280
280
  * This source code is licensed under the ISC license.
281
281
  * See the LICENSE file in the root directory of this source tree.
282
282
  */
283
- const __iconNode$6 = [
283
+ const __iconNode$7 = [
284
284
  [
285
285
  "path",
286
286
  {
@@ -289,20 +289,32 @@ const __iconNode$6 = [
289
289
  }
290
290
  ]
291
291
  ];
292
- const Folder = createLucideIcon("folder", __iconNode$6);
292
+ const Folder = createLucideIcon("folder", __iconNode$7);
293
293
  /**
294
294
  * @license lucide-react v0.552.0 - ISC
295
295
  *
296
296
  * This source code is licensed under the ISC license.
297
297
  * See the LICENSE file in the root directory of this source tree.
298
298
  */
299
- const __iconNode$5 = [
299
+ const __iconNode$6 = [
300
300
  ["line", { x1: "6", x2: "6", y1: "3", y2: "15", key: "17qcm7" }],
301
301
  ["circle", { cx: "18", cy: "6", r: "3", key: "1h7g24" }],
302
302
  ["circle", { cx: "6", cy: "18", r: "3", key: "fqmcym" }],
303
303
  ["path", { d: "M18 9a9 9 0 0 1-9 9", key: "n2h4wq" }]
304
304
  ];
305
- const GitBranch = createLucideIcon("git-branch", __iconNode$5);
305
+ const GitBranch = createLucideIcon("git-branch", __iconNode$6);
306
+ /**
307
+ * @license lucide-react v0.552.0 - ISC
308
+ *
309
+ * This source code is licensed under the ISC license.
310
+ * See the LICENSE file in the root directory of this source tree.
311
+ */
312
+ const __iconNode$5 = [
313
+ ["circle", { cx: "12", cy: "12", r: "3", key: "1v7zrd" }],
314
+ ["line", { x1: "3", x2: "9", y1: "12", y2: "12", key: "1dyftd" }],
315
+ ["line", { x1: "15", x2: "21", y1: "12", y2: "12", key: "oup4p8" }]
316
+ ];
317
+ const GitCommitHorizontal = createLucideIcon("git-commit-horizontal", __iconNode$5);
306
318
  /**
307
319
  * @license lucide-react v0.552.0 - ISC
308
320
  *
@@ -10227,11 +10239,124 @@ const PrChangesTree = ({
10227
10239
  }
10228
10240
  );
10229
10241
  };
10242
+ const CommitChangesTree = ({
10243
+ commitFiles,
10244
+ rootPath,
10245
+ horizontalPadding = "0px",
10246
+ onFileClick,
10247
+ onNodeHover
10248
+ }) => {
10249
+ const { theme: theme2 } = useTheme();
10250
+ const hasChanges = useMemo(
10251
+ () => commitFiles.added.length > 0 || commitFiles.modified.length > 0 || commitFiles.removed.length > 0 || commitFiles.renamed.length > 0,
10252
+ [commitFiles.added.length, commitFiles.modified.length, commitFiles.removed.length, commitFiles.renamed.length]
10253
+ );
10254
+ const getFileStatus = useCallback(
10255
+ (filePath) => {
10256
+ if (commitFiles.added.includes(filePath)) {
10257
+ return "added";
10258
+ }
10259
+ if (commitFiles.modified.includes(filePath)) {
10260
+ return "modified";
10261
+ }
10262
+ if (commitFiles.removed.includes(filePath)) {
10263
+ return "removed";
10264
+ }
10265
+ if (commitFiles.renamed.includes(filePath)) {
10266
+ return "renamed";
10267
+ }
10268
+ return void 0;
10269
+ },
10270
+ [commitFiles]
10271
+ );
10272
+ const handleFileSelect = useCallback(
10273
+ (filePath) => {
10274
+ const status = getFileStatus(filePath);
10275
+ onFileClick == null ? void 0 : onFileClick(filePath, status);
10276
+ },
10277
+ [getFileStatus, onFileClick]
10278
+ );
10279
+ const commitChangesData = useMemo(() => {
10280
+ if (!hasChanges) {
10281
+ return null;
10282
+ }
10283
+ const statusData = [
10284
+ ...commitFiles.added.map((filePath) => ({
10285
+ filePath,
10286
+ indexStatus: "A",
10287
+ workingTreeStatus: " ",
10288
+ status: "A"
10289
+ })),
10290
+ ...commitFiles.modified.map((filePath) => ({
10291
+ filePath,
10292
+ indexStatus: "M",
10293
+ workingTreeStatus: " ",
10294
+ status: "M"
10295
+ })),
10296
+ ...commitFiles.removed.map((filePath) => ({
10297
+ filePath,
10298
+ indexStatus: "D",
10299
+ workingTreeStatus: " ",
10300
+ status: "D"
10301
+ })),
10302
+ ...commitFiles.renamed.map((filePath) => ({
10303
+ filePath,
10304
+ indexStatus: "R",
10305
+ workingTreeStatus: " ",
10306
+ status: "R"
10307
+ }))
10308
+ ];
10309
+ const allChangedFiles = [
10310
+ ...commitFiles.added,
10311
+ ...commitFiles.modified,
10312
+ ...commitFiles.removed,
10313
+ ...commitFiles.renamed
10314
+ ].sort((a, b) => a.localeCompare(b));
10315
+ const builder = new N();
10316
+ const tree = builder.build({ files: allChangedFiles, rootPath: rootPath ?? "" });
10317
+ return { tree, statusData };
10318
+ }, [hasChanges, commitFiles, rootPath]);
10319
+ if (!hasChanges) {
10320
+ return /* @__PURE__ */ jsx(
10321
+ "div",
10322
+ {
10323
+ style: {
10324
+ padding: "12px 0",
10325
+ fontSize: theme2.fontSizes[0],
10326
+ fontFamily: theme2.fonts.body,
10327
+ color: theme2.colors.textSecondary,
10328
+ fontStyle: "italic",
10329
+ textAlign: "center"
10330
+ },
10331
+ children: "No commit selected"
10332
+ }
10333
+ );
10334
+ }
10335
+ if (!commitChangesData) {
10336
+ return null;
10337
+ }
10338
+ return /* @__PURE__ */ jsx(
10339
+ GitStatusFileTree,
10340
+ {
10341
+ fileTree: commitChangesData.tree,
10342
+ theme: theme2,
10343
+ gitStatusData: commitChangesData.statusData,
10344
+ onFileSelect: handleFileSelect,
10345
+ onNodeHover,
10346
+ transparentBackground: true,
10347
+ horizontalNodePadding: horizontalPadding,
10348
+ verticalPadding: "4px",
10349
+ openByDefault: true
10350
+ }
10351
+ );
10352
+ };
10230
10353
  const Legend = ({
10231
10354
  fileTypes,
10232
10355
  gitStatus,
10233
10356
  prFiles,
10234
10357
  prNumber,
10358
+ commitFiles,
10359
+ commitHash,
10235
10360
  fileTree,
10236
10361
  rootPath,
10237
10362
  agentLayers,
@@ -10242,6 +10367,8 @@ const Legend = ({
10242
10367
  onGitNodeHover,
10243
10368
  onPrFileClick,
10244
10369
  onPrNodeHover,
10370
+ onCommitFileClick,
10371
+ onCommitNodeHover,
10245
10372
  onAgentLayerClick,
10246
10373
  onQualityMetricClick,
10247
10374
  onClearAgentLayers,
@@ -10250,9 +10377,10 @@ const Legend = ({
10250
10377
  const { theme: theme2 } = useTheme();
10251
10378
  const hasGitStatus = gitStatus != null && (gitStatus.staged.length > 0 || gitStatus.unstaged.length > 0 || gitStatus.untracked.length > 0 || gitStatus.deleted.length > 0);
10252
10379
  const hasPrFiles = prFiles != null && (prFiles.added.length > 0 || prFiles.modified.length > 0 || prFiles.removed.length > 0 || prFiles.renamed.length > 0);
10380
+ const hasCommitFiles = commitFiles != null && (commitFiles.added.length > 0 || commitFiles.modified.length > 0 || commitFiles.removed.length > 0 || commitFiles.renamed.length > 0);
10253
10381
  const hasAgentLayers = agentLayers && agentLayers.length > 0;
10254
10382
  const hasQualityMetrics = qualityMetrics && qualityMetrics.length > 0;
10255
- const isEmpty = fileTypes.length === 0 && !hasGitStatus && !hasPrFiles && !hasAgentLayers && !hasQualityMetrics;
10383
+ const isEmpty = fileTypes.length === 0 && !hasGitStatus && !hasPrFiles && !hasCommitFiles && !hasAgentLayers && !hasQualityMetrics;
10256
10384
  const qualityModeLabels = {
10257
10385
  coverage: "Test Coverage",
10258
10386
  eslint: "Linting Quality",
@@ -10601,7 +10729,43 @@ const Legend = ({
10601
10729
  }
10602
10730
  )
10603
10731
  ] }),
10604
- fileTypes.length > 0 && !hasPrFiles && /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "8px", padding: `0 ${horizontalPadding}` }, children: [
10732
+ hasCommitFiles && /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "8px", flex: 1, minHeight: 0 }, children: [
10733
+ /* @__PURE__ */ jsxs(
10734
+ "div",
10735
+ {
10736
+ style: {
10737
+ display: "flex",
10738
+ alignItems: "center",
10739
+ gap: "6px",
10740
+ fontSize: theme2.fontSizes[0],
10741
+ fontFamily: theme2.fonts.body,
10742
+ fontWeight: 600,
10743
+ color: theme2.colors.textSecondary,
10744
+ textTransform: "uppercase",
10745
+ letterSpacing: "0.5px",
10746
+ flexShrink: 0,
10747
+ padding: `0 ${horizontalPadding}`
10748
+ },
10749
+ children: [
10750
+ /* @__PURE__ */ jsx(GitCommitHorizontal, { size: 12 }),
10751
+ "Commit Changes",
10752
+ commitHash ? ` ${commitHash.slice(0, 7)}` : "",
10753
+ hasCommitFiles && ` (${commitFiles.added.length + commitFiles.modified.length + commitFiles.removed.length + commitFiles.renamed.length} files)`
10754
+ ]
10755
+ }
10756
+ ),
10757
+ /* @__PURE__ */ jsx(
10758
+ CommitChangesTree,
10759
+ {
10760
+ commitFiles,
10761
+ rootPath,
10762
+ horizontalPadding,
10763
+ onFileClick: onCommitFileClick,
10764
+ onNodeHover: onCommitNodeHover
10765
+ }
10766
+ )
10767
+ ] }),
10768
+ fileTypes.length > 0 && !hasPrFiles && !hasCommitFiles && /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "8px", padding: `0 ${horizontalPadding}` }, children: [
10605
10769
  /* @__PURE__ */ jsx(
10606
10770
  "div",
10607
10771
  {
@@ -23061,7 +23225,16 @@ var LENS_REGISTRY = [
23061
23225
  outputsAggregate: true,
23062
23226
  colorScheme: "issues",
23063
23227
  description: "Pluggable linting utility for JavaScript and TypeScript",
23064
- command: "eslint"
23228
+ command: "eslint",
23229
+ fileMetricsRequirements: {
23230
+ completeCommand: "npx eslint . --format json",
23231
+ requiredFlags: ["--format json"],
23232
+ formatFlag: "--format json",
23233
+ withoutConfig: "Only files with issues are reported in the output",
23234
+ fallbackStrategy: "source-file-count",
23235
+ nativelyComplete: false,
23236
+ notes: "ESLint JSON output only includes files that have issues. Clean files are not listed."
23237
+ }
23065
23238
  },
23066
23239
  {
23067
23240
  id: "biome-lint",
@@ -23073,7 +23246,16 @@ var LENS_REGISTRY = [
23073
23246
  outputsAggregate: true,
23074
23247
  colorScheme: "issues",
23075
23248
  description: "Fast linter for JavaScript and TypeScript",
23076
- command: "biome lint"
23249
+ command: "biome lint",
23250
+ fileMetricsRequirements: {
23251
+ completeCommand: "npx @biomejs/biome lint . --reporter=json",
23252
+ requiredFlags: ["--reporter=json"],
23253
+ formatFlag: "--reporter=json",
23254
+ withoutConfig: "Output cannot be parsed for file metrics",
23255
+ fallbackStrategy: "source-file-count",
23256
+ nativelyComplete: true,
23257
+ notes: "Biome JSON output includes all analyzed files."
23258
+ }
23077
23259
  },
23078
23260
  {
23079
23261
  id: "oxlint",
@@ -23085,7 +23267,15 @@ var LENS_REGISTRY = [
23085
23267
  outputsAggregate: true,
23086
23268
  colorScheme: "issues",
23087
23269
  description: "Blazing fast JavaScript/TypeScript linter",
23088
- command: "oxlint"
23270
+ command: "oxlint",
23271
+ fileMetricsRequirements: {
23272
+ completeCommand: "npx oxlint --format json",
23273
+ requiredFlags: ["--format json"],
23274
+ formatFlag: "--format json",
23275
+ withoutConfig: "Output cannot be parsed for file metrics",
23276
+ fallbackStrategy: "source-file-count",
23277
+ nativelyComplete: false
23278
+ }
23089
23279
  },
23090
23280
  // Python linting
23091
23281
  {
@@ -23098,7 +23288,16 @@ var LENS_REGISTRY = [
23098
23288
  outputsAggregate: true,
23099
23289
  colorScheme: "issues",
23100
23290
  description: "Extremely fast Python linter",
23101
- command: "ruff check"
23291
+ command: "ruff check",
23292
+ fileMetricsRequirements: {
23293
+ completeCommand: "ruff check . --output-format=json",
23294
+ requiredFlags: ["--output-format=json"],
23295
+ formatFlag: "--output-format=json",
23296
+ withoutConfig: "Output cannot be parsed for file metrics",
23297
+ fallbackStrategy: "source-file-count",
23298
+ nativelyComplete: false,
23299
+ notes: "Ruff JSON output only includes files with issues."
23300
+ }
23102
23301
  },
23103
23302
  {
23104
23303
  id: "pylint",
@@ -23109,7 +23308,15 @@ var LENS_REGISTRY = [
23109
23308
  outputsAggregate: true,
23110
23309
  colorScheme: "issues",
23111
23310
  description: "Python static code analyzer",
23112
- command: "pylint"
23311
+ command: "pylint",
23312
+ fileMetricsRequirements: {
23313
+ completeCommand: "pylint --output-format=json .",
23314
+ requiredFlags: ["--output-format=json"],
23315
+ formatFlag: "--output-format=json",
23316
+ withoutConfig: "Output cannot be parsed for file metrics",
23317
+ fallbackStrategy: "source-file-count",
23318
+ nativelyComplete: false
23319
+ }
23113
23320
  },
23114
23321
  // Go linting
23115
23322
  {
@@ -23133,7 +23340,16 @@ var LENS_REGISTRY = [
23133
23340
  outputsAggregate: true,
23134
23341
  colorScheme: "issues",
23135
23342
  description: "Rust linter",
23136
- command: "cargo clippy"
23343
+ command: "cargo clippy",
23344
+ fileMetricsRequirements: {
23345
+ completeCommand: "cargo clippy --workspace --all-features --message-format json -- -D warnings",
23346
+ requiredFlags: ["--message-format json"],
23347
+ formatFlag: "--message-format json",
23348
+ withoutConfig: "Only files with issues are reported in the output",
23349
+ fallbackStrategy: "source-file-count",
23350
+ nativelyComplete: false,
23351
+ notes: "Clippy JSON output only includes files with issues. Use cargo metadata to get complete file list."
23352
+ }
23137
23353
  },
23138
23354
  // ============================================================
23139
23355
  // FORMATTING - Code formatting
@@ -23148,7 +23364,15 @@ var LENS_REGISTRY = [
23148
23364
  outputsAggregate: true,
23149
23365
  colorScheme: "binary",
23150
23366
  description: "Opinionated code formatter",
23151
- command: "prettier --check"
23367
+ command: "prettier --check",
23368
+ fileMetricsRequirements: {
23369
+ completeCommand: "npx prettier --check . --no-error-on-unmatched-pattern --log-level debug",
23370
+ requiredFlags: ["--check", "--log-level debug"],
23371
+ withoutConfig: "Without --log-level debug, file list is not available",
23372
+ fallbackStrategy: "source-file-count",
23373
+ nativelyComplete: true,
23374
+ notes: "Prettier with --log-level debug lists all checked files. This is the reference implementation for complete file metrics."
23375
+ }
23152
23376
  },
23153
23377
  {
23154
23378
  id: "biome-format",
@@ -23160,7 +23384,15 @@ var LENS_REGISTRY = [
23160
23384
  outputsAggregate: true,
23161
23385
  colorScheme: "binary",
23162
23386
  description: "Fast code formatter for JavaScript and TypeScript",
23163
- command: "biome format"
23387
+ command: "biome format",
23388
+ fileMetricsRequirements: {
23389
+ completeCommand: "npx @biomejs/biome format . --reporter=json",
23390
+ requiredFlags: ["--reporter=json"],
23391
+ formatFlag: "--reporter=json",
23392
+ withoutConfig: "Output cannot be parsed for file metrics",
23393
+ fallbackStrategy: "source-file-count",
23394
+ nativelyComplete: true
23395
+ }
23164
23396
  },
23165
23397
  // Python formatting
23166
23398
  {
@@ -23208,7 +23440,15 @@ var LENS_REGISTRY = [
23208
23440
  outputsAggregate: true,
23209
23441
  colorScheme: "binary",
23210
23442
  description: "Rust code formatter",
23211
- command: "cargo fmt --check"
23443
+ command: "cargo fmt --check",
23444
+ fileMetricsRequirements: {
23445
+ completeCommand: "cargo fmt --all --check",
23446
+ requiredFlags: ["--check"],
23447
+ withoutConfig: "Without --check, files are modified in place",
23448
+ fallbackStrategy: "source-file-count",
23449
+ nativelyComplete: false,
23450
+ notes: "rustfmt only outputs files that need formatting. Use cargo metadata or glob for complete file list."
23451
+ }
23212
23452
  },
23213
23453
  // ============================================================
23214
23454
  // TYPES - Type checking
@@ -23223,7 +23463,15 @@ var LENS_REGISTRY = [
23223
23463
  outputsAggregate: true,
23224
23464
  colorScheme: "issues",
23225
23465
  description: "TypeScript type checker",
23226
- command: "tsc --noEmit"
23466
+ command: "tsc --noEmit",
23467
+ fileMetricsRequirements: {
23468
+ completeCommand: "npx tsc --noEmit --listFiles",
23469
+ requiredFlags: ["--listFiles"],
23470
+ withoutConfig: "Only files with type errors are reported. Cannot determine total files analyzed.",
23471
+ fallbackStrategy: "source-file-count",
23472
+ nativelyComplete: false,
23473
+ notes: "The --listFiles flag is REQUIRED to get the complete list of files TypeScript analyzed. Without it, only files with errors appear in output."
23474
+ }
23227
23475
  },
23228
23476
  // Python type checking
23229
23477
  {
@@ -23274,7 +23522,16 @@ var LENS_REGISTRY = [
23274
23522
  outputsAggregate: true,
23275
23523
  colorScheme: "coverage",
23276
23524
  description: "JavaScript testing framework",
23277
- command: "jest --coverage"
23525
+ command: "jest --coverage",
23526
+ fileMetricsRequirements: {
23527
+ completeCommand: "npx jest --coverage --json --outputFile=jest-results.json",
23528
+ requiredFlags: ["--coverage", "--json"],
23529
+ formatFlag: "--json",
23530
+ withoutConfig: "Without --coverage, no per-file coverage data is available. Without --json, output cannot be parsed.",
23531
+ fallbackStrategy: "coverage-only",
23532
+ nativelyComplete: false,
23533
+ notes: "Jest coverage data provides per-file metrics for source files. Test file results are separate from source coverage."
23534
+ }
23278
23535
  },
23279
23536
  {
23280
23537
  id: "vitest",
@@ -23286,7 +23543,16 @@ var LENS_REGISTRY = [
23286
23543
  outputsAggregate: true,
23287
23544
  colorScheme: "coverage",
23288
23545
  description: "Vite-native testing framework",
23289
- command: "vitest run --coverage"
23546
+ command: "vitest run --coverage",
23547
+ fileMetricsRequirements: {
23548
+ completeCommand: "npx vitest run --coverage --reporter=json",
23549
+ requiredFlags: ["--coverage", "--reporter=json"],
23550
+ formatFlag: "--reporter=json",
23551
+ withoutConfig: "Without --coverage, no per-file coverage data is available",
23552
+ fallbackStrategy: "coverage-only",
23553
+ nativelyComplete: false,
23554
+ notes: "Vitest coverage provides per-file metrics. Requires @vitest/coverage-v8 or @vitest/coverage-istanbul."
23555
+ }
23290
23556
  },
23291
23557
  {
23292
23558
  id: "bun-test",
@@ -23298,7 +23564,35 @@ var LENS_REGISTRY = [
23298
23564
  outputsAggregate: true,
23299
23565
  colorScheme: "coverage",
23300
23566
  description: "Bun native test runner",
23301
- command: "bun test"
23567
+ command: "bun test",
23568
+ fileMetricsRequirements: {
23569
+ completeCommand: "bun test --coverage",
23570
+ requiredFlags: ["--coverage"],
23571
+ withoutConfig: "Without --coverage, no per-file coverage data is available",
23572
+ fallbackStrategy: "coverage-only",
23573
+ nativelyComplete: false,
23574
+ notes: "Bun test coverage is built-in but requires --coverage flag."
23575
+ }
23576
+ },
23577
+ {
23578
+ id: "node-test",
23579
+ name: "Node Test",
23580
+ category: "tests",
23581
+ languages: ["typescript", "javascript"],
23582
+ alternativeTo: ["jest", "vitest", "bun-test"],
23583
+ outputsFileMetrics: true,
23584
+ outputsAggregate: true,
23585
+ colorScheme: "coverage",
23586
+ description: "Node.js native test runner",
23587
+ command: "node --test",
23588
+ fileMetricsRequirements: {
23589
+ completeCommand: "node --test --experimental-test-coverage",
23590
+ requiredFlags: ["--experimental-test-coverage"],
23591
+ withoutConfig: "Without --experimental-test-coverage, no per-file coverage data is available",
23592
+ fallbackStrategy: "coverage-only",
23593
+ nativelyComplete: false,
23594
+ notes: "Node.js native test runner (node:test) uses TAP output format. Coverage requires --experimental-test-coverage flag (Node 20+). Also works with tsx --test for TypeScript."
23595
+ }
23302
23596
  },
23303
23597
  // Python testing
23304
23598
  {
@@ -23334,7 +23628,37 @@ var LENS_REGISTRY = [
23334
23628
  outputsAggregate: true,
23335
23629
  colorScheme: "coverage",
23336
23630
  description: "Rust test runner",
23337
- command: "cargo test"
23631
+ command: "cargo test",
23632
+ fileMetricsRequirements: {
23633
+ completeCommand: "cargo test --workspace --no-fail-fast -- -Z unstable-options --format json",
23634
+ requiredFlags: ["--format json"],
23635
+ formatFlag: "--format json",
23636
+ withoutConfig: "Without JSON format, output cannot be parsed for test results",
23637
+ fallbackStrategy: "coverage-only",
23638
+ nativelyComplete: false,
23639
+ notes: "JSON format requires nightly or -Z unstable-options. Consider cargo-nextest for stable JSON output."
23640
+ }
23641
+ },
23642
+ {
23643
+ id: "cargo-nextest",
23644
+ name: "Cargo Nextest",
23645
+ category: "tests",
23646
+ languages: ["rust"],
23647
+ alternativeTo: ["cargo-test"],
23648
+ outputsFileMetrics: true,
23649
+ outputsAggregate: true,
23650
+ colorScheme: "coverage",
23651
+ description: "Next-generation Rust test runner",
23652
+ command: "cargo nextest run",
23653
+ fileMetricsRequirements: {
23654
+ completeCommand: "cargo nextest run --workspace --message-format libtest-json",
23655
+ requiredFlags: ["--message-format libtest-json"],
23656
+ formatFlag: "--message-format libtest-json",
23657
+ withoutConfig: "Without JSON format, output cannot be parsed",
23658
+ fallbackStrategy: "coverage-only",
23659
+ nativelyComplete: false,
23660
+ notes: "Nextest provides stable JSON output without nightly features."
23661
+ }
23338
23662
  },
23339
23663
  // ============================================================
23340
23664
  // DEAD CODE - Unused code detection
@@ -23349,7 +23673,16 @@ var LENS_REGISTRY = [
23349
23673
  outputsAggregate: true,
23350
23674
  colorScheme: "issues",
23351
23675
  description: "Find unused files, dependencies and exports",
23352
- command: "knip"
23676
+ command: "knip",
23677
+ fileMetricsRequirements: {
23678
+ completeCommand: "npx knip --reporter json",
23679
+ requiredFlags: ["--reporter json"],
23680
+ formatFlag: "--reporter json",
23681
+ withoutConfig: "Output cannot be parsed for file metrics",
23682
+ fallbackStrategy: "source-file-count",
23683
+ nativelyComplete: false,
23684
+ notes: "Knip reports unused files and exports. It does not list all analyzed files, only those with issues."
23685
+ }
23353
23686
  },
23354
23687
  // Python
23355
23688
  {
@@ -23375,7 +23708,16 @@ var LENS_REGISTRY = [
23375
23708
  outputsAggregate: true,
23376
23709
  colorScheme: "binary",
23377
23710
  description: "Documentation coverage checker",
23378
- command: "alexandria lint"
23711
+ command: "alexandria lint",
23712
+ fileMetricsRequirements: {
23713
+ completeCommand: "npx @principal-ai/alexandria-cli coverage --json",
23714
+ requiredFlags: ["--json"],
23715
+ formatFlag: "--json",
23716
+ withoutConfig: "Output cannot be parsed for file metrics",
23717
+ fallbackStrategy: "source-file-count",
23718
+ nativelyComplete: true,
23719
+ notes: "Alexandria reports documentation coverage for all analyzed files."
23720
+ }
23379
23721
  },
23380
23722
  {
23381
23723
  id: "typedoc",
@@ -24522,7 +24864,7 @@ const CodeCityPanelContent = ({
24522
24864
  actions: actions2,
24523
24865
  events
24524
24866
  }) => {
24525
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
24867
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
24526
24868
  const { theme: theme2 } = useTheme();
24527
24869
  const [cityData, setCityData] = useState(null);
24528
24870
  const [hoverInfo, setHoverInfo] = useState(null);
@@ -25777,11 +26119,15 @@ const CodeCityPanelContent = ({
25777
26119
  gitStatus: gitSlice == null ? void 0 : gitSlice.data,
25778
26120
  prFiles: (_p = prFilesSlice == null ? void 0 : prFilesSlice.data) == null ? void 0 : _p.filesByStatus,
25779
26121
  prNumber: (_q = prFilesSlice == null ? void 0 : prFilesSlice.data) == null ? void 0 : _q.pullNumber,
26122
+ commitFiles: (_r = commitFilesSlice == null ? void 0 : commitFilesSlice.data) == null ? void 0 : _r.filesByStatus,
26123
+ commitHash: (_s = commitFilesSlice == null ? void 0 : commitFilesSlice.data) == null ? void 0 : _s.commitHash,
25780
26124
  fileTree: fileTreeSlice == null ? void 0 : fileTreeSlice.data,
25781
- rootPath: (_r = context.currentScope.repository) == null ? void 0 : _r.path,
26125
+ rootPath: (_t = context.currentScope.repository) == null ? void 0 : _t.path,
25782
26126
  onGitFileClick: handleFileClick,
25783
26127
  onGitNodeHover: handleGitNodeHover,
25784
26128
  onPrFileClick: handleFileClick,
26129
+ onCommitFileClick: handleFileClick,
26130
+ onCommitNodeHover: handleGitNodeHover,
25785
26131
  position: layout.legendPosition
25786
26132
  }
25787
26133
  ),
@@ -25796,10 +26142,12 @@ const CodeCityPanelContent = ({
25796
26142
  {
25797
26143
  fileTypes: legendFileTypes,
25798
26144
  gitStatus: gitSlice == null ? void 0 : gitSlice.data,
25799
- prFiles: (_s = prFilesSlice == null ? void 0 : prFilesSlice.data) == null ? void 0 : _s.filesByStatus,
25800
- prNumber: (_t = prFilesSlice == null ? void 0 : prFilesSlice.data) == null ? void 0 : _t.pullNumber,
26145
+ prFiles: (_u = prFilesSlice == null ? void 0 : prFilesSlice.data) == null ? void 0 : _u.filesByStatus,
26146
+ prNumber: (_v = prFilesSlice == null ? void 0 : prFilesSlice.data) == null ? void 0 : _v.pullNumber,
26147
+ commitFiles: (_w = commitFilesSlice == null ? void 0 : commitFilesSlice.data) == null ? void 0 : _w.filesByStatus,
26148
+ commitHash: (_x = commitFilesSlice == null ? void 0 : commitFilesSlice.data) == null ? void 0 : _x.commitHash,
25801
26149
  fileTree: fileTreeSlice == null ? void 0 : fileTreeSlice.data,
25802
- rootPath: (_u = context.currentScope.repository) == null ? void 0 : _u.path,
26150
+ rootPath: (_y = context.currentScope.repository) == null ? void 0 : _y.path,
25803
26151
  agentLayers: legendAgentLayers,
25804
26152
  qualityMetrics: legendQualityMetrics,
25805
26153
  colorMode,
@@ -25808,6 +26156,8 @@ const CodeCityPanelContent = ({
25808
26156
  onGitNodeHover: handleGitNodeHover,
25809
26157
  onPrFileClick: handleFileClick,
25810
26158
  onPrNodeHover: handleGitNodeHover,
26159
+ onCommitFileClick: handleFileClick,
26160
+ onCommitNodeHover: handleGitNodeHover,
25811
26161
  onAgentLayerClick: toggleAgentLayer,
25812
26162
  onQualityMetricClick: toggleQualityMetric,
25813
26163
  onClearAgentLayers: clearAgentLayers,