@shiyuphan/follow-me 0.2.0 → 0.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.
- package/README.md +44 -55
- package/dist/src/cli.js +566 -188
- package/dist/src/comments.js +66 -5
- package/dist/src/git.js +12 -0
- package/dist/src/host.js +19 -8
- package/dist/src/install.js +21 -0
- package/dist/src/plan.js +1 -1
- package/dist/src/prompt.js +343 -39
- package/dist/src/server.js +176 -67
- package/dist/src/session.js +13 -11
- package/dist/ui/dist/assets/abnfDiagram-WEYOIA3C-DcmzRkVZ.js +1 -0
- package/dist/ui/dist/assets/arc-T5QB0T1C.js +1 -0
- package/dist/ui/dist/assets/architecture-WOLXFQ4H-DUIkQTeE.js +1 -0
- package/dist/ui/dist/assets/architectureDiagram-ZHVYKT53-BUYi4-bA.js +36 -0
- package/dist/ui/dist/assets/array-BifhSqXX.js +1 -0
- package/dist/ui/dist/assets/blockDiagram-RJAE7QA3-dyJxtT9e.js +140 -0
- package/dist/ui/dist/assets/c4Diagram-XDPPPE54-CrAgiaZR.js +38 -0
- package/dist/ui/dist/assets/channel-wW7ebm0i.js +1 -0
- package/dist/ui/dist/assets/chunk-2E7WHVMD-C6fAf4Vj.js +88 -0
- package/dist/ui/dist/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- package/dist/ui/dist/assets/chunk-4EMNKR2T-BLZjwZ4Q.js +1 -0
- package/dist/ui/dist/assets/chunk-55XCU76K-DGLK2Q-L.js +1 -0
- package/dist/ui/dist/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- package/dist/ui/dist/assets/chunk-7S6XSTFO-BablszTX.js +2 -0
- package/dist/ui/dist/assets/chunk-AQDTSKZB-Cuk3B_vb.js +72 -0
- package/dist/ui/dist/assets/chunk-DSNLSHJZ-DiC78RqE.js +127 -0
- package/dist/ui/dist/assets/chunk-DUW6YSOI-Dgx8z5s3.js +1 -0
- package/dist/ui/dist/assets/chunk-HAGFOTED-X_RbvixX.js +62 -0
- package/dist/ui/dist/assets/chunk-HNE4Q36P-C14_x5ck.js +1 -0
- package/dist/ui/dist/assets/chunk-J5ZVWO5B-oDCd-gWO.js +1 -0
- package/dist/ui/dist/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- package/dist/ui/dist/assets/chunk-NGNAAXSQ-C2Wy9Xmz.js +136 -0
- package/dist/ui/dist/assets/chunk-NQOKRVIF-Dxd0dtYR.js +213 -0
- package/dist/ui/dist/assets/chunk-UHW7PFBP-BIxePNUS.js +1 -0
- package/dist/ui/dist/assets/chunk-VQ5W62QI-CKSKLbj4.js +1 -0
- package/dist/ui/dist/assets/chunk-WQQL4CDK-CWNmZGlR.js +10 -0
- package/dist/ui/dist/assets/chunk-XXDRQBXY-D-I5QHgG.js +1 -0
- package/dist/ui/dist/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- package/dist/ui/dist/assets/chunk-YZO67HFG-DFP68CFd.js +1 -0
- package/dist/ui/dist/assets/chunk-ZAUX2LTX-DY90d4QG.js +1 -0
- package/dist/ui/dist/assets/chunk-ZCHMQSOR-Dlpr-5UC.js +2 -0
- package/dist/ui/dist/assets/classDiagram-v2-4MYWR3UA-CH9uhoLJ.js +217 -0
- package/dist/ui/dist/assets/cose-bilkent-JH36ORCC-DtYHrp8D.js +1 -0
- package/dist/ui/dist/assets/cynefin-EF2NZ3EQ-BtslbtrY.js +1 -0
- package/dist/ui/dist/assets/cynefinDiagram-WF24UDRP-DUU1Jcc7.js +62 -0
- package/dist/ui/dist/assets/cytoscape.esm-BegBNzOV.js +321 -0
- package/dist/ui/dist/assets/dagre-NK4GIZVX-CDlP-dRW.js +4 -0
- package/dist/ui/dist/assets/defaultLocale-BFoDCU3G.js +1 -0
- package/dist/ui/dist/assets/diagram-CBK3MWTC-DiV2fn-r.js +24 -0
- package/dist/ui/dist/assets/diagram-I5XIIV2D-Bg5RehGi.js +24 -0
- package/dist/ui/dist/assets/diagram-ODIL2UCW-CFmazz3f.js +30 -0
- package/dist/ui/dist/assets/diagram-PFBEJUXE-uw3ZBqDp.js +3 -0
- package/dist/ui/dist/assets/diagram-RJA3I4VV-uEOYYRYa.js +41 -0
- package/dist/ui/dist/assets/diagram-TYUNFSNR-BN58LF_3.js +200 -0
- package/dist/ui/dist/assets/dist-tWS_lXDS.js +1 -0
- package/dist/ui/dist/assets/ebnfDiagram-V4P3TTPT-B68Tz-w8.js +1 -0
- package/dist/ui/dist/assets/elk-QONTBCTQ-DZZohNea.js +27 -0
- package/dist/ui/dist/assets/erDiagram-KYQIGQAA-BH_m74pv.js +99 -0
- package/dist/ui/dist/assets/eventmodeling-K75KTNOO-CTp5FHos.js +1 -0
- package/dist/ui/dist/assets/flowDiagram-IUGLLWBU-CsCvexry.js +1 -0
- package/dist/ui/dist/assets/ganttDiagram-R7GPNTJY-BDau7_0f.js +292 -0
- package/dist/ui/dist/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/dist/ui/dist/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/dist/ui/dist/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/dist/ui/dist/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/dist/ui/dist/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/dist/ui/dist/assets/gitGraph-VSP46ZUC-Bv84IoCm.js +1 -0
- package/dist/ui/dist/assets/gitGraphDiagram-PDYL7XHY-DzXcMlm8.js +106 -0
- package/dist/ui/dist/assets/graphlib-DS17s2tU.js +1 -0
- package/dist/ui/dist/assets/index-BTJoqVVN.js +133 -0
- package/dist/ui/dist/assets/index-D60U3smc.css +1 -0
- package/dist/ui/dist/assets/info-OHQRW6UA-222J0O_j.js +1 -0
- package/dist/ui/dist/assets/infoDiagram-MVDRKAX5-DE2sa3Vz.js +2 -0
- package/dist/ui/dist/assets/init-C-OQMol4.js +1 -0
- package/dist/ui/dist/assets/ishikawaDiagram-HPEHV2GE-BJDk0Zcj.js +70 -0
- package/dist/ui/dist/assets/journeyDiagram-BOSHW7O7-JSUXX5Hb.js +139 -0
- package/dist/ui/dist/assets/kanban-definition-FNSA4HC5-Bg79b49M.js +89 -0
- package/dist/ui/dist/assets/katex-B_JcIwqj.js +257 -0
- package/dist/ui/dist/assets/line-Bk5qQSIa.js +1 -0
- package/dist/ui/dist/assets/linear-PFnVMru5.js +1 -0
- package/dist/ui/dist/assets/mermaid-parser.core-Dcxlzc-S.js +7 -0
- package/dist/ui/dist/assets/mermaid.core-TeOHQJ00.js +44 -0
- package/dist/ui/dist/assets/mindmap-definition-6OY57UG3-IaNk8NnW.js +98 -0
- package/dist/ui/dist/assets/ordinal-BDEzSJ7C.js +1 -0
- package/dist/ui/dist/assets/packet-JDAUHWVQ-DMff5cVK.js +1 -0
- package/dist/ui/dist/assets/path-fybaL0A-.js +1 -0
- package/dist/ui/dist/assets/pegDiagram-ECIUJNBX-66Xu4YRc.js +1 -0
- package/dist/ui/dist/assets/pie-XZMESJXO-GEtzLCIM.js +1 -0
- package/dist/ui/dist/assets/pieDiagram-GNMPY74T-7jMBi-kU.js +39 -0
- package/dist/ui/dist/assets/prism-bash-D6zCJ74D.js +1 -0
- package/dist/ui/dist/assets/prism-c-04YixN25.js +1 -0
- package/dist/ui/dist/assets/prism-clike-DapgWyxx.js +1 -0
- package/dist/ui/dist/assets/prism-core-FDHlWQ43.js +1 -0
- package/dist/ui/dist/assets/prism-cpp-C-lJbC-6.js +1 -0
- package/dist/ui/dist/assets/prism-css-CPgOzxXp.js +1 -0
- package/dist/ui/dist/assets/prism-go-C_8qAH5n.js +1 -0
- package/dist/ui/dist/assets/prism-java-6wtusvIl.js +1 -0
- package/dist/ui/dist/assets/prism-javascript-BnO-swvr.js +1 -0
- package/dist/ui/dist/assets/prism-json-Dp_-W-Hv.js +1 -0
- package/dist/ui/dist/assets/prism-jsx-D-D0NWtC.js +1 -0
- package/dist/ui/dist/assets/prism-kotlin-BUlJgC-o.js +1 -0
- package/dist/ui/dist/assets/prism-markdown-Bc9-36OC.js +1 -0
- package/dist/ui/dist/assets/prism-markup-Cp04rIa1.js +1 -0
- package/dist/ui/dist/assets/prism-markup-templating-KkSMBj6Y.js +1 -0
- package/dist/ui/dist/assets/prism-php-Co4fM40K.js +1 -0
- package/dist/ui/dist/assets/prism-python-CfiSVtM6.js +1 -0
- package/dist/ui/dist/assets/prism-ruby-DFCASkuD.js +1 -0
- package/dist/ui/dist/assets/prism-rust-Bu9N8X3N.js +1 -0
- package/dist/ui/dist/assets/prism-sql-CYhVDMEE.js +1 -0
- package/dist/ui/dist/assets/prism-swift-B0kWc-ne.js +1 -0
- package/dist/ui/dist/assets/prism-toml-DKb54GAT.js +1 -0
- package/dist/ui/dist/assets/prism-tsx-p6J2Kc_4.js +1 -0
- package/dist/ui/dist/assets/prism-typescript-BMqONzxf.js +1 -0
- package/dist/ui/dist/assets/prism-yaml-C0JHu8gr.js +1 -0
- package/dist/ui/dist/assets/quadrantDiagram-D57K4MC3-8hIWayC2.js +7 -0
- package/dist/ui/dist/assets/radar-ABXABTNO-BTdwUOOF.js +1 -0
- package/dist/ui/dist/assets/railroad-I3PHUGI6-DcMbDqBL.js +1 -0
- package/dist/ui/dist/assets/railroad-abnf-LNEFI6M7-gTzUTWeI.js +1 -0
- package/dist/ui/dist/assets/railroad-ebnf-DWYD2UWJ-CNtdUPtk.js +1 -0
- package/dist/ui/dist/assets/railroad-peg-JR7BVNR7-DOiExAtE.js +1 -0
- package/dist/ui/dist/assets/railroadDiagram-Y72NRBL7-2kE_ygvM.js +1 -0
- package/dist/ui/dist/assets/requirementDiagram-EQYSW5RA-CoIAHRq2.js +84 -0
- package/dist/ui/dist/assets/rough.esm-Dy-Kn_BL.js +1 -0
- package/dist/ui/dist/assets/sankeyDiagram-SY24JHO5-7p8D3wim.js +40 -0
- package/dist/ui/dist/assets/sequenceDiagram-BLEHNHQU-C6QFnMvn.js +169 -0
- package/dist/ui/dist/assets/sizeCapture-INFHLROL-3uHXrFqA.js +1 -0
- package/dist/ui/dist/assets/src-FgijoBVs.js +1 -0
- package/dist/ui/dist/assets/stateDiagram-v2-A6IESKWZ-n9eAb_bT.js +291 -0
- package/dist/ui/dist/assets/swimlanes-B3ENRKFQ-U18mtUzX.js +1 -0
- package/dist/ui/dist/assets/swimlanesDiagram-AYQRV4AK-DX07QVy9.js +8 -0
- package/dist/ui/dist/assets/timeline-definition-JXYKGLGB-CD2Z8QGP.js +120 -0
- package/dist/ui/dist/assets/treeView-D4JQ5SDB-sqUjH5gB.js +1 -0
- package/dist/ui/dist/assets/treemap-SAJKECNS-DvZ38FP7.js +1 -0
- package/dist/ui/dist/assets/usecaseDiagram-WPOLBNNX-CqOGidaZ.js +328 -0
- package/dist/ui/dist/assets/vennDiagram-Q3Y3IDCW-D1SXSBQ5.js +34 -0
- package/dist/ui/dist/assets/wardley-7MLQ67FV-Bpwio-Dx.js +1 -0
- package/dist/ui/dist/assets/wardleyDiagram-IVAIDKWA-JSUXHMnk.js +78 -0
- package/dist/ui/dist/assets/xychartDiagram-4URNHDU4-B4IFqQTN.js +7 -0
- package/dist/ui/dist/index.html +15 -0
- package/dist/ui/dist/style.css +121 -0
- package/package.json +31 -10
- package/skills/follow-me/SKILL.md +15 -89
- package/dist/src/anthropic.js +0 -133
- package/dist/ui/app.js +0 -2201
- package/dist/ui/concerns.js +0 -165
- package/dist/ui/highlight.js +0 -221
- package/dist/ui/index.html +0 -94
- package/dist/ui/live.js +0 -184
- package/dist/ui/playback.js +0 -579
- package/dist/ui/questions.js +0 -189
- package/dist/ui/style.css +0 -1331
- package/dist/ui/summary.js +0 -45
package/dist/ui/questions.js
DELETED
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
// Pure logic for the question loop: telling a question from a change request, matching the
|
|
3
|
-
// previous version's questions to their answers, placing each answer in the new plan, and deciding
|
|
4
|
-
// where playback stops for one. No DOM, no fetch.
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @typedef {{ kind: "hunk", unit: string, commit: number, changes: readonly number[] | null }
|
|
8
|
-
* | { kind: "message", commit: number } | { kind: "position", commit: number }
|
|
9
|
-
* | { kind: "plan" }} Anchor
|
|
10
|
-
* @typedef {{ id: string, anchor: Anchor, body: string, kind?: string,
|
|
11
|
-
* context: { commitMessage: string, path: string | null, lines?: string[] } }} AskedComment
|
|
12
|
-
* @typedef {{ comment: string, status: string, note: string,
|
|
13
|
-
* at?: { commit: number, unit?: string } }} Response
|
|
14
|
-
* @typedef {{ version: number, comments: AskedComment[], responses: Response[] }} Previous
|
|
15
|
-
* @typedef {{ unit: string, select: { kind: "rest" } | { kind: "lines", changes: number[] } }} Ref
|
|
16
|
-
* @typedef {{ commit: number, unit: string | null, continues: number[] }} Place
|
|
17
|
-
* @typedef {{ id: string, comment: AskedComment, response: Response | null, status: string,
|
|
18
|
-
* resolved: boolean, place: Place | null }} AnswerCard
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
const QUESTION_WORDS = /^\s*(why|what|how|when|where|is|does|can|should)(?![\w'’])/i;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* What a comment is, guessed from its text: a question when it ends with a question mark or
|
|
25
|
-
* opens with a question word. The reviewer can override the guess.
|
|
26
|
-
* @param {string} text
|
|
27
|
-
* @returns {"question" | "change"}
|
|
28
|
-
*/
|
|
29
|
-
export function inferKind(text) {
|
|
30
|
-
const trimmed = text.trim();
|
|
31
|
-
return trimmed.endsWith("?") || QUESTION_WORDS.test(trimmed) ? "question" : "change";
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Whether a commit's ref takes any of the lines a comment was on. A "rest" ref takes them all.
|
|
36
|
-
* @param {Ref} ref
|
|
37
|
-
* @param {readonly number[] | null} changes null means the whole unit
|
|
38
|
-
*/
|
|
39
|
-
function takes(ref, changes) {
|
|
40
|
-
if (ref.select.kind === "rest" || changes === null) return true;
|
|
41
|
-
const own = new Set(ref.select.changes);
|
|
42
|
-
return changes.some((c) => own.has(c));
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Where an answer belongs in the new plan. The agent's own "at" wins, with its 1-based commit.
|
|
47
|
-
* Otherwise the first commit that now holds the lines asked about, and the later ones after it.
|
|
48
|
-
* null when the code is gone and the answer can only live in the Answers panel.
|
|
49
|
-
* @param {AskedComment} comment
|
|
50
|
-
* @param {Response | null} response
|
|
51
|
-
* @param {readonly { refs: readonly Ref[] }[]} commits
|
|
52
|
-
* @returns {Place | null}
|
|
53
|
-
*/
|
|
54
|
-
export function placeAnswer(comment, response, commits) {
|
|
55
|
-
const at = response?.at;
|
|
56
|
-
if (at !== undefined && at.commit >= 1 && at.commit <= commits.length) {
|
|
57
|
-
return { commit: at.commit - 1, unit: at.unit ?? null, continues: [] };
|
|
58
|
-
}
|
|
59
|
-
const { anchor } = comment;
|
|
60
|
-
if (anchor.kind !== "hunk") return null;
|
|
61
|
-
const holders = commits.flatMap((commit, index) =>
|
|
62
|
-
commit.refs.some((r) => r.unit === anchor.unit && takes(r, anchor.changes)) ? [index] : [],
|
|
63
|
-
);
|
|
64
|
-
const [first, ...later] = holders;
|
|
65
|
-
return first === undefined ? null : { commit: first, unit: anchor.unit, continues: later };
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* One card per question of the previous version, in the order they were asked.
|
|
70
|
-
* @param {Previous | null} previous
|
|
71
|
-
* @param {readonly string[]} resolved ids the reviewer marked resolved
|
|
72
|
-
* @param {readonly { refs: readonly Ref[] }[]} commits
|
|
73
|
-
* @returns {AnswerCard[]}
|
|
74
|
-
*/
|
|
75
|
-
export function answerCards(previous, resolved, commits) {
|
|
76
|
-
if (previous === null) return [];
|
|
77
|
-
return previous.comments
|
|
78
|
-
.filter((c) => c.kind === "question")
|
|
79
|
-
.map((comment) => {
|
|
80
|
-
const response = previous.responses.find((r) => r.comment === comment.id) ?? null;
|
|
81
|
-
return {
|
|
82
|
-
id: comment.id,
|
|
83
|
-
comment,
|
|
84
|
-
response,
|
|
85
|
-
status: response?.status ?? "unanswered",
|
|
86
|
-
resolved: resolved.includes(comment.id),
|
|
87
|
-
place: placeAnswer(comment, response, commits),
|
|
88
|
-
};
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* How many of the previous questions the new plan answered.
|
|
94
|
-
* @param {Previous | null} previous
|
|
95
|
-
*/
|
|
96
|
-
export function answeredCount(previous) {
|
|
97
|
-
if (previous === null) return 0;
|
|
98
|
-
const asked = new Set(previous.comments.filter((c) => c.kind === "question").map((c) => c.id));
|
|
99
|
-
return previous.responses.filter((r) => r.status === "answered" && asked.has(r.comment)).length;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* The cards that belong on a commit: those under its message when unit is null, those above a
|
|
104
|
-
* unit otherwise. A card placed on a unit the commit does not show falls back to the message.
|
|
105
|
-
* @param {readonly AnswerCard[]} cards
|
|
106
|
-
* @param {number} commit
|
|
107
|
-
* @param {string | null} unit
|
|
108
|
-
* @param {readonly string[]} shown unit ids the commit shows
|
|
109
|
-
*/
|
|
110
|
-
export function cardsAt(cards, commit, unit, shown) {
|
|
111
|
-
return cards.filter((card) => {
|
|
112
|
-
if (card.place === null || card.place.commit !== commit) return false;
|
|
113
|
-
const home =
|
|
114
|
-
card.place.unit !== null && shown.includes(card.place.unit) ? card.place.unit : null;
|
|
115
|
-
return home === unit;
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* The comment an "Ask again" posts: same place, in this plan, tied to the question it continues.
|
|
121
|
-
* An anchor whose code is gone falls back to the whole plan.
|
|
122
|
-
* @param {AnswerCard} card
|
|
123
|
-
* @param {string} body
|
|
124
|
-
*/
|
|
125
|
-
export function askAgain(card, body) {
|
|
126
|
-
const { anchor, context } = card.comment;
|
|
127
|
-
const commit = card.place?.commit ?? 0;
|
|
128
|
-
/** @type {Anchor} */
|
|
129
|
-
let next = { kind: "plan" };
|
|
130
|
-
if (anchor.kind === "hunk" && card.place?.unit) {
|
|
131
|
-
next = { kind: "hunk", unit: card.place.unit, commit, changes: anchor.changes };
|
|
132
|
-
} else if (anchor.kind === "message" || anchor.kind === "position") {
|
|
133
|
-
next = { kind: anchor.kind, commit };
|
|
134
|
-
}
|
|
135
|
-
return { anchor: next, context, body, kind: "question", follows: card.id };
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* The step where playback stops for an unresolved answer: right after the narration of the beat
|
|
140
|
-
* it sits on, so the reviewer hears the explanation and then sees the answer to their question.
|
|
141
|
-
* A card on a commit as a whole stops after that commit's intro.
|
|
142
|
-
* @param {readonly { kind: string, commit: number, unit?: string }[]} beats
|
|
143
|
-
* @param {readonly { kind: string, beat: number }[]} steps
|
|
144
|
-
* @param {number} position
|
|
145
|
-
* @param {readonly AnswerCard[]} cards
|
|
146
|
-
* @param {ReadonlySet<string>} seen cards already shown, so a replay does not stop again
|
|
147
|
-
* @returns {AnswerCard[]}
|
|
148
|
-
*/
|
|
149
|
-
export function holdAt(beats, steps, position, cards, seen) {
|
|
150
|
-
const step = steps[position];
|
|
151
|
-
if (step === undefined) return [];
|
|
152
|
-
return cards.filter((card) => {
|
|
153
|
-
if (card.resolved || seen.has(card.id) || card.place === null) return false;
|
|
154
|
-
const { commit, unit } = card.place;
|
|
155
|
-
if (unit === null) {
|
|
156
|
-
const intro = beats.findIndex((b) => b.kind === "intro" && b.commit === commit);
|
|
157
|
-
const next = steps.findIndex((s) => s.beat > intro);
|
|
158
|
-
return position === next && next !== -1;
|
|
159
|
-
}
|
|
160
|
-
const target = beats.findIndex(
|
|
161
|
-
(b) => b.kind === "chunk" && b.commit === commit && b.unit === unit,
|
|
162
|
-
);
|
|
163
|
-
if (target === -1) return false;
|
|
164
|
-
return position === steps.findIndex((s) => s.beat === target && s.kind !== "say");
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Questions and change requests on a commit, for the two counts in the commit list.
|
|
170
|
-
* @param {readonly { anchor: Anchor, kind?: string }[]} comments
|
|
171
|
-
* @param {number} commit
|
|
172
|
-
*/
|
|
173
|
-
export function kindCounts(comments, commit) {
|
|
174
|
-
const here = comments.filter((c) => c.anchor.kind !== "plan" && c.anchor.commit === commit);
|
|
175
|
-
const questions = here.filter((c) => c.kind === "question").length;
|
|
176
|
-
return { questions, changes: here.length - questions };
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* The line that says what a card is waiting on.
|
|
181
|
-
* @param {AnswerCard} card
|
|
182
|
-
*/
|
|
183
|
-
export function statusLine(card) {
|
|
184
|
-
if (card.resolved) return "Resolved";
|
|
185
|
-
if (card.status === "answered") return "Answered";
|
|
186
|
-
if (card.status === "deferred") return "Deferred";
|
|
187
|
-
if (card.status === "unanswered") return "Not answered";
|
|
188
|
-
return "Answered by changing the plan";
|
|
189
|
-
}
|