@davmash/bygone 0.10.0 → 0.11.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/CHANGELOG.md +24 -0
- package/README.md +32 -0
- package/bin/bygone.js +8 -1
- package/cli/commandSpec.js +11 -2
- package/cli/completions.js +9 -8
- package/cli/correspondence.js +71 -0
- package/cli/present.js +74 -20
- package/cli/tour.js +8 -1
- package/cli/tourExport.js +1 -1
- package/completions/_bygone +5 -3
- package/completions/bygone +5 -5
- package/completions/bygone.fish +2 -0
- package/docs/change-tour-format.md +60 -6
- package/docs/correspondence.md +259 -0
- package/docs/generating-change-tours.md +3 -0
- package/docs/present.md +3 -0
- package/docs/releasing.md +11 -0
- package/media/diff.worker.js +10 -9
- package/media/webview.css +1 -1
- package/media/webview.js +178 -178
- package/out/changeCorrespondence.js +739 -0
- package/out/changeTour.js +1359 -960
- package/out/gitComparison.js +4 -0
- package/out/standalone-main.js +3279 -1341
- package/out/tourCoverage.js +1852 -1448
- package/package.json +2 -2
- package/schemas/change-tour-source.schema.json +48 -3
- package/web/export-runtime.json +6 -6
- package/web/index.html +12 -0
- package/web/presenter.css +81 -0
- package/web/web-host.js +23 -20
|
@@ -8,16 +8,16 @@ suffix, and explicitly supplied files are validated by content rather than
|
|
|
8
8
|
rejected by extension.
|
|
9
9
|
|
|
10
10
|
An authored source is Git-backed, not portable: resolving refs and anchors
|
|
11
|
-
requires the corresponding local repository and Git objects. Version 2, 4, and
|
|
11
|
+
requires the corresponding local repository and Git objects. Version 2, 4, 5, and 6
|
|
12
12
|
compiled manifests remain bound to that repository so the presenter can load
|
|
13
13
|
live file history. Version 1 manifests remain readable as legacy portable
|
|
14
14
|
artifacts, without the mode switcher. Version 4 supports independent authored
|
|
15
15
|
tours and scene directory overviews; versions 1 and 2 remain accepted without
|
|
16
16
|
those fields.
|
|
17
17
|
|
|
18
|
-
## Version
|
|
18
|
+
## Version stability and compatibility
|
|
19
19
|
|
|
20
|
-
Format version **
|
|
20
|
+
Format version **6** is the current authoring contract. Application and document
|
|
21
21
|
versions are separate; UI fixes do not require rewriting a tour.
|
|
22
22
|
|
|
23
23
|
| Document version | Reader support | Contract |
|
|
@@ -26,8 +26,9 @@ versions are separate; UI fixes do not require rewriting a tour.
|
|
|
26
26
|
| 2 | Supported | Repository-bound manifests, real revision stacks, and endpoint walkthroughs |
|
|
27
27
|
| 3 | Retired | Remove the top-level `review` block, set source `version: 4`, and recompile |
|
|
28
28
|
| 4 | Supported | Independent authored tours and scene directory overviews; no Review Notes |
|
|
29
|
-
| 5 |
|
|
30
|
-
|
|
|
29
|
+
| 5 | Supported | Optional opening, conclusion, and chapter previews; explicit overview purpose |
|
|
30
|
+
| 6 | Use for new sources | Optional pinned symbol comparisons in walkthrough stops |
|
|
31
|
+
| Greater than 6 | Rejected with an upgrade message | Never interpreted as version 6 |
|
|
31
32
|
|
|
32
33
|
Version 4 removes the `review` field and the separate Review Notes panel.
|
|
33
34
|
Concepts, boundaries, tradeoffs, and unresolved questions belong in scene or
|
|
@@ -49,7 +50,7 @@ does not prove that the source compiles. Validate against the intended local
|
|
|
49
50
|
repository before sharing a tour.
|
|
50
51
|
|
|
51
52
|
Keep authored YAML as the editable source. Compiled JSON is generated evidence,
|
|
52
|
-
not a second authoring syntax; v2/v4/v5 manifests retain repository identity and
|
|
53
|
+
not a second authoring syntax; v2/v4/v5/v6 manifests retain repository identity and
|
|
53
54
|
resolved Git objects. Stable format support does not make missing repositories
|
|
54
55
|
or pruned objects available, and does not promise byte-identical generated
|
|
55
56
|
timestamps or presentation layout. Pin full commit IDs in `range` when the
|
|
@@ -61,6 +62,59 @@ v3 rejection, removed-field rejection, and rejection of future versions. Run
|
|
|
61
62
|
`npm test` before releasing a parser, compiler, or schema change; update those
|
|
62
63
|
checks with any new contract.
|
|
63
64
|
|
|
65
|
+
## Symbol-focused stops
|
|
66
|
+
|
|
67
|
+
Version 6 adds an optional repository-relative `correspondence` artifact and a
|
|
68
|
+
`symbol` selector on walkthrough steps. Generate the artifact as described in
|
|
69
|
+
[Symbol correspondence evidence](correspondence.md), then use an accepted
|
|
70
|
+
relation ID or one unmatched symbol ID from its inventory:
|
|
71
|
+
|
|
72
|
+
```yaml
|
|
73
|
+
version: 6
|
|
74
|
+
correspondence: evidence/symbols.json
|
|
75
|
+
# Pin range.base and range.head to the artifact's comparison.
|
|
76
|
+
anchors:
|
|
77
|
+
moved-declaration:
|
|
78
|
+
file: src/moved.py
|
|
79
|
+
revision: head
|
|
80
|
+
contains: "def transfer("
|
|
81
|
+
# Within a walkthrough scene's steps:
|
|
82
|
+
# - id: transfer
|
|
83
|
+
# title: Read the moved declaration
|
|
84
|
+
# body: Compare the complete declaration before and after the move.
|
|
85
|
+
# focus: moved-declaration
|
|
86
|
+
# symbol: { relation: relation-transfer }
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The ordinary `focus` anchor remains required and must resolve inside the selected
|
|
90
|
+
declaration on its revision side. It preserves source navigation and existing
|
|
91
|
+
anchor validation. `symbol: { symbol: after-uncertain }` selects one unmatched
|
|
92
|
+
endpoint instead. IDs are unique across the artifact's symbol inventory; matched
|
|
93
|
+
endpoints must use their accepted relation ID. An ambiguous endpoint remains
|
|
94
|
+
one-sided, with no invented origin. Symbol stops cannot also use an image or
|
|
95
|
+
connection.
|
|
96
|
+
|
|
97
|
+
Compilation revalidates the artifact against the exact Git comparison and
|
|
98
|
+
embeds complete declaration text, source spans, revisions, and both full file
|
|
99
|
+
contexts. The source artifact path must stay inside the repository, including
|
|
100
|
+
through symlinks. Stale artifacts and selectors outside the chosen declaration
|
|
101
|
+
are errors. An accepted relation is still an inferred correspondence; behavior
|
|
102
|
+
remains unassessed.
|
|
103
|
+
|
|
104
|
+
The viewer opens the declaration comparison. **Show file context** widens to the
|
|
105
|
+
complete source and destination files, highlights both declarations, and keeps
|
|
106
|
+
the current tour stop. **Return to symbol comparison** restores the slices;
|
|
107
|
+
**Return to tour** restores the authored stop after exploring another file.
|
|
108
|
+
The compiled evidence also works in an offline HTML export without the artifact
|
|
109
|
+
or repository. Export packs repeated text once. Coverage counts only changed
|
|
110
|
+
units intersecting either selected declaration, or the single available endpoint
|
|
111
|
+
for an unmatched symbol; overlapping stops do not multiply coverage.
|
|
112
|
+
|
|
113
|
+
Existing sources and ordinary anchor stops keep their existing behavior. Live
|
|
114
|
+
presentations load the source's artifact into Symbols and Files automatically;
|
|
115
|
+
offline exports retain the selected stops and their context, rather than the
|
|
116
|
+
entire symbol inventory.
|
|
117
|
+
|
|
64
118
|
## Opening and conclusion passages
|
|
65
119
|
|
|
66
120
|
Version 5 adds optional `opening` and `conclusion` at the document root and
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
# Try symbol correspondence evidence
|
|
2
|
+
|
|
3
|
+
This experimental integration connects externally produced symbol mappings to
|
|
4
|
+
Bygone's authoring context and presentation viewer. It does not run a matcher
|
|
5
|
+
or model automatically. RefactoringMiner and Java remain optional external
|
|
6
|
+
research tools; neither is a new Bygone runtime dependency.
|
|
7
|
+
|
|
8
|
+
## Generate evidence in this checkout
|
|
9
|
+
|
|
10
|
+
The development command inventories changed JS/TS, Python, Java, Go, Rust, C#, Ruby, PHP, C, Lua and
|
|
11
|
+
Mojo regular files from committed
|
|
12
|
+
Git blobs, runs the bounded analysis adapter and imports its result into the
|
|
13
|
+
validated viewer format. It uses the review merge base, just like `present`;
|
|
14
|
+
working-tree edits are excluded. No second branch or saved research report is
|
|
15
|
+
required.
|
|
16
|
+
|
|
17
|
+
Start without Java:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
npm run correspondence:analyze -- feature --base main \
|
|
21
|
+
--output /tmp/correspondence.json
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
With no Java engine configuration, this inventories symbols and pairs only
|
|
25
|
+
unambiguous declarations with identical bytes. It records partial coverage:
|
|
26
|
+
edited or renamed declarations can remain unmatched, so unmatched does not
|
|
27
|
+
prove an addition or removal. Use `--exact-only` to choose this mode even when
|
|
28
|
+
Java engine environment variables are set.
|
|
29
|
+
|
|
30
|
+
To use the local Strand correspondence engine:
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
npm run correspondence:analyze -- feature --base main --engine bygone-strand \
|
|
34
|
+
--output /tmp/correspondence-strand.json
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Bygone Strand is an original declaration matcher in the private
|
|
38
|
+
[`bygone-strand` workspace package](../packages/strand/README.md). It supports
|
|
39
|
+
JS/TS, Python, Java, Go, Rust, C#, Ruby, PHP, C, Lua and experimental Mojo. TypeScript and isolated
|
|
40
|
+
CPython parsers retain their existing behavior; the other languages share a
|
|
41
|
+
bounded Tree-sitter WASM frontend with pinned, locally shipped grammars. Scoped
|
|
42
|
+
declaration identities and syntax/token similarity infer edited continuations,
|
|
43
|
+
moves and renames. Strand requires no JVM, native addon or runtime downloads. The explicit selection ignores ambient Java configuration and
|
|
44
|
+
cannot be combined with `--exact-only` or Java flags. The default mode is
|
|
45
|
+
unchanged. See [the engine contract](../scripts/change-analysis/javascript-engine.md)
|
|
46
|
+
for evidence, ambiguity and resource limits.
|
|
47
|
+
|
|
48
|
+
This version produces one-to-one continuations. Extraction/inline detection,
|
|
49
|
+
binding resolution, editing history and behavior preservation are unassessed.
|
|
50
|
+
Python functions, async functions, classes, methods and nested declarations
|
|
51
|
+
support inferred edits and moves. Decorators and complete source diffs remain
|
|
52
|
+
visible. Python `.pyi` stubs retain inventory/exact matching only.
|
|
53
|
+
|
|
54
|
+
Go receiver and Rust impl/trait identities are conservative: receiver/type
|
|
55
|
+
renames are not inferred across owners. Mojo (`.mojo`/`.🔥`) uses a pinned
|
|
56
|
+
community grammar and remains experimental; legacy `fn` syntax is unsupported.
|
|
57
|
+
See the [package coverage and exclusions](../packages/strand/README.md) and
|
|
58
|
+
[grammar provenance](../packages/strand/src/grammars/README.md) for exact scope.
|
|
59
|
+
Parser errors/timeouts fail closed, and duplicate origins remain ambiguous.
|
|
60
|
+
`npm run test:strand` runs package and artifact integration checks.
|
|
61
|
+
|
|
62
|
+
For broader inference, build the pinned external engine following
|
|
63
|
+
[scripts/change-analysis/README.md](../scripts/change-analysis/README.md), then
|
|
64
|
+
supply its verified build digest and JDK explicitly:
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
export MAPPING_JAVA=/absolute/path/to/jdk/bin/java
|
|
68
|
+
export MAPPING_JAR=/absolute/path/to/RefactoringMiner/build/libs/RM-fat.jar
|
|
69
|
+
export MAPPING_JAR_SHA256=<verified-build-sha256>
|
|
70
|
+
npm run correspondence:analyze -- feature --base main \
|
|
71
|
+
--output /tmp/correspondence.json
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Use `--repo /absolute/path/to/checkout` to analyze another repository without
|
|
75
|
+
copying its source into this one. `--java`, `--jar` and `--jar-sha256` override
|
|
76
|
+
the environment. Supply all three engine settings together; incomplete settings,
|
|
77
|
+
unavailable/incompatible toolchains and digest mismatches fail instead of silently
|
|
78
|
+
switching modes. The adapter needs a JDK 21+ with sibling `java` and `javac`
|
|
79
|
+
(verified with JDK 21). `--exact-only` cannot be combined with Java engine flags.
|
|
80
|
+
Python comparisons additionally use `--python` or
|
|
81
|
+
`MAPPING_PYTHON` (default `python3`), CPython 3.8+ with syntax support determined
|
|
82
|
+
by that interpreter. Named Python functions/classes/methods include decorators
|
|
83
|
+
and attached terminal comments; lambdas and variable bindings are excluded.
|
|
84
|
+
Python `.pyi` files have inventory/exact matching only and explicitly mark the
|
|
85
|
+
comparison partial because the pinned engine does not parse them. Validated
|
|
86
|
+
matches between analyzed implementation declarations can still be accepted.
|
|
87
|
+
|
|
88
|
+
The output must be a new file. Import creates it exclusively and refuses an
|
|
89
|
+
existing path, including the producer report itself and symlink or hardlink
|
|
90
|
+
aliases. It never overwrites existing bytes; choose another output path.
|
|
91
|
+
Artifacts contain source text;
|
|
92
|
+
keep private repositories' evidence outside this repository.
|
|
93
|
+
|
|
94
|
+
When presenting a tour, an authored `source.correspondence` path and an
|
|
95
|
+
explicit `--correspondence` path must identify the same actual file. Symlink
|
|
96
|
+
and hardlink aliases are accepted, but a separate copy with identical bytes is
|
|
97
|
+
still a different artifact and is rejected before the manifest output or server
|
|
98
|
+
is created.
|
|
99
|
+
|
|
100
|
+
Changed files bound the candidate universe: unchanged files, unsupported
|
|
101
|
+
languages, symlinks and submodules are excluded. The artifact records this
|
|
102
|
+
scope, the engine/bridge digests, parser version, limits and failure reason.
|
|
103
|
+
Engine/bridge digests are present only when that engine is configured.
|
|
104
|
+
Timeout, truncation or process failure produces explicitly partial evidence;
|
|
105
|
+
only independent exact declarations can survive. Invalid source encoding or
|
|
106
|
+
an input budget violation fails without writing an artifact. A comparison with
|
|
107
|
+
no supported source documents is explicitly unavailable.
|
|
108
|
+
|
|
109
|
+
Generation currently runs from a source checkout with development dependencies.
|
|
110
|
+
Java and RefactoringMiner are explicit external tools, not npm
|
|
111
|
+
`optionalDependencies`: npm does not install their toolchain, and Bygone does not
|
|
112
|
+
bundle or download them. Python is needed only to generate Python inventories.
|
|
113
|
+
Viewing/importing saved evidence and opening symbol tour stops needs neither
|
|
114
|
+
Java nor Python. This keeps engine size, native parser support and runtime updates
|
|
115
|
+
outside the viewer's installation path; optional does not imply reduced evidence
|
|
116
|
+
is equivalent to a complete engine result.
|
|
117
|
+
|
|
118
|
+
## Import an existing report
|
|
119
|
+
|
|
120
|
+
Normalized reports may contain one `analysis` or a `cases` array. Select a case
|
|
121
|
+
explicitly when importing a batch:
|
|
122
|
+
|
|
123
|
+
```sh
|
|
124
|
+
bygone correspondence import mappings.json feature --base main \
|
|
125
|
+
--case module-split --output /tmp/imported-correspondence.json
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
The import resolves the selected review's merge-base/head to immutable commit
|
|
129
|
+
IDs. It checks every supplied document digest, symbol span and symbol digest
|
|
130
|
+
against those Git blobs, resolves endpoints uniquely, rejects conflicting or
|
|
131
|
+
ambiguous accepted continuations, and recomputes complete declaration diffs.
|
|
132
|
+
Producer-supplied quotations, line numbers, local diffs and equality flags are
|
|
133
|
+
not trusted. The artifact records analysis status, supplied document scope,
|
|
134
|
+
producer, unmatched counts, syntax exclusions and competing origins.
|
|
135
|
+
|
|
136
|
+
Only the selected producer case's supplied scope is checked. Source integrity
|
|
137
|
+
checks do not independently adjudicate the producer's symbol identities,
|
|
138
|
+
parsing, completeness or semantic claims. All mappings remain inferred and
|
|
139
|
+
behavior remains unassessed. Partial analysis suppresses engine-only mappings
|
|
140
|
+
unless the producer explicitly records complete search coverage for that pair.
|
|
141
|
+
The adapter permits this for analyzed implementations when only stubs are
|
|
142
|
+
skipped, or unique same-file/scope/name continuations when skipped implementation
|
|
143
|
+
files are unchanged. Skipped changed implementations, invalid parsing, engine
|
|
144
|
+
failure and truncation still prevent that claim. Import rejects complete pair
|
|
145
|
+
coverage from a failed or truncated engine; saved artifacts preserve the claim
|
|
146
|
+
and revalidate source bytes and endpoints. This remains producer-supplied search
|
|
147
|
+
evidence, not independently established lineage. Older partial artifacts without
|
|
148
|
+
pair coverage retain the exact-only guard. Independent exact-declaration
|
|
149
|
+
evidence can remain available. Extraction/inline
|
|
150
|
+
groups expose their endpoints in Analysis details; they are not accepted continuations.
|
|
151
|
+
|
|
152
|
+
Exact matching first checks unique same-file, same-scope, same-name bindings
|
|
153
|
+
with identical declaration bytes and binding context. Repeated constants in
|
|
154
|
+
different files can therefore retain their local continuations. Cross-scope
|
|
155
|
+
matching still considers all identical occurrences, including retained sources;
|
|
156
|
+
remaining competing origins are reported for variables as well as callables.
|
|
157
|
+
Local evidence does not override a conflicting engine candidate.
|
|
158
|
+
|
|
159
|
+
## Use the same artifact in both places
|
|
160
|
+
|
|
161
|
+
```sh
|
|
162
|
+
bygone tour context feature --base main \
|
|
163
|
+
--correspondence /tmp/correspondence.json --output /tmp/context.json
|
|
164
|
+
bygone present feature --base main --correspondence /tmp/correspondence.json
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
No authored `.bygone` file is required. In the viewer, select **Symbols**, filter
|
|
168
|
+
by name or path, and select a mapping to compare its complete old and new
|
|
169
|
+
source symbol slices, including edits within moved code. Variable slices can
|
|
170
|
+
exclude enclosing export/const/let syntax; inspect the complete file for that
|
|
171
|
+
context and for surrounding binding/import changes. The labels identify
|
|
172
|
+
both paths, source lines and revisions. Editor line numbers are relative to
|
|
173
|
+
the declaration slice. **Show file context** opens complete source and destination
|
|
174
|
+
files and highlights the declarations at their original lines, including moves
|
|
175
|
+
between files. **Return to symbol comparison** restores the declaration slices.
|
|
176
|
+
The **Files** rail also nests the same filtered symbol tree beneath each file.
|
|
177
|
+
Use the arrow on the right of a file (**Show Symbols** on hover) to reveal or
|
|
178
|
+
hide its symbols directly underneath. Each file starts folded and keeps its own
|
|
179
|
+
expansion state; selecting files, symbols, or tour stops does not change it.
|
|
180
|
+
Symbol names use green for after-only declarations, red for before-only declarations,
|
|
181
|
+
and amber for accepted mappings with edits, moves, renames, or reparenting. Ambiguous
|
|
182
|
+
origins and unchanged declarations stay neutral. One-sided colors describe the
|
|
183
|
+
inventory; they do not confirm additions or deletions.
|
|
184
|
+
Symbols and Files share selection; both endpoints of a move are highlighted.
|
|
185
|
+
Selecting a file opens its complete diff without advancing the tour.
|
|
186
|
+
Symbols groups declarations by file and nests classes, methods and functions
|
|
187
|
+
using their source ranges. Expand or collapse branches with the disclosure
|
|
188
|
+
buttons (also keyboard accessible). The default filter includes moved, renamed,
|
|
189
|
+
edited and unmatched declarations. **Include added or removed local symbols**
|
|
190
|
+
is checked by default; uncheck it to hide before-only and after-only declarations
|
|
191
|
+
without accepted matches, including ambiguous endpoints. These are not confirmed
|
|
192
|
+
additions or deletions. Enable **Include unchanged local symbols** to also show
|
|
193
|
+
unchanged matched declarations. Search retains ancestor paths and opens
|
|
194
|
+
matching branches. Ancestors retained only for context are dimmed.
|
|
195
|
+
Moved or reparented declarations appear at both locations; the old location is
|
|
196
|
+
labeled **Before location** and opens the same before/after comparison. Counts
|
|
197
|
+
include each accepted mapping once. **Before only**, **After only** and
|
|
198
|
+
**Ambiguous** entries have no accepted match; selecting one shows its available
|
|
199
|
+
source slice, without claiming a confirmed addition or deletion.
|
|
200
|
+
Open **Analysis details** for separate counts and expandable records for paths
|
|
201
|
+
outside analysis, syntax not inventoried, rejected engine containers, unmatched
|
|
202
|
+
symbols and competing origins, other relationships, and analysis problems.
|
|
203
|
+
Records retain reported reasons, revision sides and source locations. Links open
|
|
204
|
+
complete file context or inventoried symbols, including unchanged declarations;
|
|
205
|
+
symbol links clear search and enable both include options.
|
|
206
|
+
Ambiguous groups link every competing endpoint without picking an origin.
|
|
207
|
+
Invalid producer ranges retain paths without trusted offsets. A missing candidate
|
|
208
|
+
is distinguished from a rejected candidate; when the producer gives no explanation,
|
|
209
|
+
the viewer says so. Categories overlap, use explicit units and are not a coverage
|
|
210
|
+
percentage. Unchanged files outside a changed-file search are described as a scope
|
|
211
|
+
limit, not enumerated as missing symbols. Older artifacts retain their summaries
|
|
212
|
+
and show **Detailed diagnostics unavailable** rather than zero diagnostic counts.
|
|
213
|
+
The status always names the artifact's pinned base/head, even when exploring
|
|
214
|
+
other history comparisons. An uploaded tour does not inherit this evidence.
|
|
215
|
+
|
|
216
|
+
Both consumers revalidate the artifact against their selected comparison.
|
|
217
|
+
Advancing a branch does not silently reuse old evidence: a different head or
|
|
218
|
+
merge base requires a new import. Context's ordinary patches, counts and limits
|
|
219
|
+
are unchanged; correspondence is a separate optional field with its own
|
|
220
|
+
budgets (16 MiB artifact, 128 documents per side, 1 MiB per Git blob, 8 MiB total
|
|
221
|
+
source and 8 MiB total symbol text). Nested symbols overlap, so their diffs
|
|
222
|
+
must not be summed as coverage or subtracted from changed-line accounting.
|
|
223
|
+
For a declaration diff exceeding the comparison effort budget, its entire old
|
|
224
|
+
and new slices are retained as removal/addition rather than omitting content.
|
|
225
|
+
|
|
226
|
+
## Use symbols in authored tours
|
|
227
|
+
|
|
228
|
+
Version 6 walkthrough steps can select an accepted relation or one unmatched
|
|
229
|
+
symbol from a source's `correspondence` artifact. The compiler pins declaration
|
|
230
|
+
text and full file context into each stop, preserving one-sided ambiguous
|
|
231
|
+
endpoints. See [Symbol-focused stops](change-tour-format.md#symbol-focused-stops)
|
|
232
|
+
for the source contract, validation, coverage, and offline behavior.
|
|
233
|
+
|
|
234
|
+
## Run this checkout's real example
|
|
235
|
+
|
|
236
|
+
With the explicit engine environment above:
|
|
237
|
+
|
|
238
|
+
```sh
|
|
239
|
+
npm run correspondence:analyze -- 726796b1fe --base '726796b1fe^' \
|
|
240
|
+
--output /tmp/bygone-correspondence.json
|
|
241
|
+
BYGONE_FORCE_BUNDLED=1 node bin/bygone.js present 726796b1fe \
|
|
242
|
+
--base '726796b1fe^' --correspondence /tmp/bygone-correspondence.json
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Search for `validateChangeTourDetails`. The declaration comparison retains the
|
|
246
|
+
removed `validateAssessment(...)` call, removed context parameter and changed
|
|
247
|
+
allowed-key list. The artifact includes six moved functions and other inferred
|
|
248
|
+
continuations. `BYGONE_FORCE_BUNDLED=1` selects the newly built checkout instead
|
|
249
|
+
of an older installed desktop application.
|
|
250
|
+
|
|
251
|
+
`npm run test:correspondence` runs the source/CLI/server checks and an Electron
|
|
252
|
+
browser smoke using a portable fixture taken from that real module split.
|
|
253
|
+
This slice does not construct intermediate refactoring stages, hide raw edits,
|
|
254
|
+
add model annotations, or establish reviewer benefit.
|
|
255
|
+
|
|
256
|
+
`npm run test:correspondence:engine` uses the same explicit engine environment.
|
|
257
|
+
It runs the adapter tests, Git snapshot tests, real JVM timeout/truncation/output
|
|
258
|
+
failure checks, Python ranges/moves/renames and fresh module-split generation accepted by the viewer's
|
|
259
|
+
consumer. Large archived reports and evaluations stay on the research branch.
|
|
@@ -176,3 +176,6 @@ matters. A new scene or file does not inherently mean a new comparison. Close
|
|
|
176
176
|
by connecting the mechanism back to the promised behavior and stating material
|
|
177
177
|
limits, rather than reciting the chapter titles. Include any remaining checks without adding
|
|
178
178
|
fake code stops. See [the format](change-tour-format.md) for the fields.
|
|
179
|
+
|
|
180
|
+
For experimental revision-pinned symbol evidence in authoring context and the
|
|
181
|
+
viewer, see [symbol correspondence](correspondence.md).
|
package/docs/present.md
CHANGED
|
@@ -289,3 +289,6 @@ revisions or constructed stages; a chapter or scene boundary does not itself
|
|
|
289
289
|
mean the comparison changed. Intro, chapter, and Conclusion passages fill the
|
|
290
290
|
reading area. Exploring Files restores the prose/code split, and “Return to
|
|
291
291
|
passage” restores the full-height passage.
|
|
292
|
+
|
|
293
|
+
For experimental revision-pinned symbol evidence in authoring context and the
|
|
294
|
+
viewer, see [symbol correspondence](correspondence.md).
|
package/docs/releasing.md
CHANGED
|
@@ -82,6 +82,17 @@ Related packaging commands:
|
|
|
82
82
|
|
|
83
83
|
Before publishing, verify:
|
|
84
84
|
|
|
85
|
+
### Packaging dependency override
|
|
86
|
+
|
|
87
|
+
The development toolchain scopes an `@azure/msal-node` 7.1.0 override to
|
|
88
|
+
`@azure/identity`, which is used by `@vscode/vsce`. The version requested by
|
|
89
|
+
Azure Identity is affected by
|
|
90
|
+
[GHSA-xcx6-jx8p-x3h5](https://github.com/advisories/GHSA-xcx6-jx8p-x3h5).
|
|
91
|
+
Remove the override once Azure Identity requests a patched version. Local
|
|
92
|
+
credential construction and VSIX packaging are checked; interactive Azure
|
|
93
|
+
authentication still requires a separate authenticated check before publishing
|
|
94
|
+
through that flow. This dependency is not bundled into the shipped extension.
|
|
95
|
+
|
|
85
96
|
## Accounts You Need
|
|
86
97
|
|
|
87
98
|
You need accounts on three services:
|
package/media/diff.worker.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
"use strict";(()=>{function C(){}C.prototype={diff:function(e,t){var
|
|
2
|
-
`));var e=[],t=n.split(/(\n|\r\n)/);t[t.length-1]||t.pop();for(var
|
|
1
|
+
"use strict";(()=>{function C(){}C.prototype={diff:function(e,t){var i,o=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},r=o.callback;typeof o=="function"&&(r=o,o={}),this.options=o;var s=this;function l(x){return r?(setTimeout(function(){r(void 0,x)},0),!0):x}e=this.castInput(e),t=this.castInput(t),e=this.removeEmpty(this.tokenize(e)),t=this.removeEmpty(this.tokenize(t));var d=t.length,u=e.length,f=1,a=d+u;o.maxEditLength&&(a=Math.min(a,o.maxEditLength));var v=(i=o.timeout)!==null&&i!==void 0?i:1/0,m=Date.now()+v,p=[{oldPos:-1,lastComponent:void 0}],c=this.extractCommon(p[0],t,e,0);if(p[0].oldPos+1>=u&&c+1>=d)return l([{value:this.join(t),count:t.length}]);var h=-1/0,g=1/0;function b(){for(var x=Math.max(h,-f);x<=Math.min(g,f);x+=2){var y=void 0,I=p[x-1],w=p[x+1];I&&(p[x-1]=void 0);var N=!1;if(w){var E=w.oldPos-x;N=w&&0<=E&&E<d}var T=I&&I.oldPos+1<u;if(!N&&!T){p[x]=void 0;continue}if(!T||N&&I.oldPos+1<w.oldPos?y=s.addToPath(w,!0,void 0,0):y=s.addToPath(I,void 0,!0,1),c=s.extractCommon(y,t,e,x),y.oldPos+1>=u&&c+1>=d)return l(We(s,y.lastComponent,t,e,s.useLongestToken));p[x]=y,y.oldPos+1>=u&&(g=Math.min(g,x-1)),c+1>=d&&(h=Math.max(h,x+1))}f++}if(r)(function x(){setTimeout(function(){if(f>a||Date.now()>m)return r();b()||x()},0)})();else for(;f<=a&&Date.now()<=m;){var S=b();if(S)return S}},addToPath:function(e,t,i,o){var r=e.lastComponent;return r&&r.added===t&&r.removed===i?{oldPos:e.oldPos+o,lastComponent:{count:r.count+1,added:t,removed:i,previousComponent:r.previousComponent}}:{oldPos:e.oldPos+o,lastComponent:{count:1,added:t,removed:i,previousComponent:r}}},extractCommon:function(e,t,i,o){for(var r=t.length,s=i.length,l=e.oldPos,d=l-o,u=0;d+1<r&&l+1<s&&this.equals(t[d+1],i[l+1]);)d++,l++,u++;return u&&(e.lastComponent={count:u,previousComponent:e.lastComponent}),e.oldPos=l,d},equals:function(e,t){return this.options.comparator?this.options.comparator(e,t):e===t||this.options.ignoreCase&&e.toLowerCase()===t.toLowerCase()},removeEmpty:function(e){for(var t=[],i=0;i<e.length;i++)e[i]&&t.push(e[i]);return t},castInput:function(e){return e},tokenize:function(e){return e.split("")},join:function(e){return e.join("")}};function We(n,e,t,i,o){for(var r=[],s;e;)r.push(e),s=e.previousComponent,delete e.previousComponent,e=s;r.reverse();for(var l=0,d=r.length,u=0,f=0;l<d;l++){var a=r[l];if(a.removed){if(a.value=n.join(i.slice(f,f+a.count)),f+=a.count,l&&r[l-1].added){var m=r[l-1];r[l-1]=r[l],r[l]=m}}else{if(!a.added&&o){var v=t.slice(u,u+a.count);v=v.map(function(c,h){var g=i[f+h];return g.length>c.length?g:c}),a.value=n.join(v)}else a.value=n.join(t.slice(u,u+a.count));u+=a.count,a.added||(f+=a.count)}}var p=r[d-1];return d>1&&typeof p.value=="string"&&(p.added||p.removed)&&n.equals("",p.value)&&(r[d-2].value+=p.value,r.pop()),r}var $e=new C;function de(n,e,t){return $e.diff(n,e,t)}var ue=/^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/,ce=/\S/,Q=new C;Q.equals=function(n,e){return this.options.ignoreCase&&(n=n.toLowerCase(),e=e.toLowerCase()),n===e||this.options.ignoreWhitespace&&!ce.test(n)&&!ce.test(e)};Q.tokenize=function(n){for(var e=n.split(/([^\S\r\n]+|[()[\]{}'"\r\n]|\b)/),t=0;t<e.length-1;t++)!e[t+1]&&e[t+2]&&ue.test(e[t])&&ue.test(e[t+2])&&(e[t]+=e[t+2],e.splice(t+1,2),t--);return e};function ge(n,e,t){return Q.diff(n,e,t)}var he=new C;he.tokenize=function(n){this.options.stripTrailingCr&&(n=n.replace(/\r\n/g,`
|
|
2
|
+
`));var e=[],t=n.split(/(\n|\r\n)/);t[t.length-1]||t.pop();for(var i=0;i<t.length;i++){var o=t[i];i%2&&!this.options.newlineIsToken?e[e.length-1]+=o:(this.options.ignoreWhitespace&&(o=o.trim()),e.push(o))}return e};var Be=new C;Be.tokenize=function(n){return n.split(/(\S.+?[.!?])(?=\s+|$)/)};var Ge=new C;Ge.tokenize=function(n){return n.split(/([{}:;,]|\s+)/)};function U(n){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?U=function(e){return typeof e}:U=function(e){return e&&typeof Symbol=="function"&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},U(n)}var Ue=Object.prototype.toString,W=new C;W.useLongestToken=!0;W.tokenize=he.tokenize;W.castInput=function(n){var e=this.options,t=e.undefinedReplacement,i=e.stringifyReplacer,o=i===void 0?function(r,s){return typeof s>"u"?t:s}:i;return typeof n=="string"?n:JSON.stringify(Z(n,null,null,o),o," ")};W.equals=function(n,e){return C.prototype.equals.call(W,n.replace(/,([\r\n])/g,"$1"),e.replace(/,([\r\n])/g,"$1"))};function Z(n,e,t,i,o){e=e||[],t=t||[],i&&(n=i(o,n));var r;for(r=0;r<e.length;r+=1)if(e[r]===n)return t[r];var s;if(Ue.call(n)==="[object Array]"){for(e.push(n),s=new Array(n.length),t.push(s),r=0;r<n.length;r+=1)s[r]=Z(n[r],e,t,i,o);return e.pop(),t.pop(),s}if(n&&n.toJSON&&(n=n.toJSON()),U(n)==="object"&&n!==null){e.push(n),s={},t.push(s);var l=[],d;for(d in n)n.hasOwnProperty(d)&&l.push(d);for(l.sort(),r=0;r<l.length;r+=1)d=l[r],s[d]=Z(n[d],e,t,i,d);e.pop(),t.pop()}else s=n;return s}var z=new C;z.tokenize=function(n){return n.slice()};z.join=z.removeEmpty=function(n){return n};function ee(n,e,t){return z.diff(n,e,t)}var Pe=2e4,qe=100,j=Fe("BYGONE_MAX_INLINE_HIGHLIGHT_LINE_LENGTH",Pe),Re=Fe("BYGONE_DIFF_TIMEOUT_MS",qe);function Te(n,e,t={}){let i=ve(n),o=ve(e);if(n===e)return pe(i);if(i.length===o.length&&i.every((m,p)=>m===o[p])){let m=pe(i),p=n.match(/[^\n]*\n|[^\n]+$/g)||[],c=e.match(/[^\n]*\n|[^\n]+$/g)||[];return i.forEach((h,g)=>{p[g]!==c[g]&&(m.leftLines[g].kind=m.rows[g].left.kind="removed",m.rightLines[g].kind=m.rows[g].right.kind="added",m.leftLines[g].inlineDetail=m.rightLines[g].inlineDetail="line-ending",m.blocks.push($("replace",g,g+1,g,g+1)))}),m.blocks=me(m.blocks),m.hasChanges=!0,m.formattingOnly=!0,m}let r=Xe(i,o,t.timeoutMs??Re);if(!r)return Ye(i,o);let s=[],l=[],d=[],u=[],f=1,a=1;for(let m=0;m<r.length;m++){let p=r[m],c=p.removed?p.value:[],h=p.added?p.value:[];if(!p.added&&!p.removed){for(let g of p.value)l.push(R("context",g,f)),d.push(R("context",g,a)),s.push(k(A("context",g,f++),A("context",g,a++)));continue}if(p.removed&&m+1<r.length&&r[m+1].added){let g=r[m+1],b=Ke(c,g.value,f,a,s,l,d,u);f=b.left,a=b.right,m++;continue}if(p.removed){let g=l.length,b=d.length;for(let S of c)l.push(R("removed",S,f)),s.push(k(A("removed",S,f++),H()));u.push($("delete",g,l.length,b,d.length));continue}if(p.added){let g=l.length,b=d.length;for(let S of h)d.push(R("added",S,a)),s.push(k(H(),A("added",S,a++)));u.push($("insert",g,l.length,b,d.length))}}let v=s.some(m=>m.left.kind!=="context"||m.right.kind!=="context");return Ce({rows:s,leftLines:l,rightLines:d,blocks:me(u),reflows:u.filter(m=>m.reflow),hasChanges:v,quality:"exact"})}function Ce(n){for(let e of n.blocks)if(e.kind==="replace")for(let t of["left","right"])for(let i=e[`${t}Start`];i<e[`${t}End`];i++){let o=n[`${t}Lines`][i];o.kind!=="context"&&!o.segments&&(o.inlineDetail="omitted")}return n}function me(n){let e=[],t=!1;for(let o of n){let r=o.kind!=="replace",s=e[e.length-1];r&&t&&s.leftEnd===o.leftStart&&s.rightEnd===o.rightStart?(s.leftEnd=o.leftEnd,s.rightEnd=o.rightEnd,s.leftEnd>s.leftStart&&s.rightEnd>s.rightStart&&(s.kind="replace")):e.push({...o}),t=r}let i=[];for(let o of e){let r={...o};delete r.reflow;let s=i[i.length-1];s?.kind===r.kind&&s.leftEnd===r.leftStart&&s.rightEnd===r.rightStart?(s.leftEnd=r.leftEnd,s.rightEnd=r.rightEnd):i.push(r)}return i}function Xe(n,e,t){let i=Date.now()+t,o=p=>p.flatMap((c,h)=>{let g=M(c);return O(g)?[{key:g,index:h}]:[]}),r=o(n),s=o(e),l=ee(r.map(p=>p.key),s.map(p=>p.key),{timeout:i-Date.now()});if(!l)return;let d=[],u=0,f=0,a=(p,c)=>{if(u===p&&f===c)return!0;let h=je(n.slice(u,p),e.slice(f,c)),g=ee(h.left,h.right,{timeout:i-Date.now()});return g?(d.push(...g.map(b=>({...b,value:b.value.map(S=>h.lines[S])}))),!0):!1},v=0,m=0;for(let p of l){if(p.removed){v+=p.value.length;continue}if(p.added){m+=p.value.length;continue}for(let c=0;c<p.value.length;c++){let h=r[v++].index,g=s[m++].index;if(!a(h,g))return;let b=n[h],S=e[g];b===S?d.push({value:[b]}):d.push({removed:!0,value:[b]},{added:!0,value:[S]}),u=h+1,f=g+1}}return a(n.length,e.length)?d:void 0}function je(n,e){let t=new Map,i=[],o=r=>{let s=t.get(r);if(s!==void 0)return s;let l=i.length;return t.set(r,l),i.push(r),l};return{left:n.map(o),right:e.map(o),lines:i}}function pe(n){return{rows:n.map((e,t)=>k(A("context",e,t+1),A("context",e,t+1))),leftLines:n.map((e,t)=>R("context",e,t+1)),rightLines:n.map((e,t)=>R("context",e,t+1)),blocks:[],hasChanges:!1,quality:"exact"}}function Ye(n,e){let t=n.map((s,l)=>R("removed",s,l+1)),i=e.map((s,l)=>R("added",s,l+1)),o=[...n.map((s,l)=>k(A("removed",s,l+1),H())),...e.map((s,l)=>k(H(),A("added",s,l+1)))],r="replace";return n.length===0?r="insert":e.length===0&&(r="delete"),Ce({rows:o,leftLines:t,rightLines:i,blocks:o.length===0?[]:[$(r,0,n.length,0,e.length)],hasChanges:o.length>0,quality:"fallback"})}function ve(n){if(n.length===0)return[];let e=n.replace(/\r\n/g,`
|
|
3
3
|
`).split(`
|
|
4
|
-
`);return e[e.length-1]===""&&e.pop(),e}function
|
|
4
|
+
`);return e[e.length-1]===""&&e.pop(),e}function Ke(n,e,t,i,o,r,s,l){let d=K(n,e),u=d.filter(w=>w.left!==void 0&&w.right!==void 0&&re(w.left,w.right)).length,f=!d.some(w=>w.reflow)&&Je(n,e,u),a=d.flatMap(w=>w.reflow||w.left===void 0||w.right===void 0||re(w.left,w.right)?[w]:[{left:w.left},{right:w.right}]),v=[];for(let w=0;w<a.length;){let N=a[w];if(N.reflow||N.left!==void 0&&N.right!==void 0){v.push(N),w++;continue}let E=w;for(;w<a.length&&!a[w].reflow&&(a[w].left===void 0||a[w].right===void 0);)w++;let T=a.slice(E,w),L=T.filter(F=>F.left!==void 0),D=T.filter(F=>F.right!==void 0);if(L.length===1&&D.length===1)v.push({left:L[0].left,right:D[0].right});else for(let F of T)v.push(F)}let m=t,p=i,c=[],h=[],g=()=>{wn(c,h),c=[],h=[]},b,S=!1,x=r.length,y=s.length,I=()=>{if(!b)return;let w=$(b,x,r.length,y,s.length);S&&(w.reflow=!0),l.push(w)};for(let{left:w,right:N,reflow:E}of v){(E||w!==void 0&&N!==void 0)&&g();let T=f||E||w!==void 0&&N!==void 0?"replace":w!==void 0?"delete":"insert";(b!==T||S!==!!E||E?.start)&&(I(),b=T,S=!!E,x=r.length,y=s.length);let L,D;w!==void 0&&(L=R("removed",w,m),r.push(L)),N!==void 0&&(D=R("added",N,p),s.push(D)),E?(L&&(L.segments=E.leftSegments),D&&(D.segments=E.rightSegments)):L&&D?bn(L,D):f&&(L&&Ae(L),D&&Ae(D)),!E&&(w===void 0||N===void 0)&&(L&&c.push(L),D&&h.push(D)),o.push(k(w===void 0?H():A("removed",w,m++),N===void 0?H():A("added",N,p++)))}return I(),g(),{left:m,right:p}}function re(n,e){if(!n.trim()&&!e.trim()||J(n,e).eligible)return!0;let i=B(n);if(i&&i===B(e))return!0;let o=new Set(G(M(n)).filter(be));return G(M(e)).some(r=>o.has(r)&&be(r))}var Ve=new Set(["and","are","for","from","into","that","the","this","to","with"]);function be(n){return n.length>=3&&/^[\p{L}\p{N}_$]+$/u.test(n)&&!Ve.has(n)}function Je(n,e,t){if(t===0)return!1;let i=Math.max(n.length,e.length);if(i<=2||t*2>=i)return!0;let o=[...n,...e].map(Ze);return o[0]!==null&&o.every(r=>r===o[0])}function Ze(n){let e=n.trimStart();return/^[-*+]\s+/.test(e)?"bullet":/^\d+[.)]\s+/.test(e)?"ordered":/^>\s+/.test(e)?"quote":null}var ke=1e4,ie=2e3,Qe=.52,en=.35,_e=.38,nn=.33,Oe=.86,Y=.08,P=.05,q=-.12,we=5e3,tn=2e3,rn=5e7,Se=4,on=8,ne=4;function xe(n){let e=[];for(let t=0;t<n.length;t++){let i=n[t],o=[i],r=i.match(/^(\s*)(?:[\w-]+:\s+|[-*+]\s+)(\S.*)$/);if(r&&!/^[|>\[{]/.test(r[2]))for(;t+1<n.length;){let s=n[t+1];if(!s.trim()||s.length-s.trimStart().length<=r[1].length||/^\s*(?:[\w-]+:|[-*+]\s|\d+[.)]\s|#)/.test(s))break;o.push(s),t++}e.push(o.join(`
|
|
5
5
|
`))}return e}function K(n,e){if([...n,...e].some(o=>o.includes(`
|
|
6
|
-
`)))return
|
|
6
|
+
`)))return te(n,e);let t=xe(n),i=xe(e);return t.length===n.length&&i.length===e.length?te(n,e):te(t,i).flatMap(o=>{let r=o.left?.split(`
|
|
7
7
|
`)||[],s=o.right?.split(`
|
|
8
|
-
`)||[];if(!
|
|
9
|
-
`))){let
|
|
8
|
+
`)||[];if(!r.length||!s.length)return[...r.map(a=>({left:a})),...s.map(a=>({right:a}))];if(r.length===1&&s.length===1)return[o];let d=ae(o.left,o.right)||fe(o.left,o.right),u=d&&_(d.leftSegments),f=d&&_(d.rightSegments);return Array.from({length:Math.max(r.length,s.length)},(a,v)=>({left:r[v],right:s[v],reflow:{start:v===0,leftSegments:u?.[v],rightSegments:f?.[v]}}))})}function te(n,e){if(n.length===0)return e.map(c=>({right:c}));if(e.length===0)return n.map(c=>({left:c}));let t=0;for(;t<Math.min(n.length,e.length)&&n[t].trim()===e[t].trim();)t++;if(t)return[...n.slice(0,t).map((c,h)=>({left:c,right:e[h]})),...K(n.slice(t),e.slice(t))];let i=1,o=1,r=n[0].trim().replace(/\s+/g," "),s=e[0].trim().replace(/\s+/g," ");for(;r&&s&&r!==s;)if(s.startsWith(r+" ")&&i<n.length)r+=" "+n[i++].trim().replace(/\s+/g," ");else if(r.startsWith(s+" ")&&o<e.length)s+=" "+e[o++].trim().replace(/\s+/g," ");else break;if(r===s&&(i>1||o>1)&&![...n,...e].some(c=>c.includes(`
|
|
9
|
+
`))){let c=ae(n.slice(0,i).join(`
|
|
10
10
|
`),e.slice(0,o).join(`
|
|
11
|
-
`));if(
|
|
11
|
+
`));if(c){let h=_(c.leftSegments),g=_(c.rightSegments);return[...Array.from({length:Math.max(i,o)},(b,S)=>({left:S<i?n[S]:void 0,right:S<o?e[S]:void 0,reflow:{start:S===0,leftSegments:h[S],rightSegments:g[S]}})),...K(n.slice(i),e.slice(o))]}}let l=n.reduce((c,h)=>c+Math.min(h.length,ie),0),d=e.reduce((c,h)=>c+Math.min(h.length,ie),0);if(l*d>rn)return ye(n,e,!0);if(n.length===1&&e.length===1){let c=J(n[0],e[0]);return!n[0].trim()&&!e[0].trim()||(c.eligible||c.score>=en)&&re(n[0],e[0])&&se(n[0],e[0])&&O(M(n[0]))&&O(M(e[0]))?[{left:n[0],right:e[0]}]:[{left:n[0]},{right:e[0]}]}if(n.length*e.length>ke)return ye(n,e);let u=sn(n,e),f=Array.from({length:n.length+1},()=>new Array(e.length+1).fill(Number.NEGATIVE_INFINITY)),a=Array.from({length:n.length+1},()=>new Array(e.length+1).fill(null));f[0][0]=0;for(let c=1;c<=n.length;c++)f[c][0]=f[c-1][0]+q,a[c][0]="left";for(let c=1;c<=e.length;c++)f[0][c]=f[0][c-1]+q,a[0][c]="right";for(let c=1;c<=n.length;c++)for(let h=1;h<=e.length;h++){let g=u[c-1][h-1],S=[{move:"left",score:f[c-1][h]+q},{move:"right",score:f[c][h-1]+q},{move:"match",score:g===null?Number.NEGATIVE_INFINITY:f[c-1][h-1]+g}].reduce((x,y)=>y.score>x.score?y:x);f[c][h]=S.score,a[c][h]=S.move}let v=[],m=n.length,p=e.length;for(;m>0||p>0;){let c=a[m][p];c==="match"?v.push({left:n[--m],right:e[--p]}):c==="left"?v.push({left:n[--m]}):v.push({right:e[--p]})}return v.reverse()}function J(n,e){let t=M(n),i=M(e),o=O(t),r=O(i);if(o&&r&&t===i)return{score:1,eligible:!0,characterSimilarity:1,tokenSimilarity:1,lengthSimilarity:1};if(!o||!r)return{score:0,eligible:!1,characterSimilarity:0,tokenSimilarity:0,lengthSimilarity:0};let s=G(t),l=G(i),d=b=>b.length<=ie?b:[0,Math.floor(b.length/2)-300,b.length-600].map(S=>b.slice(S,S+600)).join(" "),u=vn(d(t),d(i)),f=mn(s,l),a=Math.min(t.length,i.length)/Math.max(t.length,i.length),v=pn(s,l),m=b=>b.match(/^(?:(?:const|let|var)\s+)?([\p{L}_$][\p{L}\p{N}_$.-]*\s*(?::|=(?!=)))\s*/u)?.[1].replace(/\s+/g,""),p=m(t),c=p&&p===m(i)?.12:0,h=Math.min(1,u*.52+f*.32+a*.1+v*.06+c),g=c>0||u>=.52||f>=.45||u>=.48&&f>=.28;return{score:h,eligible:g&&h>=Qe,characterSimilarity:u,tokenSimilarity:f,lengthSimilarity:a}}function sn(n,e){let t=n.map(c=>e.map(h=>J(c,h))),i=He(n,e),o=t.map(c=>oe(c)),r=e.map((c,h)=>oe(t.map(g=>g[h]))),s=t.map((c,h)=>c.map((g,b)=>{if(i.has(`${h}:${b}`))return Math.max(g.score,1);if(!g.eligible)return null;let S=o[h],x=r[b],y=g.score===S.best&&g.score===x.best,I=g.score>=Oe?Y/2:Y,w=S.best-S.second>=I,N=x.best-x.second>=I;return y&&w&&N?g.score:null}));if(Math.max(n.length,e.length)>on||Math.abs(n.length-e.length)>ne)return s;let l=(c,h,g)=>c.score>=_e&&se(n[h],e[g])&&Math.abs(h-g)<=ne,d=t.map((c,h)=>X(c,(g,b)=>l(g,h,b))),u=e.map((c,h)=>X(t.map(g=>g[h]),(g,b)=>l(g,b,h))),f=(c,h,g)=>c.score>=nn&&se(n[h],e[g])&&Math.abs(h-g)<=ne,a=t.map((c,h)=>X(c,(g,b)=>f(g,h,b))),v=e.map((c,h)=>X(t.map(g=>g[h]),(g,b)=>f(g,b,h))),m=(c,h)=>{let g=t[c][h];if(!l(g,c,h))return!1;let b=d[c],S=u[h];return g.score===b.best&&g.score===S.best&&b.best-b.second>=P&&S.best-S.second>=P},p=(c,h)=>{let g=t[c][h];if(!f(g,c,h))return!1;let b=a[c],S=v[h];return g.score===b.best&&g.score===S.best&&b.best-b.second>=P&&S.best-S.second>=P};return s.map((c,h)=>c.map((g,b)=>{if(g!==null)return g;let S=m(h,b)&&(ln(s,h,b)||fn(t,h,b,m)),x=an(t,h,b,(y,I)=>f(t[y][I],y,I),p);return!S&&!x?null:t[h][b].score}))}function ln(n,e,t){return e>0&&t>0&&n[e-1][t-1]!==null||e+1<n.length&&t+1<n[e+1].length&&n[e+1][t+1]!==null}function fn(n,e,t,i){return e>0&&t>0&&i(e-1,t-1)||e+1<n.length&&t+1<n[e+1].length&&i(e+1,t+1)}function an(n,e,t,i,o){let r=e,s=t;for(;r>0&&s>0&&i(r-1,s-1);)r--,s--;let l=e,d=t,u=n[e][t].score,f=1;for(;l+1<n.length&&d+1<n[l+1].length&&i(l+1,d+1);)l++,d++,u+=n[l][d].score,f++;for(let a=e-1,v=t-1;a>=r&&v>=s;a--,v--)u+=n[a][v].score,f++;return f>=3&&u/f>=_e&&o(r,s)&&o(l,d)}function X(n,e){let t=Number.NEGATIVE_INFINITY,i=Number.NEGATIVE_INFINITY;return n.forEach((o,r)=>{e(o,r)&&(o.score>t?(i=t,t=o.score):o.score>i&&(i=o.score))}),{best:t,second:i}}function oe(n){let e=Number.NEGATIVE_INFINITY,t=Number.NEGATIVE_INFINITY;for(let i of n)i.eligible&&(i.score>e?(t=e,e=i.score):i.score>t&&(t=i.score));return{best:e,second:t}}function ye(n,e,t=!1){let i=un(n,e,t);if(i.length===0)return[...n.map(l=>({left:l})),...e.map(l=>({right:l}))];let o=[],r=0,s=0;for(let l of i)De(o,n.slice(r,l.leftIndex),e.slice(s,l.rightIndex)),o.push({left:n[l.leftIndex],right:e[l.rightIndex]}),r=l.leftIndex+1,s=l.rightIndex+1;return De(o,n.slice(r),e.slice(s)),o}function un(n,e,t){let i=cn(n,e,t);if(i===null)return[];let o=He(n,e),r=i.map(({leftIndex:f,rightIndex:a,exact:v})=>({leftIndex:f,rightIndex:a,exact:v,structural:o.has(`${f}:${a}`),match:J(n[f],e[a])})).filter(f=>f.exact||f.structural||f.match.eligible),s=Ee(r,"leftIndex"),l=Ee(r,"rightIndex"),d=r.filter(f=>{if(f.exact||f.structural)return!0;let a=s.get(f.leftIndex),v=l.get(f.rightIndex);if(!a||!v||f.match.score!==a.best||f.match.score!==v.best)return!1;let m=f.match.score>=Oe?Y/2:Y;return a.best-a.second>=m&&v.best-v.second>=m}),u=gn(d,e.length);return u.length<=tn?u:[]}function cn(n,e,t){let i=Ne(n,M),o=Ne(e,M),r=new Map;for(let[d,u]of i){let f=o.get(d);if(!O(d)||u.length!==1||f?.length!==1)continue;let a=u[0],v=f[0];if(r.set(`${a}:${v}`,{leftIndex:a,rightIndex:v,exact:!0}),r.size>we)return null}if(t)return[...r.values()];let s=Ie(n),l=Ie(e);for(let[d,u]of s){let f=l.get(d);if(!(!f||u.length>Se||f.length>Se))for(let a of u)for(let v of f){let m=`${a}:${v}`;if(!r.has(m)&&(r.set(m,{leftIndex:a,rightIndex:v,exact:!1}),r.size>we))return null}}return[...r.values()]}function Ne(n,e){let t=new Map;return n.forEach((i,o)=>{let r=e(i),s=t.get(r)??[];s.push(o),t.set(r,s)}),t}function Ie(n){let e=new Map;return n.forEach((t,i)=>{let o=new Set(G(M(t)).filter(dn));for(let r of o){let s=e.get(r)??[];s.push(i),e.set(r,s)}}),e}function dn(n){return n.length>=2&&/[\p{L}\p{N}_$]/u.test(n)}function Ee(n,e){let t=new Map;for(let i of n){let o=t.get(i[e])??[];o.push(i.match),t.set(i[e],o)}return new Map([...t].map(([i,o])=>[i,oe(o)]))}function gn(n,e){let t=[...n].sort((u,f)=>u.leftIndex-f.leftIndex||u.rightIndex-f.rightIndex),i=new Array(e+2).fill(0),o=new Array(e+2).fill(-1),r=new Array(t.length).fill(0),s=new Array(t.length).fill(-1);for(let u=0;u<t.length;){let f=u+1;for(;f<t.length&&t[f].leftIndex===t[u].leftIndex;)f++;for(let a=u;a<f;a++){let v=Le(i,o,t[a].rightIndex),m=t[a].exact||t[a].structural?.5:0;r[a]=v.score+t[a].match.score+m,s[a]=v.candidateIndex}for(let a=u;a<f;a++)hn(i,o,t[a].rightIndex+1,r[a],a);u=f}let l=Le(i,o,e+1),d=[];for(let u=l.candidateIndex;u>=0;u=s[u])d.push({leftIndex:t[u].leftIndex,rightIndex:t[u].rightIndex});return d.reverse()}function Le(n,e,t){let i=0,o=-1;for(let r=t;r>0;r-=r&-r)n[r]>i&&(i=n[r],o=e[r]);return{score:i,candidateIndex:o}}function hn(n,e,t,i,o){for(let r=t;r<n.length;r+=r&-r)i>n[r]&&(n[r]=i,e[r]=o)}function De(n,e,t){if(e.length*t.length<=ke){n.push(...K(e,t));return}n.push(...e.map(i=>({left:i}))),n.push(...t.map(i=>({right:i})))}function M(n){return n.trim().replace(/\s+/g," ")}function He(n,e){let t=Me(n),i=Me(e),o=new Set;for(let[r,s]of t){let l=i.get(r);s.length===1&&l?.length===1&&o.add(`${s[0]}:${l[0]}`)}return o}function Me(n){let e=new Map;return n.forEach((t,i)=>{let o=B(t);if(!o)return;let r=e.get(o)??[];r.push(i),e.set(o,r)}),e}function se(n,e){let t=B(n),i=B(e);return!t||!i?t===i:t.split(":",1)[0]===i.split(":",1)[0]}function B(n){let e=M(n),t=[["function",/^(?:(?:export|default)\s+)*(?:async\s+)?function\s*\*?\s*([\p{L}_$][\p{L}\p{N}_$]*)\s*\(/u],["function",/^(?:async\s+)?def\s+([\p{L}_][\p{L}\p{N}_]*)\s*\(/u],["function",/^(?:pub(?:\([^)]*\))?\s+)?(?:async\s+)?fn\s+([\p{L}_][\p{L}\p{N}_]*)\s*(?:<[^>]*>)?\s*\(/u],["function",/^func\s+(?:\([^)]*\)\s*)?([\p{L}_][\p{L}\p{N}_]*)\s*\(/u],["class",/^(?:(?:export|default|abstract|public)\s+)*class\s+([\p{L}_$][\p{L}\p{N}_$]*)\b/u]];for(let[i,o]of t){let r=e.match(o);if(r)return`${i}:${r[1]}`}return null}function O(n){return n.length<3?!1:/[\p{L}\p{N}_$]/u.test(n)&&!/^[\s()[\]{};,.:+\-*/=>|&!?'"`]+$/.test(n)}function G(n){return n.toLowerCase().match(/[\p{L}_$][\p{L}\p{N}_$]*|\p{N}+(?:\.\p{N}+)?|[^\s\p{L}\p{N}_$]/gu)??[]}function mn(n,e){if(n.length+e.length===0)return 1;let t=new Map;n.forEach(o=>t.set(o,(t.get(o)??0)+1));let i=0;for(let o of e){let r=t.get(o)??0;r>0&&(i++,t.set(o,r-1))}return 2*i/(n.length+e.length)}function pn(n,e){if(n.length===0||e.length===0)return 0;let t=n[0]===e[0]?.5:0,i=n[n.length-1]===e[e.length-1]?.5:0;return t+i}function vn(n,e){let t=n.length+e.length;return t===0?1:2*de(n,e).filter(o=>!o.added&&!o.removed).reduce((o,r)=>o+r.value.length,0)/t}function bn(n,e){let t=ae(n.content,e.content);if(t){n.segments=t.leftSegments,e.segments=t.rightSegments;return}let i=fe(n.content,e.content);i&&(n.segments=i.leftSegments,e.segments=i.rightSegments)}function wn(n,e){if(!n.length||!e.length||n.length===1&&e.length===1)return;let t=f=>f.reduce((a,v)=>a+v.content.length+1,-1);if(t(n)>j||t(e)>j)return;let i=n.map(f=>f.content).join(`
|
|
12
12
|
`),o=e.map(f=>f.content).join(`
|
|
13
|
-
`),
|
|
14
|
-
|
|
13
|
+
`),r=fe(i,o);if(!r)return;let{leftSegments:s,rightSegments:l}=r,d=_(s),u=_(l);n.forEach((f,a)=>{f.segments=d[a]}),e.forEach((f,a)=>{f.segments=u[a]})}function Ae(n){/[^\s]/.test(n.content)&&(n.segments=[{kind:n.kind,text:n.content,emphasis:!0}])}var le=new Intl.Segmenter(void 0,{granularity:"grapheme"});function Sn(n,e){if(n===e)return n?[{value:n}]:[];let t=Array.from(le.segment(n),l=>l.segment),i=Array.from(le.segment(e),l=>l.segment),o=Math.min(t.length,i.length),r=0,s=0;for(;r<o&&t[r]===i[r];)r++;for(;s<o&&t[t.length-s-1]===i[i.length-s-1];)s++;return s===o&&r<o&&(r=0),s=Math.min(s,o-r),[{value:t.slice(0,r).join("")},{value:t.slice(r,t.length-s).join(""),removed:!0},{value:i.slice(r,i.length-s).join(""),added:!0},{value:s?t.slice(-s).join(""):""}].filter(l=>l.value.length>0)}function xn(n,e){let t=ge(n,e,{timeout:Re,maxEditLength:2e3});if(!t)return;let i=a=>new Set([...Array.from(le.segment(a),v=>v.index),a.length]),o=i(n),r=i(e),s=[],l=0,d=0,u="",f="";for(let a=0;a<t.length;){let v=t[a];if(!v.added&&!v.removed)u+=v.value,f+=v.value,l+=v.value.length,d+=v.value.length,a++;else for(;a<t.length&&(t[a].added||t[a].removed);){let m=t[a++];m.removed?(u+=m.value,l+=m.value.length):(f+=m.value,d+=m.value.length)}if(o.has(l)&&r.has(d)){for(let m of Sn(u,f)){let p=s[s.length-1];p&&p.added===m.added&&p.removed===m.removed?p.value+=m.value:s.push(m)}u="",f=""}}return s}function fe(n,e){if(n.length>j||e.length>j)return;let t=xn(n,e);if(!t)return;let i=[],o=[],r=!1;for(let s of t){let l=s.value;if(!s.added&&!s.removed){let u={kind:"context",text:l,emphasis:!1};i.push(u),o.push(u);continue}let d=l.length>0;r=r||d,s.removed&&i.push({kind:"removed",text:l,emphasis:d}),s.added&&o.push({kind:"added",text:l,emphasis:d})}return{leftSegments:V(i),rightSegments:V(o),hasInlineChanges:r}}function ae(n,e){let t=n.split(/(\S+)/),i=e.split(/(\S+)/);if(t.length!==i.length||t.some((l,d)=>d%2===1&&l!==i[d]))return;let o=[],r=[],s=(l,d,u)=>{if(!u)return;let f=l[l.length-1];f?.kind===d?f.text+=u:l.push({kind:d,text:u,emphasis:d!=="context"})};return t.forEach((l,d)=>{let u=i[d],f=0;if(d>0)for(;f<Math.min(l.length,u.length)&&l[f]===u[f];)f++;let a=0;for(;a<Math.min(l.length,u.length)-f&&l[l.length-a-1]===u[u.length-a-1];)a++;if(d===0)for(;f<Math.min(l.length,u.length)-a&&l[f]===u[f];)f++;s(o,"context",l.slice(0,f)),s(r,"context",u.slice(0,f)),s(o,"removed",l.slice(f,l.length-a)),s(r,"added",u.slice(f,u.length-a)),s(o,"context",l.slice(l.length-a)),s(r,"context",u.slice(u.length-a))}),{leftSegments:V(o),rightSegments:V(r)}}function V(n){let e=[];return _(n).forEach((t,i)=>{i>0&&e.push({kind:"context",text:`
|
|
14
|
+
`,emphasis:!1});let o=t.map(u=>u.text).join(""),r=o.match(/^[\t ]*/u)[0].length,s=0,l=0,d="context";for(let u of t){if(s>=r)break;u.emphasis&&(l+=Math.min(u.text.length,r-s),d=u.kind),s+=u.text.length}l&&e.push({kind:d,text:o.slice(0,l),emphasis:!0}),r>l&&e.push({kind:"context",text:o.slice(l,r),emphasis:!1}),s=0;for(let u of t){let f=Math.max(0,r-s);f<u.text.length&&e.push({...u,text:u.text.slice(f)}),s+=u.text.length}}),e}function _(n){let e=[[]];for(let t of n)t.text.split(`
|
|
15
|
+
`).forEach((i,o)=>{o>0&&e.push([]),i&&e[e.length-1].push({...t,text:i})});return e}function H(){return{kind:"placeholder",content:"",lineNumber:null}}function A(n,e,t){return{kind:n,content:e,lineNumber:t}}function R(n,e,t){return{kind:n,content:e,lineNumber:t}}function k(n,e){return{left:n,right:e}}function $(n,e,t,i,o){return{kind:n,leftStart:e,leftEnd:t,rightStart:i,rightEnd:o}}function Fe(n,e){let t=typeof process<"u"?process.env?.[n]:void 0,i=Number.parseInt(t??"",10);return Number.isFinite(i)&&i>0?i:e}self.addEventListener("message",n=>{let{id:e,leftContent:t,rightContent:i}=n.data||{};if(!(typeof e!="number"||typeof t!="string"||typeof i!="string"))try{let o=Te(t,i);self.postMessage({id:e,model:o})}catch(o){self.postMessage({id:e,error:o&&o.message||String(o)})}});})();
|
|
15
16
|
//# sourceMappingURL=diff.worker.js.map
|