cluxion-agentplugin-supercoder 0.2.11__tar.gz → 0.2.12__tar.gz

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.
Files changed (64) hide show
  1. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/PKG-INFO +1 -1
  2. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/plugin.yaml +1 -1
  3. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/pyproject.toml +1 -1
  4. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/src/cluxion_agentplugin_supercoder/core/hash_patch.py +10 -2
  5. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/tests/test_hash_patch.py +102 -1
  6. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/uv.lock +1 -1
  7. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/.github/workflows/ci.yml +0 -0
  8. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/.github/workflows/publish.yml +0 -0
  9. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/.gitignore +0 -0
  10. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/ARCHITECTURE.md +0 -0
  11. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/Docs/README.md +0 -0
  12. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/Docs/agent-surfaces.md +0 -0
  13. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/Docs/architecture.md +0 -0
  14. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/Docs/capabilities.md +0 -0
  15. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/Docs/design.md +0 -0
  16. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/Docs/installation.md +0 -0
  17. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/Docs/rust-architecture.md +0 -0
  18. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/Docs/tools.md +0 -0
  19. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/LICENSE +0 -0
  20. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/README.md +0 -0
  21. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/__init__.py +0 -0
  22. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/adapters/claude/.claude-plugin/plugin.json +0 -0
  23. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/adapters/claude/skills/supercoder/SKILL.md +0 -0
  24. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/adapters/codex/config-snippet.toml +0 -0
  25. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/adapters/hermes/README.md +0 -0
  26. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/rust/supercoder_index/Cargo.lock +0 -0
  27. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/rust/supercoder_index/Cargo.toml +0 -0
  28. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/rust/supercoder_index/pyproject.toml +0 -0
  29. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/rust/supercoder_index/src/lib.rs +0 -0
  30. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/rust/supercoder_index/src/main.rs +0 -0
  31. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/rust/supercoder_index/src/outline.rs +0 -0
  32. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/rust/supercoder_index/src/syntax.rs +0 -0
  33. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/scripts/repack_native_wheel.py +0 -0
  34. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/src/cluxion_agentplugin_supercoder/__init__.py +0 -0
  35. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/src/cluxion_agentplugin_supercoder/cli.py +0 -0
  36. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/src/cluxion_agentplugin_supercoder/core/cursor.py +0 -0
  37. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/src/cluxion_agentplugin_supercoder/core/line_budget.py +0 -0
  38. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/src/cluxion_agentplugin_supercoder/core/lint_gate.py +0 -0
  39. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/src/cluxion_agentplugin_supercoder/core/queue.py +0 -0
  40. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/src/cluxion_agentplugin_supercoder/core/repo_map.py +0 -0
  41. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/src/cluxion_agentplugin_supercoder/core/retry_loop.py +0 -0
  42. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/src/cluxion_agentplugin_supercoder/core/safety.py +0 -0
  43. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/src/cluxion_agentplugin_supercoder/core/syntax_gate.py +0 -0
  44. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/src/cluxion_agentplugin_supercoder/core/test_gate.py +0 -0
  45. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/src/cluxion_agentplugin_supercoder/doctor/__init__.py +0 -0
  46. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/src/cluxion_agentplugin_supercoder/doctor/catalog.json +0 -0
  47. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/src/cluxion_agentplugin_supercoder/doctor/framework.py +0 -0
  48. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/src/cluxion_agentplugin_supercoder/doctor/probes.py +0 -0
  49. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/src/cluxion_agentplugin_supercoder/plugin.py +0 -0
  50. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/src/cluxion_agentplugin_supercoder/runner.py +0 -0
  51. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/src/cluxion_agentplugin_supercoder/rust_bridge.py +0 -0
  52. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/src/cluxion_agentplugin_supercoder/schemas.py +0 -0
  53. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/tests/test_cursor.py +0 -0
  54. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/tests/test_doctor.py +0 -0
  55. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/tests/test_line_budget.py +0 -0
  56. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/tests/test_lint_gate.py +0 -0
  57. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/tests/test_plugin.py +0 -0
  58. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/tests/test_queue.py +0 -0
  59. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/tests/test_repo_map.py +0 -0
  60. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/tests/test_retry_loop.py +0 -0
  61. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/tests/test_rust_bridge.py +0 -0
  62. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/tests/test_safety.py +0 -0
  63. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/tests/test_syntax_gate.py +0 -0
  64. {cluxion_agentplugin_supercoder-0.2.11 → cluxion_agentplugin_supercoder-0.2.12}/tests/test_test_gate.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cluxion-agentplugin-supercoder
