bazilion 0.18.0 → 0.19.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 (96) hide show
  1. package/dist/cli.js +607 -96
  2. package/dist/cli.js.map +1 -1
  3. package/dist/daemon.js +3225 -739
  4. package/dist/daemon.js.map +1 -1
  5. package/dist/migrations/0001_init.sql +142 -3
  6. package/dist/web/client/assets/{ChatPane-CAYS_fIQ.js → ChatPane-DCyGcqdh.js} +1 -1
  7. package/dist/web/client/assets/ConfirmDialog-C908TxS5.js +1 -0
  8. package/dist/web/client/assets/{FieldRow-W_54rw5c.js → FieldRow-CELqI-1V.js} +1 -1
  9. package/dist/web/client/assets/{ProductionTeamPolicyEditor-DNXVX8Lz.js → ProductionTeamPolicyEditor-DnTcWhG8.js} +1 -1
  10. package/dist/web/client/assets/{ProfileCommunicationEditor-DN0fOzqn.js → ProfileCommunicationEditor-BVIEaW3s.js} +1 -1
  11. package/dist/web/client/assets/{ResultSourceConversation-DoU4tOWc.js → ResultSourceConversation-4gbZCh_s.js} +1 -1
  12. package/dist/web/client/assets/{TeamTabs-BmTZRI4T.js → TeamTabs-V17b45X5.js} +1 -1
  13. package/dist/web/client/assets/{TemplatesTabs-Bs_OXKwx.js → TemplatesTabs-BMK3Qok_.js} +1 -1
  14. package/dist/web/client/assets/{UnsavedChangesGuard-CPRtFReU.js → UnsavedChangesGuard-BaE-UzyS.js} +1 -1
  15. package/dist/web/client/assets/{_id-Dbmei5tg.js → _id-BU1l9gP7.js} +1 -1
  16. package/dist/web/client/assets/{_id-DL4tJFQB.js → _id-BVANQm00.js} +1 -1
  17. package/dist/web/client/assets/{_id-DR9eFC17.js → _id-Bvh5LyUv.js} +1 -1
  18. package/dist/web/client/assets/{_id-ybF-pqmr.js → _id-CArZR-IO.js} +1 -1
  19. package/dist/web/client/assets/{_id-CxAB4TDr.js → _id-tUkSe5li.js} +1 -1
  20. package/dist/web/client/assets/{activity-oUyy77jD.js → activity-CWCnqjqj.js} +1 -1
  21. package/dist/web/client/assets/{agents-DkjJp7JP.js → agents-CX4STmGK.js} +1 -1
  22. package/dist/web/client/assets/{agents-D_TrEqAg.js → agents-CdCnhH06.js} +1 -1
  23. package/dist/web/client/assets/{approvals-DhOerWdt.js → approvals-CnNpwG78.js} +1 -1
  24. package/dist/web/client/assets/{attention-DGwiF-Jy.js → attention-CEE-wWrx.js} +1 -1
  25. package/dist/web/client/assets/chevron-right-CvCEwfSl.js +1 -0
  26. package/dist/web/client/assets/{config-BJ2ZzHPR.js → config-CSEtI-dq.js} +1 -1
  27. package/dist/web/client/assets/{inbox-BUElnGep.js → inbox-MYnBtPdF.js} +1 -1
  28. package/dist/web/client/assets/index-Ct31TjS-.js +52 -0
  29. package/dist/web/client/assets/{learning-BiTHNwB3.js → learning-BIR5FTgQ.js} +1 -1
  30. package/dist/web/client/assets/{login-BmcZvAH2.js → login-DIeceuOs.js} +1 -1
  31. package/dist/web/client/assets/{mcp-Cwk9V82W.js → mcp-CX3kJpGu.js} +1 -1
  32. package/dist/web/client/assets/{members-CHDNabFh.js → members-DlhSjye1.js} +1 -1
  33. package/dist/web/client/assets/{memory-Cx_Fpd4e.js → memory-CsDd6b2l.js} +1 -1
  34. package/dist/web/client/assets/{policy-C0nMdwcG.js → policy-DkWDhG0x.js} +1 -1
  35. package/dist/web/client/assets/{results-Bz3jASs-.js → results-BHdhNHJJ.js} +1 -1
  36. package/dist/web/client/assets/review-Dyw47eM1.js +1 -0
  37. package/dist/web/client/assets/{routes-DsMY_6oy.js → routes-DtYD4WJL.js} +1 -1
  38. package/dist/web/client/assets/{services-DItA6fJ7.js → services-WUlW7oEo.js} +1 -1
  39. package/dist/web/client/assets/{skills-DbNV2vgL.js → skills-jNoUfUSZ.js} +1 -1
  40. package/dist/web/client/assets/styles-DCX6QTqJ.css +2 -0
  41. package/dist/web/client/assets/{teams-D83scDxw.js → teams-C1kYRrtP.js} +1 -1
  42. package/dist/web/client/assets/{teams-DAny1ypN.js → teams-D3FaSKE7.js} +1 -1
  43. package/dist/web/client/assets/{telegram-BOmf9vUh.js → telegram-D86AO6V9.js} +1 -1
  44. package/dist/web/client/assets/{tokens-DBGH6Bw5.js → tokens-B42KDisP.js} +1 -1
  45. package/dist/web/client/assets/{triggers-D1_pseI3.js → triggers-yEfWnQ_K.js} +1 -1
  46. package/dist/web/client/assets/{verifications-CBTo-FyV.js → verifications-DrHQEQFx.js} +2 -2
  47. package/dist/web/client/assets/{welcome-DAfPOm15.js → welcome-D8IbF_P0.js} +1 -1
  48. package/dist/web/client/assets/{x-CWY-gUaM.js → x-CXKABZ7C.js} +1 -1
  49. package/dist/web/server/assets/{_id--zoh1vv7.js → _id-D2bDA1iV.js} +1 -1
  50. package/dist/web/server/assets/{_id-6p-mDmI8.js → _id-DL-SnSnK.js} +1 -1
  51. package/dist/web/server/assets/{_id-dUnXL-My2.js → _id-Dab2CVtO2.js} +1 -1
  52. package/dist/web/server/assets/{_id-DptBl3X8.js → _id-bVispdh-.js} +1 -1
  53. package/dist/web/server/assets/{_tanstack-start-manifest_v-B3M-dfRO.js → _tanstack-start-manifest_v-BcTOb0oj.js} +84 -85
  54. package/dist/web/server/assets/{activity-C5jpoEQI.js → activity-CLDAy6rk.js} +1 -1
  55. package/dist/web/server/assets/{agents-RE6aYOb-.js → agents-CdB2kuNN.js} +1 -1
  56. package/dist/web/server/assets/{agents-nAOx_H7s.js → agents-DfHcb2H2.js} +1 -1
  57. package/dist/web/server/assets/{approvals-DhHxIDrL.js → approvals-Bq846WaP.js} +1 -1
  58. package/dist/web/server/assets/{attention-CBWzWRni.js → attention-Sm-U7s_0.js} +1 -1
  59. package/dist/web/server/assets/{auth-tB3i6cFd.js → auth-PB5dVyvX.js} +1 -1
  60. package/dist/web/server/assets/{config-D1k_tTAw.js → config-BNGTBu80.js} +1 -1
  61. package/dist/web/server/assets/{daemon-client-C7qjQ2iO.js → daemon-client-CWQvck6B.js} +35 -0
  62. package/dist/web/server/assets/{git-review-Bf5ABFJg.js → git-review-C_h_tezf.js} +1 -1
  63. package/dist/web/server/assets/{inbox-Dw4pTevh.js → inbox-DJoU-bla.js} +1 -1
  64. package/dist/web/server/assets/{learning-CF8ZzFVD.js → learning-DVb0I_3Z.js} +1 -1
  65. package/dist/web/server/assets/{mcp-D5dmBT82.js → mcp-CeZqOiDG.js} +1 -1
  66. package/dist/web/server/assets/{members-CvwEN9pm.js → members-CcYjuqxB.js} +1 -1
  67. package/dist/web/server/assets/{memory-CcPK7um7.js → memory-CH2yNT89.js} +1 -1
  68. package/dist/web/server/assets/{policy-Dh6wd2wN.js → policy-DrRKinMr.js} +1 -1
  69. package/dist/web/server/assets/{results-BWnu3gXP.js → results-fT2zyiJx.js} +1 -1
  70. package/dist/web/server/assets/review-CvUPk4HA.js +38 -0
  71. package/dist/web/server/assets/review-DYcYdUTv.js +859 -0
  72. package/dist/web/server/assets/review-packets-e36PsTSX.js +172 -0
  73. package/dist/web/server/assets/{router-Deq94UJQ.js → router-NYhuYQCd.js} +4 -4
  74. package/dist/web/server/assets/{routes-CVKkvFVv.js → routes-RdppWPiW.js} +1 -1
  75. package/dist/web/server/assets/{services-CEr61xb5.js → services-Dgu7dcTC.js} +1 -1
  76. package/dist/web/server/assets/{skills-BImC3LTO.js → skills-DL7UIWa8.js} +1 -1
  77. package/dist/web/server/assets/{teams-8zEIo08E.js → teams-Cmn7mdx9.js} +1 -1
  78. package/dist/web/server/assets/{teams-D-yaAWLV.js → teams-DiC-MBg4.js} +1 -1
  79. package/dist/web/server/assets/{telegram-CGl_LFtJ.js → telegram-CLOFnLjF.js} +1 -1
  80. package/dist/web/server/assets/{tokens-cB-uf7qm.js → tokens-BVva7GHu.js} +1 -1
  81. package/dist/web/server/assets/{triggers-CtSj79L0.js → triggers-D4orksJq.js} +1 -1
  82. package/dist/web/server/assets/{verification-B5QjcpIo.js → verification-C1SHMTX8.js} +1 -1
  83. package/dist/web/server/assets/{verifications-CUq_6ZqL.js → verifications-C_ycXrPK.js} +1 -1
  84. package/dist/web/server/assets/{verifications-BfQsfwSE.js → verifications-Ci49n2Km.js} +14 -1
  85. package/dist/web/server/server.js +75 -39
  86. package/dist/worker.js +528 -111
  87. package/dist/worker.js.map +1 -1
  88. package/package.json +3 -3
  89. package/dist/web/client/assets/ConfirmDialog-BzIiABOP.js +0 -1
  90. package/dist/web/client/assets/chevron-right-DSa4xPTs.js +0 -1
  91. package/dist/web/client/assets/createServerFn-Dzfjt7mA.js +0 -3
  92. package/dist/web/client/assets/index-Bi-HxcPG.js +0 -50
  93. package/dist/web/client/assets/review-AK9WGmpv.js +0 -1
  94. package/dist/web/client/assets/styles-C6br2xxl.css +0 -2
  95. package/dist/web/server/assets/review-DUe3vHPU.js +0 -393
  96. package/dist/web/server/assets/review-c_-cFi7H.js +0 -14
