glassbox 0.3.0 → 0.3.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 +2 -2
- package/dist/cli.js +125 -100
- package/dist/client/app.global.js +7 -7
- package/dist/client/styles.css +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -65,13 +65,13 @@ Glassbox gives you a proper diff viewer with annotation categories designed for
|
|
|
65
65
|
| **Note** | Context for the AI to consider. |
|
|
66
66
|
| **Remember** | A rule to persist to the AI's long-term config. |
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
As you annotate, `.glassbox/latest-review.md` is updated automatically. You can tell your AI tool at any time:
|
|
69
69
|
|
|
70
70
|
```
|
|
71
71
|
Read .glassbox/latest-review.md and apply the feedback.
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
The AI gets a structured file with every annotation, organized by file and line number, with clear instructions on how to interpret each category. It fixes the bugs, applies your style preferences, avoids the anti-patterns, and updates its own config with your "remember" items.
|
|
74
|
+
The AI gets a structured file with every annotation, organized by file and line number, with clear instructions on how to interpret each category. It fixes the bugs, applies your style preferences, avoids the anti-patterns, and updates its own config with your "remember" items. You don't need to formally "complete" a review to share feedback — just annotate and switch to your AI tool.
|
|
75
75
|
|
|
76
76
|
Then you run `glassbox` again. Your previous annotations carry forward — matched to the updated diff. Stale comments that no longer apply are flagged so you can keep or discard them. The loop continues until you're satisfied.
|
|
77
77
|
|
package/dist/cli.js
CHANGED
|
@@ -3083,6 +3083,17 @@ async function generateReviewExport(reviewId, repoRoot, isCurrent) {
|
|
|
3083
3083
|
return archivePath;
|
|
3084
3084
|
}
|
|
3085
3085
|
|
|
3086
|
+
// src/export/auto-export.ts
|
|
3087
|
+
var debounceTimer = null;
|
|
3088
|
+
var DEBOUNCE_MS = 2e3;
|
|
3089
|
+
function scheduleAutoExport(reviewId, repoRoot) {
|
|
3090
|
+
if (debounceTimer !== null) clearTimeout(debounceTimer);
|
|
3091
|
+
debounceTimer = setTimeout(() => {
|
|
3092
|
+
debounceTimer = null;
|
|
3093
|
+
void generateReviewExport(reviewId, repoRoot, true);
|
|
3094
|
+
}, DEBOUNCE_MS);
|
|
3095
|
+
}
|
|
3096
|
+
|
|
3086
3097
|
// src/git/image.ts
|
|
3087
3098
|
import { execSync as execSync4 } from "child_process";
|
|
3088
3099
|
import { readFileSync as readFileSync5 } from "fs";
|
|
@@ -3704,6 +3715,9 @@ apiRoutes.patch("/files/:fileId/status", async (c) => {
|
|
|
3704
3715
|
await updateFileStatus(c.req.param("fileId"), status);
|
|
3705
3716
|
return c.json({ ok: true });
|
|
3706
3717
|
});
|
|
3718
|
+
function autoExport(c) {
|
|
3719
|
+
scheduleAutoExport(c.get("reviewId"), c.get("repoRoot"));
|
|
3720
|
+
}
|
|
3707
3721
|
apiRoutes.post("/annotations", async (c) => {
|
|
3708
3722
|
const body = await c.req.json();
|
|
3709
3723
|
const annotation = await addAnnotation(
|
|
@@ -3713,34 +3727,41 @@ apiRoutes.post("/annotations", async (c) => {
|
|
|
3713
3727
|
body.category,
|
|
3714
3728
|
body.content
|
|
3715
3729
|
);
|
|
3730
|
+
autoExport(c);
|
|
3716
3731
|
return c.json(annotation, 201);
|
|
3717
3732
|
});
|
|
3718
3733
|
apiRoutes.patch("/annotations/:id", async (c) => {
|
|
3719
3734
|
const { content, category } = await c.req.json();
|
|
3720
3735
|
await updateAnnotation(c.req.param("id"), content, category);
|
|
3736
|
+
autoExport(c);
|
|
3721
3737
|
return c.json({ ok: true });
|
|
3722
3738
|
});
|
|
3723
3739
|
apiRoutes.delete("/annotations/:id", async (c) => {
|
|
3724
3740
|
await deleteAnnotation(c.req.param("id"));
|
|
3741
|
+
autoExport(c);
|
|
3725
3742
|
return c.json({ ok: true });
|
|
3726
3743
|
});
|
|
3727
3744
|
apiRoutes.patch("/annotations/:id/move", async (c) => {
|
|
3728
3745
|
const { lineNumber, side } = await c.req.json();
|
|
3729
3746
|
await moveAnnotation(c.req.param("id"), lineNumber, side);
|
|
3747
|
+
autoExport(c);
|
|
3730
3748
|
return c.json({ ok: true });
|
|
3731
3749
|
});
|
|
3732
3750
|
apiRoutes.post("/annotations/:id/keep", async (c) => {
|
|
3733
3751
|
await markAnnotationCurrent(c.req.param("id"));
|
|
3752
|
+
autoExport(c);
|
|
3734
3753
|
return c.json({ ok: true });
|
|
3735
3754
|
});
|
|
3736
3755
|
apiRoutes.post("/annotations/stale/delete-all", async (c) => {
|
|
3737
3756
|
const reviewId = resolveReviewId(c);
|
|
3738
3757
|
await deleteStaleAnnotations(reviewId);
|
|
3758
|
+
autoExport(c);
|
|
3739
3759
|
return c.json({ ok: true });
|
|
3740
3760
|
});
|
|
3741
3761
|
apiRoutes.post("/annotations/stale/keep-all", async (c) => {
|
|
3742
3762
|
const reviewId = resolveReviewId(c);
|
|
3743
3763
|
await keepAllStaleAnnotations(reviewId);
|
|
3764
|
+
autoExport(c);
|
|
3744
3765
|
return c.json({ ok: true });
|
|
3745
3766
|
});
|
|
3746
3767
|
apiRoutes.get("/annotations/all", async (c) => {
|
|
@@ -3955,16 +3976,14 @@ function ImageDiff({ file, diff }) {
|
|
|
3955
3976
|
/* @__PURE__ */ jsx("div", { className: "slice-handle slice-handle-a" }),
|
|
3956
3977
|
/* @__PURE__ */ jsx("div", { className: "slice-handle slice-handle-b" })
|
|
3957
3978
|
] }) }),
|
|
3958
|
-
!hasComparison && /* @__PURE__ */ jsx("div", { className: "image-diff-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
/* @__PURE__ */ jsx("p", { className: "image-diff-status", children: isAdded ? "New file" : "Deleted file" })
|
|
3967
|
-
] })
|
|
3979
|
+
!hasComparison && /* @__PURE__ */ jsx("div", { className: "image-diff-panel image-diff-visual", "data-panel": "image", children: /* @__PURE__ */ jsx("div", { className: "image-visual-canvas", "data-zoomable": "true", children: /* @__PURE__ */ jsx("div", { className: "image-zoom-wrap", children: /* @__PURE__ */ jsx(
|
|
3980
|
+
"img",
|
|
3981
|
+
{
|
|
3982
|
+
className: "image-layer image-layer-old",
|
|
3983
|
+
src: `/api/image/${fileId}/${isAdded ? "new" : "old"}`,
|
|
3984
|
+
alt: isAdded ? "New image" : "Deleted image"
|
|
3985
|
+
}
|
|
3986
|
+
) }) }) })
|
|
3968
3987
|
]
|
|
3969
3988
|
}
|
|
3970
3989
|
);
|
|
@@ -4526,55 +4545,58 @@ pageRoutes.get("/", async (c) => {
|
|
|
4526
4545
|
/* @__PURE__ */ jsx("button", { id: "update-banner-dismiss", className: "btn btn-sm", children: "Later" })
|
|
4527
4546
|
] })
|
|
4528
4547
|
] }),
|
|
4529
|
-
/* @__PURE__ */ jsx("
|
|
4530
|
-
/* @__PURE__ */ jsx("
|
|
4531
|
-
/* @__PURE__ */ jsx("
|
|
4532
|
-
|
|
4533
|
-
review
|
|
4534
|
-
|
|
4548
|
+
/* @__PURE__ */ jsx("div", { className: "review-body", children: [
|
|
4549
|
+
/* @__PURE__ */ jsx("aside", { className: "sidebar", children: [
|
|
4550
|
+
/* @__PURE__ */ jsx("div", { className: "sidebar-header", children: [
|
|
4551
|
+
/* @__PURE__ */ jsx("h2", { children: review.repo_name }),
|
|
4552
|
+
/* @__PURE__ */ jsx("span", { className: "review-mode", children: [
|
|
4553
|
+
review.mode,
|
|
4554
|
+
review.mode_args !== null && review.mode_args !== "" ? `: ${review.mode_args}` : ""
|
|
4555
|
+
] })
|
|
4556
|
+
] }),
|
|
4557
|
+
/* @__PURE__ */ jsx("div", { className: "file-filter", children: /* @__PURE__ */ jsx("input", { type: "text", className: "file-filter-input", id: "file-filter", placeholder: "Filter files..." }) }),
|
|
4558
|
+
/* @__PURE__ */ jsx(FileList, { files, annotationCounts, staleCounts: {} }),
|
|
4559
|
+
/* @__PURE__ */ jsx("div", { className: "sidebar-footer", children: [
|
|
4560
|
+
/* @__PURE__ */ jsx("button", { className: "btn btn-primary btn-complete", id: "complete-review", children: "Complete Review" }),
|
|
4561
|
+
/* @__PURE__ */ jsx("a", { href: "/history", className: "btn btn-sm btn-link", children: "Review History" })
|
|
4535
4562
|
] })
|
|
4536
4563
|
] }),
|
|
4537
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
4538
|
-
/* @__PURE__ */ jsx(
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
/* @__PURE__ */ jsx("div", { className: "welcome-message", children: [
|
|
4547
|
-
/* @__PURE__ */ jsx("h3", { children: "Select a file to begin reviewing" }),
|
|
4548
|
-
/* @__PURE__ */ jsx("p", { children: [
|
|
4549
|
-
files.length,
|
|
4550
|
-
" file(s) to review"
|
|
4564
|
+
/* @__PURE__ */ jsx("div", { className: "sidebar-resize", id: "sidebar-resize" }),
|
|
4565
|
+
/* @__PURE__ */ jsx("main", { className: "main-content", children: [
|
|
4566
|
+
/* @__PURE__ */ jsx("div", { className: "welcome-message", children: [
|
|
4567
|
+
/* @__PURE__ */ jsx("h3", { children: "Select a file to begin reviewing" }),
|
|
4568
|
+
/* @__PURE__ */ jsx("p", { children: [
|
|
4569
|
+
files.length,
|
|
4570
|
+
" file(s) to review"
|
|
4571
|
+
] }),
|
|
4572
|
+
/* @__PURE__ */ jsx("p", { className: "progress-summary", id: "progress-summary" })
|
|
4551
4573
|
] }),
|
|
4552
|
-
/* @__PURE__ */ jsx("
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
/* @__PURE__ */ jsx("button", { className: "
|
|
4574
|
+
/* @__PURE__ */ jsx("div", { className: "diff-container", id: "diff-container", style: "display:none" }),
|
|
4575
|
+
/* @__PURE__ */ jsx("div", { className: "diff-toolbar", id: "diff-toolbar", style: "display:none", children: [
|
|
4576
|
+
/* @__PURE__ */ jsx("div", { className: "diff-toolbar-text", children: [
|
|
4577
|
+
/* @__PURE__ */ jsx("div", { className: "diff-toolbar-left", children: [
|
|
4578
|
+
/* @__PURE__ */ jsx("div", { className: "segmented-control", children: [
|
|
4579
|
+
/* @__PURE__ */ jsx("button", { className: "segment active", "data-diff-mode": "split", children: "Split" }),
|
|
4580
|
+
/* @__PURE__ */ jsx("button", { className: "segment", "data-diff-mode": "unified", children: "Unified" })
|
|
4581
|
+
] }),
|
|
4582
|
+
/* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "wrap-toggle", children: "Wrap" }),
|
|
4583
|
+
/* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "whitespace-toggle", children: "Ignore Whitespace" })
|
|
4561
4584
|
] }),
|
|
4562
|
-
/* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "
|
|
4563
|
-
/* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "whitespace-toggle", children: "Ignore Whitespace" })
|
|
4585
|
+
/* @__PURE__ */ jsx("div", { className: "diff-toolbar-right", children: /* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "language-btn", children: "Plain Text" }) })
|
|
4564
4586
|
] }),
|
|
4565
|
-
/* @__PURE__ */ jsx("div", { className: "diff-toolbar-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4587
|
+
/* @__PURE__ */ jsx("div", { className: "diff-toolbar-image", style: "display:none", children: [
|
|
4588
|
+
/* @__PURE__ */ jsx("div", { className: "diff-toolbar-left", children: /* @__PURE__ */ jsx("div", { className: "segmented-control", children: [
|
|
4589
|
+
/* @__PURE__ */ jsx("button", { className: "segment active", "data-image-mode": "metadata", children: "Metadata" }),
|
|
4590
|
+
/* @__PURE__ */ jsx("button", { className: "segment", "data-image-mode": "difference", children: "Difference" }),
|
|
4591
|
+
/* @__PURE__ */ jsx("button", { className: "segment", "data-image-mode": "slice", children: "Slice" }),
|
|
4592
|
+
/* @__PURE__ */ jsx("button", { className: "segment", "data-image-mode": "image", style: "display:none", children: "Image" })
|
|
4593
|
+
] }) }),
|
|
4594
|
+
/* @__PURE__ */ jsx("div", { className: "diff-toolbar-right", children: [
|
|
4595
|
+
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "out", title: "Zoom out", children: raw(zoomOutSvg) }),
|
|
4596
|
+
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "fit", title: "Fit to view", children: raw(fitSvg) }),
|
|
4597
|
+
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "actual", title: "Actual size (1:1)", children: raw(actualSizeSvg) }),
|
|
4598
|
+
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "in", title: "Zoom in", children: raw(zoomInSvg) })
|
|
4599
|
+
] })
|
|
4578
4600
|
] })
|
|
4579
4601
|
] })
|
|
4580
4602
|
] })
|
|
@@ -4626,56 +4648,59 @@ pageRoutes.get("/review/:reviewId", async (c) => {
|
|
|
4626
4648
|
/* @__PURE__ */ jsx("button", { id: "update-banner-dismiss", className: "btn btn-sm", children: "Later" })
|
|
4627
4649
|
] })
|
|
4628
4650
|
] }),
|
|
4629
|
-
/* @__PURE__ */ jsx("
|
|
4630
|
-
/* @__PURE__ */ jsx("
|
|
4631
|
-
/* @__PURE__ */ jsx("
|
|
4632
|
-
|
|
4633
|
-
review
|
|
4634
|
-
|
|
4651
|
+
/* @__PURE__ */ jsx("div", { className: "review-body", children: [
|
|
4652
|
+
/* @__PURE__ */ jsx("aside", { className: "sidebar", children: [
|
|
4653
|
+
/* @__PURE__ */ jsx("div", { className: "sidebar-header", children: [
|
|
4654
|
+
/* @__PURE__ */ jsx("h2", { children: review.repo_name }),
|
|
4655
|
+
/* @__PURE__ */ jsx("span", { className: "review-mode", children: [
|
|
4656
|
+
review.mode,
|
|
4657
|
+
review.mode_args !== null && review.mode_args !== "" ? `: ${review.mode_args}` : ""
|
|
4658
|
+
] })
|
|
4659
|
+
] }),
|
|
4660
|
+
/* @__PURE__ */ jsx("div", { className: "file-filter", children: /* @__PURE__ */ jsx("input", { type: "text", className: "file-filter-input", id: "file-filter", placeholder: "Filter files..." }) }),
|
|
4661
|
+
/* @__PURE__ */ jsx(FileList, { files, annotationCounts, staleCounts: {} }),
|
|
4662
|
+
/* @__PURE__ */ jsx("div", { className: "sidebar-footer", children: [
|
|
4663
|
+
review.status === "completed" ? /* @__PURE__ */ jsx("button", { className: "btn btn-primary", id: "reopen-review", children: "Reopen Review" }) : /* @__PURE__ */ jsx("button", { className: "btn btn-primary btn-complete", id: "complete-review", children: "Complete Review" }),
|
|
4664
|
+
/* @__PURE__ */ jsx("a", { href: "/history", className: "btn btn-sm btn-link", children: "Review History" }),
|
|
4665
|
+
/* @__PURE__ */ jsx("a", { href: "/", className: "btn btn-sm btn-link", children: "Back to current review" })
|
|
4635
4666
|
] })
|
|
4636
4667
|
] }),
|
|
4637
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
4638
|
-
/* @__PURE__ */ jsx(
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
/* @__PURE__ */ jsx("main", { className: "main-content", children: [
|
|
4647
|
-
/* @__PURE__ */ jsx("div", { className: "welcome-message", children: [
|
|
4648
|
-
/* @__PURE__ */ jsx("h3", { children: "Select a file to begin reviewing" }),
|
|
4649
|
-
/* @__PURE__ */ jsx("p", { children: [
|
|
4650
|
-
files.length,
|
|
4651
|
-
" file(s) to review"
|
|
4668
|
+
/* @__PURE__ */ jsx("div", { className: "sidebar-resize", id: "sidebar-resize" }),
|
|
4669
|
+
/* @__PURE__ */ jsx("main", { className: "main-content", children: [
|
|
4670
|
+
/* @__PURE__ */ jsx("div", { className: "welcome-message", children: [
|
|
4671
|
+
/* @__PURE__ */ jsx("h3", { children: "Select a file to begin reviewing" }),
|
|
4672
|
+
/* @__PURE__ */ jsx("p", { children: [
|
|
4673
|
+
files.length,
|
|
4674
|
+
" file(s) to review"
|
|
4675
|
+
] }),
|
|
4676
|
+
/* @__PURE__ */ jsx("p", { className: "progress-summary", id: "progress-summary" })
|
|
4652
4677
|
] }),
|
|
4653
|
-
/* @__PURE__ */ jsx("
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
/* @__PURE__ */ jsx("button", { className: "
|
|
4678
|
+
/* @__PURE__ */ jsx("div", { className: "diff-container", id: "diff-container", style: "display:none" }),
|
|
4679
|
+
/* @__PURE__ */ jsx("div", { className: "diff-toolbar", id: "diff-toolbar", style: "display:none", children: [
|
|
4680
|
+
/* @__PURE__ */ jsx("div", { className: "diff-toolbar-text", children: [
|
|
4681
|
+
/* @__PURE__ */ jsx("div", { className: "diff-toolbar-left", children: [
|
|
4682
|
+
/* @__PURE__ */ jsx("div", { className: "segmented-control", children: [
|
|
4683
|
+
/* @__PURE__ */ jsx("button", { className: "segment active", "data-diff-mode": "split", children: "Split" }),
|
|
4684
|
+
/* @__PURE__ */ jsx("button", { className: "segment", "data-diff-mode": "unified", children: "Unified" })
|
|
4685
|
+
] }),
|
|
4686
|
+
/* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "wrap-toggle", children: "Wrap" }),
|
|
4687
|
+
/* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "whitespace-toggle", children: "Ignore Whitespace" })
|
|
4662
4688
|
] }),
|
|
4663
|
-
/* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "
|
|
4664
|
-
/* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "whitespace-toggle", children: "Ignore Whitespace" })
|
|
4689
|
+
/* @__PURE__ */ jsx("div", { className: "diff-toolbar-right", children: /* @__PURE__ */ jsx("button", { className: "toolbar-btn", id: "language-btn", children: "Plain Text" }) })
|
|
4665
4690
|
] }),
|
|
4666
|
-
/* @__PURE__ */ jsx("div", { className: "diff-toolbar-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
|
|
4673
|
-
|
|
4674
|
-
|
|
4675
|
-
|
|
4676
|
-
|
|
4677
|
-
|
|
4678
|
-
|
|
4691
|
+
/* @__PURE__ */ jsx("div", { className: "diff-toolbar-image", style: "display:none", children: [
|
|
4692
|
+
/* @__PURE__ */ jsx("div", { className: "diff-toolbar-left", children: /* @__PURE__ */ jsx("div", { className: "segmented-control", children: [
|
|
4693
|
+
/* @__PURE__ */ jsx("button", { className: "segment active", "data-image-mode": "metadata", children: "Metadata" }),
|
|
4694
|
+
/* @__PURE__ */ jsx("button", { className: "segment", "data-image-mode": "difference", children: "Difference" }),
|
|
4695
|
+
/* @__PURE__ */ jsx("button", { className: "segment", "data-image-mode": "slice", children: "Slice" }),
|
|
4696
|
+
/* @__PURE__ */ jsx("button", { className: "segment", "data-image-mode": "image", style: "display:none", children: "Image" })
|
|
4697
|
+
] }) }),
|
|
4698
|
+
/* @__PURE__ */ jsx("div", { className: "diff-toolbar-right", children: [
|
|
4699
|
+
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "out", title: "Zoom out", children: raw(zoomOutSvg) }),
|
|
4700
|
+
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "fit", title: "Fit to view", children: raw(fitSvg) }),
|
|
4701
|
+
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "actual", title: "Actual size (1:1)", children: raw(actualSizeSvg) }),
|
|
4702
|
+
/* @__PURE__ */ jsx("button", { className: "image-zoom-btn", "data-zoom-action": "in", title: "Zoom in", children: raw(zoomInSvg) })
|
|
4703
|
+
] })
|
|
4679
4704
|
] })
|
|
4680
4705
|
] })
|
|
4681
4706
|
] })
|
|
@@ -5129,7 +5154,7 @@ async function main() {
|
|
|
5129
5154
|
console.log("AI service test mode enabled \u2014 using mock AI responses");
|
|
5130
5155
|
}
|
|
5131
5156
|
if (debug) {
|
|
5132
|
-
console.log(`[debug] Build timestamp: ${"2026-03-
|
|
5157
|
+
console.log(`[debug] Build timestamp: ${"2026-03-16T09:22:20.931Z"}`);
|
|
5133
5158
|
}
|
|
5134
5159
|
if (projectDir) {
|
|
5135
5160
|
process.chdir(projectDir);
|