@davmash/bygone 0.8.16 → 0.9.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@davmash/bygone",
3
- "version": "0.8.16",
3
+ "version": "0.9.2",
4
4
  "description": "See how change happened. Visual diff and file history.",
5
5
  "author": "David Mashburn",
6
6
  "license": "MIT",
@@ -40,7 +40,7 @@
40
40
  "electron"
41
41
  ],
42
42
  "dependencies": {
43
- "electron": "^43.1.1",
43
+ "electron": "^43.7.6",
44
44
  "electron-updater": "^6.8.9",
45
45
  "js-yaml": "^4.3.0"
46
46
  }
@@ -7,7 +7,7 @@
7
7
  "additionalProperties": false,
8
8
  "required": ["version", "anchors", "connections", "chapters"],
9
9
  "properties": {
10
- "version": { "enum": [1, 2] },
10
+ "version": { "enum": [1, 2, 3] },
11
11
  "title": { "$ref": "#/$defs/nonEmptyString" },
12
12
  "windowTitle": {
13
13
  "$ref": "#/$defs/nonEmptyString",
@@ -34,6 +34,7 @@
34
34
  }
35
35
  }
36
36
  },
37
+ "review": { "$ref": "#/$defs/review" },
37
38
  "anchors": {
38
39
  "type": "object",
39
40
  "propertyNames": { "minLength": 1 },
@@ -56,9 +57,35 @@
56
57
  "type": "array",
57
58
  "minItems": 1,
58
59
  "items": { "$ref": "#/$defs/chapter" }
60
+ },
61
+ "tours": {
62
+ "type": "object",
63
+ "additionalProperties": false,
64
+ "minProperties": 1,
65
+ "properties": {
66
+ "historical": { "$ref": "#/$defs/historicalTour" },
67
+ "deconstructed": { "$ref": "#/$defs/deconstructedTour" }
68
+ }
59
69
  }
60
70
  },