@@ -0,0 +1,859 @@
1
+ import { a as fetchReviewFileLink, c as recordReviewConclusion, i as fetchReviewExport, l as resolveReviewFinding, n as addReviewFinding, o as fetchReviewPacket, r as createReviewPacket, s as recordReportedState, t as Route } from "./review-CvUPk4HA.js";
2
+ import { a as fetchTeamSnapshot, i as fetchTeamReview, n as fetchFileDiff, o as prepareReviewFeedback, s as sendReviewFeedback, t as captureTeamSnapshot } from "./git-review-BB3M9nYg.js";
3
+ import { r as PageShell } from "./Page-Bz-ydB8j.js";
4
+ import { t as Button } from "./Button-Dsnw22OF.js";
5
+ import { a as referenceLabel, i as changeSummary, o as snapshotLabel, r as baseLabel, s as unavailableMessage } from "./git-review-presentation-TJiHJhen.js";
6
+ import { t as TeamTabs } from "./TeamTabs-Dg4v6x0-.js";
7
+ import { useState } from "react";
8
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
+ //#region src/components/ReviewPacketPanel.tsx
10
+ var SEVERITIES = [
11
+ "blocker",
12
+ "major",
13
+ "minor",
14
+ "info"
15
+ ];
16
+ var CONCLUSIONS = [
17
+ "changes_requested",
18
+ "commented",
19
+ "recommended"
20
+ ];
21
+ /**
22
+ * The completion facts, in the order they happen. Each is shown with the state it actually has: a review
23
+ * conclusion is not acceptance, and a reported state is what the operator said rather than something the
24
+ * daemon checked.
25
+ */
26
+ var REPORTED_STATES = [
27
+ "committed",
28
+ "pushed",
29
+ "pullRequest",
30
+ "merged",
31
+ "deployed",
32
+ "productionAccepted"
33
+ ];
34
+ function applicabilityLabel(comparison) {
35
+ return comparison === "identical" ? "unchanged since capture" : comparison === "changed" ? "changed since capture (never a pass)" : "not checked";
36
+ }
37
+ function ReviewPacketPanel({ teamId, view }) {
38
+ const [reports, setReports] = useState({});
39
+ const [busy, setBusy] = useState(false);
40
+ const [error, setError] = useState(null);
41
+ const [snapshotId, setSnapshotId] = useState(view.snapshots[0]?.id ?? "");
42
+ const [reviewer, setReviewer] = useState(view.members[0]?.id ?? "");
43
+ const [finding, setFinding] = useState({
44
+ path: "",
45
+ severity: "major",
46
+ note: ""
47
+ });
48
+ const [handoff, setHandoff] = useState(null);
49
+ const [link, setLink] = useState(null);
50
+ const [reference, setReference] = useState("");
51
+ const [reportedState, setReportedState] = useState("committed");
52
+ const [linkPath, setLinkPath] = useState("");
53
+ const run = async (action) => {
54
+ setBusy(true);
55
+ setError(null);
56
+ try {
57
+ const result = await action();
58
+ if ("report" in result && result.report) setReports((current) => ({
59
+ ...current,
60
+ [result.report.packet.id]: result.report
61
+ }));
62
+ else if ("message" in result) setError(result);
63
+ } finally {
64
+ setBusy(false);
65
+ }
66
+ };
67
+ const create = () => run(() => createReviewPacket({ data: {
68
+ id: teamId,
69
+ snapshotId,
70
+ reviewerAgentId: reviewer || null
71
+ } }));
72
+ const load = (packetId) => run(() => fetchReviewPacket({ data: {
73
+ id: teamId,
74
+ packetId
75
+ } }));
76
+ const reportFor = (packetId) => reports[packetId];
77
+ return /* @__PURE__ */ jsxs("section", {
78
+ className: "space-y-3",
79
+ "aria-label": "Review packets",
80
+ children: [
81
+ /* @__PURE__ */ jsxs("div", {
82
+ className: "flex items-baseline justify-between gap-2",
83
+ children: [/* @__PURE__ */ jsx("h3", { children: "Review packets" }), /* @__PURE__ */ jsx("span", {
84
+ className: "muted",
85
+ children: "A packet binds one captured revision. Findings are recorded against it; resolving one needs an explicit decision or a named later revision."
86
+ })]
87
+ }),
88
+ /* @__PURE__ */ jsxs("div", {
89
+ className: "flex flex-wrap items-end gap-2",
90
+ children: [
91
+ /* @__PURE__ */ jsxs("label", {
92
+ className: "flex flex-col text-sm",
93
+ children: [/* @__PURE__ */ jsx("span", {
94
+ className: "muted",
95
+ children: "Revision"
96
+ }), /* @__PURE__ */ jsxs("select", {
97
+ value: snapshotId,
98
+ onChange: (event) => setSnapshotId(event.target.value),
99
+ className: "unstyled",
100
+ children: [view.snapshots.length === 0 ? /* @__PURE__ */ jsx("option", {
101
+ value: "",
102
+ children: "(none captured)"
103
+ }) : null, view.snapshots.map((snapshot) => /* @__PURE__ */ jsxs("option", {
104
+ value: snapshot.id,
105
+ children: [snapshot.id.slice(0, 12), snapshot.complete ? "" : " — INCOMPLETE"]
106
+ }, snapshot.id))]
107
+ })]
108
+ }),
109
+ /* @__PURE__ */ jsxs("label", {
110
+ className: "flex flex-col text-sm",
111
+ children: [/* @__PURE__ */ jsx("span", {
112
+ className: "muted",
113
+ children: "Reviewer (optional)"
114
+ }), /* @__PURE__ */ jsxs("select", {
115
+ value: reviewer,
116
+ onChange: (event) => setReviewer(event.target.value),
117
+ className: "unstyled",
118
+ children: [/* @__PURE__ */ jsx("option", {
119
+ value: "",
120
+ children: "none — nothing delegated"
121
+ }), view.members.map((member) => /* @__PURE__ */ jsx("option", {
122
+ value: member.id,
123
+ children: member.name
124
+ }, member.id))]
125
+ })]
126
+ }),
127
+ /* @__PURE__ */ jsx(Button, {
128
+ variant: "primary",
129
+ disabled: busy || !snapshotId,
130
+ onClick: create,
131
+ children: "Open packet"
132
+ })
133
+ ]
134
+ }),
135
+ error ? /* @__PURE__ */ jsx("p", {
136
+ role: "alert",
137
+ className: "rounded-sm border border-fawn p-2 text-sm",
138
+ children: error.message
139
+ }) : null,
140
+ view.packets.length === 0 ? /* @__PURE__ */ jsx("p", {
141
+ className: "muted",
142
+ children: "No review packets yet."
143
+ }) : /* @__PURE__ */ jsx("ul", {
144
+ className: "list",
145
+ children: view.packets.map((entry) => {
146
+ const report = reportFor(entry.packet.id);
147
+ return /* @__PURE__ */ jsxs("li", {
148
+ className: "card space-y-2",
149
+ children: [
150
+ /* @__PURE__ */ jsxs("div", {
151
+ className: "flex flex-wrap items-baseline justify-between gap-2",
152
+ children: [/* @__PURE__ */ jsxs("div", { children: [
153
+ /* @__PURE__ */ jsx("strong", { children: entry.packet.state }),
154
+ " ",
155
+ /* @__PURE__ */ jsxs("span", {
156
+ className: "muted",
157
+ children: [
158
+ entry.packet.reviewerAgentId ?? "no reviewer",
159
+ " ·",
160
+ " ",
161
+ entry.packet.snapshot.id.slice(0, 12)
162
+ ]
163
+ })
164
+ ] }), /* @__PURE__ */ jsxs("div", {
165
+ className: "flex gap-2",
166
+ children: [/* @__PURE__ */ jsx(Button, {
167
+ variant: "ghost",
168
+ disabled: busy,
169
+ onClick: () => load(entry.packet.id),
170
+ children: "Details"
171
+ }), /* @__PURE__ */ jsx(Button, {
172
+ variant: "ghost",
173
+ disabled: busy,
174
+ onClick: async () => {
175
+ setBusy(true);
176
+ const result = await fetchReviewExport({ data: {
177
+ id: teamId,
178
+ packetId: entry.packet.id
179
+ } });
180
+ setBusy(false);
181
+ if ("handoff" in result) setHandoff({
182
+ packetId: entry.packet.id,
183
+ patch: result.patch,
184
+ text: result.handoff
185
+ });
186
+ else if ("message" in result) setError(result);
187
+ },
188
+ children: "Handoff"
189
+ })]
190
+ })]
191
+ }),
192
+ /* @__PURE__ */ jsxs("p", {
193
+ className: "muted",
194
+ children: [
195
+ entry.counts.findings,
196
+ " finding(s), ",
197
+ entry.counts.unresolved,
198
+ " unresolved",
199
+ entry.counts.blockers > 0 ? `, ${entry.counts.blockers} blocker(s)` : "",
200
+ " ·",
201
+ " ",
202
+ entry.conclusion ?? "no conclusion yet"
203
+ ]
204
+ }),
205
+ handoff?.packetId === entry.packet.id ? /* @__PURE__ */ jsxs("div", {
206
+ className: "space-y-1",
207
+ children: [
208
+ /* @__PURE__ */ jsx("h4", { children: "Handoff" }),
209
+ /* @__PURE__ */ jsx("pre", {
210
+ className: "overflow-x-auto rounded-sm border border-fawn p-2 text-xs",
211
+ children: handoff.text
212
+ }),
213
+ handoff.patch ? /* @__PURE__ */ jsx("pre", {
214
+ className: "overflow-x-auto rounded-sm border border-fawn p-2 text-xs",
215
+ children: handoff.patch
216
+ }) : null,
217
+ /* @__PURE__ */ jsx(Button, {
218
+ variant: "ghost",
219
+ onClick: () => {
220
+ navigator.clipboard?.writeText(handoff.patch || handoff.text);
221
+ },
222
+ children: "Copy"
223
+ })
224
+ ]
225
+ }) : null,
226
+ report ? /* @__PURE__ */ jsxs(Fragment, { children: [
227
+ /* @__PURE__ */ jsxs("p", {
228
+ className: "muted",
229
+ children: ["applicability: ", applicabilityLabel(report.applicability.comparison)]
230
+ }),
231
+ /* @__PURE__ */ jsx("ul", { children: report.findings.map((item) => /* @__PURE__ */ jsxs("li", { children: [
232
+ /* @__PURE__ */ jsxs("span", {
233
+ className: "muted",
234
+ children: [
235
+ "[",
236
+ item.severity,
237
+ "]"
238
+ ]
239
+ }),
240
+ " ",
241
+ /* @__PURE__ */ jsxs("code", { children: [item.path, item.lineStart === null ? "" : `:${item.lineStart}${item.lineEnd && item.lineEnd !== item.lineStart ? `-${item.lineEnd}` : ""}`] }),
242
+ " ",
243
+ "— ",
244
+ item.note,
245
+ item.resolution ? /* @__PURE__ */ jsxs("span", {
246
+ className: "muted",
247
+ children: [
248
+ " ",
249
+ "· resolved (",
250
+ item.resolution.kind,
251
+ ") by ",
252
+ item.resolution.by.kind
253
+ ]
254
+ }) : item.state === "unverified" ? /* @__PURE__ */ jsx("span", {
255
+ className: "muted",
256
+ children: " · UNVERIFIED — not correlated to this revision"
257
+ }) : /* @__PURE__ */ jsx(Button, {
258
+ variant: "ghost",
259
+ disabled: busy,
260
+ onClick: () => run(() => resolveReviewFinding({ data: {
261
+ id: teamId,
262
+ packetId: entry.packet.id,
263
+ findingId: item.id,
264
+ resolutionKind: "explicit",
265
+ resolutionNote: "resolved by the operator"
266
+ } })),
267
+ children: "Resolve explicitly"
268
+ })
269
+ ] }, item.id)) }),
270
+ /* @__PURE__ */ jsxs("div", {
271
+ className: "flex flex-wrap items-end gap-2",
272
+ children: [
273
+ /* @__PURE__ */ jsxs("label", {
274
+ className: "flex flex-col text-sm",
275
+ children: [/* @__PURE__ */ jsx("span", {
276
+ className: "muted",
277
+ children: "Finding path"
278
+ }), /* @__PURE__ */ jsx("input", {
279
+ value: finding.path,
280
+ onChange: (event) => setFinding({
281
+ ...finding,
282
+ path: event.target.value
283
+ })
284
+ })]
285
+ }),
286
+ /* @__PURE__ */ jsxs("label", {
287
+ className: "flex flex-col text-sm",
288
+ children: [/* @__PURE__ */ jsx("span", {
289
+ className: "muted",
290
+ children: "Severity"
291
+ }), /* @__PURE__ */ jsx("select", {
292
+ value: finding.severity,
293
+ onChange: (event) => setFinding({
294
+ ...finding,
295
+ severity: event.target.value
296
+ }),
297
+ children: SEVERITIES.map((severity) => /* @__PURE__ */ jsx("option", {
298
+ value: severity,
299
+ children: severity
300
+ }, severity))
301
+ })]
302
+ }),
303
+ /* @__PURE__ */ jsxs("label", {
304
+ className: "flex flex-col grow text-sm",
305
+ children: [/* @__PURE__ */ jsx("span", {
306
+ className: "muted",
307
+ children: "Note"
308
+ }), /* @__PURE__ */ jsx("input", {
309
+ value: finding.note,
310
+ onChange: (event) => setFinding({
311
+ ...finding,
312
+ note: event.target.value
313
+ })
314
+ })]
315
+ }),
316
+ /* @__PURE__ */ jsx(Button, {
317
+ variant: "ghost",
318
+ disabled: busy || !finding.path || !finding.note,
319
+ onClick: () => run(() => addReviewFinding({ data: {
320
+ id: teamId,
321
+ packetId: entry.packet.id,
322
+ path: finding.path,
323
+ severity: finding.severity,
324
+ note: finding.note
325
+ } })),
326
+ children: "Add finding"
327
+ })
328
+ ]
329
+ }),
330
+ /* @__PURE__ */ jsxs("div", {
331
+ className: "flex flex-wrap items-center gap-2",
332
+ children: [/* @__PURE__ */ jsx("span", {
333
+ className: "muted",
334
+ children: "Conclusion:"
335
+ }), CONCLUSIONS.map((conclusion) => /* @__PURE__ */ jsx(Button, {
336
+ variant: "ghost",
337
+ disabled: busy,
338
+ onClick: () => run(() => recordReviewConclusion({ data: {
339
+ id: teamId,
340
+ packetId: entry.packet.id,
341
+ conclusion
342
+ } })),
343
+ children: conclusion
344
+ }, conclusion))]
345
+ }),
346
+ /* @__PURE__ */ jsxs("div", {
347
+ className: "space-y-1",
348
+ children: [
349
+ /* @__PURE__ */ jsx("span", {
350
+ className: "muted",
351
+ children: "Where a file link points. The workspace belongs to the machine running the daemon, so this says which host it names and whether it is the reviewed revision."
352
+ }),
353
+ /* @__PURE__ */ jsxs("div", {
354
+ className: "flex flex-wrap items-center gap-2",
355
+ children: [
356
+ /* @__PURE__ */ jsx("input", {
357
+ placeholder: "changed path",
358
+ value: linkPath,
359
+ onChange: (event) => setLinkPath(event.target.value)
360
+ }),
361
+ /* @__PURE__ */ jsx(Button, {
362
+ variant: "ghost",
363
+ disabled: busy || !linkPath,
364
+ onClick: async () => {
365
+ const result = await fetchReviewFileLink({ data: {
366
+ id: teamId,
367
+ packetId: entry.packet.id,
368
+ path: linkPath
369
+ } });
370
+ if ("link" in result) setLink({
371
+ packetId: entry.packet.id,
372
+ link: result.link
373
+ });
374
+ else if ("message" in result) setError(result);
375
+ },
376
+ children: "Resolve location"
377
+ }),
378
+ link?.packetId === entry.packet.id ? /* @__PURE__ */ jsx(Button, {
379
+ variant: "ghost",
380
+ onClick: () => void navigator.clipboard?.writeText(link.link.copyTarget),
381
+ children: "Copy location"
382
+ }) : null
383
+ ]
384
+ }),
385
+ link?.packetId === entry.packet.id ? /* @__PURE__ */ jsxs("p", {
386
+ className: "muted",
387
+ children: [
388
+ /* @__PURE__ */ jsx("code", { children: link.link.copyTarget }),
389
+ " · on",
390
+ " ",
391
+ link.link.host.daemon ?? "the daemon host",
392
+ " ·",
393
+ " ",
394
+ link.link.mode === "live" ? "the reviewed revision" : link.link.mode === "stale" ? "the CURRENT file, not the reviewed revision" : "unknown",
395
+ " ",
396
+ "·",
397
+ " ",
398
+ link.link.canOpen ? `an editor is configured on the daemon host (${link.link.command})` : "no editor configured, so nothing can be opened here"
399
+ ]
400
+ }) : null
401
+ ]
402
+ }),
403
+ /* @__PURE__ */ jsxs("p", {
404
+ className: "muted",
405
+ children: [
406
+ "completed: change prepared=",
407
+ String(report.facts.changePrepared),
408
+ " checks current=",
409
+ String(report.facts.checksCurrent),
410
+ " reviewed=",
411
+ String(report.facts.reviewed),
412
+ " — a conclusion is not acceptance, and nothing here commits, pushes, merges or deploys."
413
+ ]
414
+ }),
415
+ /* @__PURE__ */ jsxs("div", {
416
+ className: "space-y-1",
417
+ children: [
418
+ /* @__PURE__ */ jsx("span", {
419
+ className: "muted",
420
+ children: "Beyond this point nothing is verified: Bazilion has no code-host integration, so these are whatever you report."
421
+ }),
422
+ /* @__PURE__ */ jsxs("div", {
423
+ className: "flex flex-wrap items-center gap-2",
424
+ children: [
425
+ /* @__PURE__ */ jsx("select", {
426
+ className: "unstyled",
427
+ value: reportedState,
428
+ onChange: (event) => setReportedState(event.target.value),
429
+ children: REPORTED_STATES.map((state) => /* @__PURE__ */ jsx("option", {
430
+ value: state,
431
+ children: state
432
+ }, state))
433
+ }),
434
+ /* @__PURE__ */ jsx("input", {
435
+ placeholder: "commit id, URL, release name…",
436
+ value: reference,
437
+ onChange: (event) => setReference(event.target.value)
438
+ }),
439
+ /* @__PURE__ */ jsx(Button, {
440
+ variant: "ghost",
441
+ disabled: busy,
442
+ onClick: () => run(() => recordReportedState({ data: {
443
+ id: teamId,
444
+ packetId: entry.packet.id,
445
+ state: reportedState,
446
+ reference: reference || null
447
+ } })),
448
+ children: "Report"
449
+ })
450
+ ]
451
+ }),
452
+ /* @__PURE__ */ jsxs("p", {
453
+ className: "muted",
454
+ children: [
455
+ "reported (reported, not verified):",
456
+ " ",
457
+ Object.entries(report.packet.reported).filter(([, value]) => value !== null).map(([key, value]) => `${key}=${value}`).join(" ") || "nothing yet"
458
+ ]
459
+ })
460
+ ]
461
+ })
462
+ ] }) : null
463
+ ]
464
+ }, entry.packet.id);
465
+ })
466
+ })
467
+ ]
468
+ });
469
+ }
470
+ //#endregion
471
+ //#region src/routes/teams/$id/review.tsx?tsr-split=component
472
+ function ReviewPage() {
473
+ const loaded = Route.useLoaderData();
474
+ const teamId = loaded.team.id;
475
+ const [base, setBase] = useState("");
476
+ const [appliedBase, setAppliedBase] = useState("");
477
+ const [review, setReview] = useState(loaded.review);
478
+ const [unavailable, setUnavailable] = useState(loaded.unavailable);
479
+ const [snapshots, setSnapshots] = useState(loaded.snapshots);
480
+ const [selected, setSelected] = useState(null);
481
+ const [diff, setDiff] = useState(null);
482
+ const [snapshot, setSnapshot] = useState(null);
483
+ const [latestSnapshotId, setLatestSnapshotId] = useState(() => loaded.snapshots[0]?.snapshotId ?? null);
484
+ const [note, setNote] = useState("");
485
+ const [agentId, setAgentId] = useState(() => loaded.members[0]?.id ?? "");
486
+ const [composed, setComposed] = useState(null);
487
+ const [status, setStatus] = useState(null);
488
+ const [busy, setBusy] = useState(false);
489
+ async function load(nextBase = appliedBase) {
490
+ setBusy(true);
491
+ setStatus({
492
+ kind: "info",
493
+ message: "Loading changes…"
494
+ });
495
+ try {
496
+ const data = await fetchTeamReview({ data: {
497
+ id: teamId,
498
+ ...nextBase ? { base: nextBase } : {}
499
+ } });
500
+ if (!data) return;
501
+ setReview(data.review);
502
+ setUnavailable(data.unavailable);
503
+ setSnapshots(data.snapshots);
504
+ setAppliedBase(nextBase);
505
+ setSelected(null);
506
+ setDiff(null);
507
+ setStatus(null);
508
+ } finally {
509
+ setBusy(false);
510
+ }
511
+ }
512
+ async function openDiff(path) {
513
+ setSelected(path);
514
+ setDiff(null);
515
+ setStatus({
516
+ kind: "info",
517
+ message: "Loading diff…"
518
+ });
519
+ setDiff(await fetchFileDiff({ data: {
520
+ id: teamId,
521
+ path,
522
+ ...appliedBase ? { base: appliedBase } : {}
523
+ } }));
524
+ setStatus(null);
525
+ }
526
+ async function capture() {
527
+ setBusy(true);
528
+ setStatus({
529
+ kind: "info",
530
+ message: "Capturing a source snapshot…"
531
+ });
532
+ const result = await captureTeamSnapshot({ data: { id: teamId } });
533
+ if ("reference" in result) {
534
+ setStatus({
535
+ kind: "info",
536
+ message: `Captured ${referenceLabel(result.reference)}`
537
+ });
538
+ await load();
539
+ } else setStatus({
540
+ kind: "error",
541
+ message: unavailableMessage(result.code, result.message)
542
+ });
543
+ setBusy(false);
544
+ }
545
+ async function prepare() {
546
+ if (!selected) return;
547
+ setBusy(true);
548
+ setStatus({
549
+ kind: "info",
550
+ message: "Preparing feedback…"
551
+ });
552
+ const result = await prepareReviewFeedback({ data: {
553
+ id: teamId,
554
+ path: selected,
555
+ ...latestSnapshotId ? { snapshotId: latestSnapshotId } : {},
556
+ ...note.trim() ? { note } : {}
557
+ } });
558
+ if ("message" in result && "reference" in result) {
559
+ setComposed(result);
560
+ setStatus(null);
561
+ } else setStatus({
562
+ kind: "error",
563
+ message: unavailableMessage(result.code, result.message)
564
+ });
565
+ setBusy(false);
566
+ }
567
+ async function send() {
568
+ if (!composed || !agentId) return;
569
+ setBusy(true);
570
+ const result = await sendReviewFeedback({ data: {
571
+ agentId,
572
+ message: composed.message
573
+ } });
574
+ setStatus("queued" in result ? {
575
+ kind: "info",
576
+ message: "Feedback queued for the Agent. It runs as the next turn."
577
+ } : {
578
+ kind: "error",
579
+ message: unavailableMessage(result.code, result.message)
580
+ });
581
+ if ("queued" in result) setComposed(null);
582
+ setBusy(false);
583
+ }
584
+ async function openSnapshot(snapshotId) {
585
+ setStatus({
586
+ kind: "info",
587
+ message: "Loading snapshot…"
588
+ });
589
+ const loadedSnapshot = await fetchTeamSnapshot({ data: {
590
+ id: teamId,
591
+ snapshotId
592
+ } });
593
+ setSnapshot(loadedSnapshot);
594
+ setStatus(loadedSnapshot ? null : {
595
+ kind: "error",
596
+ message: "That snapshot is no longer retained."
597
+ });
598
+ }
599
+ const changes = review?.changes;
600
+ return /* @__PURE__ */ jsxs(PageShell, { children: [
601
+ /* @__PURE__ */ jsxs("header", { children: [/* @__PURE__ */ jsxs("h1", { children: [loaded.team.name || loaded.team.id, " review"] }), /* @__PURE__ */ jsx("p", { children: "Changes since a pinned baseline, and the source snapshots taken for them. Inspection is read-only — nothing here stages, commits or reverts anything." })] }),
602
+ /* @__PURE__ */ jsx(TeamTabs, { teamId }),
603
+ /* @__PURE__ */ jsxs("section", {
604
+ className: "space-y-2",
605
+ "aria-label": "Comparison base",
606
+ children: [
607
+ /* @__PURE__ */ jsxs("div", {
608
+ className: "flex flex-col gap-2 sm:flex-row sm:items-end",
609
+ children: [/* @__PURE__ */ jsxs("label", {
610
+ className: "flex min-w-0 flex-1 flex-col gap-1",
611
+ children: [/* @__PURE__ */ jsx("span", { children: "Comparison base" }), /* @__PURE__ */ jsx("input", {
612
+ className: "input",
613
+ value: base,
614
+ placeholder: "HEAD",
615
+ onChange: (event) => setBase(event.target.value),
616
+ onKeyDown: (event) => {
617
+ if (event.key === "Enter") load(base);
618
+ }
619
+ })]
620
+ }), /* @__PURE__ */ jsxs("div", {
621
+ className: "flex gap-2",
622
+ children: [/* @__PURE__ */ jsx(Button, {
623
+ variant: "ghost",
624
+ disabled: busy,
625
+ onClick: () => void load(base),
626
+ children: "Apply base"
627
+ }), /* @__PURE__ */ jsx(Button, {
628
+ variant: "primary",
629
+ disabled: busy,
630
+ onClick: () => void load(),
631
+ children: "Refresh"
632
+ })]
633
+ })]
634
+ }),
635
+ changes && /* @__PURE__ */ jsx("p", {
636
+ className: "text-sm opacity-80",
637
+ children: baseLabel(changes.identity, changes)
638
+ }),
639
+ /* @__PURE__ */ jsx("p", {
640
+ className: "text-xs opacity-70",
641
+ children: "A branch name is resolved to a concrete commit when the review loads, so a moving tip cannot rewrite what you are looking at."
642
+ })
643
+ ]
644
+ }),
645
+ status && /* @__PURE__ */ jsx("p", {
646
+ role: status.kind === "error" ? "alert" : "status",
647
+ className: "text-sm",
648
+ children: status.message
649
+ }),
650
+ unavailable && /* @__PURE__ */ jsxs("section", {
651
+ className: "rounded-sm border border-fawn bg-ivory p-3",
652
+ "aria-label": "Review unavailable",
653
+ children: [/* @__PURE__ */ jsx("p", {
654
+ role: "alert",
655
+ children: unavailableMessage(unavailable.code, unavailable.message)
656
+ }), unavailable.code && /* @__PURE__ */ jsxs("p", {
657
+ className: "text-xs opacity-70",
658
+ children: ["code: ", unavailable.code]
659
+ })]
660
+ }),
661
+ changes && /* @__PURE__ */ jsxs("section", {
662
+ className: "space-y-2",
663
+ "aria-label": "Changes since baseline",
664
+ children: [
665
+ /* @__PURE__ */ jsx("h2", { children: "Changes since baseline" }),
666
+ changes.changes.length === 0 && /* @__PURE__ */ jsx("p", { children: "No changes since this baseline." }),
667
+ changes.changes.length > 0 && /* @__PURE__ */ jsx("ul", {
668
+ className: "divide-y divide-fawn rounded-sm border border-fawn",
669
+ children: changes.changes.map((change) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("button", {
670
+ type: "button",
671
+ "aria-current": selected === change.path ? "true" : void 0,
672
+ onClick: () => void openDiff(change.path),
673
+ className: "flex w-full flex-col gap-1 px-3 py-2 text-left hover:bg-sapphire-glow focus:bg-sapphire-glow",
674
+ children: [/* @__PURE__ */ jsx("span", {
675
+ className: "break-all font-mono text-sm",
676
+ children: change.previousPath ? `${change.previousPath} → ${change.path}` : change.path
677
+ }), /* @__PURE__ */ jsxs("span", {
678
+ className: "text-xs opacity-80",
679
+ children: [changeSummary(change), change.patchTruncated ? " · diff truncated" : ""]
680
+ })]
681
+ }) }, `${change.status}:${change.path}`))
682
+ }),
683
+ changes.truncated && /* @__PURE__ */ jsx("p", {
684
+ className: "text-sm",
685
+ children: "This list is incomplete: more files changed than the review limit allows."
686
+ }),
687
+ (changes.withheld.excluded > 0 || changes.withheld.untracked > 0) && /* @__PURE__ */ jsxs("p", {
688
+ className: "text-xs opacity-80",
689
+ children: [
690
+ changes.withheld.excluded,
691
+ " excluded and ",
692
+ changes.withheld.untracked,
693
+ " untracked path(s) withheld by scope policy."
694
+ ]
695
+ }),
696
+ changes.issues.map((issue) => /* @__PURE__ */ jsxs("p", {
697
+ className: "text-xs opacity-80",
698
+ children: [
699
+ "note: ",
700
+ issue.code,
701
+ ": ",
702
+ issue.message
703
+ ]
704
+ }, `${issue.code}:${issue.message}`))
705
+ ]
706
+ }),
707
+ selected && /* @__PURE__ */ jsxs("section", {
708
+ className: "space-y-2",
709
+ "aria-label": "Selected file diff",
710
+ children: [
711
+ /* @__PURE__ */ jsx("h2", {
712
+ className: "break-all font-mono text-base",
713
+ children: selected
714
+ }),
715
+ diff === null ? /* @__PURE__ */ jsx("p", {
716
+ className: "text-sm",
717
+ children: "Loading…"
718
+ }) : diff.patch === null ? /* @__PURE__ */ jsxs("p", {
719
+ className: "text-sm",
720
+ children: [
721
+ "No diff text for this file",
722
+ diff.omitted ? ` (${diff.omitted.replaceAll("_", " ")})` : "",
723
+ "."
724
+ ]
725
+ }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("pre", {
726
+ className: "max-h-96 overflow-auto whitespace-pre-wrap break-words rounded-sm bg-[rgba(42,31,22,0.04)] p-3 font-mono text-xs",
727
+ children: diff.patch
728
+ }), diff.truncated && /* @__PURE__ */ jsx("p", {
729
+ className: "text-xs",
730
+ children: "This diff was truncated at the patch limit."
731
+ })] }),
732
+ /* @__PURE__ */ jsxs("div", {
733
+ className: "space-y-2 rounded-sm border border-fawn p-3",
734
+ children: [
735
+ /* @__PURE__ */ jsx("h3", { children: "Send feedback about this file" }),
736
+ /* @__PURE__ */ jsxs("label", {
737
+ className: "flex flex-col gap-1",
738
+ children: [/* @__PURE__ */ jsx("span", { children: "Note (optional)" }), /* @__PURE__ */ jsx("textarea", {
739
+ className: "input",
740
+ rows: 2,
741
+ value: note,
742
+ onChange: (event) => setNote(event.target.value)
743
+ })]
744
+ }),
745
+ /* @__PURE__ */ jsxs("label", {
746
+ className: "flex flex-col gap-1",
747
+ children: [/* @__PURE__ */ jsx("span", { children: "Agent" }), /* @__PURE__ */ jsx("select", {
748
+ className: "input",
749
+ value: agentId,
750
+ onChange: (event) => setAgentId(event.target.value),
751
+ children: loaded.members.map((member) => /* @__PURE__ */ jsx("option", {
752
+ value: member.id,
753
+ children: member.name
754
+ }, member.id))
755
+ })]
756
+ }),
757
+ /* @__PURE__ */ jsxs("div", {
758
+ className: "flex flex-wrap gap-2",
759
+ children: [/* @__PURE__ */ jsx(Button, {
760
+ variant: "ghost",
761
+ disabled: busy,
762
+ onClick: () => void prepare(),
763
+ children: "Preview message"
764
+ }), /* @__PURE__ */ jsx(Button, {
765
+ variant: "primary",
766
+ disabled: busy || !composed || !agentId,
767
+ onClick: () => void send(),
768
+ children: "Queue for Agent"
769
+ })]
770
+ }),
771
+ latestSnapshotId ? /* @__PURE__ */ jsxs("p", {
772
+ className: "text-xs opacity-70",
773
+ children: [
774
+ "Referenced snapshot: ",
775
+ latestSnapshotId.slice(0, 12),
776
+ ". It is rechecked now, and the verdict is stated in the message."
777
+ ]
778
+ }) : /* @__PURE__ */ jsx("p", {
779
+ className: "text-xs opacity-70",
780
+ children: "No snapshot captured for this Team yet, so the feedback will say its source identity is unknown rather than implying the lines still match."
781
+ }),
782
+ composed && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
783
+ className: "text-sm",
784
+ children: composed.applicability === "current" ? "This file is unchanged since the snapshot." : composed.applicability === "stale" ? "This file changed since the snapshot — the selected lines may have moved." : `Source identity unknown (${composed.applicabilityReason}).`
785
+ }), /* @__PURE__ */ jsx("pre", {
786
+ className: "max-h-64 overflow-auto whitespace-pre-wrap break-words rounded-sm bg-[rgba(42,31,22,0.04)] p-3 font-mono text-xs",
787
+ children: composed.message
788
+ })] })
789
+ ]
790
+ })
791
+ ]
792
+ }),
793
+ /* @__PURE__ */ jsxs("section", {
794
+ className: "space-y-2",
795
+ "aria-label": "Source snapshots",
796
+ children: [
797
+ /* @__PURE__ */ jsxs("div", {
798
+ className: "flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between",
799
+ children: [/* @__PURE__ */ jsx("h2", { children: "Source snapshots" }), /* @__PURE__ */ jsx(Button, {
800
+ variant: "ghost",
801
+ disabled: busy,
802
+ onClick: () => void capture(),
803
+ children: "Capture snapshot"
804
+ })]
805
+ }),
806
+ /* @__PURE__ */ jsx("p", {
807
+ className: "text-xs opacity-70",
808
+ children: "A snapshot records HEAD, the index and digests of changed files — never file content. Untracked content is only included when a path is named explicitly."
809
+ }),
810
+ snapshots.length === 0 && /* @__PURE__ */ jsx("p", { children: "No retained snapshots for this Team." }),
811
+ snapshots.length > 0 && /* @__PURE__ */ jsx("ul", {
812
+ className: "divide-y divide-fawn rounded-sm border border-fawn",
813
+ children: snapshots.map((entry) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("button", {
814
+ type: "button",
815
+ onClick: () => void openSnapshot(entry.snapshotId),
816
+ className: "w-full px-3 py-2 text-left font-mono text-xs hover:bg-sapphire-glow focus:bg-sapphire-glow",
817
+ children: snapshotLabel(entry)
818
+ }) }, entry.snapshotId))
819
+ }),
820
+ snapshot && /* @__PURE__ */ jsxs("div", {
821
+ className: "space-y-1",
822
+ children: [
823
+ /* @__PURE__ */ jsxs("p", {
824
+ className: "text-sm",
825
+ children: [
826
+ snapshot.id.slice(0, 12),
827
+ " · ",
828
+ snapshot.complete ? "complete" : "incomplete — applicability unknown",
829
+ " · head ",
830
+ snapshot.head?.slice(0, 12) ?? "(unborn)"
831
+ ]
832
+ }),
833
+ snapshot.entries.length > 0 && /* @__PURE__ */ jsx("ul", {
834
+ className: "space-y-1 font-mono text-xs",
835
+ children: snapshot.entries.map((entry) => /* @__PURE__ */ jsxs("li", { children: [
836
+ entry.layer,
837
+ " · ",
838
+ entry.kind,
839
+ " · ",
840
+ entry.path,
841
+ entry.bytes === null ? "" : ` · ${entry.bytes}B`
842
+ ] }, `${entry.layer}:${entry.path}`))
843
+ }),
844
+ snapshot.exclusions.length > 0 && /* @__PURE__ */ jsxs("p", {
845
+ className: "text-xs opacity-80",
846
+ children: ["withheld: ", snapshot.exclusions.map((item) => `${item.path} (${item.reason})`).join(", ")]
847
+ })
848
+ ]
849
+ })
850
+ ]
851
+ }),
852
+ loaded.packets ? /* @__PURE__ */ jsx(ReviewPacketPanel, {
853
+ teamId,
854
+ view: loaded.packets
855
+ }) : null
856
+ ] });
857
+ }
858
+ //#endregion
859
+ export { ReviewPage as component };