@lumy-pack/line-lore 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -20
- package/dist/cli.mjs +306 -95
- package/dist/core/ancestry/ancestry.d.ts +32 -1
- package/dist/core/ancestry/index.d.ts +1 -1
- package/dist/core/blame/blame.d.ts +2 -2
- package/dist/core/index.d.ts +1 -1
- package/dist/core/pr-lookup/index.d.ts +1 -0
- package/dist/core/pr-lookup/pr-lookup.d.ts +18 -2
- package/dist/index.cjs +292 -92
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +292 -92
- package/dist/platform/github/github-adapter.d.ts +3 -1
- package/dist/platform/gitlab/gitlab-adapter.d.ts +3 -1
- package/dist/types/blame.d.ts +2 -0
- package/dist/types/cache.d.ts +2 -0
- package/dist/types/git.d.ts +7 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/platform.d.ts +3 -1
- package/dist/types/trace.d.ts +3 -0
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,9 +25,12 @@ yarn add @lumy-pack/line-lore
|
|
|
25
25
|
### CLI Usage
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
# Trace a single line to its PR
|
|
28
|
+
# Trace a single line to its originating PR
|
|
29
29
|
npx @lumy-pack/line-lore trace src/auth.ts -L 42
|
|
30
30
|
|
|
31
|
+
# Trace the last meaningful change to a line
|
|
32
|
+
npx @lumy-pack/line-lore trace src/auth.ts -L 42 --mode change
|
|
33
|
+
|
|
31
34
|
# Trace a line range
|
|
32
35
|
npx @lumy-pack/line-lore trace src/config.ts -L 10,50
|
|
33
36
|
|
|
@@ -61,14 +64,21 @@ npx @lumy-pack/line-lore trace src/auth.ts -L 42 --quiet
|
|
|
61
64
|
```typescript
|
|
62
65
|
import { trace, graph, health, clearCache } from '@lumy-pack/line-lore';
|
|
63
66
|
|
|
64
|
-
// Trace a line to its PR
|
|
65
|
-
const
|
|
67
|
+
// Trace a line to its originating PR (default mode)
|
|
68
|
+
const originResult = await trace({
|
|
69
|
+
file: 'src/auth.ts',
|
|
70
|
+
line: 42,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Trace the last meaningful change to a line
|
|
74
|
+
const changeResult = await trace({
|
|
66
75
|
file: 'src/auth.ts',
|
|
67
76
|
line: 42,
|
|
77
|
+
mode: 'change',
|
|
68
78
|
});
|
|
69
79
|
|
|
70
80
|
// Find the PR node
|
|
71
|
-
const prNode =
|
|
81
|
+
const prNode = originResult.nodes.find(n => n.type === 'pull_request');
|
|
72
82
|
if (prNode) {
|
|
73
83
|
console.log(`PR #${prNode.prNumber}: ${prNode.prTitle}`);
|
|
74
84
|
}
|
|
@@ -89,9 +99,11 @@ console.log(`Git version: ${report.gitVersion}`);
|
|
|
89
99
|
|
|
90
100
|
## How It Works
|
|
91
101
|
|
|
92
|
-
@lumy-pack/line-lore executes a
|
|
102
|
+
@lumy-pack/line-lore executes a deterministic pipeline with two trace modes:
|
|
93
103
|
|
|
94
|
-
1. **Line → Commit (Blame)**:
|
|
104
|
+
1. **Line → Commit (Blame)**:
|
|
105
|
+
- `origin`: `git blame -w -C -C -M` — follows copy/move history across renames; whitespace-only changes ignored
|
|
106
|
+
- `change`: `git blame -w` — finds the last meaningful local change; ignores whitespace but does **not** track renames/copies, so a rename commit itself is attributed as the change
|
|
95
107
|
2. **Cosmetic Detection**: AST structural comparison to skip formatting-only changes
|
|
96
108
|
3. **Commit → Merge Commit**: Ancestry-path traversal + patch-id matching to resolve merge commits
|
|
97
109
|
4. **Merge Commit → PR**: Commit message parsing + platform API lookup (filters unmerged PRs)
|
|
@@ -111,19 +123,21 @@ Strategy 1 — Cache ─────────────────── c
|
|
|
111
123
|
│ hit? → return cached PRInfo
|
|
112
124
|
│ miss + --cache-only? → return null (skip all fallbacks)
|
|
113
125
|
▼
|
|
114
|
-
Strategy 2 —
|
|
115
|
-
│
|
|
116
|
-
│
|
|
126
|
+
Strategy 2 — Platform API ──────────── cost: 1 HTTP request
|
|
127
|
+
│ gh api repos/{owner}/{repo}/commits/{sha}/pulls
|
|
128
|
+
│ Filter: merged PRs only (mergedAt != null)
|
|
129
|
+
│ found? → return PRInfo
|
|
130
|
+
▼
|
|
131
|
+
Strategy 3 — Ancestry-path + Message ─ cost: 1-2 git-log traversals
|
|
132
|
+
│ Search verified merge candidates:
|
|
133
|
+
│ • first-parent ancestry path first
|
|
134
|
+
│ • full ancestry path second
|
|
117
135
|
│ Parse merge subject with 3 regex patterns:
|
|
118
136
|
│ • /Merge pull request #(\d+)/ — GitHub merge commit
|
|
119
137
|
│ • /\(#(\d+)\)\s*$/ — Squash merge convention
|
|
120
|
-
│ •
|
|
121
|
-
│ If
|
|
122
|
-
│
|
|
123
|
-
▼
|
|
124
|
-
Strategy 3 — Platform API ──────────── cost: 1 HTTP request
|
|
125
|
-
│ gh api repos/{owner}/{repo}/commits/{sha}/pulls
|
|
126
|
-
│ Filter: merged PRs only (mergedAt != null)
|
|
138
|
+
│ • /See merge request ...!(\d+)$/ — GitLab merge commit
|
|
139
|
+
│ If message has no PR number and API is available:
|
|
140
|
+
│ query the merge commit SHA directly
|
|
127
141
|
│ found? → return PRInfo
|
|
128
142
|
▼
|
|
129
143
|
Strategy 4 — Patch-ID matching ─────── cost: streaming 500+ commits
|
|
@@ -136,7 +150,7 @@ Strategy 4 — Patch-ID matching ─────── cost: streaming 500+ comm
|
|
|
136
150
|
All failed → null
|
|
137
151
|
```
|
|
138
152
|
|
|
139
|
-
**Why this order?**
|
|
153
|
+
**Why this order?** Direct API lookup is the strongest Level 2 signal, so it runs before local ancestry heuristics. Verified ancestry is still cheaper than patch-id scanning and resolves most merge-based workflows without diff streaming.
|
|
140
154
|
|
|
141
155
|
**Patch-ID explained**: `git patch-id --stable` generates a content-based hash from a commit's diff, ignoring all metadata (author, date, message). When a commit is rebased, its SHA changes but the patch-id stays the same — enabling deterministic matching of rebased commits.
|
|
142
156
|
|
|
@@ -170,7 +184,7 @@ interface TraceNode {
|
|
|
170
184
|
|
|
171
185
|
| Type | Symbol | Meaning | When it appears |
|
|
172
186
|
|------|--------|---------|-----------------|
|
|
173
|
-
| `original_commit` | `●` | The commit
|
|
187
|
+
| `original_commit` | `●` | The commit selected by the active trace mode | Always (at least one) |
|
|
174
188
|
| `cosmetic_commit` | `○` | A formatting-only change (whitespace, imports) | When AST detects no logic change |
|
|
175
189
|
| `merge_commit` | `◆` | The merge commit on the base branch | Merge-based workflows |
|
|
176
190
|
| `rebased_commit` | `◇` | A rebased version of the original commit | Rebase workflows with patch-id match |
|
|
@@ -206,6 +220,13 @@ interface TraceNode {
|
|
|
206
220
|
└─ https://github.com/org/repo/pull/42
|
|
207
221
|
```
|
|
208
222
|
|
|
223
|
+
**Last meaningful change mode (`--mode change`):**
|
|
224
|
+
```
|
|
225
|
+
● Commit e4f5a6b [exact] via blame
|
|
226
|
+
▸ PR #55 refactor: update validation logic
|
|
227
|
+
└─ https://github.com/org/repo/pull/55
|
|
228
|
+
```
|
|
229
|
+
|
|
209
230
|
**Squash merge (Level 2):**
|
|
210
231
|
```
|
|
211
232
|
● Commit e4f5a6b [exact] via blame-CMw
|
|
@@ -334,7 +355,7 @@ import { trace, graph, health, clearCache, LineLoreError } from '@lumy-pack/line
|
|
|
334
355
|
|
|
335
356
|
### `trace(options): Promise<TraceFullResult>`
|
|
336
357
|
|
|
337
|
-
Trace a code line to its originating PR.
|
|
358
|
+
Trace a code line to its originating or last-change PR, depending on the selected mode.
|
|
338
359
|
|
|
339
360
|
**Options (`TraceOptions`):**
|
|
340
361
|
|
|
@@ -344,6 +365,7 @@ Trace a code line to its originating PR.
|
|
|
344
365
|
| `line` | `number` | yes | — | Starting line number (1-indexed) |
|
|
345
366
|
| `endLine` | `number` | no | — | Ending line for range queries |
|
|
346
367
|
| `remote` | `string` | no | `'origin'` | Git remote name |
|
|
368
|
+
| `mode` | `'origin' \| 'change'` | no | `'origin'` | `origin` uses `git blame -w -C -C -M` (follows copy/move history across renames), `change` uses `git blame -w` (finds the last meaningful local change, ignoring whitespace but not copy/move) |
|
|
347
369
|
| `deep` | `boolean` | no | `false` | Expand patch-id scan range (500→2000), continue search after merge commit match |
|
|
348
370
|
| `noAst` | `boolean` | no | `false` | Disable AST analysis |
|
|
349
371
|
| `noCache` | `boolean` | no | `false` | Disable cache reads and writes |
|
|
@@ -389,6 +411,7 @@ const result = await trace({
|
|
|
389
411
|
file: 'src/config.ts',
|
|
390
412
|
line: 10,
|
|
391
413
|
endLine: 50,
|
|
414
|
+
mode: 'origin',
|
|
392
415
|
deep: true, // search harder for squash merges
|
|
393
416
|
noCache: true, // skip cache for fresh results
|
|
394
417
|
});
|
|
@@ -631,8 +654,9 @@ import type {
|
|
|
631
654
|
|
|
632
655
|
| Command | Purpose |
|
|
633
656
|
|---------|---------|
|
|
634
|
-
| `npx @lumy-pack/line-lore trace <file>` | Trace a line to its PR |
|
|
657
|
+
| `npx @lumy-pack/line-lore trace <file>` | Trace a line to its origin or last-change PR |
|
|
635
658
|
| `-L, --line <num>` | Starting line (required) |
|
|
659
|
+
| `--mode <origin\|change>` | Choose between content origin and last meaningful change |
|
|
636
660
|
| `--end-line <num>` | Ending line for range |
|
|
637
661
|
| `--deep` | Deep trace (squash merges) |
|
|
638
662
|
| `--output <format>` | Output as json, llm, or human |
|