glassbox 0.9.10 → 0.9.11-rc.1

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.
package/README.md CHANGED
@@ -341,6 +341,12 @@ npm link # Symlink for global 'glassbox' command
341
341
  - **[Hot Sheet](https://github.com/brianwestphal/hotsheet)** — Lightweight local project management for AI-assisted development. Pairs well with Glassbox for tracking review feedback as actionable tickets.
342
342
  - **[Changelog](CHANGELOG.md)** — Full release history
343
343
 
344
+ ## Sponsor
345
+
346
+ Glassbox is free and open-source. If it saves you time on your AI workflow, consider sponsoring continued development:
347
+
348
+ [![Sponsor on GitHub](https://img.shields.io/badge/Sponsor-%E2%9D%A4-ea4aaa?logo=githubsponsors&logoColor=white)](https://github.com/sponsors/brianwestphal)
349
+
344
350
  ## License
345
351
 
346
352
  MIT
package/dist/cli.js CHANGED
@@ -3250,7 +3250,7 @@ async function generateReviewExport(reviewId, repoRoot, isCurrent) {
3250
3250
  lines.push("# Code Review");
3251
3251
  lines.push("");
3252
3252
  lines.push(`- **Repository**: ${review.repo_name}`);
3253
- lines.push(`- **Review mode**: ${review.mode}${review.mode_args !== null && review.mode_args !== "" ? ` (${review.mode_args})` : ""}`);
3253
+ lines.push(`- **Review mode**: ${review.mode}`);
3254
3254
  lines.push(`- **Review ID**: ${review.id}`);
3255
3255
  lines.push(`- **Date**: ${(/* @__PURE__ */ new Date()).toISOString()}`);
3256
3256
  lines.push(`- **Files reviewed**: ${files.filter((f) => f.status === "reviewed").length}/${files.length}`);
@@ -5704,23 +5704,40 @@ function Layout({ title, reviewId, children }) {
5704
5704
  ] });
5705
5705
  }
5706
5706
 
5707
+ // src/utils/formatReviewMode.ts
5708
+ var FULL_SHA_RE = /^[0-9a-f]{40}$/i;
5709
+ function shortenIfSha(ref) {
5710
+ if (FULL_SHA_RE.test(ref)) return ref.slice(0, 7);
5711
+ return ref;
5712
+ }
5713
+ function argsFor(mode, prefix, modeArgs) {
5714
+ if (modeArgs !== null && modeArgs !== "") return modeArgs;
5715
+ if (mode.startsWith(prefix)) return mode.slice(prefix.length);
5716
+ return "";
5717
+ }
5718
+ function formatReviewMode(mode, modeArgs) {
5719
+ if (mode === "commit" || mode.startsWith("commit:")) {
5720
+ return `commit: ${shortenIfSha(argsFor(mode, "commit:", modeArgs))}`;
5721
+ }
5722
+ if (mode === "range" || mode.startsWith("range:")) {
5723
+ const raw = argsFor(mode, "range:", modeArgs);
5724
+ const [from = "", to = ""] = raw.split("..");
5725
+ return `range: ${shortenIfSha(from)}..${shortenIfSha(to)}`;
5726
+ }
5727
+ if (mode === "branch" || mode.startsWith("branch:")) {
5728
+ return `branch: ${argsFor(mode, "branch:", modeArgs)}`;
5729
+ }
5730
+ if (mode === "files" || mode.startsWith("files:")) {
5731
+ return `files: ${argsFor(mode, "files:", modeArgs)}`;
5732
+ }
5733
+ return mode;
5734
+ }
5735
+
5707
5736
  // src/components/reviewHistory.tsx
5708
5737
  import { jsx as jsx5, jsxs as jsxs5 } from "kerfjs/jsx-runtime";
5709
5738
  function titleCase(s) {
5710
5739
  return s.replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
5711
5740
  }
5712
- function shortenArgs(args) {
5713
- const shaPattern = /\b([0-9a-f]{7,40})\b/gi;
5714
- const result = { hasLong: false };
5715
- const short = args.replace(shaPattern, (match) => {
5716
- if (match.length > 8) {
5717
- result.hasLong = true;
5718
- return match.slice(0, 7);
5719
- }
5720
- return match;
5721
- });
5722
- return { short, full: result.hasLong ? args : "" };
5723
- }
5724
5741
  function ReviewHistory({ reviews, currentReviewId }) {
5725
5742
  const hasOtherReviews = reviews.some((r) => r.id !== currentReviewId);
5726
5743
  const hasCompletedOthers = reviews.some((r) => r.id !== currentReviewId && r.status === "completed");
@@ -5729,24 +5746,14 @@ function ReviewHistory({ reviews, currentReviewId }) {
5729
5746
  reviews.length === 0 ? /* @__PURE__ */ jsx5("p", { style: "color:var(--text-dim)", children: "No previous reviews found." }) : /* @__PURE__ */ jsx5("div", { children: reviews.map((r) => {
5730
5747
  const isCurrent = r.id === currentReviewId;
5731
5748
  const href = isCurrent ? "/" : `/review/${r.id}`;
5732
- let argsDisplay = null;
5733
- if (r.mode_args !== null && r.mode_args !== "") {
5734
- const { short, full } = shortenArgs(r.mode_args);
5735
- argsDisplay = full !== "" ? /* @__PURE__ */ jsxs5("span", { title: full, children: [
5736
- ": ",
5737
- short
5738
- ] }) : /* @__PURE__ */ jsxs5("span", { children: [
5739
- ": ",
5740
- short
5741
- ] });
5742
- }
5749
+ const modeLabel = titleCase(formatReviewMode(r.mode, r.mode_args));
5750
+ const fullArgs = r.mode_args !== null && r.mode_args !== "" && /[0-9a-f]{40}/i.test(r.mode_args) ? r.mode_args : "";
5743
5751
  return /* @__PURE__ */ jsxs5("div", { children: [
5744
5752
  /* @__PURE__ */ jsx5("a", { href, className: "history-item-link", children: /* @__PURE__ */ jsxs5("div", { className: "history-item", "data-review-id": r.id, children: [
5745
5753
  /* @__PURE__ */ jsxs5("h3", { children: [
5746
5754
  r.repo_name,
5747
5755
  " - ",
5748
- titleCase(r.mode),
5749
- argsDisplay,
5756
+ fullArgs !== "" ? /* @__PURE__ */ jsx5("span", { title: fullArgs, children: modeLabel }) : modeLabel,
5750
5757
  isCurrent ? /* @__PURE__ */ jsx5("span", { className: "status-badge in_progress", style: "margin-left:8px", children: "Current" }) : null,
5751
5758
  /* @__PURE__ */ jsx5("span", { className: `status-badge ${r.status}`, style: "margin-left:8px", children: titleCase(r.status) })
5752
5759
  ] }),
@@ -5874,10 +5881,7 @@ function ReviewShell({ reviewId, review, files, annotationCounts, staleCounts, f
5874
5881
  /* @__PURE__ */ jsxs7("aside", { className: "sidebar", children: [
5875
5882
  /* @__PURE__ */ jsxs7("div", { className: "sidebar-header", children: [
5876
5883
  /* @__PURE__ */ jsx7("h2", { children: review.repo_name }),
5877
- /* @__PURE__ */ jsxs7("span", { className: "review-mode", children: [
5878
- review.mode,
5879
- review.mode_args !== null && review.mode_args !== "" ? `: ${review.mode_args}` : ""
5880
- ] })
5884
+ /* @__PURE__ */ jsx7("span", { className: "review-mode", children: formatReviewMode(review.mode, review.mode_args) })
5881
5885
  ] }),
5882
5886
  /* @__PURE__ */ jsx7("div", { className: "file-filter", children: /* @__PURE__ */ jsx7("input", { type: "text", className: "file-filter-input", id: "file-filter", placeholder: "Filter files..." }) }),
5883
5887
  /* @__PURE__ */ jsx7(FileList, { files, annotationCounts, staleCounts }),
@@ -6670,7 +6674,7 @@ async function main() {
6670
6674
  console.log("AI service test mode enabled \u2014 using mock AI responses");
6671
6675
  }
6672
6676
  if (debug) {
6673
- console.log(`[debug] Build timestamp: ${"2026-05-22T06:46:43.267Z"}`);
6677
+ console.log(`[debug] Build timestamp: ${"2026-05-22T07:55:40.035Z"}`);
6674
6678
  }
6675
6679
  if (projectDir !== null) {
6676
6680
  process.chdir(projectDir);