openspec-stat 1.1.0 → 1.3.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 (45) hide show
  1. package/README.md +44 -0
  2. package/README.zh-CN.md +44 -0
  3. package/dist/cjs/cli.js +12 -127
  4. package/dist/cjs/commands/init.d.ts +7 -0
  5. package/dist/cjs/commands/init.js +58 -0
  6. package/dist/cjs/commands/multi.d.ts +16 -0
  7. package/dist/cjs/commands/multi.js +172 -0
  8. package/dist/cjs/commands/single.d.ts +2 -0
  9. package/dist/cjs/commands/single.js +148 -0
  10. package/dist/cjs/formatters.d.ts +4 -4
  11. package/dist/cjs/formatters.js +268 -30
  12. package/dist/cjs/git-analyzer.d.ts +1 -0
  13. package/dist/cjs/git-analyzer.js +6 -0
  14. package/dist/cjs/i18n/locales/en.json +80 -1
  15. package/dist/cjs/i18n/locales/zh-CN.json +80 -1
  16. package/dist/cjs/multi/config-validator.d.ts +3 -0
  17. package/dist/cjs/multi/config-validator.js +130 -0
  18. package/dist/cjs/multi/config-wizard.d.ts +50 -0
  19. package/dist/cjs/multi/config-wizard.js +331 -0
  20. package/dist/cjs/multi/multi-repo-analyzer.d.ts +14 -0
  21. package/dist/cjs/multi/multi-repo-analyzer.js +210 -0
  22. package/dist/cjs/stats-aggregator.js +25 -0
  23. package/dist/cjs/types.d.ts +57 -0
  24. package/dist/esm/cli.js +43 -137
  25. package/dist/esm/commands/init.d.ts +7 -0
  26. package/dist/esm/commands/init.js +49 -0
  27. package/dist/esm/commands/multi.d.ts +16 -0
  28. package/dist/esm/commands/multi.js +192 -0
  29. package/dist/esm/commands/single.d.ts +2 -0
  30. package/dist/esm/commands/single.js +162 -0
  31. package/dist/esm/formatters.d.ts +4 -4
  32. package/dist/esm/formatters.js +361 -55
  33. package/dist/esm/git-analyzer.d.ts +1 -0
  34. package/dist/esm/git-analyzer.js +104 -77
  35. package/dist/esm/i18n/locales/en.json +80 -1
  36. package/dist/esm/i18n/locales/zh-CN.json +80 -1
  37. package/dist/esm/multi/config-validator.d.ts +3 -0
  38. package/dist/esm/multi/config-validator.js +109 -0
  39. package/dist/esm/multi/config-wizard.d.ts +50 -0
  40. package/dist/esm/multi/config-wizard.js +535 -0
  41. package/dist/esm/multi/multi-repo-analyzer.d.ts +14 -0
  42. package/dist/esm/multi/multi-repo-analyzer.js +446 -0
  43. package/dist/esm/stats-aggregator.js +29 -0
  44. package/dist/esm/types.d.ts +57 -0
  45. package/package.json +1 -1
