thurview 0.15.0 → 0.17.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.
- package/README.md +118 -89
- package/dist/cli.js +9 -0
- package/dist/cli.js.map +1 -1
- package/dist/document/compile.js +81 -2
- package/dist/document/compile.js.map +1 -1
- package/dist/document/parse.js +37 -13
- package/dist/document/parse.js.map +1 -1
- package/dist/document/schema.js +36 -0
- package/dist/document/schema.js.map +1 -1
- package/dist/queue.js +123 -0
- package/dist/queue.js.map +1 -0
- package/dist/server/server.js +3 -9
- package/dist/server/server.js.map +1 -1
- package/dist/store.js +10 -0
- package/dist/store.js.map +1 -1
- package/dist/ui/app.css +80 -0
- package/dist/ui/app.js +213 -12
- package/dist/ui/app.js.map +3 -3
- package/package.json +1 -1
- package/skills/thurview/references/components.md +47 -0
- package/skills/thurview/references/document-authoring.md +5 -2
- package/skills/thurview/references/lifecycle.md +21 -0
package/dist/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/app.css
CHANGED
|
@@ -1133,6 +1133,61 @@ kbd {
|
|
|
1133
1133
|
.seq .msg text:hover {
|
|
1134
1134
|
text-decoration: underline;
|
|
1135
1135
|
}
|
|
1136
|
+
.flow text {
|
|
1137
|
+
font: 12px var(--font-mono);
|
|
1138
|
+
fill: var(--fg);
|
|
1139
|
+
}
|
|
1140
|
+
.flow .step rect,
|
|
1141
|
+
.flow .step path {
|
|
1142
|
+
fill: var(--bg-code);
|
|
1143
|
+
stroke: var(--line);
|
|
1144
|
+
}
|
|
1145
|
+
.flow .step:not(.plain) {
|
|
1146
|
+
cursor: pointer;
|
|
1147
|
+
}
|
|
1148
|
+
.flow .step:not(.plain) text {
|
|
1149
|
+
fill: var(--link);
|
|
1150
|
+
}
|
|
1151
|
+
.flow .step:not(.plain):hover rect,
|
|
1152
|
+
.flow .step:not(.plain):hover path {
|
|
1153
|
+
stroke: var(--accent);
|
|
1154
|
+
}
|
|
1155
|
+
/* The step takes focus, so the focus has to be visible on the shape itself:
|
|
1156
|
+
a UA outline on an SVG group lands nowhere the reader can see. */
|
|
1157
|
+
.flow .step:focus {
|
|
1158
|
+
outline: none;
|
|
1159
|
+
}
|
|
1160
|
+
.flow .step:focus-visible rect,
|
|
1161
|
+
.flow .step:focus-visible path {
|
|
1162
|
+
stroke: var(--accent);
|
|
1163
|
+
stroke-width: 2;
|
|
1164
|
+
}
|
|
1165
|
+
/* A step nobody can open reads as the aside it is, not as a broken link.
|
|
1166
|
+
A decision is a path rather than a rect, so both shapes carry the rule. */
|
|
1167
|
+
.flow .step.plain rect,
|
|
1168
|
+
.flow .step.plain path {
|
|
1169
|
+
fill: var(--bg3);
|
|
1170
|
+
stroke-dasharray: 4 4;
|
|
1171
|
+
}
|
|
1172
|
+
.flow .step text.who {
|
|
1173
|
+
font-size: 10.5px;
|
|
1174
|
+
fill: var(--muted);
|
|
1175
|
+
}
|
|
1176
|
+
.flow .step.decision text {
|
|
1177
|
+
font-style: italic;
|
|
1178
|
+
}
|
|
1179
|
+
.flow .edge path {
|
|
1180
|
+
stroke: var(--fg2);
|
|
1181
|
+
marker-end: url(#flow-arr);
|
|
1182
|
+
}
|
|
1183
|
+
.flow .edge text {
|
|
1184
|
+
font-size: 10.5px;
|
|
1185
|
+
fill: var(--muted);
|
|
1186
|
+
}
|
|
1187
|
+
.flow .edge.back path {
|
|
1188
|
+
stroke: var(--muted);
|
|
1189
|
+
stroke-dasharray: 3 3;
|
|
1190
|
+
}
|
|
1136
1191
|
.callstack {
|
|
1137
1192
|
font-family: var(--font-mono);
|
|
1138
1193
|
font-size: 12.5px;
|
|
@@ -1450,6 +1505,31 @@ kbd {
|
|
|
1450
1505
|
font-weight: 700;
|
|
1451
1506
|
flex: 1;
|
|
1452
1507
|
}
|
|
1508
|
+
/* Why it is this row's turn sits under the title, so the reason is read with
|
|
1509
|
+
the name rather than hunted for across the row. */
|
|
1510
|
+
.home .item .why {
|
|
1511
|
+
display: block;
|
|
1512
|
+
font-family: var(--font-body);
|
|
1513
|
+
font-weight: 400;
|
|
1514
|
+
font-size: 12px;
|
|
1515
|
+
color: var(--muted);
|
|
1516
|
+
margin-top: 2px;
|
|
1517
|
+
}
|
|
1518
|
+
.home .item .cr {
|
|
1519
|
+
font-size: 12px;
|
|
1520
|
+
text-decoration: none;
|
|
1521
|
+
}
|
|
1522
|
+
.home .item .cr:hover {
|
|
1523
|
+
color: var(--accent);
|
|
1524
|
+
}
|
|
1525
|
+
.home h3.repo {
|
|
1526
|
+
display: flex;
|
|
1527
|
+
gap: 10px;
|
|
1528
|
+
align-items: center;
|
|
1529
|
+
text-transform: none;
|
|
1530
|
+
letter-spacing: 0;
|
|
1531
|
+
font-family: var(--font-mono);
|
|
1532
|
+
}
|
|
1453
1533
|
.empty-state {
|
|
1454
1534
|
padding: 40px;
|
|
1455
1535
|
text-align: center;
|
package/dist/ui/app.js
CHANGED
|
@@ -908,6 +908,73 @@
|
|
|
908
908
|
// src/ui/diagrams.ts
|
|
909
909
|
init_dom();
|
|
910
910
|
init_dom();
|
|
911
|
+
|
|
912
|
+
// src/ui/flow-layout.ts
|
|
913
|
+
var boxW = 210;
|
|
914
|
+
var boxH = 46;
|
|
915
|
+
var gapX = 40;
|
|
916
|
+
var gapY = 58;
|
|
917
|
+
var pad = 14;
|
|
918
|
+
var minW = 700;
|
|
919
|
+
function layoutFlow(b) {
|
|
920
|
+
const layer = /* @__PURE__ */ new Map([[b.steps[0].id, 0]]);
|
|
921
|
+
const queue = [b.steps[0].id];
|
|
922
|
+
while (queue.length) {
|
|
923
|
+
const cur = queue.shift();
|
|
924
|
+
for (const e of b.edges)
|
|
925
|
+
if (e.from === cur && !layer.has(e.to)) {
|
|
926
|
+
layer.set(e.to, layer.get(cur) + 1);
|
|
927
|
+
queue.push(e.to);
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
const rows = [];
|
|
931
|
+
for (const s of b.steps) {
|
|
932
|
+
const li = layer.get(s.id);
|
|
933
|
+
(rows[li] ??= []).push(s.id);
|
|
934
|
+
}
|
|
935
|
+
const span = (e) => layer.get(e.from) - layer.get(e.to);
|
|
936
|
+
const loops = b.edges.filter((e) => span(e) >= 0).sort((p, q) => span(p) - span(q));
|
|
937
|
+
const lanes = loops.length > 0;
|
|
938
|
+
const widest = Math.max(...rows.map((r) => r.length));
|
|
939
|
+
const laneGap = 18;
|
|
940
|
+
const lane = lanes ? 34 + (loops.length - 1) * laneGap : 0;
|
|
941
|
+
const band = lanes ? gapY / 2 : 0;
|
|
942
|
+
const width = Math.max(minW, pad * 2 + widest * boxW + (widest - 1) * gapX + lane);
|
|
943
|
+
const height = pad * 2 + band * 2 + rows.length * boxH + (rows.length - 1) * gapY;
|
|
944
|
+
const at = (id) => {
|
|
945
|
+
const li = layer.get(id);
|
|
946
|
+
const row = rows[li];
|
|
947
|
+
const spanW = row.length * boxW + (row.length - 1) * gapX;
|
|
948
|
+
const x = pad + (width - lane - pad * 2 - spanW) / 2 + row.indexOf(id) * (boxW + gapX);
|
|
949
|
+
return { x, y: pad + band + li * (boxH + gapY), cx: x + boxW / 2, li };
|
|
950
|
+
};
|
|
951
|
+
const edges = b.edges.map((edge) => {
|
|
952
|
+
const from = at(edge.from);
|
|
953
|
+
const to = at(edge.to);
|
|
954
|
+
const back = to.li < from.li;
|
|
955
|
+
if (to.li > from.li) {
|
|
956
|
+
const mid = from.y + boxH + (to.y - from.y - boxH) / 2;
|
|
957
|
+
return {
|
|
958
|
+
edge,
|
|
959
|
+
back,
|
|
960
|
+
d: `M${from.cx},${from.y + boxH} V${mid} H${to.cx} V${to.y - 4}`,
|
|
961
|
+
label: { x: (from.cx + to.cx) / 2 + 6, y: mid - 5, at: "middle" }
|
|
962
|
+
};
|
|
963
|
+
}
|
|
964
|
+
const laneX = width - lane + 17 + loops.indexOf(edge) * laneGap;
|
|
965
|
+
const out = from.y + boxH + gapY / 2;
|
|
966
|
+
const into = to.y - gapY / 2;
|
|
967
|
+
return {
|
|
968
|
+
edge,
|
|
969
|
+
back,
|
|
970
|
+
d: `M${from.cx},${from.y + boxH} V${out} H${laneX} V${into} H${to.cx} V${to.y - 4}`,
|
|
971
|
+
label: { x: laneX - 6, y: (out + into) / 2, at: "end" }
|
|
972
|
+
};
|
|
973
|
+
});
|
|
974
|
+
return { width, height, at, edges };
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
// src/ui/diagrams.ts
|
|
911
978
|
function openAnchor(id) {
|
|
912
979
|
const a = state.data?.document?.anchors[id];
|
|
913
980
|
if (a) openAnchorPeek(a);
|
|
@@ -1116,6 +1183,84 @@
|
|
|
1116
1183
|
ops
|
|
1117
1184
|
);
|
|
1118
1185
|
}
|
|
1186
|
+
function flowDiagram(b, doc) {
|
|
1187
|
+
const fit = (text, room, px) => {
|
|
1188
|
+
const max = Math.floor(room / (px * 0.605));
|
|
1189
|
+
return text.length > max ? `${text.slice(0, max - 1)}\u2026` : text;
|
|
1190
|
+
};
|
|
1191
|
+
const { width, height, at, edges } = layoutFlow(b);
|
|
1192
|
+
const el = svg("svg", { viewBox: `0 0 ${width} ${height}`, class: "flow" });
|
|
1193
|
+
el.appendChild(
|
|
1194
|
+
svg(
|
|
1195
|
+
"defs",
|
|
1196
|
+
{},
|
|
1197
|
+
svg(
|
|
1198
|
+
"marker",
|
|
1199
|
+
{
|
|
1200
|
+
id: "flow-arr",
|
|
1201
|
+
viewBox: "0 0 10 10",
|
|
1202
|
+
refX: "9",
|
|
1203
|
+
refY: "5",
|
|
1204
|
+
markerWidth: "7",
|
|
1205
|
+
markerHeight: "7",
|
|
1206
|
+
orient: "auto"
|
|
1207
|
+
},
|
|
1208
|
+
svg("path", { d: "M0,0 L10,5 L0,10 z", fill: "currentColor" })
|
|
1209
|
+
)
|
|
1210
|
+
)
|
|
1211
|
+
);
|
|
1212
|
+
for (const { edge, d, back, label: label2 } of edges) {
|
|
1213
|
+
const g = svg("g", { class: back ? "edge back" : "edge" });
|
|
1214
|
+
g.appendChild(svg("path", { d, fill: "none", "marker-end": "url(#flow-arr)" }));
|
|
1215
|
+
if (edge.case)
|
|
1216
|
+
g.appendChild(svg("text", { x: label2.x, y: label2.y, "text-anchor": label2.at }, edge.case));
|
|
1217
|
+
el.appendChild(g);
|
|
1218
|
+
}
|
|
1219
|
+
for (const s of b.steps) {
|
|
1220
|
+
const { x, y, cx } = at(s.id);
|
|
1221
|
+
const g = svg("g", {
|
|
1222
|
+
class: `step${s.decision ? " decision" : ""}${s.anchor ? "" : " plain"}`
|
|
1223
|
+
});
|
|
1224
|
+
g.appendChild(
|
|
1225
|
+
s.decision ? svg("path", {
|
|
1226
|
+
d: `M${x + 16},${y} H${x + boxW - 16} L${x + boxW},${y + boxH / 2} L${x + boxW - 16},${y + boxH} H${x + 16} L${x},${y + boxH / 2} Z`
|
|
1227
|
+
}) : svg("rect", { x, y, width: boxW, height: boxH, rx: 6 })
|
|
1228
|
+
);
|
|
1229
|
+
const room = boxW - (s.decision ? 44 : 20);
|
|
1230
|
+
const actor = s.actor ? doc.actors[s.actor]?.label ?? s.actor : null;
|
|
1231
|
+
if (actor)
|
|
1232
|
+
g.appendChild(
|
|
1233
|
+
svg(
|
|
1234
|
+
"text",
|
|
1235
|
+
{ class: "who", x: cx, y: y + 17, "text-anchor": "middle" },
|
|
1236
|
+
fit(actor, room, 10.5)
|
|
1237
|
+
)
|
|
1238
|
+
);
|
|
1239
|
+
g.appendChild(
|
|
1240
|
+
svg(
|
|
1241
|
+
"text",
|
|
1242
|
+
{ x: cx, y: actor ? y + 33 : y + boxH / 2 + 4, "text-anchor": "middle" },
|
|
1243
|
+
fit(s.label, room, 12)
|
|
1244
|
+
)
|
|
1245
|
+
);
|
|
1246
|
+
g.appendChild(svg("title", {}, s.anchor ? `${s.label} \u2014 ${s.anchor}` : s.label));
|
|
1247
|
+
if (s.anchor) {
|
|
1248
|
+
const open = () => openAnchor(s.anchor);
|
|
1249
|
+
g.setAttribute("role", "button");
|
|
1250
|
+
g.setAttribute("tabindex", "0");
|
|
1251
|
+
g.addEventListener("click", open);
|
|
1252
|
+
g.addEventListener("keydown", (e) => {
|
|
1253
|
+
const k = e.key;
|
|
1254
|
+
if (k === "Enter" || k === " ") {
|
|
1255
|
+
e.preventDefault();
|
|
1256
|
+
open();
|
|
1257
|
+
}
|
|
1258
|
+
});
|
|
1259
|
+
}
|
|
1260
|
+
el.appendChild(g);
|
|
1261
|
+
}
|
|
1262
|
+
return h("div", { class: "diagram" }, h("div", { class: "dhead" }, b.label), el);
|
|
1263
|
+
}
|
|
1119
1264
|
|
|
1120
1265
|
// src/ui/views/review.ts
|
|
1121
1266
|
function renderReview(root) {
|
|
@@ -1549,6 +1694,9 @@
|
|
|
1549
1694
|
case "database":
|
|
1550
1695
|
wrap.appendChild(databaseLens(b, doc));
|
|
1551
1696
|
break;
|
|
1697
|
+
case "flow":
|
|
1698
|
+
wrap.appendChild(flowDiagram(b, doc));
|
|
1699
|
+
break;
|
|
1552
1700
|
}
|
|
1553
1701
|
if (threads.length)
|
|
1554
1702
|
wrap.appendChild(h("div", { class: "thread-pins" }, threads.map(threadPinRow)));
|
|
@@ -2722,18 +2870,9 @@
|
|
|
2722
2870
|
async function home() {
|
|
2723
2871
|
clear(app);
|
|
2724
2872
|
const reviews = await api.reviews();
|
|
2725
|
-
const el = h("div", { class: "home" }, h("h2", null, "
|
|
2873
|
+
const el = h("div", { class: "home" }, h("h2", null, "Queue"));
|
|
2726
2874
|
const active = reviews.filter((r) => !r.dismissed);
|
|
2727
2875
|
const dismissed = reviews.filter((r) => r.dismissed);
|
|
2728
|
-
const item = (r) => h(
|
|
2729
|
-
"div",
|
|
2730
|
-
{ class: "item", onclick: () => location.href = `/review/${r.id}` },
|
|
2731
|
-
h("span", { class: "t" }, r.title),
|
|
2732
|
-
h("span", { class: `badge ${statusClass2(r.status)}` }, r.status),
|
|
2733
|
-
r.openThreads ? h("span", { class: "badge accent" }, `${r.openThreads} open`) : null,
|
|
2734
|
-
h("span", { class: "muted mono", style: { fontSize: "12px" } }, bindingLabel(r)),
|
|
2735
|
-
h("span", { class: "muted", style: { fontSize: "12px" } }, timeAgo(r.updatedAt))
|
|
2736
|
-
);
|
|
2737
2876
|
if (!active.length)
|
|
2738
2877
|
el.appendChild(
|
|
2739
2878
|
h(
|
|
@@ -2742,13 +2881,75 @@
|
|
|
2742
2881
|
"Nothing published yet. Ask your agent for a review of a change, an explainer of the codebase, or a design of what to build next."
|
|
2743
2882
|
)
|
|
2744
2883
|
);
|
|
2745
|
-
|
|
2884
|
+
const groups = /* @__PURE__ */ new Map();
|
|
2885
|
+
for (const r of active) groups.set(r.queue.repo, [...groups.get(r.queue.repo) ?? [], r]);
|
|
2886
|
+
for (const [repo, rows] of groups) {
|
|
2887
|
+
const yours = rows.filter((r) => r.queue.turn === "you").length;
|
|
2888
|
+
el.appendChild(
|
|
2889
|
+
h(
|
|
2890
|
+
"h3",
|
|
2891
|
+
{ class: "repo" },
|
|
2892
|
+
repo,
|
|
2893
|
+
yours ? h("span", { class: "badge accent" }, `${yours} your turn`) : null
|
|
2894
|
+
)
|
|
2895
|
+
);
|
|
2896
|
+
rows.forEach((r) => el.appendChild(queueItem(r)));
|
|
2897
|
+
}
|
|
2746
2898
|
if (dismissed.length) {
|
|
2747
2899
|
el.appendChild(h("h3", { class: "muted" }, "Dismissed"));
|
|
2748
|
-
dismissed.forEach((r) => el.appendChild(
|
|
2900
|
+
dismissed.forEach((r) => el.appendChild(queueItem(r)));
|
|
2749
2901
|
}
|
|
2750
2902
|
app.appendChild(el);
|
|
2751
2903
|
}
|
|
2904
|
+
var TURN = { you: "your turn", agent: "agent", nobody: "nobody" };
|
|
2905
|
+
var DECISION = { approve: "approved", "request-changes": "changes requested", close: "closed" };
|
|
2906
|
+
function queueItem(r) {
|
|
2907
|
+
const q = r.queue;
|
|
2908
|
+
const cr = q.change;
|
|
2909
|
+
const age = q.factsAt ? `forge read ${timeAgo(q.factsAt)}` : cr ? "forge not read yet" : "";
|
|
2910
|
+
return h(
|
|
2911
|
+
"div",
|
|
2912
|
+
{ class: "item", onclick: () => location.href = `/review/${r.id}` },
|
|
2913
|
+
h("span", { class: `badge turn ${q.turn === "you" ? "accent" : ""}` }, TURN[q.turn]),
|
|
2914
|
+
h(
|
|
2915
|
+
"span",
|
|
2916
|
+
{ class: "t" },
|
|
2917
|
+
r.title,
|
|
2918
|
+
h("span", { class: "why" }, [r.kind ?? "review", q.why, age].filter(Boolean).join(" \xB7 "))
|
|
2919
|
+
),
|
|
2920
|
+
cr ? h(
|
|
2921
|
+
"a",
|
|
2922
|
+
{
|
|
2923
|
+
class: "mono muted cr",
|
|
2924
|
+
href: cr.url ?? void 0,
|
|
2925
|
+
target: "_blank",
|
|
2926
|
+
rel: "noopener",
|
|
2927
|
+
onclick: (e) => e.stopPropagation()
|
|
2928
|
+
},
|
|
2929
|
+
`#${cr.number}${cr.state && cr.state !== "open" ? ` ${cr.state}` : ""}`
|
|
2930
|
+
) : h("span", { class: "mono muted" }, bindingLabel(r)),
|
|
2931
|
+
r.openThreads ? h("span", { class: "badge accent" }, `${r.openThreads} open`) : null,
|
|
2932
|
+
q.pin ? h(
|
|
2933
|
+
"span",
|
|
2934
|
+
{ class: `badge ${q.pin === "behind" ? "warn" : "ok"}` },
|
|
2935
|
+
q.pin === "behind" ? "pin behind head" : "at head"
|
|
2936
|
+
) : null,
|
|
2937
|
+
q.decision ? h(
|
|
2938
|
+
"span",
|
|
2939
|
+
{
|
|
2940
|
+
class: `badge ${q.decision.posted === false ? "warn" : ""}`,
|
|
2941
|
+
title: q.decision.posted === null ? null : q.decision.posted ? "posted to the change request" : "not posted to the change request yet"
|
|
2942
|
+
},
|
|
2943
|
+
DECISION[q.decision.decision] + (q.decision.posted === null ? "" : q.decision.posted ? " \xB7 posted" : " \xB7 not posted")
|
|
2944
|
+
) : null,
|
|
2945
|
+
q.ci ? h(
|
|
2946
|
+
"span",
|
|
2947
|
+
{ class: `badge ${q.ci.trustworthy ? "ok" : "warn"}`, title: q.ci.verdict },
|
|
2948
|
+
q.ci.trustworthy ? "CI gates" : "CI not a gate"
|
|
2949
|
+
) : null,
|
|
2950
|
+
h("span", { class: "muted", style: { fontSize: "12px" } }, timeAgo(r.updatedAt))
|
|
2951
|
+
);
|
|
2952
|
+
}
|
|
2752
2953
|
function bindingLabel(r) {
|
|
2753
2954
|
if (r.binding.kind === "pr") return `PR #${r.binding.name}`;
|
|
2754
2955
|
if (r.binding.kind === "codebase") return r.binding.name === "**" ? "codebase" : r.binding.name;
|