pr-docent 0.1.0 → 0.2.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.ko.md +214 -0
- package/README.md +141 -80
- package/bin/pr-docent.mjs +34 -5
- package/host/claude.mjs +78 -0
- package/host/native.mjs +3 -7
- package/host/pr-docent-host.mjs +66 -75
- package/host/render-short.mjs +96 -0
- package/host/short-cli.mjs +56 -0
- package/host/short.mjs +71 -0
- package/package.json +8 -2
- package/scripts/check-short.mjs +37 -0
- package/scripts/check-tour.mjs +18 -6
- package/scripts/short-prompt.md +63 -0
- package/scripts/tour-prompt.md +36 -19
- package/src/diff.js +18 -2
- package/src/guidelines.js +102 -0
- package/src/short-scenes.js +127 -0
- package/src/short.js +158 -0
- package/src/tour.js +44 -2
package/src/tour.js
CHANGED
|
@@ -17,6 +17,36 @@
|
|
|
17
17
|
|
|
18
18
|
export const LEVELS = ["focus", "skim", "skip"];
|
|
19
19
|
|
|
20
|
+
const SHA = /^[0-9a-f]{40}$/;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The commits a tour was made for, when its generator recorded them: the PR's head commit and the
|
|
24
|
+
* diff's base (the merge base with the target branch). Written by the tools, never by Claude.
|
|
25
|
+
*/
|
|
26
|
+
function revisionOf(pr) {
|
|
27
|
+
return SHA.test(pr.head ?? "") ? { head: pr.head, ...(SHA.test(pr.base ?? "") ? { base: pr.base } : {}) } : {};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Whether a tour still matches the PR, given the PR's current { head, base, commits }:
|
|
32
|
+
* "current"; "added" (new commits on top); "rewritten" (force push, rebase, fixup: the tour's
|
|
33
|
+
* head is gone from the PR's commits); "base" (same commits against a different base, such as a
|
|
34
|
+
* retargeted PR); "unknown" (the tour doesn't say, or the PR couldn't be read).
|
|
35
|
+
* Commit ids cover all history below them, so an unchanged head means unchanged commits.
|
|
36
|
+
*/
|
|
37
|
+
export function tourFreshness(tourPr, current) {
|
|
38
|
+
if (!tourPr?.head || !current?.head) return "unknown";
|
|
39
|
+
if (tourPr.head !== current.head) return current.commits?.includes(tourPr.head) ? "added" : "rewritten";
|
|
40
|
+
return tourPr.base && current.base && tourPr.base !== current.base ? "base" : "current";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Of the tour made here and the one posted in the comments, the one to play: a current one first, then the local one. */
|
|
44
|
+
export function pickTour(local, posted, current) {
|
|
45
|
+
const fresh = (raw) => raw && tourFreshness(raw.pr, current) === "current";
|
|
46
|
+
if (fresh(local) || !fresh(posted)) return local ?? posted;
|
|
47
|
+
return posted;
|
|
48
|
+
}
|
|
49
|
+
|
|
20
50
|
/** Validates and normalizes raw JSON. Returns { tour, errors }; tour is null when there are errors. */
|
|
21
51
|
export function parseTour(raw) {
|
|
22
52
|
const errors = [];
|
|
@@ -52,7 +82,7 @@ export function parseTour(raw) {
|
|
|
52
82
|
return {
|
|
53
83
|
tour: {
|
|
54
84
|
version: 1,
|
|
55
|
-
pr: { owner: pr.owner, repo: pr.repo, number: pr.number },
|
|
85
|
+
pr: { owner: pr.owner, repo: pr.repo, number: pr.number, ...revisionOf(pr) },
|
|
56
86
|
title: String(raw.title ?? ""),
|
|
57
87
|
summary: String(raw.summary ?? ""),
|
|
58
88
|
chapters,
|
|
@@ -155,11 +185,23 @@ export function findTourInBlocks(blocks, { owner, repo, number }) {
|
|
|
155
185
|
} catch {
|
|
156
186
|
continue;
|
|
157
187
|
}
|
|
158
|
-
|
|
188
|
+
const forThisPr = raw?.version === 1 && raw.pr?.owner === owner && raw.pr?.repo === repo && raw.pr?.number === number;
|
|
189
|
+
if (forThisPr && Array.isArray(raw.chapters)) found = raw; // a short in the same comment has scenes instead
|
|
159
190
|
}
|
|
160
191
|
return found;
|
|
161
192
|
}
|
|
162
193
|
|
|
194
|
+
/** "ko" when the tour's text has Hangul, otherwise "en": the language to narrate it in. */
|
|
195
|
+
export function tourLanguage(tour) {
|
|
196
|
+
const text = [
|
|
197
|
+
tour.title,
|
|
198
|
+
tour.summary,
|
|
199
|
+
...tour.chapters.flatMap((c) => [c.title, c.summary]),
|
|
200
|
+
...flattenSteps(tour).flatMap((s) => [s.note, s.point]),
|
|
201
|
+
].join(" ");
|
|
202
|
+
return /[가-힣]/.test(text) ? "ko" : "en";
|
|
203
|
+
}
|
|
204
|
+
|
|
163
205
|
/** The bundled tour file name for a PR, e.g. "your-org--your-repo--42.json". */
|
|
164
206
|
export function tourFileName({ owner, repo, number }) {
|
|
165
207
|
return `${owner}--${repo}--${number}.json`;
|