@@ -3,10 +3,10 @@ function _toArray(arr) { return _arrayWithHoles(arr) || _iterableToArray(arr) ||
3
3
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
4
4
  function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
5
5
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
6
- function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
7
6
  function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
8
7
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
9
8
  function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
9
+ function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
10
10
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
11
11
  function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
12
12
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
@@ -26,12 +26,39 @@ export var GitAnalyzer = /*#__PURE__*/function () {
26
26
  this.config = config;
27
27
  }
28
28
  _createClass(GitAnalyzer, [{
29
- key: "getCommits",
29
+ key: "fetchRemote",
30
30
  value: function () {
31
- var _getCommits = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(since, until, branches) {
32
- var sinceStr, untilStr, logOptions, _iterator, _step, branch, log, commits, _iterator2, _step2, commit, commitBranches;
31
+ var _fetchRemote = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
33
32
  return _regeneratorRuntime().wrap(function _callee$(_context) {
34
33
  while (1) switch (_context.prev = _context.next) {
34
+ case 0:
35
+ _context.prev = 0;
36
+ _context.next = 3;
37
+ return this.git.fetch();
38
+ case 3:
39
+ _context.next = 7;
40
+ break;
41
+ case 5:
42
+ _context.prev = 5;
43
+ _context.t0 = _context["catch"](0);
44
+ case 7:
45
+ case "end":
46
+ return _context.stop();
47
+ }
48
+ }, _callee, this, [[0, 5]]);
49
+ }));
50
+ function fetchRemote() {
51
+ return _fetchRemote.apply(this, arguments);
52
+ }
53
+ return fetchRemote;
54
+ }()
55
+ }, {
56
+ key: "getCommits",
57
+ value: function () {
58
+ var _getCommits = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(since, until, branches) {
59
+ var sinceStr, untilStr, logOptions, _iterator, _step, branch, log, commits, _iterator2, _step2, commit, commitBranches;
60
+ return _regeneratorRuntime().wrap(function _callee2$(_context2) {
61
+ while (1) switch (_context2.prev = _context2.next) {
35
62
  case 0:
36
63
  sinceStr = since.toISOString();
37
64
  untilStr = until.toISOString();
@@ -55,24 +82,24 @@ export var GitAnalyzer = /*#__PURE__*/function () {
55
82
  } else {
56
83
  logOptions['--all'] = null;
57
84
  }
58
- _context.next = 6;
85
+ _context2.next = 6;
59
86
  return this.git.log(logOptions);
60
87
  case 6:
61
- log = _context.sent;
88
+ log = _context2.sent;
62
89
  commits = [];
63
90
  _iterator2 = _createForOfIteratorHelper(log.all);
64
- _context.prev = 9;
91
+ _context2.prev = 9;
65
92
  _iterator2.s();
66
93
  case 11:
67
94
  if ((_step2 = _iterator2.n()).done) {
68
- _context.next = 19;
95
+ _context2.next = 19;
69
96
  break;
70
97
  }
71
98
  commit = _step2.value;
72
- _context.next = 15;
99
+ _context2.next = 15;
73
100
  return this.getCommitBranches(commit.hash, branches);
74
101
  case 15:
75
- commitBranches = _context.sent;
102
+ commitBranches = _context2.sent;
76
103
  commits.push({
77
104
  hash: commit.hash,
78
105
  author: commit.author_name,
@@ -82,26 +109,26 @@ export var GitAnalyzer = /*#__PURE__*/function () {
82
109
  branches: commitBranches
83
110
  });
84
111
  case 17:
85
- _context.next = 11;
112
+ _context2.next = 11;
86
113
  break;
87
114
  case 19:
88
- _context.next = 24;
115
+ _context2.next = 24;
89
116
  break;
90
117
  case 21:
91
- _context.prev = 21;
92
- _context.t0 = _context["catch"](9);
93
- _iterator2.e(_context.t0);
118
+ _context2.prev = 21;
119
+ _context2.t0 = _context2["catch"](9);
120
+ _iterator2.e(_context2.t0);
94
121
  case 24:
95
- _context.prev = 24;
122
+ _context2.prev = 24;
96
123
  _iterator2.f();
97
- return _context.finish(24);
124
+ return _context2.finish(24);
98
125
  case 27:
99
- return _context.abrupt("return", commits);
126
+ return _context2.abrupt("return", commits);
100
127
  case 28:
101
128
  case "end":
102
- return _context.stop();
129
+ return _context2.stop();
103
130
  }
104
- }, _callee, this, [[9, 21, 24, 27]]);
131
+ }, _callee2, this, [[9, 21, 24, 27]]);
105
132
  }));