61
71
  "allOf": [
72
+ {
73
+ "if": { "properties": { "version": { "enum": [1, 2] } }, "required": ["version"] },
74
+ "then": {
75
+ "not": { "anyOf": [{ "required": ["tours"] }, { "required": ["review"] }] },
76
+ "properties": {
77
+ "chapters": {
78
+ "items": {
79
+ "properties": {
80
+ "scenes": {
81
+ "items": { "not": { "required": ["overview"] } }
82
+ }
83
+ }
84
+ }
85
+ }
86
+ }
87
+ }
88
+ },
62
89
  {
63
90
  "if": { "properties": { "version": { "const": 1 } }, "required": ["version"] },
64
91
  "then": {
@@ -79,7 +106,7 @@
79
106
  }
80
107
  },
81
108
  {
82
- "if": { "properties": { "version": { "const": 2 } }, "required": ["version"] },
109
+ "if": { "properties": { "version": { "enum": [2, 3] } }, "required": ["version"] },
83
110
  "then": {
84
111
  "properties": {
85
112
  "chapters": {
@@ -100,6 +127,7 @@
100
127
  ],
101
128
  "$defs": {
102
129
  "nonEmptyString": { "type": "string", "minLength": 1 },
130
+ "reviewString": { "type": "string", "minLength": 1, "pattern": "\\S" },
103
131
  "stringArray": {
104
132
  "type": "array",
105
133
  "items": { "type": "string" }
@@ -146,6 +174,28 @@
146
174
  "takeaway": { "$ref": "#/$defs/nonEmptyString" }
147
175
  }
148
176
  },
177
+ "sceneOverview": {
178
+ "type": "object",
179
+ "additionalProperties": false,
180
+ "required": ["kind"],
181
+ "properties": {
182
+ "kind": { "const": "directory-diff" },
183
+ "comparison": {
184
+ "type": "object",
185
+ "additionalProperties": false,
186
+ "required": ["from", "to"],
187
+ "properties": {
188
+ "from": { "$ref": "#/$defs/nonEmptyString" },
189
+ "to": { "$ref": "#/$defs/nonEmptyString" }
190
+ }
191
+ },
192
+ "path": {
193
+ "type": "string",
194
+ "minLength": 1,
195
+ "pattern": "^(?!/)(?![A-Za-z]:)(?!.*\\\\)(?!.*(?:^|/)\\.\\.(?:/|$)).*$"
196
+ }
197
+ }
198
+ },
149
199
  "requirement": {
150
200
  "type": "object",
151
201
  "additionalProperties": false,
@@ -158,6 +208,63 @@
158
208
  "confidence": { "enum": ["high", "medium", "low"] }
159
209
  }
160
210
  },
211
+ "review": {
212
+ "type": "object",
213
+ "additionalProperties": false,
214
+ "required": ["baseOid", "headOid", "items"],
215
+ "properties": {
216
+ "baseOid": { "$ref": "#/$defs/fullGitOid" },
217
+ "headOid": { "$ref": "#/$defs/fullGitOid" },
218
+ "items": {
219
+ "type": "array",
220
+ "minItems": 1,
221
+ "items": { "$ref": "#/$defs/reviewItem" }
222
+ }
223
+ }
224
+ },
225
+ "fullGitOid": {
226
+ "type": "string",
227
+ "pattern": "^(?:[0-9a-fA-F]{40}|[0-9a-fA-F]{64})$"
228
+ },
229
+ "reviewItem": {
230
+ "type": "object",
231
+ "additionalProperties": false,
232
+ "required": ["id", "kind", "title", "body", "evidence"],
233
+ "properties": {
234
+ "id": { "$ref": "#/$defs/reviewString" },
235
+ "kind": { "enum": ["concept", "boundary", "tradeoff", "question"] },
236
+ "title": { "$ref": "#/$defs/reviewString" },
237
+ "body": { "$ref": "#/$defs/reviewString" },
238
+ "evidence": {
239
+ "type": "array",
240
+ "items": { "$ref": "#/$defs/reviewEvidence" }
241
+ },
242
+ "nextCheck": { "$ref": "#/$defs/reviewString" }
243
+ },
244
+ "allOf": [
245
+ {
246
+ "if": {
247
+ "properties": { "kind": { "const": "question" } },
248
+ "required": ["kind"]
249
+ },
250
+ "then": { "required": ["nextCheck"] },
251
+ "else": {
252
+ "properties": {
253
+ "evidence": { "minItems": 1 }
254
+ }
255
+ }
256
+ }
257
+ ]
258
+ },
259
+ "reviewEvidence": {
260
+ "type": "object",
261
+ "additionalProperties": false,
262
+ "required": ["sceneId", "stepId"],
263
+ "properties": {
264
+ "sceneId": { "$ref": "#/$defs/reviewString" },
265
+ "stepId": { "$ref": "#/$defs/reviewString" }
266
+ }
267
+ },
161
268
  "step": {
162
269
  "type": "object",
163
270
  "additionalProperties": false,
@@ -191,11 +298,13 @@
191
298
  "required": ["id", "title", "summary", "bullets", "tags", "takeaway", "steps"],
192
299
  "properties": {
193
300
  "id": { "$ref": "#/$defs/nonEmptyString" },
301
+ "kind": { "const": "walkthrough" },
194
302
  "title": { "$ref": "#/$defs/nonEmptyString" },
195
303
  "summary": { "$ref": "#/$defs/nonEmptyString" },
196
304
  "bullets": { "$ref": "#/$defs/stringArray" },
197
305
  "tags": { "$ref": "#/$defs/stringArray" },
198
306
  "takeaway": { "$ref": "#/$defs/nonEmptyString" },
307
+ "overview": { "allOf": [{ "$ref": "#/$defs/sceneOverview" }, { "not": { "required": ["comparison"] } }] },
199
308
  "steps": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/step" } }
200
309
  }
201
310
  }
@@ -247,6 +356,7 @@
247
356
  "bullets": { "$ref": "#/$defs/stringArray" },
248
357
  "tags": { "$ref": "#/$defs/stringArray" },
249
358
  "takeaway": { "$ref": "#/$defs/nonEmptyString" },
359
+ "overview": { "$ref": "#/$defs/sceneOverview" },
250
360
  "stack": { "type": "array", "minItems": 2, "maxItems": 6, "items": { "$ref": "#/$defs/stackEntry" } },
251
361
  "files": { "$ref": "#/$defs/stringArray" },
252
362
  "steps": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/stackStep" } }
@@ -306,6 +416,7 @@
306
416
  "bullets": { "$ref": "#/$defs/stringArray" },
307
417
  "tags": { "$ref": "#/$defs/stringArray" },
308
418
  "takeaway": { "$ref": "#/$defs/nonEmptyString" },
419
+ "overview": { "$ref": "#/$defs/sceneOverview" },
309
420
  "base": { "$ref": "#/$defs/nonEmptyString" },
310
421
  "target": { "$ref": "#/$defs/nonEmptyString" },
311
422
  "stack": { "type": "array", "minItems": 2, "maxItems": 6, "items": { "$ref": "#/$defs/stackEntry" } },
@@ -341,6 +452,59 @@
341
452
  }
342
453
  }
343
454
  }