3
- Version: 0.2.11
3
+ Version: 0.2.12
4
4
  Summary: Universal agent coding harness plugin: cursor logic, safe patch, line budget, Rust index, test gates.
5
5
  Project-URL: Homepage, https://github.com/cluxion/cluxion-Agentplugin-supercoder
6
6
  Project-URL: Repository, https://github.com/cluxion/cluxion-Agentplugin-supercoder
@@ -1,5 +1,5 @@
1
1
  name: cluxion-agentplugin-supercoder
2
- version: 0.2.11
2
+ version: 0.2.12
3
3
  description: "Universal agent coding harness: cursor, safe patch, line budget, Rust index."
4
4
  author: cluxion
5
5
  kind: standalone
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "cluxion-agentplugin-supercoder"
7
- version = "0.2.11"
7
+ version = "0.2.12"
8
8
  description = "Universal agent coding harness plugin: cursor logic, safe patch, line budget, Rust index, test gates."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -17,6 +17,7 @@ except ImportError:
17
17
  fcntl = None # type: ignore[assignment]
18
18
 
19
19
  DEFAULT_FUZZY_THRESHOLD = 0.86
20
+ AMBIGUITY_MARGIN = 0.015
20
21
  MAX_CONTEXT_SCAN = 8
21
22
  MAX_LINE_DRIFT = 2
22
23
 
