@davmash/bygone 0.9.4 → 0.9.7
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/CHANGELOG.md +13 -0
- package/media/webview.js +183 -137
- package/out/standalone-main.js +62 -1
- package/package.json +1 -1
- package/skills/pr-tour-guide/SKILL.md +47 -1
- package/web/index.html +1 -0
- package/web/presenter.css +24 -0
- package/web/web-host.js +55 -9
package/out/standalone-main.js
CHANGED
|
@@ -18785,7 +18785,7 @@ var require_package = __commonJS({
|
|
|
18785
18785
|
displayName: "Bygone",
|
|
18786
18786
|
desktopName: "com.davidmashburn.bygone.desktop",
|
|
18787
18787
|
description: "See how change happened. Visual diff and file history for VS Code.",
|
|
18788
|
-
version: "0.9.
|
|
18788
|
+
version: "0.9.7",
|
|
18789
18789
|
author: "David Mashburn",
|
|
18790
18790
|
license: "MIT",
|
|
18791
18791
|
private: false,
|
|
@@ -32133,6 +32133,67 @@ ${error.message}`);
|
|
|
32133
32133
|
assert.ok(["auto", "scroll"].includes(initial.content.overflowY), "The narrative content uses scrolling");
|
|
32134
32134
|
assert.equal(initial.activeKeys.length, 1, "Exactly one reading item is active initially");
|
|
32135
32135
|
assert.equal(initial.activeKeys[0], "title", "The title starts as the active reading item");
|
|
32136
|
+
const originalHeight = await evaluate("document.querySelector('#tour-narrative').getBoundingClientRect().height");
|
|
32137
|
+
const originalPreference = await evaluate("localStorage.getItem('bygone.tourNarrativeHeight')");
|
|
32138
|
+
const resizeKey = async (key) => {
|
|
32139
|
+
await evaluate(`document.querySelector('#tour-narrative-resizer').dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, key: ${JSON.stringify(key)} }))`);
|
|
32140
|
+
await waitForRaf();
|
|
32141
|
+
};
|
|
32142
|
+
const readSplit = () => evaluate(`(() => {
|
|
32143
|
+
const narrative = document.querySelector('#tour-narrative').getBoundingClientRect();
|
|
32144
|
+
const code = document.querySelector('#container').getBoundingClientRect();
|
|
32145
|
+
const resizer = document.querySelector('#tour-narrative-resizer');
|
|
32146
|
+
const handle = resizer.getBoundingClientRect();
|
|
32147
|
+
return { height: narrative.height, codeTop: code.top, codeHeight: code.height,
|
|
32148
|
+
handleY: handle.top + handle.height / 2, handleX: handle.left + handle.width / 2,
|
|
32149
|
+
value: Number(resizer.getAttribute('aria-valuenow')),
|
|
32150
|
+
max: Number(resizer.getAttribute('aria-valuemax')),
|
|
32151
|
+
stored: Number(localStorage.getItem('bygone.tourNarrativeHeight')),
|
|
32152
|
+
cursor: getComputedStyle(resizer).cursor };
|
|
32153
|
+
})()`);
|
|
32154
|
+
const assertSplit = (split) => {
|
|
32155
|
+
assert.ok(Math.abs(split.codeTop - split.height) <= 1, "Code starts at the narrative boundary");
|
|
32156
|
+
assert.ok(Math.abs(split.handleY - split.height) <= 1, "The divider tracks the narrative boundary");
|
|
32157
|
+
assert.equal(split.value, split.height, "The separator exposes its current height");
|
|
32158
|
+
assert.ok(split.codeHeight >= 180, "Resizing preserves room for code");
|
|
32159
|
+
};
|
|
32160
|
+
const dragSplit = async (height) => {
|
|
32161
|
+
const split = await readSplit();
|
|
32162
|
+
const x = Math.round(split.handleX);
|
|
32163
|
+
const y = Math.round(split.handleY);
|
|
32164
|
+
browserContents.sendInputEvent({ type: "mouseMove", x, y });
|
|
32165
|
+
browserContents.sendInputEvent({ type: "mouseDown", button: "left", clickCount: 1, x, y });
|
|
32166
|
+
browserContents.sendInputEvent({ type: "mouseMove", x, y: height });
|
|
32167
|
+
await waitFor(`Number(document.querySelector('#tour-narrative-resizer').getAttribute('aria-valuenow')) === ${height}`, "dragged narrative boundary");
|
|
32168
|
+
browserContents.sendInputEvent({ type: "mouseUp", button: "left", clickCount: 1, x, y: height });
|
|
32169
|
+
await waitFor("!document.body.classList.contains('is-resizing-tour-narrative')", "narrative drag completion");
|
|
32170
|
+
await waitForRaf();
|
|
32171
|
+
};
|
|
32172
|
+
try {
|
|
32173
|
+
assert.equal((await readSplit()).cursor, "row-resize", "The narrative divider is draggable");
|
|
32174
|
+
await resizeKey("Home");
|
|
32175
|
+
let split = await readSplit();
|
|
32176
|
+
assert.equal(split.height, 180, "Home sets the minimum narrative height");
|
|
32177
|
+
assertSplit(split);
|
|
32178
|
+
await resizeKey("End");
|
|
32179
|
+
split = await readSplit();
|
|
32180
|
+
assert.equal(split.height, split.max, "End sets the maximum narrative height");
|
|
32181
|
+
assertSplit(split);
|
|
32182
|
+
await resizeKey("ArrowUp");
|
|
32183
|
+
assert.equal((await readSplit()).height, split.max - 16, "ArrowUp reduces the narrative height");
|
|
32184
|
+
await resizeKey("ArrowDown");
|
|
32185
|
+
assert.equal((await readSplit()).height, split.max, "ArrowDown increases the narrative height");
|
|
32186
|
+
const target = Math.round((180 + split.max) / 2);
|
|
32187
|
+
await dragSplit(target);
|
|
32188
|
+
split = await readSplit();
|
|
32189
|
+
assertSplit(split);
|
|
32190
|
+
assert.equal(split.stored, target, "Dragging saves the narrative height");
|
|
32191
|
+
assert.deepEqual((await read()).activeKeys, initial.activeKeys, "Resizing preserves the selected passage");
|
|
32192
|
+
assert.deepEqual((await read()).url, initial.url, "Resizing preserves the reading URL");
|
|
32193
|
+
} finally {
|
|
32194
|
+
await dragSplit(Math.round(originalHeight));
|
|
32195
|
+
await evaluate(originalPreference === null ? "localStorage.removeItem('bygone.tourNarrativeHeight')" : `localStorage.setItem('bygone.tourNarrativeHeight', ${JSON.stringify(originalPreference)})`);
|
|
32196
|
+
}
|
|
32136
32197
|
assert.equal(initial.items.filter((item) => item.kind === "title").length, 1, "The title item is unique");
|
|
32137
32198
|
assert.equal(initial.items.filter((item) => item.kind === "chapter").length, 2, "Each chapter has a reading item");
|
|
32138
32199
|
assert.equal(initial.items.filter((item) => item.kind === "scene").length, 2, "Each scene has a reading item");
|
package/package.json
CHANGED
|
@@ -134,8 +134,50 @@ Then read patches only for likely narrative-bearing files. Account explicitly fo
|
|
|
134
134
|
|
|
135
135
|
Compiled tours and context dossiers are large because they embed source snapshots. Inspect them progressively and do not load every patch unless the narrative really needs it.
|
|
136
136
|
|
|
137
|
+
## Gather ticket and PR framing
|
|
138
|
+
|
|
139
|
+
When available, read the ticket and PR context supplied by the user or directly
|
|
140
|
+
linked from the change, using accessible read-only sources. Follow relevant
|
|
141
|
+
parent-project or review links when they explain the change; keep discovery
|
|
142
|
+
bounded to this work. Missing metadata should not block a useful code tour.
|
|
143
|
+
|
|
144
|
+
Capture the facts that help a reader understand the change:
|
|
145
|
+
|
|
146
|
+
- **Ticket:** identifier, title, problem and requested outcome, relevant details
|
|
147
|
+
or acceptance criteria, creator/requester and assignee as distinct roles,
|
|
148
|
+
creation date or relevant timeline, and its place in a parent project, epic,
|
|
149
|
+
or larger initiative.
|
|
150
|
+
- **PR:** number, title, URL, author, relevant creation/merge dates, associated
|
|
151
|
+
ticket, and actual review history: who reviewed, when, their recorded outcome,
|
|
152
|
+
and consequential feedback or resulting changes.
|
|
153
|
+
|
|
154
|
+
Be explicit about whose ticket it was, who authored the PR, and who reviewed
|
|
155
|
+
it when the sources establish those roles. Credit implementation contributors
|
|
156
|
+
when known; PR authorship alone does not establish sole implementation credit.
|
|
157
|
+
A requested reviewer is not an actual reviewer; a comment is not an approval. Do not assume an earlier review
|
|
158
|
+
covers the current head or an entire multi-PR range. For stacked work, keep
|
|
159
|
+
ticket, author, timing, and review provenance attached to the correct PR.
|
|
160
|
+
|
|
161
|
+
Link the supporting ticket, PR, and review sources in the tour's narrative.
|
|
162
|
+
Distinguish the ticket's requested outcome and the author's stated intent from
|
|
163
|
+
behavior established by code and tests. Do not invent ownership, dates, project
|
|
164
|
+
relationships, ticket associations, review status, or approval. Briefly disclose
|
|
165
|
+
material gaps or conflicting context where they affect the explanation; omit
|
|
166
|
+
irrelevant unavailable fields rather than filling the tour with placeholders.
|
|
167
|
+
|
|
137
168
|
## Plan the explanation
|
|
138
169
|
|
|
170
|
+
Begin with an opening slide that summarizes the high-level context before the
|
|
171
|
+
implementation: the problem, its place in the larger project, the ticket and
|
|
172
|
+
PR relationship, and what this change contributes. Include relevant people,
|
|
173
|
+
timing, and review status concisely; put detailed provenance beside the later
|
|
174
|
+
claims it explains. If separate authored modes have independent entry points,
|
|
175
|
+
give each enough opening context to stand on its own.
|
|
176
|
+
|
|
177
|
+
Use the first scene's summary/bullets or equivalent supported narrative fields
|
|
178
|
+
for this opening; do not invent a slide kind or metadata keys. Keep source
|
|
179
|
+
anchors for code claims and source links for external context distinct.
|
|
180
|
+
|
|
139
181
|
Identify the smallest set of reviewer questions that makes the change understandable. Organize by conceptual dependency rather than filename order. Usually move through:
|
|
140
182
|
|
|
141
183
|
1. motivation, contract, or invariant;
|
|
@@ -294,7 +336,10 @@ After structural validation, check that:
|
|
|
294
336
|
|
|
295
337
|
Treat this as a required self-audit, not a claim the validator can prove. For each item, cite concrete evidence you actually opened or mark it not applicable; the hand-off must distinguish verified findings from interpretation.
|
|
296
338
|
|
|
297
|
-
- the
|
|
339
|
+
- the opening slide establishes the problem, project context, and available
|
|
340
|
+
ticket/PR provenance before the first implementation step;
|
|
341
|
+
- ticket ownership, dates, and actual review claims are traceable to opened
|
|
342
|
+
sources and scoped to the PR/revision they describe;
|
|
298
343
|
- chapter boundaries follow conceptual transitions rather than a fixed count or one-scene-per-chapter pattern;
|
|
299
344
|
- important production behavior is not hidden in the complete Files rail;
|
|
300
345
|
- tests are connected to the behavior they prove;
|
|
@@ -361,6 +406,7 @@ Report:
|
|
|
361
406
|
counts, plus compiled counts when generated complete-change or per-mode
|
|
362
407
|
scenes change them;
|
|
363
408
|
- omitted or unread evidence;
|
|
409
|
+
- ticket/PR context sources used and material unavailable or conflicting context;
|
|
364
410
|
- validation and visual verification performed;
|
|
365
411
|
- whether generated files are temporary, uncommitted, committed, or pushed.
|
|
366
412
|
|
package/web/index.html
CHANGED
|
@@ -137,6 +137,7 @@
|
|
|
137
137
|
</div>
|
|
138
138
|
<div id="tour-narrative-content" class="tour-narrative-content" tabindex="0" role="region" aria-label="Tour reading flow"></div>
|
|
139
139
|
</section>
|
|
140
|
+
<div id="tour-narrative-resizer" class="tour-narrative-resizer" role="separator" aria-label="Resize tour text" title="Resize tour text (Up/Down; Home/End)" aria-controls="tour-narrative" aria-orientation="horizontal" aria-valuemin="180" tabindex="0"></div>
|
|
140
141
|
<div class="web-toolbar">
|
|
141
142
|
<div class="web-toolbar-group">
|
|
142
143
|
<button id="web-compare-test" type="button" title="Compare sample files">Compare Test Files</button>
|
package/web/presenter.css
CHANGED
|
@@ -398,6 +398,29 @@ body.tour-mode #container {
|
|
|
398
398
|
display: none;
|
|
399
399
|
}
|
|
400
400
|
|
|
401
|
+
.tour-narrative-resizer {
|
|
402
|
+
position: fixed;
|
|
403
|
+
z-index: 120;
|
|
404
|
+
top: calc(var(--tour-narrative-height) - 4px);
|
|
405
|
+
right: 0;
|
|
406
|
+
left: var(--tour-rail-width);
|
|
407
|
+
height: 8px;
|
|
408
|
+
cursor: row-resize;
|
|
409
|
+
touch-action: none;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
.tour-narrative-resizer:hover,
|
|
413
|
+
.tour-narrative-resizer:focus-visible,
|
|
414
|
+
body.is-resizing-tour-narrative .tour-narrative-resizer {
|
|
415
|
+
background: rgba(169, 159, 255, 0.75);
|
|
416
|
+
outline: none;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
body:not(.tour-mode) .tour-narrative-resizer,
|
|
420
|
+
body.tour-derived-mode .tour-narrative-resizer {
|
|
421
|
+
display: none;
|
|
422
|
+
}
|
|
423
|
+
|
|
401
424
|
.tour-narrative-toolbar {
|
|
402
425
|
display: flex;
|
|
403
426
|
min-width: 0;
|
|
@@ -1364,6 +1387,7 @@ body.tour-directory-file-open #file-info { display: none; }
|
|
|
1364
1387
|
}
|
|
1365
1388
|
|
|
1366
1389
|
.tour-sidebar-resizer { display: none; }
|
|
1390
|
+
.tour-narrative-resizer { left: 0; }
|
|
1367
1391
|
.tour-narrative { top: 0; left: 0; height: min(38vh, 360px); padding: 10px 14px 12px; }
|
|
1368
1392
|
.tour-narrative-toolbar { gap: 6px; }
|
|
1369
1393
|
.tour-narration-controls select { max-width: 150px; }
|