openspec-stat 1.0.0 → 1.2.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.
@@ -66,6 +66,16 @@ export interface BranchStats {
66
66
  deletions: number;
67
67
  netChanges: number;
68
68
  }
69
+ export interface ProposalStats {
70
+ proposal: string;
71
+ commits: number;
72
+ contributors: Set<string>;
73
+ codeFilesChanged: number;
74
+ additions: number;
75
+ deletions: number;
76
+ netChanges: number;
77
+ commitHashes: Set<string>;
78
+ }
69
79
  export interface StatsResult {
70
80
  timeRange: {
71
81
  since: Date;
@@ -73,5 +83,6 @@ export interface StatsResult {
73
83
  };
74
84
  branches: string[];
75
85
  authors: Map<string, AuthorStats>;
86
+ proposals: Map<string, ProposalStats>;
76
87
  totalCommits: number;
77
88
  }
package/dist/esm/cli.js CHANGED
@@ -13,7 +13,7 @@ import { getDefaultTimeRange, parseDateTime, parseBranches } from "./time-utils.
13
13
  import { selectBranches } from "./branch-selector.js";
14
14
  import { initI18n, t } from "./i18n/index.js";
15
15
  var program = new Command();
16
- program.name('openspec-stat').description('Track team members\' OpenSpec proposals and code changes in Git repositories').version('0.0.1').option('-r, --repo <path>', 'Repository path', '.').option('-b, --branches <branches>', 'Branch list, comma-separated').option('--no-interactive', 'Disable interactive branch selection').option('-s, --since <datetime>', 'Start time (default: yesterday 20:00)').option('-u, --until <datetime>', 'End time (default: today 20:00)').option('-a, --author <name>', 'Filter by specific author').option('--json', 'Output in JSON format').option('--csv', 'Output in CSV format').option('--markdown', 'Output in Markdown format').option('-c, --config <path>', 'Configuration file path').option('-v, --verbose', 'Verbose output mode').option('-l, --lang <language>', 'Language for output (en, zh-CN)', 'en').action( /*#__PURE__*/function () {
16
+ program.name('openspec-stat').description("Track team members' OpenSpec proposals and code changes in Git repositories").version('0.0.1').option('-r, --repo <path>', 'Repository path', '.').option('-b, --branches <branches>', 'Branch list, comma-separated').option('--no-interactive', 'Disable interactive branch selection').option('-s, --since <datetime>', 'Start time (default: yesterday 20:00)').option('-u, --until <datetime>', 'End time (default: today 20:00)').option('-a, --author <name>', 'Filter by specific author').option('--json', 'Output in JSON format').option('--csv', 'Output in CSV format').option('--markdown', 'Output in Markdown format').option('-c, --config <path>', 'Configuration file path').option('-v, --verbose', 'Verbose output mode').option('-l, --lang <language>', 'Language for output (en, zh-CN)', 'en').action( /*#__PURE__*/function () {
17
17
  var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(options) {
18
18
  var config, since, until, defaultRange, branches, analyzer, activeAuthors, commits, analyses, i, commit, analysis, aggregator, result, formatter;
19
19
  return _regeneratorRuntime().wrap(function _callee$(_context) {
@@ -34,14 +34,70 @@ export var OutputFormatter = /*#__PURE__*/function () {
34
34
  output += chalk.gray(t('output.totalCommits', {
35
35
  count: String(result.totalCommits)
36
36
  }));
37
+
38
+ // Proposal Summary Table
39
+ if (result.proposals.size > 0) {
40
+ output += chalk.bold.magenta("\n".concat(t('output.proposalSummary'), "\n"));
41
+ var proposalTable = new Table({
42
+ head: [chalk.magenta(t('table.proposal')), chalk.magenta(t('table.commits')), chalk.magenta(t('table.contributors')), chalk.magenta(t('table.codeFiles')), chalk.magenta(t('table.additions')), chalk.magenta(t('table.deletions')), chalk.magenta(t('table.netChanges'))],
43
+ style: {
44
+ head: [],
45
+ border: []
46
+ }
47
+ });
48
+ var sortedProposals = Array.from(result.proposals.values()).sort(function (a, b) {
49
+ return b.netChanges - a.netChanges;
50
+ });
51
+ var _iterator = _createForOfIteratorHelper(sortedProposals),
52
+ _step;
53
+ try {
54
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
55
+ var proposalStats = _step.value;
56
+ var contributors = Array.from(proposalStats.contributors).join(', ');
57
+ proposalTable.push([proposalStats.proposal, proposalStats.commits.toString(), contributors, proposalStats.codeFilesChanged.toString(), chalk.green("+".concat(proposalStats.additions)), chalk.red("-".concat(proposalStats.deletions)), proposalStats.netChanges >= 0 ? chalk.green("+".concat(proposalStats.netChanges)) : chalk.red("".concat(proposalStats.netChanges))]);
58
+ }
59
+ } catch (err) {
60
+ _iterator.e(err);
61
+ } finally {
62
+ _iterator.f();
63
+ }
64
+ output += proposalTable.toString() + '\n';
65
+
66
+ // Proposal summary totals
67
+ var totalProposals = result.proposals.size;
68
+ var totalProposalCommits = Array.from(result.proposals.values()).reduce(function (sum, p) {
69
+ return sum + p.commits;
70
+ }, 0);
71
+ var totalProposalFiles = Array.from(result.proposals.values()).reduce(function (sum, p) {
72
+ return sum + p.codeFilesChanged;
73
+ }, 0);
74
+ var totalProposalAdditions = Array.from(result.proposals.values()).reduce(function (sum, p) {
75
+ return sum + p.additions;
76
+ }, 0);
77
+ var totalProposalDeletions = Array.from(result.proposals.values()).reduce(function (sum, p) {
78
+ return sum + p.deletions;
79
+ }, 0);
80
+ var totalProposalNetChanges = Array.from(result.proposals.values()).reduce(function (sum, p) {
81
+ return sum + p.netChanges;
82
+ }, 0);
83
+ output += chalk.gray(t('output.proposalTotal', {
84
+ count: totalProposals.toString(),
85
+ commits: totalProposalCommits.toString(),
86
+ files: totalProposalFiles.toString(),
87
+ additions: totalProposalAdditions.toString(),
88
+ deletions: totalProposalDeletions.toString(),
89
+ netChanges: totalProposalNetChanges.toString()
90
+ }));
91
+ }
92
+ output += chalk.bold.cyan("\n".concat(t('output.authorSummary'), "\n"));
37
93
  var sortedAuthors = Array.from(result.authors.values()).sort(function (a, b) {
38
94
  return b.commits - a.commits;
39
95
  });
40
- var _iterator = _createForOfIteratorHelper(sortedAuthors),
41
- _step;
96
+ var _iterator2 = _createForOfIteratorHelper(sortedAuthors),
97
+ _step2;
42
98
  try {
43
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
44
- var stats = _step.value;
99
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
100
+ var stats = _step2.value;
45
101
  output += chalk.bold.cyan("\n".concat(stats.author, "\n"));
46
102
  if (stats.branchStats && stats.branchStats.size > 0) {
47
103
  var branchTable = new Table({
@@ -54,17 +110,17 @@ export var OutputFormatter = /*#__PURE__*/function () {
54
110
  var sortedBranches = Array.from(stats.branchStats.values()).sort(function (a, b) {
55
111
  return b.commits - a.commits;
56
112
  });
57
- var _iterator2 = _createForOfIteratorHelper(sortedBranches),
58
- _step2;
113
+ var _iterator3 = _createForOfIteratorHelper(sortedBranches),
114
+ _step3;
59
115
  try {
60
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
61
- var branchStat = _step2.value;
116
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
117
+ var branchStat = _step3.value;
62
118
  branchTable.push([branchStat.branch, branchStat.commits.toString(), branchStat.openspecProposals.size.toString(), branchStat.codeFilesChanged.toString(), chalk.green("+".concat(branchStat.additions)), chalk.red("-".concat(branchStat.deletions)), branchStat.netChanges >= 0 ? chalk.green("+".concat(branchStat.netChanges)) : chalk.red("".concat(branchStat.netChanges))]);
63
119
  }
64
120
  } catch (err) {
65
- _iterator2.e(err);
121
+ _iterator3.e(err);
66
122
  } finally {
67
- _iterator2.f();
123
+ _iterator3.f();
68
124
  }
69
125
  branchTable.push([chalk.bold.yellow(t('table.totalDeduplicated')), chalk.bold(stats.commits.toString()), chalk.bold(stats.openspecProposals.size.toString()), chalk.bold(stats.codeFilesChanged.toString()), chalk.bold.green("+".concat(stats.additions)), chalk.bold.red("-".concat(stats.deletions)), stats.netChanges >= 0 ? chalk.bold.green("+".concat(stats.netChanges)) : chalk.bold.red("".concat(stats.netChanges))]);
70
126
  output += branchTable.toString() + '\n';
@@ -86,9 +142,9 @@ export var OutputFormatter = /*#__PURE__*/function () {
86
142
  }
87
143
  }
88
144
  } catch (err) {
89
- _iterator.e(err);
145
+ _iterator2.e(err);
90
146
  } finally {
91
- _iterator.f();
147
+ _iterator2.f();
92
148
  }
93
149
  return output;
94
150
  }
@@ -102,6 +158,38 @@ export var OutputFormatter = /*#__PURE__*/function () {
102
158
  },
103
159
  branches: result.branches,
104
160
  totalCommits: result.totalCommits,
161
+ proposals: {
162
+ items: Array.from(result.proposals.values()).map(function (stats) {
163
+ return {
164
+ proposal: stats.proposal,
165
+ commits: stats.commits,
166
+ contributors: Array.from(stats.contributors),
167
+ contributorCount: stats.contributors.size,
168
+ codeFilesChanged: stats.codeFilesChanged,
169
+ additions: stats.additions,
170
+ deletions: stats.deletions,
171
+ netChanges: stats.netChanges
172
+ };
173
+ }),
174
+ summary: {
175
+ totalProposals: result.proposals.size,
176
+ totalCommits: Array.from(result.proposals.values()).reduce(function (sum, p) {
177
+ return sum + p.commits;
178
+ }, 0),
179
+ totalCodeFiles: Array.from(result.proposals.values()).reduce(function (sum, p) {
180
+ return sum + p.codeFilesChanged;
181
+ }, 0),
182
+ totalAdditions: Array.from(result.proposals.values()).reduce(function (sum, p) {
183
+ return sum + p.additions;
184
+ }, 0),
185
+ totalDeletions: Array.from(result.proposals.values()).reduce(function (sum, p) {
186
+ return sum + p.deletions;
187
+ }, 0),
188
+ totalNetChanges: Array.from(result.proposals.values()).reduce(function (sum, p) {
189
+ return sum + p.netChanges;
190
+ }, 0)
191
+ }
192
+ },
105
193
  authors: Array.from(result.authors.values()).map(function (stats) {
106
194
  var _stats$lastCommitDate;
107
195
  return {
@@ -123,23 +211,72 @@ export var OutputFormatter = /*#__PURE__*/function () {
123
211
  key: "formatCSV",
124
212
  value: function formatCSV(result) {
125
213
  var rows = [];
214
+
215
+ // Proposal summary section
216
+ rows.push("\n# ".concat(t('output.proposalSummary')));
217
+ rows.push("".concat(t('table.proposal'), ",").concat(t('table.commits'), ",").concat(t('table.contributors'), ",").concat(t('table.codeFiles'), ",").concat(t('table.additions'), ",").concat(t('table.deletions'), ",").concat(t('table.netChanges')));
218
+ var sortedProposals = Array.from(result.proposals.values()).sort(function (a, b) {
219
+ return b.netChanges - a.netChanges;
220
+ });
221
+ var _iterator4 = _createForOfIteratorHelper(sortedProposals),
222
+ _step4;
223
+ try {
224
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
225
+ var stats = _step4.value;
226
+ var contributors = Array.from(stats.contributors).join(';');
227
+ rows.push([stats.proposal, stats.commits, "\"".concat(contributors, "\""), stats.codeFilesChanged, stats.additions, stats.deletions, stats.netChanges].join(','));
228
+ }
229
+
230
+ // Proposal totals
231
+ } catch (err) {
232
+ _iterator4.e(err);
233
+ } finally {
234
+ _iterator4.f();
235
+ }
236
+ var totalProposals = result.proposals.size;
237
+ var totalProposalCommits = Array.from(result.proposals.values()).reduce(function (sum, p) {
238
+ return sum + p.commits;
239
+ }, 0);
240
+ var totalProposalFiles = Array.from(result.proposals.values()).reduce(function (sum, p) {
241
+ return sum + p.codeFilesChanged;
242
+ }, 0);
243
+ var totalProposalAdditions = Array.from(result.proposals.values()).reduce(function (sum, p) {
244
+ return sum + p.additions;
245
+ }, 0);
246
+ var totalProposalDeletions = Array.from(result.proposals.values()).reduce(function (sum, p) {
247
+ return sum + p.deletions;
248
+ }, 0);
249
+ var totalProposalNetChanges = Array.from(result.proposals.values()).reduce(function (sum, p) {
250
+ return sum + p.netChanges;
251
+ }, 0);
252
+ rows.push('');
253
+ rows.push("# ".concat(t('output.proposalTotalLabel')));
254
+ rows.push("".concat(t('table.proposals'), ",").concat(totalProposals));
255
+ rows.push("".concat(t('table.commits'), ",").concat(totalProposalCommits));
256
+ rows.push("".concat(t('table.codeFiles'), ",").concat(totalProposalFiles));
257
+ rows.push("".concat(t('table.additions'), ",").concat(totalProposalAdditions));
258
+ rows.push("".concat(t('table.deletions'), ",").concat(totalProposalDeletions));
259
+ rows.push("".concat(t('table.netChanges'), ",").concat(totalProposalNetChanges));
260
+
261
+ // Author summary section
262
+ rows.push("\n# ".concat(t('output.authorSummary')));
126
263
  rows.push("".concat(t('table.author'), ",").concat(t('table.period'), ",").concat(t('table.commits'), ",").concat(t('table.proposalsCount'), ",").concat(t('table.proposalsList'), ",").concat(t('table.codeFiles'), ",").concat(t('table.additions'), ",").concat(t('table.deletions'), ",").concat(t('table.netChanges'), ",").concat(t('table.lastCommitDate')));
127
264
  var sortedAuthors = Array.from(result.authors.values()).sort(function (a, b) {
128
265
  return b.commits - a.commits;
129
266
  });
130
- var _iterator3 = _createForOfIteratorHelper(sortedAuthors),
131
- _step3;
267
+ var _iterator5 = _createForOfIteratorHelper(sortedAuthors),
268
+ _step5;
132
269
  try {
133
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
270
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
134
271
  var _stats$lastCommitDate2;
135
- var stats = _step3.value;
136
- var proposals = Array.from(stats.openspecProposals).join(';');
137
- rows.push([stats.author, stats.statisticsPeriod || '-', stats.commits, stats.openspecProposals.size, "\"".concat(proposals, "\""), stats.codeFilesChanged, stats.additions, stats.deletions, stats.netChanges, ((_stats$lastCommitDate2 = stats.lastCommitDate) === null || _stats$lastCommitDate2 === void 0 ? void 0 : _stats$lastCommitDate2.toISOString()) || ''].join(','));
272
+ var _stats = _step5.value;
273
+ var proposals = Array.from(_stats.openspecProposals).join(';');
274
+ rows.push([_stats.author, _stats.statisticsPeriod || '-', _stats.commits, _stats.openspecProposals.size, "\"".concat(proposals, "\""), _stats.codeFilesChanged, _stats.additions, _stats.deletions, _stats.netChanges, ((_stats$lastCommitDate2 = _stats.lastCommitDate) === null || _stats$lastCommitDate2 === void 0 ? void 0 : _stats$lastCommitDate2.toISOString()) || ''].join(','));
138
275
  }
139
276
  } catch (err) {
140
- _iterator3.e(err);
277
+ _iterator5.e(err);
141
278
  } finally {
142
- _iterator3.f();
279
+ _iterator5.f();
143
280
  }
144
281
  return rows.join('\n');
145
282
  }
@@ -162,33 +299,81 @@ export var OutputFormatter = /*#__PURE__*/function () {
162
299
  md += t('markdown.totalCommits', {
163
300
  count: String(result.totalCommits)
164
301
  });
165
- md += t('markdown.statistics');
302
+
303
+ // Proposal summary
304
+ md += "\n## ".concat(t('output.proposalSummary'), "\n\n");
305
+ md += "| ".concat(t('table.proposal'), " | ").concat(t('table.commits'), " | ").concat(t('table.contributors'), " | ").concat(t('table.codeFiles'), " | ").concat(t('table.additions'), " | ").concat(t('table.deletions'), " | ").concat(t('table.netChanges'), " |\n");
306
+ md += '|--------|---------|-------------|------------|-----------|-----------|-------------|\n';
307
+ var sortedProposals = Array.from(result.proposals.values()).sort(function (a, b) {
308
+ return b.netChanges - a.netChanges;
309
+ });
310
+ var _iterator6 = _createForOfIteratorHelper(sortedProposals),
311
+ _step6;
312
+ try {
313
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
314
+ var stats = _step6.value;
315
+ var contributors = Array.from(stats.contributors).join(', ');
316
+ md += "| ".concat(stats.proposal, " | ").concat(stats.commits, " | ").concat(contributors, " | ").concat(stats.codeFilesChanged, " | +").concat(stats.additions, " | -").concat(stats.deletions, " | ").concat(stats.netChanges >= 0 ? '+' : '').concat(stats.netChanges, " |\n");
317
+ }
318
+
319
+ // Proposal totals
320
+ } catch (err) {
321
+ _iterator6.e(err);
322
+ } finally {
323
+ _iterator6.f();
324
+ }
325
+ var totalProposals = result.proposals.size;
326
+ var totalProposalCommits = Array.from(result.proposals.values()).reduce(function (sum, p) {
327
+ return sum + p.commits;
328
+ }, 0);
329
+ var totalProposalFiles = Array.from(result.proposals.values()).reduce(function (sum, p) {
330
+ return sum + p.codeFilesChanged;
331
+ }, 0);
332
+ var totalProposalAdditions = Array.from(result.proposals.values()).reduce(function (sum, p) {
333
+ return sum + p.additions;
334
+ }, 0);
335
+ var totalProposalDeletions = Array.from(result.proposals.values()).reduce(function (sum, p) {
336
+ return sum + p.deletions;
337
+ }, 0);
338
+ var totalProposalNetChanges = Array.from(result.proposals.values()).reduce(function (sum, p) {
339
+ return sum + p.netChanges;
340
+ }, 0);
341
+ md += "\n**".concat(t('output.proposalTotalLabel'), "**\n");
342
+ md += "- ".concat(t('table.proposals'), ": ").concat(totalProposals, "\n");
343
+ md += "- ".concat(t('table.commits'), ": ").concat(totalProposalCommits, "\n");
344
+ md += "- ".concat(t('table.codeFiles'), ": ").concat(totalProposalFiles, "\n");
345
+ md += "- ".concat(t('table.additions'), ": +").concat(totalProposalAdditions, "\n");
346
+ md += "- ".concat(t('table.deletions'), ": -").concat(totalProposalDeletions, "\n");
347
+ md += "- ".concat(t('table.netChanges'), ": ").concat(totalProposalNetChanges >= 0 ? '+' : '').concat(totalProposalNetChanges, "\n");
348
+
349
+ // Author summary
350
+ md += "\n## ".concat(t('output.authorSummary'), "\n\n");
166
351
  md += "| ".concat(t('table.author'), " | ").concat(t('table.period'), " | ").concat(t('table.commits'), " | ").concat(t('table.proposals'), " | ").concat(t('table.codeFiles'), " | ").concat(t('table.additions'), " | ").concat(t('table.deletions'), " | ").concat(t('table.netChanges'), " |\n");
167
352
  md += '|--------|--------|---------|-----------|------------|-----------|-----------|-------------|\n';
168
353
  var sortedAuthors = Array.from(result.authors.values()).sort(function (a, b) {
169
354
  return b.commits - a.commits;
170
355
  });
171
- var _iterator4 = _createForOfIteratorHelper(sortedAuthors),
172
- _step4;
356
+ var _iterator7 = _createForOfIteratorHelper(sortedAuthors),
357
+ _step7;
173
358
  try {
174
- for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
175
- var stats = _step4.value;
176
- md += "| ".concat(stats.author, " | ").concat(stats.statisticsPeriod || '-', " | ").concat(stats.commits, " | ").concat(stats.openspecProposals.size, " | ").concat(stats.codeFilesChanged, " | +").concat(stats.additions, " | -").concat(stats.deletions, " | ").concat(stats.netChanges >= 0 ? '+' : '').concat(stats.netChanges, " |\n");
359
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
360
+ var _stats2 = _step7.value;
361
+ md += "| ".concat(_stats2.author, " | ").concat(_stats2.statisticsPeriod || '-', " | ").concat(_stats2.commits, " | ").concat(_stats2.openspecProposals.size, " | ").concat(_stats2.codeFilesChanged, " | +").concat(_stats2.additions, " | -").concat(_stats2.deletions, " | ").concat(_stats2.netChanges >= 0 ? '+' : '').concat(_stats2.netChanges, " |\n");
177
362
  }
178
363
  } catch (err) {
179
- _iterator4.e(err);
364
+ _iterator7.e(err);
180
365
  } finally {
181
- _iterator4.f();
366
+ _iterator7.f();
182
367
  }
183
368
  md += t('markdown.proposalDetails');
184
- var _iterator5 = _createForOfIteratorHelper(sortedAuthors),
185
- _step5;
369
+ var _iterator8 = _createForOfIteratorHelper(sortedAuthors),
370
+ _step8;
186
371
  try {
187
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
188
- var _stats = _step5.value;
189
- if (_stats.openspecProposals.size > 0) {
190
- md += "### ".concat(_stats.author, "\n\n");
191
- for (var _i = 0, _Array$from = Array.from(_stats.openspecProposals); _i < _Array$from.length; _i++) {
372
+ for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
373
+ var _stats3 = _step8.value;
374
+ if (_stats3.openspecProposals.size > 0) {
375
+ md += "### ".concat(_stats3.author, "\n\n");
376
+ for (var _i = 0, _Array$from = Array.from(_stats3.openspecProposals); _i < _Array$from.length; _i++) {
192
377
  var proposal = _Array$from[_i];
193
378
  md += "- ".concat(proposal, "\n");
194
379
  }
@@ -196,9 +381,9 @@ export var OutputFormatter = /*#__PURE__*/function () {
196
381
  }
197
382
  }
198
383
  } catch (err) {
199
- _iterator5.e(err);
384
+ _iterator8.e(err);
200
385
  } finally {
201
- _iterator5.f();
386
+ _iterator8.f();
202
387
  }
203
388
  return md;
204
389
  }
@@ -37,21 +37,23 @@ export var GitAnalyzer = /*#__PURE__*/function () {
37
37
  untilStr = until.toISOString();
38
38
  logOptions = {
39
39
  '--since': sinceStr,
40
- '--until': untilStr,
41
- '--all': null
40
+ '--until': untilStr
42
41
  };
43
42
  if (branches.length > 0) {
43
+ delete logOptions['--all'];
44
44
  _iterator = _createForOfIteratorHelper(branches);
45
45
  try {
46
46
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
47
47
  branch = _step.value;
48
- logOptions["--remotes=".concat(branch)] = null;
48
+ logOptions[branch] = null;
49
49
  }
50
50
  } catch (err) {
51
51
  _iterator.e(err);
52
52
  } finally {
53
53
  _iterator.f();
54
54
  }
55
+ } else {
56
+ logOptions['--all'] = null;
55
57
  }
56
58
  _context.next = 6;
57
59
  return this.git.log(logOptions);
@@ -5,7 +5,7 @@ var __filename = fileURLToPath(import.meta.url);
5
5
  var __dirname = dirname(__filename);
6
6
  var currentLanguage = 'en';
7
7
  var translations = {
8
- 'en': {},
8
+ en: {},
9
9
  'zh-CN': {}
10
10
  };
11
11
  function loadTranslations() {
@@ -12,11 +12,11 @@
12
12
  "cli.option.config": "Configuration file path",
13
13
  "cli.option.verbose": "Verbose output mode",
14
14
  "cli.option.lang": "Language for output (en, zh-CN)",
15
-
15
+
16
16
  "loading.config": "🔍 Loading configuration...",
17
17
  "loading.activeUsers": "🔍 Fetching active users...",
18
18
  "loading.analyzing": "🔍 Analyzing commit history...",
19
-
19
+
20
20
  "info.timeRange": "📅 Time Range: {{since}} ~ {{until}}",
21
21
  "info.branches": "🌿 Branches: {{branches}}",
22
22
  "info.allBranches": "All branches",
@@ -24,13 +24,13 @@
24
24
  "info.foundCommits": "📝 Found {{count}} commits, analyzing...",
25
25
  "info.analysisProgress": " Analysis progress: {{current}}/{{total}}",
26
26
  "info.qualifyingCommits": "✅ Found {{count}} qualifying commits (containing OpenSpec proposals and code changes)",
27
-
27
+
28
28
  "warning.noCommits": "⚠️ No commits found matching the criteria",
29
29
  "warning.noQualifyingCommits": "⚠️ No commits found containing both OpenSpec proposals and code changes",
30
30
  "warning.noBranches": "⚠️ No remote branches found",
31
-
31
+
32
32
  "error.prefix": "❌ Error:",
33
-
33
+
34
34
  "branch.fetching": "\n🔍 Fetching active branches...",
35
35
  "branch.selectMode": "How would you like to select branches?",
36
36
  "branch.mode.select": "Select from active branches",
@@ -42,17 +42,23 @@
42
42
  "branch.customSeparator": "--- Custom input ---",
43
43
  "branch.selected": "\n✓ Selected branches:",
44
44
  "branch.lastCommit": "last commit: {{date}}",
45
-
45
+
46
46
  "output.title": "\n📊 OpenSpec Statistics Report\n",
47
47
  "output.timeRange": "Time Range: {{since}} ~ {{until}}\n",
48
48
  "output.branches": "Branches: {{branches}}\n",
49
49
  "output.totalCommits": "Total Commits: {{count}}\n\n",
50
50
  "output.proposals": " Proposals: {{proposals}}\n",
51
-
51
+ "output.proposalSummary": "📋 Proposal Summary (by proposal)",
52
+ "output.proposalTotal": " 📊 Total: {{count}} proposals | {{commits}} commits | {{files}} files | +{{additions}}/-{{deletions}} lines (net: {{netChanges}})\n",
53
+ "output.proposalTotalLabel": "Proposal Summary Total",
54
+ "output.authorSummary": "👥 Author Summary (by contributor)",
55
+
52
56
  "table.branch": "Branch",
53
57
  "table.period": "Period",
54
58
  "table.commits": "Commits",
55
59
  "table.proposals": "Proposals",
60
+ "table.proposal": "Proposal",
61
+ "table.contributors": "Contributors",
56
62
  "table.codeFiles": "Code Files",
57
63
  "table.additions": "Additions",
58
64
  "table.deletions": "Deletions",
@@ -62,7 +68,7 @@
62
68
  "table.proposalsList": "Proposals List",
63
69
  "table.proposalsCount": "Proposals Count",
64
70
  "table.totalDeduplicated": "TOTAL (Deduplicated)",
65
-
71
+
66
72
  "markdown.title": "# OpenSpec Statistics Report\n\n",
67
73
  "markdown.timeRange": "**Time Range**: {{since}} ~ {{until}}\n\n",
68
74
  "markdown.branches": "**Branches**: {{branches}}\n\n",
@@ -12,11 +12,11 @@
12
12
  "cli.option.config": "配置文件路径",
13
13
  "cli.option.verbose": "详细输出模式",
14
14
  "cli.option.lang": "输出语言(en, zh-CN)",
15
-
15
+
16
16
  "loading.config": "🔍 正在加载配置...",
17
17
  "loading.activeUsers": "🔍 正在获取活跃用户...",
18
18
  "loading.analyzing": "🔍 正在分析提交历史...",
19
-
19
+
20
20
  "info.timeRange": "📅 时间范围:{{since}} ~ {{until}}",
21
21
  "info.branches": "🌿 分支:{{branches}}",
22
22
  "info.allBranches": "所有分支",
@@ -24,13 +24,13 @@
24
24
  "info.foundCommits": "📝 找到 {{count}} 个提交,正在分析...",
25
25
  "info.analysisProgress": " 分析进度:{{current}}/{{total}}",
26
26
  "info.qualifyingCommits": "✅ 找到 {{count}} 个符合条件的提交(包含 OpenSpec 提案和代码变更)",
27
-
27
+
28
28
  "warning.noCommits": "⚠️ 未找到符合条件的提交",
29
29
  "warning.noQualifyingCommits": "⚠️ 未找到同时包含 OpenSpec 提案和代码变更的提交",
30
30
  "warning.noBranches": "⚠️ 未找到远程分支",
31
-
31
+
32
32
  "error.prefix": "❌ 错误:",
33
-
33
+
34
34
  "branch.fetching": "\n🔍 正在获取活跃分支...",
35
35
  "branch.selectMode": "您想如何选择分支?",
36
36
  "branch.mode.select": "从活跃分支中选择",
@@ -42,17 +42,23 @@
42
42
  "branch.customSeparator": "--- 自定义输入 ---",
43
43
  "branch.selected": "\n✓ 已选择的分支:",
44
44
  "branch.lastCommit": "最后提交:{{date}}",
45
-
45
+
46
46
  "output.title": "\n📊 OpenSpec 统计报告\n",
47
47
  "output.timeRange": "时间范围:{{since}} ~ {{until}}\n",
48
48
  "output.branches": "分支:{{branches}}\n",
49
49
  "output.totalCommits": "总提交数:{{count}}\n\n",
50
50
  "output.proposals": " 提案:{{proposals}}\n",
51
-
51
+ "output.proposalSummary": "📋 提案汇总(按提案统计)",
52
+ "output.proposalTotal": " 📊 总计:{{count}} 个提案 | {{commits}} 次提交 | {{files}} 个文件 | +{{additions}}/-{{deletions}} 行(净变更:{{netChanges}})\n",
53
+ "output.proposalTotalLabel": "提案汇总总计",
54
+ "output.authorSummary": "👥 作者汇总(按贡献者统计)",
55
+
52
56
  "table.branch": "分支",
53
57
  "table.period": "周期",
54
58
  "table.commits": "提交数",
55
59
  "table.proposals": "提案数",
60
+ "table.proposal": "提案",
61
+ "table.contributors": "贡献者",
56
62
  "table.codeFiles": "代码文件",
57
63
  "table.additions": "新增行数",
58
64
  "table.deletions": "删除行数",
@@ -62,7 +68,7 @@
62
68
  "table.proposalsList": "提案列表",
63
69
  "table.proposalsCount": "提案数量",
64
70
  "table.totalDeduplicated": "总计(去重)",
65
-
71
+
66
72
  "markdown.title": "# OpenSpec 统计报告\n\n",
67
73
  "markdown.timeRange": "**时间范围**:{{since}} ~ {{until}}\n\n",
68
74
  "markdown.branches": "**分支**:{{branches}}\n\n",