455
+ },
456
+ "historicalTour": {
457
+ "type": "object",
458
+ "additionalProperties": false,
459
+ "required": ["chapters"],
460
+ "properties": {
461
+ "chapters": {
462
+ "type": "array",
463
+ "minItems": 1,
464
+ "items": { "$ref": "#/$defs/historicalChapter" }
465
+ }
466
+ }
467
+ },
468
+ "historicalChapter": {
469
+ "type": "object",
470
+ "additionalProperties": false,
471
+ "required": ["id", "title", "scenes"],
472
+ "properties": {
473
+ "id": { "$ref": "#/$defs/nonEmptyString" },
474
+ "title": { "$ref": "#/$defs/nonEmptyString" },
475
+ "scenes": {
476
+ "type": "array",
477
+ "minItems": 1,
478
+ "items": {
479
+ "oneOf": [
480
+ { "$ref": "#/$defs/scene" },
481
+ { "$ref": "#/$defs/stackedScene" }
482
+ ]
483
+ }
484
+ }
485
+ }
486
+ },
487
+ "deconstructedTour": {
488
+ "type": "object",
489
+ "additionalProperties": false,
490
+ "required": ["chapters"],
491
+ "properties": {
492
+ "chapters": {
493
+ "type": "array",
494
+ "minItems": 1,
495
+ "items": { "$ref": "#/$defs/chapter" },
496
+ "contains": {
497
+ "type": "object",
498
+ "required": ["scenes"],
499
+ "properties": {
500
+ "scenes": {
501
+ "type": "array",
502
+ "contains": { "$ref": "#/$defs/deconstructedScene" }
503
+ }
504
+ }
505
+ }
506
+ }
507
+ }
344
508
  }
345
509
  }
346
510
  }
@@ -98,6 +98,10 @@ Do not rebuild, commit, push, publish, or open a browser unless the user request
98
98
 
99
99
  Determine the intended head and base from the request and repository state. Prefer an explicit base; do not guess when different bases would materially change the explanation.
100
100
 
101
+ Treat workspace paths named by the request as the explicit scope. The context
102
+ does not provide a path filter, so do not silently narrow or broaden that scope
103
+ based on which files seem easiest to explain; surface any scope ambiguity.
104
+
101
105
  For a hosted review, resolve both immutable endpoint OIDs from provider metadata. Never assume the current checkout is the requested review head. For GitHub:
102
106
 
103
107
  ```sh
@@ -109,9 +113,16 @@ test -n "$HEAD_OID" && test "$HEAD_OID" != null
109
113
  bygone tour context "$HEAD_OID" --base "$BASE_OID" --output /tmp/change-context.json
110
114
  ```
111
115
 
112
- Use the equivalent API or CLI fields for other providers. If you are not reviewing a hosted change, compute the merge-base against the intended integration branch and pass that exact base OID or ref. Keep the existing preference for explicit endpoints and do not guess.
116
+ Use the equivalent API or CLI fields for other providers. If the requested
117
+ endpoints are unresolved, reversed, divergent, or have multiple candidates,
118
+ stop and report the ambiguity. Never silently invent an endpoint, choose among
119
+ candidates, or substitute a merge-base. If you are not reviewing a hosted
120
+ change, compute the merge-base only when the intended integration branch is
121
+ explicit, and pass that exact base OID or ref.
113
122
 
114
- Use immutable commit IDs in the eventual tour. Dirty working-tree changes are reported but excluded from committed-range context.
123
+ Use immutable commit IDs in the eventual tour. Dirty working-tree changes and
124
+ unsaved buffers are reported separately but excluded from committed-range
125
+ context, authored evidence, and compiled source.
115
126
 
116
127
  Inspect progressively instead of loading every patch immediately:
117
128
 
@@ -164,19 +175,52 @@ Retrieve the current contract:
164
175
  bygone tour schema > /tmp/change-tour-source.schema.json