@@ -157,6 +158,8 @@ def _best_fuzzy_span(text: str, reference: str) -> tuple[int, int, str, float, b
157
158
  offsets = [0]
158
159
  for line in lines:
159
160
  offsets.append(offsets[-1] + len(line))
161
+ sm = SequenceMatcher(autojunk=False)
162
+ sm.set_seq2(reference)
160
163
  for start, end, block in _candidate_spans(text, reference, MAX_LINE_DRIFT):
161
164
  # compute line range [start_line, end_line) for overlap test
162
165
  start_line = 0
@@ -165,12 +168,17 @@ def _best_fuzzy_span(text: str, reference: str) -> tuple[int, int, str, float, b
165
168
  end_line = start_line
166
169
  while end_line < len(offsets) - 1 and offsets[end_line] < end:
167
170
  end_line += 1
168
- score = SequenceMatcher(None, block, reference, autojunk=False).ratio()
171
+ sm.set_seq1(block)
172
+ if best is not None:
173
+ prune_below = best[3] - AMBIGUITY_MARGIN
174
+ if sm.real_quick_ratio() < prune_below or sm.quick_ratio() < prune_below:
175
+ continue
176
+ score = sm.ratio()
169
177
  if best is None or score > best[3]:
170
178
  best = (start, end, block, score)
171
179
  best_lines = (start_line, end_line)
172
180
  ambiguous = False
173
- elif score >= DEFAULT_FUZZY_THRESHOLD and best and abs(score - best[3]) < 0.015:
181
+ elif score >= DEFAULT_FUZZY_THRESHOLD and best and abs(score - best[3]) < AMBIGUITY_MARGIN:
174
182
  # only treat as ambiguous if a genuinely different (non-overlapping) location matches closely
175
183
  if best_lines is not None and not (end_line <= best_lines[0] or start_line >= best_lines[1]):
176
184
  continue # overlapping window on same location -> not real ambiguity
@@ -4,11 +4,112 @@ import concurrent.futures
4
4
  import contextlib
5
5
  import os
6
6
  import tempfile
7
+ import time
8
+ from difflib import SequenceMatcher
7
9
  from pathlib import Path
8
10
 
9
11
  import pytest
10
12
 
11
- from cluxion_agentplugin_supercoder.core.hash_patch import apply_patch, file_hash
13
+ from cluxion_agentplugin_supercoder.core.hash_patch import (
14
+ AMBIGUITY_MARGIN,
15
+ DEFAULT_FUZZY_THRESHOLD,
16
+ MAX_LINE_DRIFT,
17
+ _best_fuzzy_span,
18
+ _candidate_spans,
19
+ apply_patch,
20
+ file_hash,
21
+ )
22
+
23
+
24
+ def _best_fuzzy_span_legacy(text: str, reference: str) -> tuple[int, int, str, float, bool] | None:
25
+ """Pre-optimization reference implementation for byte-identical regression checks."""
26
+ best: tuple[int, int, str, float] | None = None
27
+ best_lines: tuple[int, int] | None = None
28
+ ambiguous = False
29
+ lines = text.splitlines(keepends=True)
30
+ offsets = [0]
31
+ for line in lines:
32
+ offsets.append(offsets[-1] + len(line))
33
+ for start, end, block in _candidate_spans(text, reference, MAX_LINE_DRIFT):
34
+ start_line = 0
35
+ while start_line < len(offsets) - 1 and offsets[start_line + 1] <= start:
36
+ start_line += 1
37
+ end_line = start_line
38
+ while end_line < len(offsets) - 1 and offsets[end_line] < end:
39
+ end_line += 1
40
+ score = SequenceMatcher(None, block, reference, autojunk=False).ratio()
41
+ if best is None or score > best[3]:
42
+ best = (start, end, block, score)
43
+ best_lines = (start_line, end_line)
44
+ ambiguous = False
45
+ elif score >= DEFAULT_FUZZY_THRESHOLD and best and abs(score - best[3]) < AMBIGUITY_MARGIN:
46
+ if best_lines is not None and not (end_line <= best_lines[0] or start_line >= best_lines[1]):
47
+ continue
48
+ ambiguous = True
49
+ if best is None:
50
+ return None
51
+ return best[0], best[1], best[2], best[3], ambiguous
52
+
53
+
54
+ def _fuzzy_result_key(result: tuple[int, int, str, float, bool] | None) -> tuple | None:
55
+ if result is None:
56
+ return None
57
+ start, end, _block, score, ambiguous = result
58
+ return (start, end, score, ambiguous)
59
+
60
+
61
+ @pytest.mark.parametrize(
62
+ ("text", "reference"),
63
+ [
64
+ pytest.param(
65
+ "\n".join(f"line_{i} = {i}" for i in range(20))
66
+ + "\n"
67
+ + "def target():\n return 42\n"
68
+ + "\n".join(f"tail_{i} = {i}" for i in range(20))
69
+ + "\n",
70
+ "def target():\n return 43\n",
71
+ id="exact-best-in-middle",
72
+ ),
73
+ pytest.param(
74
+ "def f():\n return 1\n\n" + "def f():\n return 1\n",
75
+ "def f():\n return 2\n",
76
+ id="ambiguous-near-ties",
77
+ ),
78
+ pytest.param(
79
+ "alpha\nbeta\ngamma\ndelta\n",
80
+ "alpha\nBETA\ngamma\n",
81
+ id="clear-single-best",
82
+ ),
83
+ pytest.param(
84
+ "alpha\nbeta\ngamma\n",
85
+ "completely different content\n",
86
+ id="no-match",
87
+ ),
88
+ ],
89
+ )
90
+ def test_best_fuzzy_span_matches_legacy(text: str, reference: str) -> None:
91
+ legacy = _fuzzy_result_key(_best_fuzzy_span_legacy(text, reference))
92
+ optimized = _fuzzy_result_key(_best_fuzzy_span(text, reference))
93
+ assert optimized == legacy
94
+
95
+
96
+ def test_best_fuzzy_span_large_file_benchmark() -> None:
97
+ """Optimized path should be materially faster on a ~500-line fuzzy search."""
98
+ filler = "\n".join(f"# filler line {i:03d} with some padding text" for i in range(480)) + "\n"
99
+ target = "def handler(request):\n value = compute(request)\n return value\n"
100
+ text = filler + target + filler
101
+ reference = "def handler(request):\n value = compute(request) # cached\n return value\n"
102
+
103
+ legacy_start = time.perf_counter()
104
+ legacy = _best_fuzzy_span_legacy(text, reference)
105
+ legacy_elapsed = time.perf_counter() - legacy_start
106
+
107
+ optimized_start = time.perf_counter()
108
+ optimized = _best_fuzzy_span(text, reference)
109
+ optimized_elapsed = time.perf_counter() - optimized_start
110
+
111
+ assert _fuzzy_result_key(optimized) == _fuzzy_result_key(legacy)
112
+ assert optimized_elapsed < legacy_elapsed * 0.6
12
113
 
13
114
 
14
115
  def test_exact_patch(tmp_path: Path) -> None:
@@ -160,7 +160,7 @@ wheels = [
160
160
 
161
161
  [[package]]
162
162
  name = "cluxion-agentplugin-supercoder"
163
- version = "0.2.11"
163
+ version = "0.2.12"
164
164
  source = { editable = "." }
165
165
  dependencies = [
166
166
  { name = "psutil" },