pi-jscpd 0.2.1 → 0.2.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/CHANGELOG.md +23 -1
- package/CONTRIBUTING.md +30 -2
- package/README.md +122 -55
- package/SECURITY.md +1 -1
- package/docs/adoption.md +131 -0
- package/docs/automatic-checkpoint.md +4 -3
- package/docs/benchmarks.md +78 -0
- package/docs/compatibility.md +54 -13
- package/docs/effect-architecture.md +2 -2
- package/docs/fallow-coexistence.md +1 -1
- package/docs/images/jscpd-findings.png +0 -0
- package/docs/m8-validation.md +389 -0
- package/docs/overlay-interaction.md +1 -1
- package/docs/release.md +10 -2
- package/package.json +9 -8
- package/scripts/check-compatibility.mjs +4 -4
- package/skills/jscpd/SKILL.md +1 -1
- package/src/jscpd-report.ts +19 -8
- package/src/presentation.ts +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,27 @@ published releases use [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.2] - 2026-09-18
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Added an explicit **pi-jscpd** benchmarks table and `docs/benchmarks.md` for
|
|
15
|
+
isolated `/jscpd scan` runs on pinned public Vite, React, Vue, Svelte,
|
|
16
|
+
Express, and Prettier trees.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Keep jscpd summary statistics when a structured report lists more clone pairs
|
|
21
|
+
than the session may retain, and present bounded findings instead of failing
|
|
22
|
+
the whole scan as an invalid report.
|
|
23
|
+
- Certified Pi 0.85.1 across both supported Node fixtures and widened the Pi
|
|
24
|
+
peer range through the 0.85 line after API review, packed-artifact checks,
|
|
25
|
+
compact/expanded transcript probes, narrow real-TUI smoke tests, and active
|
|
26
|
+
scan cancellation/cleanup verification.
|
|
27
|
+
- Concentrated the approved public version in one reviewed source so release
|
|
28
|
+
preparation no longer repeats the same version literal across publication
|
|
29
|
+
guards.
|
|
30
|
+
|
|
10
31
|
## [0.2.1] - 2026-09-06
|
|
11
32
|
|
|
12
33
|
### Added
|
|
@@ -123,7 +144,8 @@ published releases use [Semantic Versioning](https://semver.org/).
|
|
|
123
144
|
- Project paths, child output, reports, temporary directories, cancellation,
|
|
124
145
|
configuration trust, and lifecycle cleanup are bounded and fail open.
|
|
125
146
|
|
|
126
|
-
[Unreleased]: https://github.com/revazi/pi-jscpd/compare/v0.2.
|
|
147
|
+
[Unreleased]: https://github.com/revazi/pi-jscpd/compare/v0.2.2...HEAD
|
|
148
|
+
[0.2.2]: https://github.com/revazi/pi-jscpd/compare/v0.2.1...v0.2.2
|
|
127
149
|
[0.2.1]: https://github.com/revazi/pi-jscpd/compare/v0.2.0...v0.2.1
|
|
128
150
|
[0.2.0]: https://github.com/revazi/pi-jscpd/compare/v0.1.1...v0.2.0
|
|
129
151
|
[0.1.1]: https://github.com/revazi/pi-jscpd/compare/v0.1.0...v0.1.1
|
package/CONTRIBUTING.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Contributing to pi-jscpd
|
|
1
|
+
# 👋 Contributing to pi-jscpd
|
|
2
2
|
|
|
3
3
|
Thanks for helping improve `pi-jscpd`. Changes should preserve the extension's
|
|
4
4
|
quiet, advisory, read-only, bounded, and fail-open behavior. jscpd remains the
|
|
@@ -23,6 +23,30 @@ agent flow is insufficient. Do not propose an independent clone detector,
|
|
|
23
23
|
automatic source edits, surprise binary installation, or mandatory
|
|
24
24
|
JavaScript-only parsing in the core workflow.
|
|
25
25
|
|
|
26
|
+
## Validation and adoption feedback
|
|
27
|
+
|
|
28
|
+
Use the [feedback form](https://github.com/revazi/pi-jscpd/issues/new?template=adoption-feedback.yml)
|
|
29
|
+
for installation, scoped scans, finding review, navigation, configuration, and
|
|
30
|
+
team-workflow observations. Prefer the [bug report](https://github.com/revazi/pi-jscpd/issues/new?template=bug-report.yml)
|
|
31
|
+
for a reproducible defect and the [feature request](https://github.com/revazi/pi-jscpd/issues/new?template=feature-request.yml)
|
|
32
|
+
for a concrete proposal. Suspected vulnerabilities belong in private reporting
|
|
33
|
+
under [SECURITY.md](SECURITY.md).
|
|
34
|
+
|
|
35
|
+
Feedback is optional and manually submitted to a public issue. Supply only
|
|
36
|
+
versions, coarse size/latency/count buckets, generic formats, and at most six
|
|
37
|
+
short observation bullets. Do not include credentials, private paths, source
|
|
38
|
+
fragments, raw reports, raw child output, terminal captures, account/repository
|
|
39
|
+
identifiers, or attachments. Choose Unknown / Not tested rather than conducting
|
|
40
|
+
new scans or sharing identifying details. The form is guidance, not an automatic
|
|
41
|
+
redaction mechanism: review every answer before submitting.
|
|
42
|
+
|
|
43
|
+
Distinguish the pairs actually inspected from omitted/unreviewed findings, and
|
|
44
|
+
keep inspection candidates, likely expected repetition, and uncertain judgments
|
|
45
|
+
separate. These are provisional priorities—not approved refactors or a measured
|
|
46
|
+
false-positive rate. Feedback informs the next milestone; it does not activate a
|
|
47
|
+
feature candidate by itself. Existing [validation limitations](docs/m8-validation.md#remaining-acceptance-and-decision)
|
|
48
|
+
remain explicit.
|
|
49
|
+
|
|
26
50
|
## Development setup
|
|
27
51
|
|
|
28
52
|
Use a host from the [compatibility matrix](docs/compatibility.md). Install the
|
|
@@ -42,7 +66,11 @@ approved Effect runtime boundary, type checks strict ESM TypeScript, runs
|
|
|
42
66
|
Biome's formatting/lint checks, and executes the network-free test suite. The
|
|
43
67
|
documentation and hygiene checks validate public local links, release metadata,
|
|
44
68
|
ignored/private path policy, package metadata, and the non-publishing readiness
|
|
45
|
-
workflow.
|
|
69
|
+
workflow. Tests also parse every issue-template YAML file, validate the form
|
|
70
|
+
fields used by this repository, and check feedback privacy/bucket requirements
|
|
71
|
+
and issue-template links without contacting GitHub. The exact-pinned development
|
|
72
|
+
`yaml` dependency is only a validation parser; it adds no extension runtime
|
|
73
|
+
service. `pack:certify` installs and exercises the exact tarball.
|
|
46
74
|
CI repeats those checks on Node 22.19.0 and 24.12.0.
|
|
47
75
|
|
|
48
76
|
Tests must not require network access, read or modify global Pi configuration,
|
package/README.md
CHANGED
|
@@ -6,14 +6,22 @@
|
|
|
6
6
|
[](./LICENSE)
|
|
7
7
|
[](https://github.com/revazi/pi-jscpd/issues)
|
|
8
8
|
|
|
9
|
-
A quiet, read-only duplication guardrail for the
|
|
9
|
+
A quiet, read-only duplication guardrail for the
|
|
10
|
+
[Pi coding agent](https://github.com/earendil-works/pi), powered by
|
|
11
|
+
[jscpd](https://github.com/kucherenko/jscpd).
|
|
10
12
|
|
|
11
13
|
`pi-jscpd` detects duplicate blocks introduced during a Pi session, shows both
|
|
12
14
|
locations, and helps you inspect, refactor, test, and verify the result. jscpd
|
|
13
15
|
remains the source of truth for tokenization, clone detection, supported
|
|
14
16
|
languages, and statistics.
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
| 🤫 Quiet | 🧭 Advisory | 🌍 Polyglot | 🛟 Fail open |
|
|
19
|
+
| --- | --- | --- | --- |
|
|
20
|
+
| Clean checks stay out of the model | Never blocks a write or edits source | Uses jscpd’s languages, not a JS-only parser | A missing analyzer never breaks Pi |
|
|
21
|
+
|
|
22
|
+
[Install](#install) · [Usage](#usage) · [pi-jscpd benchmarks](#pi-jscpd-benchmarks) · [Overview](#interactive-overview) · [Safety](#safety-and-privacy)
|
|
23
|
+
|
|
24
|
+
## 📦 Install
|
|
17
25
|
|
|
18
26
|
```sh
|
|
19
27
|
pi install npm:pi-jscpd
|
|
@@ -23,14 +31,18 @@ pi install npm:pi-jscpd
|
|
|
23
31
|
separate analyzer setup or runtime download. It prefers a compatible project or
|
|
24
32
|
`PATH` installation and otherwise uses its bundled analyzer.
|
|
25
33
|
|
|
26
|
-
Start Pi in your project
|
|
34
|
+
Start (or restart) Pi in your project, check readiness, then scan a directory
|
|
35
|
+
that exists in your project:
|
|
27
36
|
|
|
28
37
|
```text
|
|
29
38
|
/jscpd status
|
|
39
|
+
/jscpd scan src
|
|
30
40
|
```
|
|
31
41
|
|
|
32
|
-
|
|
33
|
-
|
|
42
|
+
No extension configuration is required. A scoped scan finds matches only within
|
|
43
|
+
its targets; use `/jscpd scan` to include the whole project. If no compatible
|
|
44
|
+
binary is available, the extension stays dormant and Pi continues normally;
|
|
45
|
+
status explains how to recover.
|
|
34
46
|
|
|
35
47
|
In TUI sessions, the extension performs one best-effort, metadata-only npm check
|
|
36
48
|
and shows a warning only when a newer `pi-jscpd` release is available. The check
|
|
@@ -38,21 +50,21 @@ is bounded to 1.5 seconds, never sends project data, and never downloads or
|
|
|
38
50
|
installs package content. Set `PI_JSCPD_DISABLE_UPDATE_NOTICE=1` (or run Pi
|
|
39
51
|
offline) to disable it.
|
|
40
52
|
|
|
41
|
-
## Usage
|
|
53
|
+
## ⌨️ Usage
|
|
42
54
|
|
|
43
55
|
Run `/jscpd` to open the interactive overview. Opening it shows status only; it
|
|
44
56
|
never starts an implicit scan.
|
|
45
57
|
|
|
46
|
-
| Command | Purpose |
|
|
47
|
-
| --- | --- |
|
|
48
|
-
| `/jscpd` | Open the responsive overview |
|
|
49
|
-
| `/jscpd changed` | Show unacknowledged duplication introduced this session |
|
|
50
|
-
| `/jscpd scan` | Scan the whole project |
|
|
51
|
-
| `/jscpd scan src tests` | Scan specific in-project files or directories |
|
|
52
|
-
| `/jscpd status` | Show binary, configuration, mode, and last-check status |
|
|
53
|
-
| `/jscpd off` | Disable scans for the current session |
|
|
54
|
-
| `/jscpd on` | Re-enable scans for the current session |
|
|
55
|
-
| `/jscpd help` | Show command help |
|
|
58
|
+
| | Command | Purpose |
|
|
59
|
+
| --- | --- | --- |
|
|
60
|
+
| 🖥️ | `/jscpd` | Open the responsive overview |
|
|
61
|
+
| 🆕 | `/jscpd changed` | Show unacknowledged duplication introduced this session |
|
|
62
|
+
| 🔍 | `/jscpd scan` | Scan the whole project |
|
|
63
|
+
| 📂 | `/jscpd scan src tests` | Scan specific in-project files or directories |
|
|
64
|
+
| 📋 | `/jscpd status` | Show binary, configuration, mode, and last-check status |
|
|
65
|
+
| ⏸️ | `/jscpd off` | Disable scans for the current session |
|
|
66
|
+
| ▶️ | `/jscpd on` | Re-enable scans for the current session |
|
|
67
|
+
| ❓ | `/jscpd help` | Show command help |
|
|
56
68
|
|
|
57
69
|
Pi can use the same operations through the `jscpd_run` tool:
|
|
58
70
|
|
|
@@ -78,7 +90,32 @@ description at startup and loads its full workflow guidance on demand when a
|
|
|
78
90
|
duplication task matches or the user invokes the skill command. The extension
|
|
79
91
|
and `jscpd_run` tool remain usable when skills are disabled.
|
|
80
92
|
|
|
81
|
-
|
|
93
|
+
For short walkthroughs, see [clean scans, new session duplication, and intentional
|
|
94
|
+
duplication](docs/adoption.md). A finding is a reason to inspect, not permission
|
|
95
|
+
to refactor.
|
|
96
|
+
|
|
97
|
+
## 📊 pi-jscpd benchmarks
|
|
98
|
+
|
|
99
|
+
These are **pi-jscpd** benchmarks, not a raw `jscpd` CLI. Each cell is an isolated
|
|
100
|
+
Pi 0.85.1 `/jscpd scan` through this extension (packaged jscpd `5.1.2` still
|
|
101
|
+
detects). Full-tree snapshots, not session findings and not a quality ranking.
|
|
102
|
+
Median of three fresh host processes on macOS arm64 / Node 24.12.0, 2026-09-17.
|
|
103
|
+
|
|
104
|
+
| | Project | Version | Blocks | Dup. lines | `/jscpd scan` |
|
|
105
|
+
| --- | --- | --- | ---: | ---: | ---: |
|
|
106
|
+
| ⚡ | [Vite](https://github.com/vitejs/vite) | [v8.3.0](https://github.com/vitejs/vite/tree/434e8e9495436a60789f2b588a04a6a24a3d1661) | 524 | 5.91% | 498 ms |
|
|
107
|
+
| ⏱️ | [React](https://github.com/facebook/react) | [v19.3.0](https://github.com/facebook/react/tree/1d34f91dfde6bba84d08b683aaba164c7194dacb) | 10,812 | 17.38% | 3.11 s |
|
|
108
|
+
| ⚡ | [Vue](https://github.com/vuejs/core) | [v3.5.43](https://github.com/vuejs/core/tree/5be58b4c475c1d14b4abacbfeda610394a0ee4e5) | 805 | 6.71% | 451 ms |
|
|
109
|
+
| ⏱️ | [Svelte](https://github.com/sveltejs/svelte) | [svelte@5.57.0](https://github.com/sveltejs/svelte/tree/7bc0a70fe64dbb3fa3848b741963f31d1e10a8dc) | 1,102 | 8.27% | 1.25 s |
|
|
110
|
+
| ⚡ | [Express](https://github.com/expressjs/express) | [v5.2.1](https://github.com/expressjs/express/tree/dbac741a49a5a64336b70c06e85c2e2706e36336) | 274 | 11.19% | 142 ms |
|
|
111
|
+
| ⏱️ | [Prettier](https://github.com/prettier/prettier) | [3.9.8](https://github.com/prettier/prettier/tree/4f2ab6765d7cb29408a2abdac75d023d64d44107) | 976 | 4.88% | 1.16 s |
|
|
112
|
+
|
|
113
|
+
⚡ under 1 s · ⏱️ 1 s or more. Totals are jscpd’s; the session lists a bounded subset.
|
|
114
|
+
Version links open the exact scanned commit. Method and sample times:
|
|
115
|
+
[pi-jscpd benchmark method](docs/benchmarks.md). Scheduled refresh:
|
|
116
|
+
[#111](https://github.com/revazi/pi-jscpd/issues/111).
|
|
117
|
+
|
|
118
|
+
## 🔄 How session checks work
|
|
82
119
|
|
|
83
120
|
At session start, the extension captures one bounded, in-memory project baseline.
|
|
84
121
|
It then tracks successful writes and edits made through Pi's built-in `write`
|
|
@@ -87,11 +124,11 @@ and `edit` tools.
|
|
|
87
124
|
After Pi settles, one coalesced background check compares the current project
|
|
88
125
|
with the baseline:
|
|
89
126
|
|
|
90
|
-
- clean checks stay out of model context;
|
|
91
|
-
- failures remain advisory and available through `/jscpd status`;
|
|
92
|
-
- new duplicate blocks are reported with both locations;
|
|
93
|
-
- existing repository duplication is omitted from changed-only results; and
|
|
94
|
-
- actionable automatic findings never trigger a surprise model turn.
|
|
127
|
+
- 🤫 clean checks stay out of model context;
|
|
128
|
+
- ⚠️ failures remain advisory and available through `/jscpd status`;
|
|
129
|
+
- 📍 new duplicate blocks are reported with both locations;
|
|
130
|
+
- 🗂️ existing repository duplication is omitted from changed-only results; and
|
|
131
|
+
- 🚫 actionable automatic findings never trigger a surprise model turn.
|
|
95
132
|
|
|
96
133
|
Displayed findings are acknowledged for the active conversation branch so the
|
|
97
134
|
same unchanged block is not repeatedly reported. Baselines, source bytes,
|
|
@@ -101,20 +138,27 @@ Manual edits, shell commands, custom mutation tools, deletes, and renames are no
|
|
|
101
138
|
attributed because Pi does not provide a stable structured file list for them.
|
|
102
139
|
Use `/jscpd scan` when changes happened outside built-in `write` or `edit`.
|
|
103
140
|
|
|
104
|
-
## Interactive overview
|
|
141
|
+
## 🖥️ Interactive overview
|
|
142
|
+
|
|
143
|
+

|
|
144
|
+
|
|
145
|
+
*Real Pi TUI, disposable synthetic project, explicit project scan and Enter to
|
|
146
|
+
expand. Monochrome terminal-cell capture cropped to the overlay; no mock results.
|
|
147
|
+
This is current duplication, not a session-delta example.
|
|
148
|
+
[Capture details and text alternative](docs/adoption.md#visual-provenance).*
|
|
105
149
|
|
|
106
150
|
Bare `/jscpd` opens a status-first, Fallow-style bounded TUI with:
|
|
107
151
|
|
|
108
|
-
- a framed overview of mode, binary, configuration, last check, and explicit
|
|
152
|
+
- 📋 a framed overview of mode, binary, configuration, last check, and explicit
|
|
109
153
|
changed/project scan actions;
|
|
110
|
-
- a searchable, scrollable findings navigator that retains up to 100 findings,
|
|
154
|
+
- 🔎 a searchable, scrollable findings navigator that retains up to 100 findings,
|
|
111
155
|
initially shows 10, and reveals the next 10 with `L` or by navigating past the
|
|
112
156
|
last shown row—without rescanning or changing configuration;
|
|
113
|
-
- both duplicate locations, size, format, session relationship, inline detail,
|
|
157
|
+
- 📍 both duplicate locations, size, format, session relationship, inline detail,
|
|
114
158
|
verification, and omission/ambiguity context;
|
|
115
|
-
- `j`/`k`, arrows, Home/End, paging, expand/collapse, search, and multi-selection
|
|
159
|
+
- ⌨️ `j`/`k`, arrows, Home/End, paging, expand/collapse, search, and multi-selection
|
|
116
160
|
controls consistent with Pi Fallow's navigator; and
|
|
117
|
-
- a bounded `e`/`a` handoff that closes the overlay and loads selected findings
|
|
161
|
+
- ✉️ a bounded `e`/`a` handoff that closes the overlay and loads selected findings
|
|
118
162
|
into Pi's editor for user review.
|
|
119
163
|
|
|
120
164
|
The extra overlay cache is in-memory and TUI-only. `maxFindings` still caps
|
|
@@ -125,7 +169,7 @@ runs project tests, or refactors automatically. In RPC, JSON, and print modes,
|
|
|
125
169
|
explicit subcommands remain available and the bare command uses a bounded
|
|
126
170
|
non-interactive fallback.
|
|
127
171
|
|
|
128
|
-
## Configuration
|
|
172
|
+
## ⚙️ Configuration
|
|
129
173
|
|
|
130
174
|
Project configuration is optional:
|
|
131
175
|
|
|
@@ -156,9 +200,16 @@ Clone thresholds, formats, ignore rules, and other detection policy belong in
|
|
|
156
200
|
jscpd's normal configuration, such as `.jscpd.json` or package-level jscpd
|
|
157
201
|
settings. The extension does not maintain a parallel clone policy.
|
|
158
202
|
|
|
159
|
-
## Fallow coexistence
|
|
203
|
+
## 🤝 Fallow coexistence
|
|
204
|
+
|
|
205
|
+
| | Choose | When it fits |
|
|
206
|
+
| --- | --- | --- |
|
|
207
|
+
| 🧬 | `pi-jscpd` | Focused polyglot duplicate-block review, session deltas, or reuse of existing jscpd detection/CI policy |
|
|
208
|
+
| 🌿 | Pi Fallow | Broader JavaScript/TypeScript codebase analysis, including duplication, dead code, complexity, and related checks |
|
|
209
|
+
| 🤝 | Both | Fallow's broader checks plus scoped jscpd analysis where its formats or existing policy add value; avoid checking the same duplication scope twice without a reason |
|
|
160
210
|
|
|
161
|
-
|
|
211
|
+
Neither replaces the other's full workflow or your repository's tests and CI
|
|
212
|
+
policy. Pi Fallow can also detect duplication. With the default `auto` policy,
|
|
162
213
|
`pi-jscpd` conservatively detects supported signs of active Fallow duplication
|
|
163
214
|
analysis and moves automatic jscpd checks to on-demand mode to avoid duplicate
|
|
164
215
|
warnings.
|
|
@@ -170,25 +221,25 @@ Explicit `/jscpd changed`, project scans, and scoped scans remain available. Set
|
|
|
170
221
|
See [Fallow coexistence](docs/fallow-coexistence.md) for the supported signals
|
|
171
222
|
and limitations.
|
|
172
223
|
|
|
173
|
-
## Safety and privacy
|
|
224
|
+
## 🔒 Safety and privacy
|
|
174
225
|
|
|
175
|
-
- Advisory and read-only by default.
|
|
176
|
-
- Never downloads packages at runtime or mutates source.
|
|
177
|
-
- Invokes binaries with argument arrays, never a shell command string.
|
|
178
|
-
- Keeps reports in restrictive temporary directories and removes them after
|
|
226
|
+
- 🧭 Advisory and read-only by default.
|
|
227
|
+
- 📦 Never downloads packages at runtime or mutates source.
|
|
228
|
+
- 🧱 Invokes binaries with argument arrays, never a shell command string.
|
|
229
|
+
- 🧹 Keeps reports in restrictive temporary directories and removes them after
|
|
179
230
|
success, failure, timeout, cancellation, or shutdown.
|
|
180
|
-
- Bounds process time, output, report size, findings, paths, and persisted state.
|
|
181
|
-
- Omits source fragments, raw child output, temporary paths, and internal
|
|
231
|
+
- ⏱️ Bounds process time, output, report size, findings, paths, and persisted state.
|
|
232
|
+
- 🙈 Omits source fragments, raw child output, temporary paths, and internal
|
|
182
233
|
fingerprints from results.
|
|
183
|
-
- Reads extension configuration only for trusted projects.
|
|
184
|
-
- Fails open so analyzer problems do not break the Pi session.
|
|
234
|
+
- 🔐 Reads extension configuration only for trusted projects.
|
|
235
|
+
- 🛟 Fails open so analyzer problems do not break the Pi session.
|
|
185
236
|
|
|
186
|
-
## Requirements
|
|
237
|
+
## ✅ Requirements
|
|
187
238
|
|
|
188
239
|
| Component | Supported |
|
|
189
240
|
| --- | --- |
|
|
190
241
|
| Node.js | `>=22.19.0 <23` or `>=24 <25` |
|
|
191
|
-
| Pi packages | `>=0.84.4 <0.85.0` |
|
|
242
|
+
| Pi packages | `>=0.84.4 <0.85.0` or `>=0.85.1 <0.86.0` (tested with `0.85.1`) |
|
|
192
243
|
| TypeBox | `>=1.3.7 <2` |
|
|
193
244
|
| Effect | Exact reviewed `3.22.1` runtime foundation |
|
|
194
245
|
| jscpd | Bundled `5.1.2`; compatible project-local or `PATH` v5 installations are preferred |
|
|
@@ -196,7 +247,20 @@ and limitations.
|
|
|
196
247
|
See the [compatibility policy](docs/compatibility.md) for the exact tested
|
|
197
248
|
fixtures and certification matrix.
|
|
198
249
|
|
|
199
|
-
##
|
|
250
|
+
## 💬 Share feedback
|
|
251
|
+
|
|
252
|
+
Tried a scan or the onboarding examples? Use the optional [validation and adoption
|
|
253
|
+
feedback form](https://github.com/revazi/pi-jscpd/issues/new?template=adoption-feedback.yml).
|
|
254
|
+
It asks for version information and coarse size, latency, and finding-review
|
|
255
|
+
buckets; “Unknown” and “Not tested” are welcome. No new scan is required.
|
|
256
|
+
|
|
257
|
+
Submissions are public and manual—no telemetry or automatic submission is added.
|
|
258
|
+
Do not include credentials, private paths, source fragments, raw reports, raw
|
|
259
|
+
child output, terminal captures, or account/repository identifiers. For a
|
|
260
|
+
reproducible defect, prefer the [bug report](https://github.com/revazi/pi-jscpd/issues/new?template=bug-report.yml);
|
|
261
|
+
report vulnerabilities [privately](SECURITY.md).
|
|
262
|
+
|
|
263
|
+
## 🧩 More Pi packages by Revaz
|
|
200
264
|
|
|
201
265
|
| Package | Purpose |
|
|
202
266
|
| --- | --- |
|
|
@@ -206,7 +270,7 @@ fixtures and certification matrix.
|
|
|
206
270
|
| [`pi-tmux-orchestrator`](https://www.npmjs.com/package/pi-tmux-orchestrator) | Multi-agent coordination in tmux |
|
|
207
271
|
| [`@tasklight/pi-tasklight`](https://www.npmjs.com/package/@tasklight/pi-tasklight) | Tasklight notifications for Pi |
|
|
208
272
|
|
|
209
|
-
## Development
|
|
273
|
+
## 🛠️ Development
|
|
210
274
|
|
|
211
275
|
```sh
|
|
212
276
|
npm ci --ignore-scripts
|
|
@@ -228,16 +292,19 @@ workflow files.
|
|
|
228
292
|
|
|
229
293
|
Useful documentation:
|
|
230
294
|
|
|
231
|
-
- [
|
|
232
|
-
- [
|
|
233
|
-
- [
|
|
234
|
-
- [
|
|
235
|
-
- [
|
|
236
|
-
- [
|
|
237
|
-
- [
|
|
238
|
-
- [
|
|
239
|
-
- [
|
|
240
|
-
|
|
241
|
-
|
|
295
|
+
- 📊 [pi-jscpd benchmarks](docs/benchmarks.md)
|
|
296
|
+
- ✨ [First scans and safe finding review](docs/adoption.md)
|
|
297
|
+
- 🧬 [Effect architecture and conformance](docs/effect-architecture.md)
|
|
298
|
+
- ⏱️ [Automatic checkpoint lifecycle](docs/automatic-checkpoint.md)
|
|
299
|
+
- 🖥️ [`/jscpd` overlay contract](docs/overlay-interaction.md)
|
|
300
|
+
- 🤝 [Fallow coexistence](docs/fallow-coexistence.md)
|
|
301
|
+
- ✅ [Compatibility and packed-artifact certification](docs/compatibility.md)
|
|
302
|
+
- 📋 [Real-project validation evidence](docs/m8-validation.md)
|
|
303
|
+
- 🏷️ [Release preparation and publication policy](docs/release.md)
|
|
304
|
+
- 👋 [Contributing](CONTRIBUTING.md)
|
|
305
|
+
- 🔐 [Security policy](SECURITY.md)
|
|
306
|
+
- 📝 [Changelog](CHANGELOG.md)
|
|
307
|
+
|
|
308
|
+
## 📄 License
|
|
242
309
|
|
|
243
310
|
[MIT](./LICENSE) © 2026 Revaz Zakalashvili
|
package/SECURITY.md
CHANGED
package/docs/adoption.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# ✨ First scans and safe finding review
|
|
2
|
+
|
|
3
|
+
[Install and run your first scan](../README.md#install), then choose the smallest
|
|
4
|
+
useful scope below. These examples describe expected workflows, not transcripts
|
|
5
|
+
or claims about your repository. All scans are read-only and advisory.
|
|
6
|
+
|
|
7
|
+
## ✦ Clean scan: start with one scope
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
/jscpd scan src
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
If jscpd finds no duplicate blocks under `src` with the current detection policy,
|
|
14
|
+
the explicit result is clean. This does **not** prove the entire repository is
|
|
15
|
+
free of duplication: matches outside that target, ignored files, unsupported
|
|
16
|
+
formats, and blocks below the configured thresholds are outside the result.
|
|
17
|
+
A failure or timeout is not a clean scan; `/jscpd status` gives bounded diagnostics
|
|
18
|
+
and Pi can continue normally.
|
|
19
|
+
|
|
20
|
+
To compare two areas, include both:
|
|
21
|
+
|
|
22
|
+
```text
|
|
23
|
+
/jscpd scan src lib
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Replace the targets with existing in-project paths. Quote a path containing spaces,
|
|
27
|
+
for example `/jscpd scan "sample app"`. Scoped scans compare only their targets;
|
|
28
|
+
`/jscpd changed` instead compares the full project and filters by tracked Pi edits.
|
|
29
|
+
|
|
30
|
+
## 🔄 New in this session: distinguish new work from existing debt
|
|
31
|
+
|
|
32
|
+
Suppose `src/orders.py` already contains a block when a fresh Pi session begins.
|
|
33
|
+
Later, Pi's built-in `write` or `edit` adds matching code in `src/summary.py`.
|
|
34
|
+
With a usable baseline and an identifiable new pair, the changed check can show:
|
|
35
|
+
|
|
36
|
+
- `src/summary.py`: **new in this session**;
|
|
37
|
+
- `src/orders.py`: **existing match**;
|
|
38
|
+
- the duplicate block's line spans, size, and format for inspection.
|
|
39
|
+
|
|
40
|
+
```text
|
|
41
|
+
/jscpd changed
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Automatic checks normally surface actionable new findings after Pi settles,
|
|
45
|
+
without starting another model turn. If the finding was already surfaced, an
|
|
46
|
+
explicit changed check may omit it because it is acknowledged—not because it was
|
|
47
|
+
fixed. Existing repository duplication is also omitted from changed-only findings.
|
|
48
|
+
Use `/jscpd scan src` (or a project scan for matches outside `src`) to inspect
|
|
49
|
+
current duplication regardless of acknowledgement.
|
|
50
|
+
|
|
51
|
+
A full or scoped `scan` labels **current locations**; it does not determine which
|
|
52
|
+
side is new. A missing/partial baseline or ambiguous identity is not proof of a
|
|
53
|
+
new duplicate. Shell commands, manual edits, and custom mutation tools are not
|
|
54
|
+
tracked as Pi-owned changes; use an explicit `scan` for those changes.
|
|
55
|
+
See [session checks](../README.md#how-session-checks-work) for the lifecycle and
|
|
56
|
+
[Fallow coexistence](fallow-coexistence.md) when automatic checks are on demand.
|
|
57
|
+
|
|
58
|
+
## 📌 Intentional duplication: use normal jscpd policy
|
|
59
|
+
|
|
60
|
+
A duplicate test fixture may deliberately preserve an independent example or a
|
|
61
|
+
protocol boundary. Inspect both locations and ask whether they should evolve
|
|
62
|
+
together. Keeping the duplicate can be the correct outcome; no exclusion is
|
|
63
|
+
required merely to dismiss an advisory finding.
|
|
64
|
+
|
|
65
|
+
If the maintainer decides a fixture directory should be outside detection,
|
|
66
|
+
merge a narrow exclusion into the repository's existing `.jscpd.json` policy:
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"ignore": ["**/test/fixtures/**"]
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
This is an example for a deliberately excluded fixture directory, not a
|
|
75
|
+
recommendation to ignore all tests. Preserve other ignore entries and settings;
|
|
76
|
+
do not replace an existing configuration with this snippet. Repositories using
|
|
77
|
+
package-level jscpd settings should keep their policy there instead. Detection
|
|
78
|
+
policy does not belong in `.pi/jscpd-guardrail.json`.
|
|
79
|
+
|
|
80
|
+
Review the policy change through the normal agent/code-review flow, then rerun
|
|
81
|
+
the same scan scope. Fewer findings after an exclusion mean less code was analyzed,
|
|
82
|
+
not that source duplication was removed. Start a fresh Pi session (rather than
|
|
83
|
+
resuming previously tracked edits) before a session-delta comparison under changed
|
|
84
|
+
detection policy so its baseline uses the same policy.
|
|
85
|
+
|
|
86
|
+
## 🔍 Review without automatic refactoring
|
|
87
|
+
|
|
88
|
+
1. Open `/jscpd`, choose a scan action, then press Enter on a finding to expand
|
|
89
|
+
both locations. Opening the overview itself does not scan.
|
|
90
|
+
2. Read both blocks and surrounding behavior before deciding whether to share
|
|
91
|
+
code, retain independent implementations, or propose a narrow exclusion.
|
|
92
|
+
3. Optionally press `e` to load the current/selected finding into Pi's editor.
|
|
93
|
+
Review the prompt before submitting; the handoff does not submit or edit code.
|
|
94
|
+
4. Only make a justified change through your normal agent flow. Run relevant
|
|
95
|
+
project tests, then repeat the same scan scope. Verification can report removed,
|
|
96
|
+
remaining, or newly created duplicate blocks; it does not prove behavior is
|
|
97
|
+
correct. Respect omitted and safely unclassified counts.
|
|
98
|
+
|
|
99
|
+
[Full overlay controls](overlay-interaction.md#keyboard-and-accessibility-contract)
|
|
100
|
+
and the on-demand `/skill:jscpd` provide the detailed workflow without adding
|
|
101
|
+
routine guidance to every model turn. `/jscpd off` disables both explicit and
|
|
102
|
+
automatic scans for this session; `/jscpd on` restores scanning. Neither edits
|
|
103
|
+
configuration, enforces a threshold on Pi writes, or refactors code.
|
|
104
|
+
|
|
105
|
+
## 📷 Visual provenance
|
|
106
|
+
|
|
107
|
+
The [README image](images/jscpd-findings.png) comes from the unmodified source
|
|
108
|
+
extension at `fa7872d`, loaded by real Pi 0.85.1 with Node 24.12.0 and bundled
|
|
109
|
+
jscpd 5.1.2 on macOS arm64. An isolated, disposable project contained two generated
|
|
110
|
+
Python files; no private repository was used. The real analyzer found one pair
|
|
111
|
+
(14 lines, 89 tokens). Both files existed before Pi started, so this image shows
|
|
112
|
+
**current locations**, not newly introduced duplication.
|
|
113
|
+
|
|
114
|
+
Capture sequence: regular TUI at 80 columns by 32 rows, `/jscpd`, `s` for project
|
|
115
|
+
scan, Enter to expand the finding. The terminal cells were rasterized in monochrome
|
|
116
|
+
and cropped to the overlay. No text, counts, labels, or results were substituted;
|
|
117
|
+
compact-row truncation and wrapping are the actual TUI output. The image is
|
|
118
|
+
1192×652 pixels and is intended to remain readable when scaled to README width.
|
|
119
|
+
|
|
120
|
+
Text alternative: one Python duplicate block links `src/orders.py:1-14` and
|
|
121
|
+
`src/summary.py:1-14`. Detail records a verification checkpoint, explains that a
|
|
122
|
+
project scan cannot decide which location is new, and asks the user to inspect
|
|
123
|
+
both locations and surrounding behavior before changing code.
|
|
124
|
+
|
|
125
|
+
The capture run used offline mode, isolated home/agent/temp directories, no
|
|
126
|
+
session persistence, no project trust approval, no resource discovery, and no
|
|
127
|
+
provider or built-in tool calls. Pi quit normally; no analyzer reports remained.
|
|
128
|
+
Only the cropped sanitized PNG and this aggregate provenance are retained—not
|
|
129
|
+
raw terminal output, source fixtures, reports, host/account data, or private paths.
|
|
130
|
+
This adoption visual is separate from the [#99 validation
|
|
131
|
+
evidence](m8-validation.md); it makes no additional performance or usability claim.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Automatic advisory checkpoint decision
|
|
1
|
+
# ⏱️ Automatic advisory checkpoint decision
|
|
2
2
|
|
|
3
3
|
Status: **implemented with Effect-owned scheduling and automatic delivery**
|
|
4
4
|
|
|
@@ -33,8 +33,9 @@ candidate check, not one process per write or model turn.
|
|
|
33
33
|
|
|
34
34
|
## Evidence
|
|
35
35
|
|
|
36
|
-
The decision was evaluated against Pi 0.84.4
|
|
37
|
-
documentation, public type definitions, and
|
|
36
|
+
The decision was originally evaluated against Pi 0.84.4 and rechecked against
|
|
37
|
+
Pi 0.85.1's published extension documentation, public type definitions, and
|
|
38
|
+
`AgentSession` runtime. The 0.85 lifecycle contract remains compatible.
|
|
38
39
|
|
|
39
40
|
Pi documents and types distinguish the candidate events as follows:
|
|
40
41
|
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# 📊 pi-jscpd benchmarks
|
|
2
|
+
|
|
3
|
+
These rows are **pi-jscpd benchmarks**, not a raw `jscpd` CLI. Each sample loads the
|
|
4
|
+
source extension into an isolated Pi 0.85.1 RPC host and runs `/jscpd scan` on a
|
|
5
|
+
pinned public tree. jscpd `5.1.2` remains the detector; the times and outcomes
|
|
6
|
+
include capability resolution, report decoding, normalization, and the public
|
|
7
|
+
notify. They are **full-tree duplication snapshots**, not session-delta findings
|
|
8
|
+
and not a code-quality ranking.
|
|
9
|
+
|
|
10
|
+
Host: macOS arm64, Node 24.12.0, Pi 0.85.1, packaged jscpd `5.1.2`. Date:
|
|
11
|
+
2026-09-17. No project `.jscpd.json`. Shallow clones of the listed tags. Reports
|
|
12
|
+
stayed in owned temporary directories and were removed. Pi ran offline, without
|
|
13
|
+
discovery, project trust, session persistence, a provider, or built-in tools.
|
|
14
|
+
|
|
15
|
+
Three fresh Pi processes per project. **Scan** is milliseconds from `/jscpd scan`
|
|
16
|
+
until the extension notify. Host ready (start + command discovery) was about
|
|
17
|
+
1.2–1.5 s and is **not** included in scan time.
|
|
18
|
+
|
|
19
|
+
## pi-jscpd snapshot
|
|
20
|
+
|
|
21
|
+
| Project | Pin | Sources | Duplicate blocks | Dup. lines | Median `/jscpd scan` |
|
|
22
|
+
| --- | --- | ---: | ---: | ---: | ---: |
|
|
23
|
+
| [Vite](https://github.com/vitejs/vite) | [v8.3.0](https://github.com/vitejs/vite/tree/434e8e9495436a60789f2b588a04a6a24a3d1661) | 1,107 | 524 | 5.91% | 498 ms |
|
|
24
|
+
| [React](https://github.com/facebook/react) | [v19.3.0](https://github.com/facebook/react/tree/1d34f91dfde6bba84d08b683aaba164c7194dacb) | 7,962 | 10,812 | 17.38% | 3.11 s |
|
|
25
|
+
| [Vue](https://github.com/vuejs/core) | [v3.5.43](https://github.com/vuejs/core/tree/5be58b4c475c1d14b4abacbfeda610394a0ee4e5) | 598 | 805 | 6.71% | 451 ms |
|
|
26
|
+
| [Svelte](https://github.com/sveltejs/svelte) | [svelte@5.57.0](https://github.com/sveltejs/svelte/tree/7bc0a70fe64dbb3fa3848b741963f31d1e10a8dc) | 4,499 | 1,102 | 8.27% | 1.25 s |
|
|
27
|
+
| [Express](https://github.com/expressjs/express) | [v5.2.1](https://github.com/expressjs/express/tree/dbac741a49a5a64336b70c06e85c2e2706e36336) | 183 | 274 | 11.19% | 142 ms |
|
|
28
|
+
| [Prettier](https://github.com/prettier/prettier) | [3.9.8](https://github.com/prettier/prettier/tree/4f2ab6765d7cb29408a2abdac75d023d64d44107) | 3,320 | 976 | 4.88% | 1.16 s |
|
|
29
|
+
|
|
30
|
+
Every row returned findings. Notifies stayed at 47 lines (presentation cap).
|
|
31
|
+
React and Svelte keep jscpd’s full totals; the session retains at most 1,000
|
|
32
|
+
path-resolved pairs and does not keep source fragments or the raw JSON.
|
|
33
|
+
|
|
34
|
+
Prettier clone counts were 976 / 982 / 976. The table keeps the repeating
|
|
35
|
+
976 / 4.88% snapshot.
|
|
36
|
+
|
|
37
|
+
Sample `/jscpd scan` times (ms):
|
|
38
|
+
|
|
39
|
+
| Project | First | Later | Median |
|
|
40
|
+
| --- | ---: | ---: | ---: |
|
|
41
|
+
| Vite | 560 | 470, 498 | 498 |
|
|
42
|
+
| React | 3,107 | 3,210, 2,974 | 3,107 |
|
|
43
|
+
| Vue | 399 | 459, 451 | 451 |
|
|
44
|
+
| Svelte | 1,292 | 1,251, 1,241 | 1,251 |
|
|
45
|
+
| Express | 142 | 141, 145 | 142 |
|
|
46
|
+
| Prettier | 1,163 | 1,112, 1,177 | 1,163 |
|
|
47
|
+
|
|
48
|
+
## How to read this
|
|
49
|
+
|
|
50
|
+
- This is the extension’s explicit project scan, not `jscpd` invoked by hand
|
|
51
|
+
and not a TUI overlay run.
|
|
52
|
+
- **Sources** and **duplicate blocks** come from the public notify summary after
|
|
53
|
+
decoding. They are jscpd totals, even when extra pairs are omitted from the
|
|
54
|
+
listed findings.
|
|
55
|
+
- **Median scan** is not a SLA. It includes analyzer work plus `pi-jscpd`
|
|
56
|
+
decoding and presentation.
|
|
57
|
+
- A higher percentage is not “worse code.” Scaffolding and tests duplicate on
|
|
58
|
+
purpose.
|
|
59
|
+
|
|
60
|
+
Scheduled refresh is tracked in
|
|
61
|
+
[issue #111](https://github.com/revazi/pi-jscpd/issues/111).
|
|
62
|
+
|
|
63
|
+
## Reproduction
|
|
64
|
+
|
|
65
|
+
On a supported Node fixture with this repository’s locked dependencies:
|
|
66
|
+
|
|
67
|
+
1. Shallow-clone each tag into an owned temporary directory.
|
|
68
|
+
2. Start isolated Pi 0.85.1 in RPC mode: offline, no session, no discovery, no
|
|
69
|
+
project trust, no built-in tools, `--tools jscpd_run`, and `-e` pointing at
|
|
70
|
+
this source extension. Put the packaged `node_modules/.bin` on `PATH`.
|
|
71
|
+
3. After the host is ready, send `/jscpd scan`. Time until the extension notify.
|
|
72
|
+
Keep only the summary line (counts and timings). Do not retain notify bodies,
|
|
73
|
+
paths, or reports.
|
|
74
|
+
4. Repeat in three fresh Pi processes. Confirm stderr is empty and report
|
|
75
|
+
directories are gone after shutdown.
|
|
76
|
+
5. Delete the clone.
|
|
77
|
+
|
|
78
|
+
Do not commit clones, reports, or source fragments.
|