165
176
  ```
166
177
 
167
- Write a version 2 `.bygone` file. The legacy `.bygone.yaml` spelling remains
168
- valid when generic YAML tooling requires it. Treat the authored source and its
169
- compiled `.tour.json` as Git-backed, non-portable artifacts: pin `range.base`
170
- and `range.head` to the exact OIDs from the context, and keep them with the
171
- corresponding repository so Bygone can resolve those objects and live history.
172
- For every deconstructed scene, author the underlying real `stack` explicitly;
173
- do not infer it from the synthetic explanation stages or Git history.
178
+ Write a version 3 `.bygone` file for new tours. The legacy `.bygone.yaml`
179
+ spelling remains valid when generic YAML tooling requires it. Treat the
180
+ authored source and its compiled `.tour.json` as Git-backed, non-portable
181
+ artifacts: pin `range.base` and `range.head` to the exact OIDs from the
182
+ context, and keep them with the corresponding repository so Bygone can resolve
183
+ those objects and live history. Versions 1 and 2 remain readable for legacy
184
+ inputs; v3 is the format for independent authored modes, directory overviews,
185
+ and review notes.
174
186
 
175
187
  Set optional `windowTitle` when the tour should appear in the native window
176
188
  title — for example a pull request number (`PR-1234`) so multiple open tours
177
189
  stay distinguishable. When omitted, the presenter falls back to `title`.
178
190
 
179
- For every step:
191
+ ### Choose the authored modes
192
+
193
+ The root `chapters` is required and is the compatibility tour. It shares the
194
+ top-level `range`, `anchors`, and `connections` with any independent modes.
195
+ When the source supplies them, `tours.historical.chapters` and
196
+ `tours.deconstructed.chapters` are separate authored tours; keep their chapter,
197
+ scene, and step order independent rather than expecting Bygone to match content
198
+ across modes.
199
+
200
+ - **Historical** explains real revision states. Its scenes may be walkthroughs
201
+ or `stacked-diff` scenes, never `deconstructed-diff` scenes. Every stacked
202
+ panel must resolve to a real Git revision; an explicitly authored Historical
203
+ stack may contain two to six revisions, but its first and last panels must be
204
+ the resolved review base and head.
205
+ - **Deconstructed** explains the change through synthetic cumulative stages. It
206
+ must contain at least one `deconstructed-diff` scene and may include
207
+ walkthrough scenes for context or proof. A mode-specific deconstructed scene
208
+ may omit `stack` and endpoint `steps`: its stages, not Git history, define the
209
+ explanation panels.
210
+ - If a mode is omitted, v3 derives it from the root chapters by scene identity
211
+ and order. Root walkthroughs and real stacks supply Historical; root
212
+ deconstructed scenes supply Deconstructed. A root deconstructed scene enters
213
+ Historical only when it also has explicit endpoint walkthrough `steps`; a
214
+ real revision `stack` by itself is not that walkthrough. No cross-mode
215
+ correspondence is inferred from filenames or narrative text.
216
+
217
+ For a root v3 `deconstructed-diff` scene, provide both an explicit real
218
+ revision `stack` and regular endpoint `steps`. The stack is used for the real
219
+ Historical/Final fallback and must have the same base and final endpoints as
220
+ the source range; the synthetic stages remain separate. A
221
+ mode-specific Deconstructed scene may omit those fields as described above.
222
+
223
+ For every walkthrough step:
180
224
 
181
225
  - make one concise explanatory claim;
182
226
  - focus an anchor in `base` or `head` evidence;
@@ -185,13 +229,49 @@ For every step:
185
229
  - connect behavior to tests, error handling, or other concrete proof;
186
230
  - add a connection only when the relationship between two locations materially improves understanding.
187
231
 
232
+ For every `stacked-diff` step, use a real changed file and a `pair` of adjacent
233
+ stack entry IDs; use `side` or `lines` only to refine the focus. For every
234
+ deconstructed stage, assign concrete change-unit (hunk) IDs through `changes`
235
+ and build a cumulative teaching order. Assign each changed hunk exactly once,
236
+ or exclude it explicitly with a reason; unsupported, binary, and rename-path
237
+ changes generally need whole-file exclusions. Do not infer a real stack from
238
+ the synthetic stages or describe an explanation panel as a commit.
239
+
188
240
  Keep deconstructed-tour coordinates distinct:
189
241
 
190
- - A **stage** is a conceptual phase or cumulative comparison state; a **tour step** is one navigable explanation item within that stage.
242
+ - A **stage** is an authored synthetic phase and cumulative comparison state;
243
+ it is not a Git revision.
244
+ - The presenter derives one or more navigable Deconstructed tour steps from a
245
+ stage's introduced changes. A root deconstructed scene's endpoint `steps`
246
+ are ordinary anchor-based walkthrough items for the real range, not those
247
+ synthetic stage steps.
191
248
  - Do not refer to either by an unqualified ordinal such as "Stage 2" or "Step 11" in authored titles, summaries, narration, or takeaways. Prefer the stable descriptive title so the reference survives edits.
192
249
  - When an ordinal is necessary, qualify the coordinate: "stage 2 of 4" versus "tour step 11 of 46."
193
250
  - Treat presenter-generated labels as UI context; do not repeat them in authored prose unless the distinction itself needs explanation.
194
251
 
252
+ Version 3 scenes may include a directory Overview:
253
+
254
+ ```yaml
255
+ overview:
256
+ kind: directory-diff
257
+ path: web
258
+ ```
259
+
260
+ Keep `path` relative and POSIX-style; omit it or use `.` for the repository
261
+ root. Stacked and Deconstructed scenes may set `overview.comparison` to two
262
+ distinct stack-entry IDs or to `explanation-baseline` and
263
+ `explanation-stage-<stage-id>`. Walkthrough overviews always use the review's
264
+ base-to-head comparison and reject an explicit comparison.
265
+
266
+ Use the optional v3 top-level `review` block for evidence-linked concepts,
267
+ boundaries, tradeoffs, and unresolved questions instead of presenting open
268
+ questions as settled scene narration. Pin `review.baseOid` and `review.headOid`
269
+ to the resolved range. `concept`, `boundary`, and `tradeoff` items need at
270
+ least one link to a root authored walkthrough scene and step; a `question` may
271
+ have empty evidence but must provide `nextCheck`. Do not add an ad hoc `notes`
272
+ key. See `examples/bygone-history.bygone` for review notes and
273
+ `examples/navigation-lab.bygone.yaml` for independently authored v3 modes.
274
+
195
275
  Never emit generated line numbers or hunk indexes. Verify candidate snippets against the pinned object when uncertain:
196
276
 
197
277
  ```sh
