-
Notifications
You must be signed in to change notification settings - Fork 0
Adopt a benchmarked PyChase code-duplication gate #276
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
leynos
wants to merge
16
commits into
main
Choose a base branch
from
code-duplication-gate
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
5771648
Add code-duplication detector benchmark
leynos 2fd57c7
Extract shared async-callable validator
leynos a48b593
Deduplicate logging convenience wrappers
leynos f416b3f
Adopt PyChase code-duplication gate
leynos e1309ef
Pin Skylos tool interpreter to Python 3.14
leynos 2b165cd
Cache uv tool and script environments in CI
leynos 21dc818
Fix the Skylos interpreter pin and the skylos-allow target
leynos dd769e1
Harden benchmark duplication gate review fixes
leynos 84a2155
Validate duplication benchmark oracle
leynos 4c6eb45
Use SYMBOL for Skylos allow entries
leynos 4124af2
Share canonical duplication fixes
leynos 26c0a34
Simplify PyChase member validation
leynos cf62022
Cover PyChase member validation boundaries
leynos 8ff8285
Harden duplication gate review contracts
leynos 7202664
Track TEI duplication consolidation
leynos 490a0c3
Harden duplication gate workflows
leynos File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,3 +21,4 @@ __pycache__/ | |
| .grepai/ | ||
| *.swo | ||
| *~ | ||
| .pyscn/ | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| # Code-duplication detector benchmark | ||
|
|
||
| This directory contains the reusable, tool-neutral corpus and normalizer for | ||
| the PyChase and pyscn clone-detection comparison. It is development evidence, | ||
| not part of the Episodic application or its test fixtures. | ||
|
|
||
| `corpus/` is a deliberately small Python project. Its own `pyproject.toml` | ||
| bounds project-root discovery without configuring either detector. The | ||
| `pricing` module holds original routines; `reporting` clones them as labelled | ||
| Type-1 to Type-4 duplicates; `controls` holds structurally similar but | ||
| semantically distinct false-positive bait. | ||
|
|
||
| `expectations.json` is the oracle. Each entry labels one pair of source units | ||
| before detector output is considered, assigns it to either the | ||
| `syntactic-clone` (Types 1-3) or `semantic-clone` (Type 4) lane, and explains | ||
| why merging the pair would or would not be a defensible refactor. Add a new | ||
| label only when its clone status can be decided without trusting a detector. Do | ||
| not change a label merely to make a detector result pass. | ||
|
|
||
| The `score.py` module is intentionally specific to the two released JSON | ||
| schemas captured by this comparison. Reuse it for reruns of this corpus; add a | ||
| separate parser when evaluating a different detector rather than disguising | ||
| schema differences inside an existing parser. | ||
|
|
||
| `configs/` holds the permissive pyscn capability settings. `results/` retains | ||
| the tool output, normalized scores, generational tuning tables, and the | ||
| production-scan adjudication from 2026-08-22. The large production report is | ||
| compressed with deterministic gzip metadata; its SHA-256 digest is recorded in | ||
| `production-adjudication.json`. | ||
|
|
||
| Run the corpus commands from `benchmarks/duplication/corpus/`: | ||
|
|
||
| ```bash | ||
| uvx pyscn@1.29.1 analyze --select clones --json -c ../configs/pyscn-permissive.toml . | ||
| PYTHONHASHSEED=0 uvx pychase@0.1.0 --json --threshold 0.6 --min-lines 5 --min-nodes 10 . | ||
| ``` | ||
|
|
||
| Run the production comparison from the repository root: | ||
|
|
||
| ```bash | ||
| PYTHONHASHSEED=0 uvx pychase@0.1.0 --json --threshold 0.9 --min-lines 13 --min-nodes 50 episodic | ||
| ``` | ||
|
|
||
| `PYTHONHASHSEED` must be pinned for repository-scale PyChase runs: above 200 | ||
| units it buckets MinHash signatures with the built-in `hash()`, so an unpinned | ||
| seed makes near-threshold findings flicker between runs. | ||
|
|
||
| The elapsed times recorded in `results/scores.json` are single wall-clock | ||
| observations, not performance benchmarks. They are retained to expose | ||
| order-of-magnitude differences only. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| """Duplication detector comparison corpus and scoring support.""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| # Permissive capability-measurement settings for the corpus comparison. | ||
| # The floors match the PyChase permissive run; all clone types are enabled. | ||
| [clones] | ||
| min_lines = 5 | ||
| min_nodes = 10 | ||
| enabled_clone_types = ["type1", "type2", "type3", "type4"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| """Public surface for the duplication detector corpus.""" | ||
|
|
||
| from .pricing import order_total_price | ||
|
|
||
| __all__ = ["order_total_price"] |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
Repository: leynos/episodic
Length of output: 2476
🌐 Web query:
latest released versions of the cyclopts and tomlkit Python packages💡 Result:
As of August 23, 2026, the latest released versions of the specified Python packages are as follows: - cyclopts: The latest stable version is 4.17.0, released on June 9, 2026 [1]. - tomlkit: The latest stable version is 0.15.1, released on July 17, 2026 [2][3].
Citations:
🏁 Script executed:
Repository: leynos/episodic
Length of output: 15116
🏁 Script executed:
Repository: leynos/episodic
Length of output: 1959
🌐 Web query:
PyPI cyclopts 4.22.5 tomlkit 0.13.2 release versions and compatibility💡 Result:
The libraries cyclopts and tomlkit have the following release and compatibility information: Cyclopts 4.22.5 This version requires Python 3.10 or newer [1]. Cyclopts is a command-line interface framework for Python [2]. Tomlkit 0.13.2 This version was released on August 14, 2024 [3][4]. It requires Python 3.8 or newer [5]. Tomlkit is a style-preserving TOML library for Python [3]. Summary Table Library | Version | Python Compatibility --- | --- | --- cyclopts | 4.22.5 | >= 3.10 [1] tomlkit | 0.13.2 | >= 3.8 [5]
Citations:
🏁 Script executed:
Repository: leynos/episodic
Length of output: 12432
🏁 Script executed:
Repository: leynos/episodic
Length of output: 604
🌐 Web query:
site:docs.astral.sh/uv scripts inline metadata dependencies uv run script lockfile --no-project💡 Result:
When using uv to run Python scripts with inline metadata (PEP 723), uv handles dependency management by creating isolated, ephemeral virtual environments [1][2][3]. Key aspects of your query: 1. Inline Metadata Dependencies: Scripts can define dependencies directly within the file using a TOML block [1][4]. When you run such a script, uv reads this metadata and automatically installs the required packages into a dedicated, isolated environment cached by uv [1][2][3]. 2. --no-project flag: The --no-project flag tells uv to avoid discovering or using any project or workspace configuration in the current directory or its parents [5]. When used, uv treats the environment as isolated from any existing project structure [5]. Notably, when you run a script that already contains inline metadata, uv automatically isolates the script's environment from any active project, meaning --no-project is not strictly required to achieve this isolation [1][6]. 3. Lockfiles: uv does not generate a standard project lockfile (like uv.lock) for individual scripts with inline metadata [1]. Instead, the environment is managed dynamically based on the inline requirements. If you were working within a project, the project's own lockfile would be ignored for the execution of a script with inline metadata [1][6]. In summary, running a script with inline metadata via uv run effectively creates a self-contained execution environment that ignores local project dependencies, fulfilling the isolation purpose of --no-project automatically [1][6].
Citations:
Pin the gate dependencies in both execution paths. Pin
cyclopts==4.22.5andtomlkit==0.15.1induplication-testand in the inline metadata ofscripts/duplication_gate.py. Both targets currently resolve these dependencies dynamically.🤖 Prompt for AI Agents