106
133
  function getCommits(_x, _x2, _x3) {
107
134
  return _getCommits.apply(this, arguments);
@@ -111,41 +138,41 @@ export var GitAnalyzer = /*#__PURE__*/function () {
111
138
  }, {
112
139
  key: "getCommitBranches",
113
140
  value: function () {
114
- var _getCommitBranches = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(commitHash, targetBranches) {
141
+ var _getCommitBranches = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(commitHash, targetBranches) {
115
142
  var result, allBranches;
116
- return _regeneratorRuntime().wrap(function _callee2$(_context2) {
117
- while (1) switch (_context2.prev = _context2.next) {
143
+ return _regeneratorRuntime().wrap(function _callee3$(_context3) {
144
+ while (1) switch (_context3.prev = _context3.next) {
118
145
  case 0:
119
- _context2.prev = 0;
120
- _context2.next = 3;
146
+ _context3.prev = 0;
147
+ _context3.next = 3;
121
148
  return this.git.raw(['branch', '-r', '--contains', commitHash]);
122
149
  case 3:
123
- result = _context2.sent;
150
+ result = _context3.sent;
124
151
  allBranches = result.split('\n').map(function (b) {
125
152
  return b.trim();
126
153
  }).filter(function (b) {
127
154
  return b && !b.includes('HEAD');
128
155
  });
129
156
  if (!(targetBranches.length === 0)) {
130
- _context2.next = 7;
157
+ _context3.next = 7;
131
158
  break;
132
159
  }
133
- return _context2.abrupt("return", allBranches);
160
+ return _context3.abrupt("return", allBranches);
134
161
  case 7:
135
- return _context2.abrupt("return", allBranches.filter(function (branch) {
162
+ return _context3.abrupt("return", allBranches.filter(function (branch) {
136
163
  return targetBranches.some(function (target) {
137
164
  return branch === target || branch.includes(target);
138
165
  });
139
166
  }));
140
167
  case 10:
141
- _context2.prev = 10;
142
- _context2.t0 = _context2["catch"](0);
143
- return _context2.abrupt("return", []);
168
+ _context3.prev = 10;
169
+ _context3.t0 = _context3["catch"](0);
170
+ return _context3.abrupt("return", []);
144
171
  case 13:
145
172
  case "end":
146
- return _context2.stop();
173
+ return _context3.stop();
147
174
  }
148
- }, _callee2, this, [[0, 10]]);
175
+ }, _callee3, this, [[0, 10]]);
149
176
  }));
150
177
  function getCommitBranches(_x4, _x5) {
151
178
  return _getCommitBranches.apply(this, arguments);
@@ -155,16 +182,16 @@ export var GitAnalyzer = /*#__PURE__*/function () {
155
182
  }, {
156
183
  key: "analyzeCommit",
157
184
  value: function () {
158
- var _analyzeCommit = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(commit) {
185
+ var _analyzeCommit = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(commit) {
159
186
  var show, lines, fileChanges, openspecProposals, hasCodeChanges, openspecDir, excludeExts, _iterator3, _step3, _loop, totalAdditions, totalDeletions;
160
- return _regeneratorRuntime().wrap(function _callee3$(_context4) {
161
- while (1) switch (_context4.prev = _context4.next) {
187
+ return _regeneratorRuntime().wrap(function _callee4$(_context5) {
188
+ while (1) switch (_context5.prev = _context5.next) {
162
189
  case 0:
163
- _context4.prev = 0;
164
- _context4.next = 3;
190
+ _context5.prev = 0;
191
+ _context5.next = 3;
165
192
  return this.git.show(['--numstat', '--format=', commit.hash]);
166
193
  case 3:
167
- show = _context4.sent;
194
+ show = _context5.sent;
168
195
  lines = show.split('\n').filter(function (line) {
169
196
  return line.trim();
170
197
  });
@@ -174,19 +201,19 @@ export var GitAnalyzer = /*#__PURE__*/function () {
174
201
  openspecDir = this.config.openspecDir || 'openspec/';
175
202
  excludeExts = this.config.excludeExtensions || [];
176
203
  _iterator3 = _createForOfIteratorHelper(lines);
177
- _context4.prev = 11;
204
+ _context5.prev = 11;
178
205
  _loop = /*#__PURE__*/_regeneratorRuntime().mark(function _loop() {
179
206
  var line, parts, _parts, addStr, delStr, pathParts, path, additions, deletions, proposalMatch, isExcluded, isInOpenspec;
180
- return _regeneratorRuntime().wrap(function _loop$(_context3) {
181
- while (1) switch (_context3.prev = _context3.next) {
207
+ return _regeneratorRuntime().wrap(function _loop$(_context4) {
208
+ while (1) switch (_context4.prev = _context4.next) {
182
209
  case 0:
183
210
  line = _step3.value;
184
211
  parts = line.split(/\s+/);
185
212
  if (!(parts.length < 3)) {
186
- _context3.next = 4;
213
+ _context4.next = 4;
187
214
  break;
188
215
  }
189
- return _context3.abrupt("return", 1);
216
+ return _context4.abrupt("return", 1);
190
217
  case 4:
191
218
  _parts = _toArray(parts), addStr = _parts[0], delStr = _parts[1], pathParts = _parts.slice(2);
192
219
  path = pathParts.join(' ');
@@ -213,40 +240,40 @@ export var GitAnalyzer = /*#__PURE__*/function () {
213
240
  }
214
241
  case 12:
215
242
  case "end":
216
- return _context3.stop();
243
+ return _context4.stop();
217
244
  }
218
245
  }, _loop);
219
246
  });
220
247
  _iterator3.s();
221
248
  case 14:
222
249
  if ((_step3 = _iterator3.n()).done) {
223
- _context4.next = 20;
250
+ _context5.next = 20;
224
251
  break;
225
252
  }
226
- return _context4.delegateYield(_loop(), "t0", 16);
253
+ return _context5.delegateYield(_loop(), "t0", 16);
227
254
  case 16:
228
- if (!_context4.t0) {
229
- _context4.next = 18;
255
+ if (!_context5.t0) {
256
+ _context5.next = 18;
230
257
  break;
231
258
  }
232
- return _context4.abrupt("continue", 18);
259
+ return _context5.abrupt("continue", 18);
233
260
  case 18:
234
- _context4.next = 14;
261
+ _context5.next = 14;
235
262
  break;
236
263
  case 20:
237
- _context4.next = 25;
264
+ _context5.next = 25;
238
265
  break;
239
266
  case 22:
240
- _context4.prev = 22;
241
- _context4.t1 = _context4["catch"](11);
242
- _iterator3.e(_context4.t1);
267
+ _context5.prev = 22;
268
+ _context5.t1 = _context5["catch"](11);
269
+ _iterator3.e(_context5.t1);
243
270
  case 25:
244
- _context4.prev = 25;
271
+ _context5.prev = 25;
245
272
  _iterator3.f();
246
- return _context4.finish(25);
273
+ return _context5.finish(25);
247
274
  case 28:
248
275
  if (!(openspecProposals.size > 0 && hasCodeChanges)) {
249
- _context4.next = 32;
276
+ _context5.next = 32;
250
277
  break;
251
278
  }
252
279
  totalAdditions = fileChanges.reduce(function (sum, f) {
@@ -255,7 +282,7 @@ export var GitAnalyzer = /*#__PURE__*/function () {
255
282
  totalDeletions = fileChanges.reduce(function (sum, f) {
256
283
  return sum + f.deletions;
257
284
  }, 0);
258
- return _context4.abrupt("return", {
285
+ return _context5.abrupt("return", {
259
286
  commit: commit,
260
287
  openspecProposals: openspecProposals,
261
288
  codeFiles: fileChanges,
@@ -264,17 +291,17 @@ export var GitAnalyzer = /*#__PURE__*/function () {
264
291
  netChanges: totalAdditions - totalDeletions
265
292
  });
266
293
  case 32:
267
- return _context4.abrupt("return", null);
294
+ return _context5.abrupt("return", null);
268
295
  case 35:
269
- _context4.prev = 35;
270
- _context4.t2 = _context4["catch"](0);
271
- console.error("Error analyzing commit ".concat(commit.hash, ":"), _context4.t2);
272
- return _context4.abrupt("return", null);
296
+ _context5.prev = 35;
297
+ _context5.t2 = _context5["catch"](0);
298
+ console.error("Error analyzing commit ".concat(commit.hash, ":"), _context5.t2);
299
+ return _context5.abrupt("return", null);
273
300
  case 39:
274
301
  case "end":
275
- return _context4.stop();
302
+ return _context5.stop();
276
303
  }
277
- }, _callee3, this, [[0, 35], [11, 22, 25, 28]]);
304
+ }, _callee4, this, [[0, 35], [11, 22, 25, 28]]);
278
305
  }));
279
306
  function analyzeCommit(_x6) {
280
307
  return _analyzeCommit.apply(this, arguments);
@@ -284,7 +311,7 @@ export var GitAnalyzer = /*#__PURE__*/function () {
284
311
  }, {
285
312
  key: "getActiveAuthors",
286
313
  value: function () {
287
- var _getActiveAuthors = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4() {
314
+ var _getActiveAuthors = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5() {
288
315
  var weeks,
289
316
  since,
290
317
  log,
@@ -293,20 +320,20 @@ export var GitAnalyzer = /*#__PURE__*/function () {
293
320
  _step4,
294
321
  commit,
295
322
  normalizedAuthor,
296
- _args5 = arguments;
297
- return _regeneratorRuntime().wrap(function _callee4$(_context5) {
298
- while (1) switch (_context5.prev = _context5.next) {
323
+ _args6 = arguments;
324
+ return _regeneratorRuntime().wrap(function _callee5$(_context6) {
325
+ while (1) switch (_context6.prev = _context6.next) {
299
326
  case 0:
300
- weeks = _args5.length > 0 && _args5[0] !== undefined ? _args5[0] : 2;
327
+ weeks = _args6.length > 0 && _args6[0] !== undefined ? _args6[0] : 2;
301
328
  since = new Date();
302
329
  since.setDate(since.getDate() - weeks * 7);
303
- _context5.next = 5;
330
+ _context6.next = 5;
304
331
  return this.git.log({
305
332
  '--since': since.toISOString(),
306
333
  '--all': null
307
334
  });
308
335
  case 5:
309
- log = _context5.sent;
336
+ log = _context6.sent;
310
337
  authors = new Set();
311
338
  _iterator4 = _createForOfIteratorHelper(log.all);
312
339
  try {
@@ -320,12 +347,12 @@ export var GitAnalyzer = /*#__PURE__*/function () {
320
347
  } finally {
321
348
  _iterator4.f();
322
349
  }
323
- return _context5.abrupt("return", authors);
350
+ return _context6.abrupt("return", authors);
324
351
  case 10:
325
352
  case "end":
326
- return _context5.stop();
353
+ return _context6.stop();
327
354
  }
328
- }, _callee4, this);
355
+ }, _callee5, this);
329
356
  }));
330
357
  function getActiveAuthors() {
331
358
  return _getActiveAuthors.apply(this, arguments);
@@ -16,6 +16,7 @@
16
16
  "loading.config": "🔍 Loading configuration...",
17
17
  "loading.activeUsers": "🔍 Fetching active users...",
18
18
  "loading.analyzing": "🔍 Analyzing commit history...",
19
+ "loading.fetching": "🔄 Fetching remote branches...",
19
20
 
20
21
  "info.timeRange": "📅 Time Range: {{since}} ~ {{until}}",
21
22
  "info.branches": "🌿 Branches: {{branches}}",
@@ -48,11 +49,18 @@
48
49
  "output.branches": "Branches: {{branches}}\n",
49
50
  "output.totalCommits": "Total Commits: {{count}}\n\n",
50
51
  "output.proposals": " Proposals: {{proposals}}\n",
52
+ "output.proposalSummary": "📋 Proposal Summary (by proposal)",
53
+ "output.proposalTotal": " 📊 Total: {{count}} proposals | {{commits}} commits | {{files}} files | +{{additions}}/-{{deletions}} lines (net: {{netChanges}})\n",
54
+ "output.proposalTotalLabel": "Proposal Summary Total",
55
+ "output.authorSummary": "👥 Author Summary (by contributor)",
56
+ "output.contributorHint": "💡 Use --show-contributors to see detailed statistics for each contributor",
51
57
 
52
58
  "table.branch": "Branch",
53
59
  "table.period": "Period",
54
60
  "table.commits": "Commits",
55
61
  "table.proposals": "Proposals",
62
+ "table.proposal": "Proposal",
63
+ "table.contributors": "Contributors",
56
64
  "table.codeFiles": "Code Files",
57
65
  "table.additions": "Additions",
58
66
  "table.deletions": "Deletions",
@@ -68,5 +76,76 @@
68
76
  "markdown.branches": "**Branches**: {{branches}}\n\n",
69
77
  "markdown.totalCommits": "**Total Commits**: {{count}}\n\n",
70
78
  "markdown.statistics": "## Statistics\n\n",
71
- "markdown.proposalDetails": "\n## Proposal Details\n\n"
79
+ "markdown.proposalDetails": "\n## Proposal Details\n\n",
80
+
81
+ "multi.beta.warning": "⚠️ BETA: Multi-repository mode is experimental",
82
+ "multi.beta.feedback": " Please report issues at: https://github.com/Orchardxyz/openspec-stat/issues",
83
+ "multi.loading.config": "🔍 Loading multi-repository configuration...",
84
+ "multi.repo.cloning": "☁️ Cloning {{repo}}...",
85
+ "multi.repo.cloned": "✅ Successfully cloned {{repo}}",
86
+ "multi.repo.fetching": "🔄 Fetching remote branches for {{repo}}...",
87
+ "multi.repo.analyzing": "📊 Analyzing {{repo}} ({{type}})...",
88
+ "multi.repo.completed": "✅ Completed {{repo}}: {{commits}} commits",
89
+ "multi.repo.failed": "❌ Failed {{repo}}: {{error}}",
90
+ "multi.repo.skipped": "⏭️ Skipped {{repo}}: disabled",
91
+ "multi.cleanup.start": "🧹 Cleaning up temporary directories...",
92
+ "multi.cleanup.done": "✅ Cleanup completed",
93
+ "multi.summary.title": "\n📦 Multi-Repository Summary\n",
94
+ "multi.summary.repos": "Repositories: {{total}} ({{success}} succeeded, {{failed}} failed)",
95
+ "multi.progress.batch": "Processing batch {{current}}/{{total}}...",
96
+ "multi.table.repository": "Repository",
97
+ "multi.table.type": "Type",
98
+
99
+ "init.welcome": "\n📋 OpenSpec Configuration Wizard\n",
100
+ "init.welcomeMulti": "\n📋 OpenSpec Multi-Repository Configuration Wizard (BETA)\n",
101
+ "init.configName": "Configuration file name:",
102
+ "init.addRepository": "\n📦 Repository {{number}}",
103
+ "init.repoType": "Repository type:",
104
+ "init.repoType.local": "📁 Local - I have this repository on my machine",
105
+ "init.repoType.remote": "☁️ Remote - Clone from remote URL",
106
+ "init.repoName": "Repository name (for display):",
107
+ "init.repoPath": "Local path (absolute or relative):",
108
+ "init.repoUrl": "Git URL (e.g., git@github.com:org/repo.git):",
109
+ "init.repoUrlInvalid": "Invalid Git URL format",
110
+ "init.useFullClone": "Use full clone (recommended for accuracy)?",
111
+ "init.cloneDepth": "Clone depth (number of commits):",
112
+ "init.branches": "Branches to analyze (comma-separated):",
113
+ "init.addMore": "Add another repository?",
114
+ "init.timeConfig": "\n⏰ Time Range Configuration",
115
+ "init.useDefaultTime": "Use default time range (yesterday 20:00 - today 20:00)?",
116
+ "init.sinceHours": "Start time offset (hours, negative for past):",
117
+ "init.untilHours": "End time (hour of day, 0-23):",
118
+ "init.advanced": "\n⚙️ Advanced Options",
119
+ "init.configureAdvanced": "Configure advanced options?",
120
+ "init.openspecDir": "OpenSpec directory path:",
121
+ "init.maxConcurrent": "Maximum concurrent repository operations:",
122
+ "init.authorMapping": "Configure author name mapping?",
123
+ "init.authorMappingInfo": "\nAuthor mapping helps unify multiple Git identities for the same person.\n",
124
+ "init.gitIdentity": "Git identity (name or email):",
125
+ "init.unifiedName": "Unified name for \"{{identity}}\":",
126
+ "init.addMoreMapping": "Add another mapping?",
127
+ "init.preview": "\n✅ Configuration Preview:\n",
128
+ "init.save": "\nSave this configuration?",
129
+ "init.saved": "\n✅ Configuration saved to {{path}}",
130
+ "init.runCommand": "\nRun: openspec-stat multi -c {{path}}",
131
+ "init.templateCreated": "✅ Template created at {{path}}",
132
+ "init.templateEdit": "Please edit the file and configure your repositories.",
133
+
134
+ "config.validation.noRepos": "Invalid config: \"repositories\" must be an array",
135
+ "config.validation.emptyRepos": "Invalid config: at least one repository is required",
136
+ "config.validation.noName": "Repository {{index}}: \"name\" is required",
137
+ "config.validation.invalidType": "Repository \"{{name}}\": \"type\" must be \"local\" or \"remote\"",
138
+ "config.validation.noPath": "Repository \"{{name}}\": \"path\" is required for local type",
139
+ "config.validation.noUrl": "Repository \"{{name}}\": \"url\" is required for remote type",
140
+ "config.validation.noBranches": "Repository \"{{name}}\": at least one branch is required",
141
+ "config.summary.title": "\n📋 Configuration Summary\n",
142
+ "config.summary.repositories": "Repositories:",
143
+ "config.summary.timeRange": "\nTime Range:",
144
+ "config.summary.since": " Since: {{hours}} hours",
145
+ "config.summary.until": " Until: {{hours}}:00",
146
+ "config.summary.parallelism": "\nParallelism:",
147
+ "config.summary.maxConcurrent": " Max concurrent: {{count}}",
148
+ "config.summary.remoteCache": "\nRemote Cache:",
149
+ "config.summary.cacheDir": " Directory: {{dir}}",
150
+ "config.summary.autoCleanup": " Auto cleanup: {{enabled}}"
72
151
  }
@@ -16,6 +16,7 @@
16
16
  "loading.config": "🔍 正在加载配置...",
17
17
  "loading.activeUsers": "🔍 正在获取活跃用户...",
18
18
  "loading.analyzing": "🔍 正在分析提交历史...",
19
+ "loading.fetching": "🔄 正在拉取远程分支...",
19
20
 
20
21
  "info.timeRange": "📅 时间范围:{{since}} ~ {{until}}",
21
22
  "info.branches": "🌿 分支:{{branches}}",
@@ -48,11 +49,18 @@
48
49
  "output.branches": "分支:{{branches}}\n",
49
50
  "output.totalCommits": "总提交数:{{count}}\n\n",
50
51
  "output.proposals": " 提案:{{proposals}}\n",
52
+ "output.proposalSummary": "📋 提案汇总(按提案统计)",
53
+ "output.proposalTotal": " 📊 总计:{{count}} 个提案 | {{commits}} 次提交 | {{files}} 个文件 | +{{additions}}/-{{deletions}} 行(净变更:{{netChanges}})\n",
54
+ "output.proposalTotalLabel": "提案汇总总计",
55
+ "output.authorSummary": "👥 作者汇总(按贡献者统计)",
56
+ "output.contributorHint": "💡 使用 --show-contributors 选项可查看每个贡献者的详细统计信息",
51
57
 
52
58
  "table.branch": "分支",
53
59
  "table.period": "周期",
54
60
  "table.commits": "提交数",
55
61
  "table.proposals": "提案数",
62
+ "table.proposal": "提案",
63
+ "table.contributors": "贡献者",
56
64
  "table.codeFiles": "代码文件",
57
65
  "table.additions": "新增行数",
58
66
  "table.deletions": "删除行数",
@@ -68,5 +76,76 @@
68
76
  "markdown.branches": "**分支**:{{branches}}\n\n",
69
77
  "markdown.totalCommits": "**总提交数**:{{count}}\n\n",
70
78
  "markdown.statistics": "## 统计数据\n\n",
71
- "markdown.proposalDetails": "\n## 提案详情\n\n"
79
+ "markdown.proposalDetails": "\n## 提案详情\n\n",
80
+
81
+ "multi.beta.warning": "⚠️ 测试版:多仓库模式为实验性功能",
82
+ "multi.beta.feedback": " 请反馈问题至:https://github.com/Orchardxyz/openspec-stat/issues",
83
+ "multi.loading.config": "🔍 正在加载多仓库配置...",
84
+ "multi.repo.cloning": "☁️ 正在克隆 {{repo}}...",
85
+ "multi.repo.cloned": "✅ 成功克隆 {{repo}}",
86
+ "multi.repo.fetching": "🔄 正在拉取 {{repo}} 的远程分支...",
87
+ "multi.repo.analyzing": "📊 正在分析 {{repo}} ({{type}})...",
88
+ "multi.repo.completed": "✅ 完成 {{repo}}:{{commits}} 次提交",
89
+ "multi.repo.failed": "❌ 失败 {{repo}}:{{error}}",
90
+ "multi.repo.skipped": "⏭️ 跳过 {{repo}}:已禁用",
91
+ "multi.cleanup.start": "🧹 正在清理临时目录...",
92
+ "multi.cleanup.done": "✅ 清理完成",
93
+ "multi.summary.title": "\n📦 多仓库汇总\n",
94
+ "multi.summary.repos": "仓库:{{total}} 个({{success}} 成功,{{failed}} 失败)",
95
+ "multi.progress.batch": "正在处理批次 {{current}}/{{total}}...",
96
+ "multi.table.repository": "仓库",
97
+ "multi.table.type": "类型",
98
+
99
+ "init.welcome": "\n📋 OpenSpec 配置向导\n",
100
+ "init.welcomeMulti": "\n📋 OpenSpec 多仓库配置向导(测试版)\n",
101
+ "init.configName": "配置文件名:",
102
+ "init.addRepository": "\n📦 仓库 {{number}}",
103
+ "init.repoType": "仓库类型:",
104
+ "init.repoType.local": "📁 本地 - 我的机器上已有此仓库",
105
+ "init.repoType.remote": "☁️ 远程 - 从远程 URL 克隆",
106
+ "init.repoName": "仓库名称(用于显示):",
107
+ "init.repoPath": "本地路径(绝对或相对路径):",
108
+ "init.repoUrl": "Git URL(例如:git@github.com:org/repo.git):",
109
+ "init.repoUrlInvalid": "无效的 Git URL 格式",
110
+ "init.useFullClone": "使用完整克隆(推荐以确保准确性)?",
111
+ "init.cloneDepth": "克隆深度(提交数量):",
112
+ "init.branches": "要分析的分支(逗号分隔):",
113
+ "init.addMore": "添加另一个仓库?",
114
+ "init.timeConfig": "\n⏰ 时间范围配置",
115
+ "init.useDefaultTime": "使用默认时间范围(昨天 20:00 - 今天 20:00)?",
116
+ "init.sinceHours": "开始时间偏移(小时,负数表示过去):",
117
+ "init.untilHours": "结束时间(一天中的小时,0-23):",
118
+ "init.advanced": "\n⚙️ 高级选项",
119
+ "init.configureAdvanced": "配置高级选项?",
120
+ "init.openspecDir": "OpenSpec 目录路径:",
121
+ "init.maxConcurrent": "最大并发仓库操作数:",
122
+ "init.authorMapping": "配置作者名称映射?",
123
+ "init.authorMappingInfo": "\n作者映射帮助统一同一人的多个 Git 身份。\n",
124
+ "init.gitIdentity": "Git 身份(名称或邮箱):",
125
+ "init.unifiedName": "\"{{identity}}\" 的统一名称:",
126
+ "init.addMoreMapping": "添加另一个映射?",
127
+ "init.preview": "\n✅ 配置预览:\n",
128
+ "init.save": "\n保存此配置?",
129
+ "init.saved": "\n✅ 配置已保存至 {{path}}",
130
+ "init.runCommand": "\n运行:openspec-stat multi -c {{path}}",
131
+ "init.templateCreated": "✅ 模板已创建于 {{path}}",
132
+ "init.templateEdit": "请编辑文件并配置您的仓库。",
133
+
134
+ "config.validation.noRepos": "无效配置:\"repositories\" 必须是数组",
135
+ "config.validation.emptyRepos": "无效配置:至少需要一个仓库",
136
+ "config.validation.noName": "仓库 {{index}}:需要 \"name\"",
137
+ "config.validation.invalidType": "仓库 \"{{name}}\":\"type\" 必须是 \"local\" 或 \"remote\"",
138
+ "config.validation.noPath": "仓库 \"{{name}}\":本地类型需要 \"path\"",
139
+ "config.validation.noUrl": "仓库 \"{{name}}\":远程类型需要 \"url\"",
140
+ "config.validation.noBranches": "仓库 \"{{name}}\":至少需要一个分支",
141
+ "config.summary.title": "\n📋 配置摘要\n",
142
+ "config.summary.repositories": "仓库:",
143
+ "config.summary.timeRange": "\n时间范围:",
144
+ "config.summary.since": " 开始:{{hours}} 小时",
145
+ "config.summary.until": " 结束:{{hours}}:00",
146
+ "config.summary.parallelism": "\n并发:",
147
+ "config.summary.maxConcurrent": " 最大并发数:{{count}}",
148
+ "config.summary.remoteCache": "\n远程缓存:",
149
+ "config.summary.cacheDir": " 目录:{{dir}}",
150
+ "config.summary.autoCleanup": " 自动清理:{{enabled}}"
72
151
  }
@@ -0,0 +1,3 @@
1
+ import { MultiRepoConfig } from '../types.js';
2
+ export declare function validateAndFillDefaults(config: any): MultiRepoConfig;
3
+ export declare function printConfigSummary(config: MultiRepoConfig): void;