@@ -220,7 +300,16 @@ Treat this as a required self-audit, not a claim the validator can prove. For ea
220
300
  - tests are connected to the behavior they prove;
221
301
  - connections express causal, contractual, data-flow, ordering, or proof relationships;
222
302
  - binary files and omitted patches are surfaced explicitly;
223
- - deconstructed tours contain no unqualified "Stage N" or "Step N" references, and comparison stages and navigable tour steps use distinct nouns;
303
+ - every Historical tour excludes synthetic deconstructed scenes, and every
304
+ Deconstructed tour contains at least one deconstructed scene;
305
+ - deconstructed stages cover every included change unit exactly once or record
306
+ an explicit exclusion, contain no unqualified "Stage N" or "Step N"
307
+ references, and keep comparison stages distinct from navigable tour steps;
308
+ - root deconstructed scenes have the required real stack and endpoint
309
+ walkthrough evidence, while mode-specific synthetic scenes do not claim
310
+ that evidence exists;
311
+ - v3 review-note OIDs match the resolved range and evidence links resolve to
312
+ authored root walkthrough steps;
224
313
  - the final step supplies proof or a clear reviewer conclusion.
225
314
 
226
315
  ## Always print the open command
@@ -268,7 +357,9 @@ Report:
268
357
  - the exact base and head OIDs;
269
358
  - the **open command** for the primary artifact (`bygone present --tour …`, `bygone review …`, `bygone --git-diff …`, etc.);
270
359
  - the source and compiled artifact paths;
271
- - authored chapter, scene, and step counts, plus compiled counts when the generated complete-change appendix changes them;
360
+ - authored root and Historical/Deconstructed chapter, scene, step, and stage
361
+ counts, plus compiled counts when generated complete-change or per-mode
362
+ scenes change them;
272
363
  - omitted or unread evidence;
273
364
  - validation and visual verification performed;
274
365
  - whether generated files are temporary, uncommitted, committed, or pushed.
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <meta http-equiv="Content-Security-Policy" content="default-src 'self'; base-uri 'none'; object-src 'none'; frame-src 'none'; form-action 'none'; img-src 'self' data:; font-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src 'self'; worker-src 'self' blob:;">
6
+ <meta http-equiv="Content-Security-Policy" content="default-src 'self'; base-uri 'none'; object-src 'none'; frame-src http://127.0.0.1:*; form-action 'none'; img-src 'self' data:; font-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src 'self'; worker-src 'self' blob:;">
7
7
  <title>Bygone</title>
8
8
  <link href="../media/webview.css" rel="stylesheet">
9
9
  </head>