pi-jscpd 0.2.0 → 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 CHANGED
@@ -7,6 +7,34 @@ 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
+
31
+ ## [0.2.1] - 2026-09-06
32
+
33
+ ### Added
34
+
35
+ - Added a quiet, TUI-only update warning using one bounded, best-effort npm
36
+ metadata check, with offline and environment-variable opt-outs.
37
+
10
38
  ## [0.2.0] - 2026-09-06
11
39
 
12
40
  ### Added
@@ -116,7 +144,9 @@ published releases use [Semantic Versioning](https://semver.org/).
116
144
  - Project paths, child output, reports, temporary directories, cancellation,
117
145
  configuration trust, and lifecycle cleanup are bounded and fail open.
118
146
 
119
- [Unreleased]: https://github.com/revazi/pi-jscpd/compare/v0.2.0...HEAD
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
149
+ [0.2.1]: https://github.com/revazi/pi-jscpd/compare/v0.2.0...v0.2.1
120
150
  [0.2.0]: https://github.com/revazi/pi-jscpd/compare/v0.1.1...v0.2.0
121
151
  [0.1.1]: https://github.com/revazi/pi-jscpd/compare/v0.1.0...v0.1.1
122
152
  [0.1.0]: https://github.com/revazi/pi-jscpd/releases/tag/v0.1.0
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. `pack:certify` installs and exercises the exact tarball.
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: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
7
7
  [![GitHub issues](https://img.shields.io/github/issues/revazi/pi-jscpd.svg)](https://github.com/revazi/pi-jscpd/issues)
8
8
 
9
- A quiet, read-only duplication guardrail for the [Pi coding agent](https://github.com/earendil-works/pi), powered by [jscpd](https://github.com/kucherenko/jscpd).
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
- ## Install
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,30 +31,40 @@ 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 and verify the setup:
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
- If no compatible binary is available, the extension stays dormant and Pi
33
- continues normally.
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
- ## Usage
47
+ In TUI sessions, the extension performs one best-effort, metadata-only npm check
48
+ and shows a warning only when a newer `pi-jscpd` release is available. The check
49
+ is bounded to 1.5 seconds, never sends project data, and never downloads or
50
+ installs package content. Set `PI_JSCPD_DISABLE_UPDATE_NOTICE=1` (or run Pi
51
+ offline) to disable it.
52
+
53
+ ## ⌨️ Usage
36
54
 
37
55
  Run `/jscpd` to open the interactive overview. Opening it shows status only; it
38
56
  never starts an implicit scan.
39
57
 
40
- | Command | Purpose |
41
- | --- | --- |
42
- | `/jscpd` | Open the responsive overview |
43
- | `/jscpd changed` | Show unacknowledged duplication introduced this session |
44
- | `/jscpd scan` | Scan the whole project |
45
- | `/jscpd scan src tests` | Scan specific in-project files or directories |
46
- | `/jscpd status` | Show binary, configuration, mode, and last-check status |
47
- | `/jscpd off` | Disable scans for the current session |
48
- | `/jscpd on` | Re-enable scans for the current session |
49
- | `/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 |
50
68
 
51
69
  Pi can use the same operations through the `jscpd_run` tool:
52
70
 
@@ -72,7 +90,32 @@ description at startup and loads its full workflow guidance on demand when a
72
90
  duplication task matches or the user invokes the skill command. The extension
73
91
  and `jscpd_run` tool remain usable when skills are disabled.
74
92
 
75
- ## How session checks work
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
76
119
 
77
120
  At session start, the extension captures one bounded, in-memory project baseline.
78
121
  It then tracks successful writes and edits made through Pi's built-in `write`
@@ -81,11 +124,11 @@ and `edit` tools.
81
124
  After Pi settles, one coalesced background check compares the current project
82
125
  with the baseline:
83
126
 
84
- - clean checks stay out of model context;
85
- - failures remain advisory and available through `/jscpd status`;
86
- - new duplicate blocks are reported with both locations;
87
- - existing repository duplication is omitted from changed-only results; and
88
- - 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.
89
132
 
90
133
  Displayed findings are acknowledged for the active conversation branch so the
91
134
  same unchanged block is not repeatedly reported. Baselines, source bytes,
@@ -95,20 +138,27 @@ Manual edits, shell commands, custom mutation tools, deletes, and renames are no
95
138
  attributed because Pi does not provide a stable structured file list for them.
96
139
  Use `/jscpd scan` when changes happened outside built-in `write` or `edit`.
97
140
 
98
- ## Interactive overview
141
+ ## 🖥️ Interactive overview
142
+
143
+ ![Real /jscpd findings view: one Python duplicate block, both current locations, and advisory review guidance](docs/images/jscpd-findings.png)
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).*
99
149
 
100
150
  Bare `/jscpd` opens a status-first, Fallow-style bounded TUI with:
101
151
 
102
- - a framed overview of mode, binary, configuration, last check, and explicit
152
+ - 📋 a framed overview of mode, binary, configuration, last check, and explicit
103
153
  changed/project scan actions;
104
- - a searchable, scrollable findings navigator that retains up to 100 findings,
154
+ - 🔎 a searchable, scrollable findings navigator that retains up to 100 findings,
105
155
  initially shows 10, and reveals the next 10 with `L` or by navigating past the
106
156
  last shown row—without rescanning or changing configuration;
107
- - both duplicate locations, size, format, session relationship, inline detail,
157
+ - 📍 both duplicate locations, size, format, session relationship, inline detail,
108
158
  verification, and omission/ambiguity context;
109
- - `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
110
160
  controls consistent with Pi Fallow's navigator; and
111
- - 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
112
162
  into Pi's editor for user review.
113
163
 
114
164
  The extra overlay cache is in-memory and TUI-only. `maxFindings` still caps
@@ -119,7 +169,7 @@ runs project tests, or refactors automatically. In RPC, JSON, and print modes,
119
169
  explicit subcommands remain available and the bare command uses a bounded
120
170
  non-interactive fallback.
121
171
 
122
- ## Configuration
172
+ ## ⚙️ Configuration
123
173
 
124
174
  Project configuration is optional:
125
175
 
@@ -150,9 +200,16 @@ Clone thresholds, formats, ignore rules, and other detection policy belong in
150
200
  jscpd's normal configuration, such as `.jscpd.json` or package-level jscpd
151
201
  settings. The extension does not maintain a parallel clone policy.
152
202
 
153
- ## 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 |
154
210
 
155
- Pi Fallow can also detect duplication. With the default `auto` policy,
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,
156
213
  `pi-jscpd` conservatively detects supported signs of active Fallow duplication
157
214
  analysis and moves automatic jscpd checks to on-demand mode to avoid duplicate
158
215
  warnings.
@@ -164,25 +221,25 @@ Explicit `/jscpd changed`, project scans, and scoped scans remain available. Set
164
221
  See [Fallow coexistence](docs/fallow-coexistence.md) for the supported signals
165
222
  and limitations.
166
223
 
167
- ## Safety and privacy
224
+ ## 🔒 Safety and privacy
168
225
 
169
- - Advisory and read-only by default.
170
- - Never downloads packages at runtime or mutates source.
171
- - Invokes binaries with argument arrays, never a shell command string.
172
- - 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
173
230
  success, failure, timeout, cancellation, or shutdown.
174
- - Bounds process time, output, report size, findings, paths, and persisted state.
175
- - 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
176
233
  fingerprints from results.
177
- - Reads extension configuration only for trusted projects.
178
- - 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.
179
236
 
180
- ## Requirements
237
+ ## ✅ Requirements
181
238
 
182
239
  | Component | Supported |
183
240
  | --- | --- |
184
241
  | Node.js | `>=22.19.0 <23` or `>=24 <25` |
185
- | 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`) |
186
243
  | TypeBox | `>=1.3.7 <2` |
187
244
  | Effect | Exact reviewed `3.22.1` runtime foundation |
188
245
  | jscpd | Bundled `5.1.2`; compatible project-local or `PATH` v5 installations are preferred |
@@ -190,7 +247,20 @@ and limitations.
190
247
  See the [compatibility policy](docs/compatibility.md) for the exact tested
191
248
  fixtures and certification matrix.
192
249
 
193
- ## More Pi packages by Revaz
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
194
264
 
195
265
  | Package | Purpose |
196
266
  | --- | --- |
@@ -200,7 +270,7 @@ fixtures and certification matrix.
200
270
  | [`pi-tmux-orchestrator`](https://www.npmjs.com/package/pi-tmux-orchestrator) | Multi-agent coordination in tmux |
201
271
  | [`@tasklight/pi-tasklight`](https://www.npmjs.com/package/@tasklight/pi-tasklight) | Tasklight notifications for Pi |
202
272
 
203
- ## Development
273
+ ## 🛠️ Development
204
274
 
205
275
  ```sh
206
276
  npm ci --ignore-scripts
@@ -222,16 +292,19 @@ workflow files.
222
292
 
223
293
  Useful documentation:
224
294
 
225
- - [Effect architecture and conformance](docs/effect-architecture.md)
226
- - [Automatic checkpoint lifecycle](docs/automatic-checkpoint.md)
227
- - [`/jscpd` overlay contract](docs/overlay-interaction.md)
228
- - [Fallow coexistence](docs/fallow-coexistence.md)
229
- - [Compatibility and packed-artifact certification](docs/compatibility.md)
230
- - [Release preparation and publication policy](docs/release.md)
231
- - [Contributing](CONTRIBUTING.md)
232
- - [Security policy](SECURITY.md)
233
- - [Changelog](CHANGELOG.md)
234
-
235
- ## License
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
236
309
 
237
310
  [MIT](./LICENSE) © 2026 Revaz Zakalashvili
package/SECURITY.md CHANGED
@@ -1,4 +1,4 @@
1
- # Security policy
1
+ # 🔐 Security policy
2
2
 
3
3
  ## Supported versions
4
4
 
@@ -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's installed extension
37
- documentation, public type definitions, and `AgentSession` runtime.
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.