@davmash/bygone 0.8.5 → 0.8.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/README.md +6 -0
- package/cli/present.js +57 -2
- package/docs/change-tour-format.md +5 -0
- package/docs/present.md +32 -0
- package/docs/product-surface.md +1 -0
- package/media/webview.css +1 -1
- package/out/changeTour.js +8 -3
- package/out/standalone-main.js +584 -24
- package/out/tourCoverage.js +8 -3
- package/out/windowTitle.js +143 -0
- package/package.json +1 -1
- package/schemas/change-tour-source.schema.json +4 -0
- package/skills/pr-tour-guide/SKILL.md +4 -0
- package/standalone/index.html +13 -5
- package/web/index.html +41 -5
- package/web/presenter.css +136 -0
- package/web/web-host.js +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -2,11 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.8.7
|
|
6
|
+
|
|
7
|
+
- Refined tour narration controls with clearer playback state, sentence-level skipping, and consolidated play/pause behavior
|
|
8
|
+
- Allowed narration skips to continue across adjacent tour steps and slides while preserving paused playback
|
|
9
|
+
- Improved tour and comparison toolbar controls, including clearer disabled word-wrap feedback
|
|
10
|
+
|
|
11
|
+
## 0.8.6
|
|
12
|
+
|
|
13
|
+
- Added optional authored-tour `windowTitle` labels and context-aware desktop and VS Code window titles
|
|
14
|
+
- Fixed tour presenter windows so authored `windowTitle` values appear in the native title instead of staying on the default `Bygone Tour` label
|
|
15
|
+
|
|
5
16
|
## 0.8.5
|
|
6
17
|
|
|
7
18
|
- Fixed Homebrew cask `bygone` CLI launch on Apple Silicon by routing through a bundle-aware launcher script inside the app
|
|
8
19
|
- Documented the macOS **“app is damaged”** workaround for unsigned desktop downloads (README, releasing docs, PR Tour Guide skill)
|
|
9
20
|
|
|
21
|
+
**macOS install:** Desktop builds are unsigned. If Gatekeeper reports the app is damaged, run `xattr -cr /Applications/Bygone.app` then open the app.
|
|
22
|
+
|
|
10
23
|
## 0.8.4
|
|
11
24
|
|
|
12
25
|
- Clarified PR Tour Guide skill install commands for project scope and agent-specific global installs
|
package/README.md
CHANGED
|
@@ -98,6 +98,12 @@ new comparison brings the central app window forward and replaces its current
|
|
|
98
98
|
session after any unsaved-change confirmation. Tours reuse a dedicated window
|
|
99
99
|
owned by that same app process.
|
|
100
100
|
|
|
101
|
+
When Bygone is quit or restarted for an upgrade, the desktop app remembers the
|
|
102
|
+
open Explore session and tour windows. A normal no-argument launch restores
|
|
103
|
+
them; an explicit file, directory, review, or presentation launch takes
|
|
104
|
+
precedence. Windows whose source files or Git targets no longer exist are
|
|
105
|
+
skipped or replaced with a blank Explore window.
|
|
106
|
+
|
|
101
107
|
Shell completion is generated from the same command specification as `bygone --help`, including contextual file arguments and local Git refs for branch review. `npm run dev:sync`, the desktop app's command-line installer, and the Homebrew packages install completions automatically. To install one manually, choose the command for your shell:
|
|
102
108
|
|
|
103
109
|
```bash
|
package/cli/present.js
CHANGED
|
@@ -3,6 +3,7 @@ const { createServer } = require('http');
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const { spawn } = require('child_process');
|
|
5
5
|
const { buildChangeTourManifest, parseChangeTourStory } = require('../out/changeTour.js');
|
|
6
|
+
const { buildTourWindowTitle } = require('../out/windowTitle.js');
|
|
6
7
|
const { tokenMatches } = require('./commandSpec.js');
|
|
7
8
|
const { loadTourSource } = require('./tourFile.js');
|
|
8
9
|
|
|
@@ -39,8 +40,26 @@ async function startPresentation(args, cwd, packageRoot, options = {}) {
|
|
|
39
40
|
process.stdout.write(`Wrote change-tour manifest to ${resolvedOutput}\n`);
|
|
40
41
|
}
|
|
41
42
|
|
|
43
|
+
const tourWindowTitle = buildTourWindowTitle(manifest, 'Bygone');
|
|
44
|
+
const presenterIndexPath = path.join(packageRoot, 'web', 'index.html');
|
|
45
|
+
let presenterIndexTemplate;
|
|
46
|
+
|
|
42
47
|
const server = createServer((request, response) => {
|
|
43
48
|
const requestUrl = new URL(request.url || '/', 'http://127.0.0.1');
|
|
49
|
+
if (requestUrl.pathname === '/narration/claim') {
|
|
50
|
+
if (request.method !== 'POST') {
|
|
51
|
+
respond(response, 405, 'Method not allowed');
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (!isSameOriginLoopbackRequest(request)) {
|
|
55
|
+
respond(response, 403, 'Forbidden');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
options.onNarrationClaim?.();
|
|
59
|
+
response.writeHead(204, { 'Cache-Control': 'no-store' });
|
|
60
|
+
response.end();
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
44
63
|
if (requestUrl.pathname === '/tour.json') {
|
|
45
64
|
response.writeHead(200, {
|
|
46
65
|
'Content-Type': 'application/json; charset=utf-8',
|
|
@@ -49,6 +68,21 @@ async function startPresentation(args, cwd, packageRoot, options = {}) {
|
|
|
49
68
|
response.end(serializedManifest);
|
|
50
69
|
return;
|
|
51
70
|
}
|
|
71
|
+
if (requestUrl.pathname === '/' || requestUrl.pathname === '/index.html') {
|
|
72
|
+
if (!presenterIndexTemplate) {
|
|
73
|
+
presenterIndexTemplate = readFileSync(presenterIndexPath, 'utf8');
|
|
74
|
+
}
|
|
75
|
+
const html = presenterIndexTemplate.replace(
|
|
76
|
+
/<title>Bygone Tour<\/title>/,
|
|
77
|
+
`<title>${escapeHtml(tourWindowTitle)}</title>`
|
|
78
|
+
);
|
|
79
|
+
response.writeHead(200, {
|
|
80
|
+
'Content-Type': 'text/html; charset=utf-8',
|
|
81
|
+
'Cache-Control': 'no-store'
|
|
82
|
+
});
|
|
83
|
+
response.end(html);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
52
86
|
const targetPath = resolveAssetPath(packageRoot, requestUrl.pathname);
|
|
53
87
|
if (!targetPath) {
|
|
54
88
|
respond(response, 404, 'Not found');
|
|
@@ -120,7 +154,7 @@ function parsePresentArgs(args) {
|
|
|
120
154
|
|
|
121
155
|
function resolveAssetPath(packageRoot, requestPath) {
|
|
122
156
|
if (requestPath === '/' || requestPath === '/index.html') {
|
|
123
|
-
return
|
|
157
|
+
return null;
|
|
124
158
|
}
|
|
125
159
|
if (!requestPath.startsWith('/web/') && !requestPath.startsWith('/media/')) {
|
|
126
160
|
return null;
|
|
@@ -160,7 +194,28 @@ function respond(response, statusCode, message) {
|
|
|
160
194
|
response.end(message);
|
|
161
195
|
}
|
|
162
196
|
|
|
197
|
+
function isSameOriginLoopbackRequest(request) {
|
|
198
|
+
const origin = request.headers.origin;
|
|
199
|
+
const host = request.headers.host;
|
|
200
|
+
if (typeof origin !== 'string' || typeof host !== 'string') return false;
|
|
201
|
+
try {
|
|
202
|
+
const parsed = new URL(origin);
|
|
203
|
+
return parsed.protocol === 'http:' && parsed.hostname === '127.0.0.1' && parsed.host === host;
|
|
204
|
+
} catch {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function escapeHtml(text) {
|
|
210
|
+
return text
|
|
211
|
+
.replaceAll('&', '&')
|
|
212
|
+
.replaceAll('<', '<')
|
|
213
|
+
.replaceAll('>', '>')
|
|
214
|
+
.replaceAll('"', '"');
|
|
215
|
+
}
|
|
216
|
+
|
|
163
217
|
module.exports = {
|
|
164
218
|
parsePresentArgs,
|
|
165
|
-
startPresentation
|
|
219
|
+
startPresentation,
|
|
220
|
+
escapeHtml
|
|
166
221
|
};
|
|
@@ -35,11 +35,16 @@ contents, and diffs into the portable JSON manifest served by the presenter.
|
|
|
35
35
|
Compilation fails if an anchor has no match or has multiple matches without an
|
|
36
36
|
explicit `occurrence`.
|
|
37
37
|
|
|
38
|
+
The optional `windowTitle` sets the native window title for the tour presenter.
|
|
39
|
+
Use a short label such as a pull request number when several tours may be open at
|
|
40
|
+
once. When omitted, the presenter falls back to `title`, then a generic tour label.
|
|
41
|
+
|
|
38
42
|
## Structure
|
|
39
43
|
|
|
40
44
|
```yaml
|
|
41
45
|
version: 1
|
|
42
46
|
title: A reviewer-facing title
|
|
47
|
+
windowTitle: PR-1234
|
|
43
48
|
sourceUrl: https://example.test/pull/123
|
|
44
49
|
range:
|
|
45
50
|
base: 0123456789abcdef
|
package/docs/present.md
CHANGED
|
@@ -14,6 +14,38 @@ The Files rail is independent of the narrative. Browsing another file keeps
|
|
|
14
14
|
the active tour anchor visible and offers **Return to Tour** to restore the
|
|
15
15
|
scene's intended focus.
|
|
16
16
|
|
|
17
|
+
## Listen to a tour
|
|
18
|
+
|
|
19
|
+
Use **Listen** in the narrative header or **Present → Listen to Tour** in the
|
|
20
|
+
desktop app to read the tour aloud with a device voice. Narration works
|
|
21
|
+
offline and does not send tour text to a hosted speech service.
|
|
22
|
+
|
|
23
|
+
- **Pause/Resume** retains the current sentence; **Stop** clears playback. The
|
|
24
|
+
outer jump controls move one sentence backward or forward within the current
|
|
25
|
+
narration item.
|
|
26
|
+
- Existing Previous and Next controls move through the same scene/step order
|
|
27
|
+
used by continuous narration.
|
|
28
|
+
- Choose any device voice exposed by the browser and a speed from 0.75× to
|
|
29
|
+
1.5×. Bygone stores those preferences locally and returns to the system
|
|
30
|
+
default if a selected voice disappears.
|
|
31
|
+
- The visible sentence is highlighted while it is spoken. Pausing retains a
|
|
32
|
+
distinct paused highlight without moving keyboard focus.
|
|
33
|
+
- Direct scene, file, or search navigation interrupts speech and leaves it
|
|
34
|
+
paused at the selected tour position. Resume continues from there.
|
|
35
|
+
|
|
36
|
+
Automatic narration reads chapter and scene framing, summaries, bullets,
|
|
37
|
+
step titles and bodies, connection labels, and takeaways. It does not
|
|
38
|
+
automatically read diff contents, code blocks, hashes, line numbers, or raw
|
|
39
|
+
URLs. Those remain visible and available to assistive technology normally.
|
|
40
|
+
|
|
41
|
+
Device voice names and quality depend on the operating system and browser.
|
|
42
|
+
If no device speech engine is exposed, Bygone disables Listen with a specific
|
|
43
|
+
unsupported-device message; lack of network access alone never disables it.
|
|
44
|
+
|
|
45
|
+
Future narration work may add opt-in treatment for code and raw URLs, plus
|
|
46
|
+
higher-quality hosted voices or routing through the agent that originated the
|
|
47
|
+
conversation. Those remain separate from the offline, device-first baseline.
|
|
48
|
+
|
|
17
49
|
## Read provenance correctly
|
|
18
50
|
|
|
19
51
|
- Normal walkthrough scenes point to exact committed source evidence.
|
package/docs/product-surface.md
CHANGED
|
@@ -48,6 +48,7 @@ not packaged.
|
|
|
48
48
|
| --- | --- | --- | --- | --- | --- |
|
|
49
49
|
| Explain the current branch automatically | Present → Present Current Branch; `bygone present` | Committed merge-base-to-tip range | Read-only | Core | presentation launch and generated-tour tests |
|
|
50
50
|
| Open an authored walkthrough | Present → Open Authored Tour; `bygone present --tour`; VS Code hand-off | Manifest range, scene, step, exact source anchor | Read-only | Core | reproducible example and tour validation tests |
|
|
51
|
+
| Listen to a generated or authored tour | Narrative Listen controls; Present → Listen to Tour | Existing manifest narrative segmented locally by scene/step and visible sentence | Read-only device TTS; voice/rate preferences remain local; continuous playback follows tour navigation and direct exploration pauses it | Core | narration model/controller and presenter-host tests |
|
|
51
52
|
| Explain a real stack | `stacked-diff` scene | Exact real Git revisions per panel | Read-only | Advanced | `examples/stacked-diff.bygone` |
|
|
52
53
|
| Explain a change in conceptual stages | `deconstructed-diff` scene | Explicitly labeled synthetic explanation stages backed by exact hunk IDs | Read-only | Advanced/experimental authoring | `examples/deconstructed-diff.bygone` |
|
|
53
54
|
| Browse away from the narration | Files rail, change navigation | Browsed file versus active tour focus remain distinct | Read-only; Return to Tour restores narrative focus | Core | tour focus and persistent-anchor tests |
|