cluxion-agentplugin-supercoder 0.2.8__tar.gz → 0.2.10__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.
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/PKG-INFO +1 -1
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/pyproject.toml +1 -1
- cluxion_agentplugin_supercoder-0.2.10/src/cluxion_agentplugin_supercoder/__init__.py +10 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/src/cluxion_agentplugin_supercoder/core/line_budget.py +28 -17
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/src/cluxion_agentplugin_supercoder/core/repo_map.py +9 -4
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/src/cluxion_agentplugin_supercoder/doctor/probes.py +55 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/src/cluxion_agentplugin_supercoder/rust_bridge.py +29 -9
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/tests/test_doctor.py +76 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/tests/test_line_budget.py +13 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/tests/test_repo_map.py +11 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/uv.lock +1 -1
- cluxion_agentplugin_supercoder-0.2.8/src/cluxion_agentplugin_supercoder/__init__.py +0 -5
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/.github/workflows/ci.yml +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/.github/workflows/publish.yml +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/.gitignore +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/ARCHITECTURE.md +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/Docs/README.md +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/Docs/agent-surfaces.md +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/Docs/architecture.md +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/Docs/capabilities.md +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/Docs/design.md +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/Docs/installation.md +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/Docs/rust-architecture.md +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/Docs/tools.md +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/LICENSE +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/README.md +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/__init__.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/adapters/claude/.claude-plugin/plugin.json +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/adapters/claude/skills/supercoder/SKILL.md +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/adapters/codex/config-snippet.toml +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/adapters/hermes/README.md +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/plugin.yaml +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/rust/supercoder_index/Cargo.lock +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/rust/supercoder_index/Cargo.toml +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/rust/supercoder_index/pyproject.toml +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/rust/supercoder_index/src/lib.rs +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/rust/supercoder_index/src/main.rs +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/rust/supercoder_index/src/outline.rs +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/rust/supercoder_index/src/syntax.rs +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/scripts/repack_native_wheel.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/src/cluxion_agentplugin_supercoder/cli.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/src/cluxion_agentplugin_supercoder/core/cursor.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/src/cluxion_agentplugin_supercoder/core/hash_patch.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/src/cluxion_agentplugin_supercoder/core/lint_gate.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/src/cluxion_agentplugin_supercoder/core/queue.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/src/cluxion_agentplugin_supercoder/core/retry_loop.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/src/cluxion_agentplugin_supercoder/core/safety.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/src/cluxion_agentplugin_supercoder/core/syntax_gate.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/src/cluxion_agentplugin_supercoder/core/test_gate.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/src/cluxion_agentplugin_supercoder/doctor/__init__.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/src/cluxion_agentplugin_supercoder/doctor/catalog.json +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/src/cluxion_agentplugin_supercoder/doctor/framework.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/src/cluxion_agentplugin_supercoder/plugin.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/src/cluxion_agentplugin_supercoder/runner.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/src/cluxion_agentplugin_supercoder/schemas.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/tests/test_cursor.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/tests/test_hash_patch.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/tests/test_lint_gate.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/tests/test_plugin.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/tests/test_queue.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/tests/test_retry_loop.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/tests/test_rust_bridge.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/tests/test_safety.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/tests/test_syntax_gate.py +0 -0
- {cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/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.
|
|
3
|
+
Version: 0.2.10
|
|
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
|
{cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/pyproject.toml
RENAMED
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cluxion-agentplugin-supercoder"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.10"
|
|
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"
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
__version__ = version("cluxion-agentplugin-supercoder")
|
|
7
|
+
except PackageNotFoundError: # pragma: no cover
|
|
8
|
+
__version__ = "0.2.8"
|
|
9
|
+
|
|
10
|
+
__all__ = ["__version__"]
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import re
|
|
5
6
|
from dataclasses import dataclass
|
|
6
7
|
|
|
7
8
|
|
|
@@ -32,25 +33,35 @@ def budget_for(mode: str, *, requested_lines: int, remaining: int = 10_000) -> B
|
|
|
32
33
|
return BudgetDecision(True, "within_budget", cap, remaining - requested_lines)
|
|
33
34
|
|
|
34
35
|
|
|
36
|
+
_ASCII_CODING_KEYWORDS = (
|
|
37
|
+
"code",
|
|
38
|
+
"fix",
|
|
39
|
+
"implement",
|
|
40
|
+
"refactor",
|
|
41
|
+
"patch",
|
|
42
|
+
"test",
|
|
43
|
+
"bug",
|
|
44
|
+
"debug",
|
|
45
|
+
)
|
|
46
|
+
_KOREAN_CODING_KEYWORDS = (
|
|
47
|
+
"코드",
|
|
48
|
+
"수정",
|
|
49
|
+
"구현",
|
|
50
|
+
"리팩터",
|
|
51
|
+
"패치",
|
|
52
|
+
"테스트",
|
|
53
|
+
"버그",
|
|
54
|
+
)
|
|
55
|
+
_ASCII_CODING_PATTERNS = tuple(
|
|
56
|
+
re.compile(rf"\b{re.escape(keyword)}\b", re.IGNORECASE) for keyword in _ASCII_CODING_KEYWORDS
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
35
60
|
def is_coding_task(prompt: str) -> bool:
|
|
36
61
|
text = prompt.lower()
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"implement",
|
|
41
|
-
"refactor",
|
|
42
|
-
"patch",
|
|
43
|
-
"test",
|
|
44
|
-
"bug",
|
|
45
|
-
"코드",
|
|
46
|
-
"수정",
|
|
47
|
-
"구현",
|
|
48
|
-
"리팩터",
|
|
49
|
-
"패치",
|
|
50
|
-
"테스트",
|
|
51
|
-
"버그",
|
|
52
|
-
)
|
|
53
|
-
return any(needle in text for needle in needles)
|
|
62
|
+
if any(pattern.search(text) for pattern in _ASCII_CODING_PATTERNS):
|
|
63
|
+
return True
|
|
64
|
+
return any(keyword in text for keyword in _KOREAN_CODING_KEYWORDS)
|
|
54
65
|
|
|
55
66
|
|
|
56
67
|
__all__ = ["BudgetDecision", "budget_for", "is_coding_task"]
|
|
@@ -43,13 +43,17 @@ def build_repo_map(
|
|
|
43
43
|
base = Path(root).resolve()
|
|
44
44
|
if not base.is_dir():
|
|
45
45
|
return {"ok": False, "error": f"root is not a directory: {base}"}
|
|
46
|
-
|
|
46
|
+
capped_max_files = max(1, int(max_files))
|
|
47
|
+
entries = rust_bridge.scan_repo(base, max_files=capped_max_files)
|
|
48
|
+
total_candidates = rust_bridge.count_scan_candidates(base)
|
|
49
|
+
files_capped = max(0, total_candidates - capped_max_files)
|
|
47
50
|
entries = _rank_entries(entries)
|
|
48
51
|
|
|
49
52
|
lines: list[str] = []
|
|
50
53
|
used = 0
|
|
51
54
|
files_mapped = 0
|
|
52
|
-
files_omitted =
|
|
55
|
+
files_omitted = files_capped
|
|
56
|
+
budget_exhausted = False
|
|
53
57
|
outlined_files = 0
|
|
54
58
|
symbol_total = 0
|
|
55
59
|
budget = max(200, int(budget_chars))
|
|
@@ -57,7 +61,7 @@ def build_repo_map(
|
|
|
57
61
|
for entry in entries:
|
|
58
62
|
rel = str(entry.get("path", ""))
|
|
59
63
|
total_lines = int(entry.get("total_lines", 0))
|
|
60
|
-
if
|
|
64
|
+
if budget_exhausted:
|
|
61
65
|
files_omitted += 1
|
|
62
66
|
continue
|
|
63
67
|
block = [f"{rel} ({total_lines}L)"]
|
|
@@ -80,6 +84,7 @@ def build_repo_map(
|
|
|
80
84
|
block_text = "\n".join(block)
|
|
81
85
|
if used + len(block_text) + 1 > budget:
|
|
82
86
|
files_omitted += 1
|
|
87
|
+
budget_exhausted = True
|
|
83
88
|
continue
|
|
84
89
|
lines.append(block_text)
|
|
85
90
|
used += len(block_text) + 1
|
|
@@ -90,7 +95,7 @@ def build_repo_map(
|
|
|
90
95
|
"root": str(base),
|
|
91
96
|
"backend": rust_bridge.resolve_backend(),
|
|
92
97
|
"map": "\n".join(lines),
|
|
93
|
-
"files_scanned": len(entries),
|
|
98
|
+
"files_scanned": len(entries) + files_capped,
|
|
94
99
|
"files_mapped": files_mapped,
|
|
95
100
|
"files_omitted": files_omitted,
|
|
96
101
|
"outlined_files": outlined_files,
|
|
@@ -120,6 +120,61 @@ def native_module_importable(ctx: DoctorContext) -> tuple[str, str]:
|
|
|
120
120
|
|
|
121
121
|
# plugin-specific probes (deterministic ones only) - for supercoder we can add if symbols found
|
|
122
122
|
# for now, handler_exception_coverage is cross-cutting
|
|
123
|
+
_EXPECTED_TOOLS = (
|
|
124
|
+
"supercoder_plan",
|
|
125
|
+
"supercoder_read_window",
|
|
126
|
+
"supercoder_patch",
|
|
127
|
+
"supercoder_cursor_map",
|
|
128
|
+
"supercoder_syntax_gate",
|
|
129
|
+
"supercoder_lint_gate",
|
|
130
|
+
"supercoder_repo_map",
|
|
131
|
+
"supercoder_test_gate",
|
|
132
|
+
"supercoder_brief",
|
|
133
|
+
"supercoder_doctor",
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@_register("hermes_contract_tool_registration")
|
|
138
|
+
def hermes_contract_tool_registration(ctx: DoctorContext) -> tuple[str, str]:
|
|
139
|
+
try:
|
|
140
|
+
from cluxion_agentplugin_supercoder.plugin import register
|
|
141
|
+
|
|
142
|
+
class _MockCtx:
|
|
143
|
+
def __init__(self) -> None:
|
|
144
|
+
self.tools: list[tuple[str, str, dict, object, str]] = []
|
|
145
|
+
|
|
146
|
+
def register_tool(
|
|
147
|
+
self,
|
|
148
|
+
*,
|
|
149
|
+
name: str,
|
|
150
|
+
toolset: str,
|
|
151
|
+
schema: dict,
|
|
152
|
+
handler: object,
|
|
153
|
+
emoji: str,
|
|
154
|
+
) -> None:
|
|
155
|
+
self.tools.append((name, toolset, schema, handler, emoji))
|
|
156
|
+
|
|
157
|
+
mock = _MockCtx()
|
|
158
|
+
register(mock)
|
|
159
|
+
registered = [name for name, *_ in mock.tools]
|
|
160
|
+
missing = [name for name in _EXPECTED_TOOLS if name not in registered]
|
|
161
|
+
if missing:
|
|
162
|
+
return "fail", f"missing tools: {', '.join(missing)}"
|
|
163
|
+
extras = [name for name in registered if name not in _EXPECTED_TOOLS]
|
|
164
|
+
if extras:
|
|
165
|
+
return "fail", f"unexpected tools: {', '.join(extras)}"
|
|
166
|
+
for name, toolset, schema, handler, _emoji in mock.tools:
|
|
167
|
+
if toolset != "supercoder":
|
|
168
|
+
return "fail", f"{name}: toolset={toolset!r}"
|
|
169
|
+
if not isinstance(schema, dict) or not schema.get("name"):
|
|
170
|
+
return "fail", f"{name}: invalid schema"
|
|
171
|
+
if not callable(handler):
|
|
172
|
+
return "fail", f"{name}: handler not callable"
|
|
173
|
+
return "pass", f"{len(_EXPECTED_TOOLS)} tools registered with schemas and handlers"
|
|
174
|
+
except Exception as e:
|
|
175
|
+
return "fail", f"registration error: {e}"
|
|
176
|
+
|
|
177
|
+
|
|
123
178
|
@_register("handler_exception_coverage")
|
|
124
179
|
def handler_exception_coverage(ctx: DoctorContext) -> tuple[str, str]:
|
|
125
180
|
try:
|
|
@@ -107,14 +107,7 @@ def _parse_backend_json(raw: str, command: str) -> dict[str, object]:
|
|
|
107
107
|
return parsed
|
|
108
108
|
|
|
109
109
|
|
|
110
|
-
def
|
|
111
|
-
root: Path,
|
|
112
|
-
*,
|
|
113
|
-
max_files: int,
|
|
114
|
-
extensions: tuple[str, ...],
|
|
115
|
-
) -> dict[str, object]:
|
|
116
|
-
from cluxion_agentplugin_supercoder.core.hash_patch import file_hash
|
|
117
|
-
|
|
110
|
+
def _collect_candidates(root: Path, *, extensions: tuple[str, ...]) -> list[str]:
|
|
118
111
|
candidates: list[str] = []
|
|
119
112
|
for path in root.rglob("*"):
|
|
120
113
|
if not path.is_file():
|
|
@@ -125,6 +118,27 @@ def _py_scan(
|
|
|
125
118
|
continue
|
|
126
119
|
candidates.append(str(path.relative_to(root)))
|
|
127
120
|
candidates.sort()
|
|
121
|
+
return candidates
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def count_scan_candidates(
|
|
125
|
+
root: Path,
|
|
126
|
+
*,
|
|
127
|
+
extensions: tuple[str, ...] = DEFAULT_EXTENSIONS,
|
|
128
|
+
) -> int:
|
|
129
|
+
"""Return how many files match scan_repo criteria before the max_files cap."""
|
|
130
|
+
return len(_collect_candidates(root, extensions=extensions))
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def _py_scan(
|
|
134
|
+
root: Path,
|
|
135
|
+
*,
|
|
136
|
+
max_files: int,
|
|
137
|
+
extensions: tuple[str, ...],
|
|
138
|
+
) -> dict[str, object]:
|
|
139
|
+
from cluxion_agentplugin_supercoder.core.hash_patch import file_hash
|
|
140
|
+
|
|
141
|
+
candidates = _collect_candidates(root, extensions=extensions)
|
|
128
142
|
entries: list[dict[str, object]] = []
|
|
129
143
|
for rel in candidates[:max_files]:
|
|
130
144
|
try:
|
|
@@ -138,7 +152,12 @@ def _py_scan(
|
|
|
138
152
|
"total_lines": text.count("\n") + (1 if text else 0),
|
|
139
153
|
}
|
|
140
154
|
)
|
|
141
|
-
return {
|
|
155
|
+
return {
|
|
156
|
+
"ok": True,
|
|
157
|
+
"entries": entries,
|
|
158
|
+
"count": len(entries),
|
|
159
|
+
"total_candidates": len(candidates),
|
|
160
|
+
}
|
|
142
161
|
|
|
143
162
|
|
|
144
163
|
def _binary() -> str:
|
|
@@ -158,6 +177,7 @@ __all__ = [
|
|
|
158
177
|
"DEFAULT_MAX_FILES",
|
|
159
178
|
"INDEX_BACKEND_ENV",
|
|
160
179
|
"INDEX_BIN_ENV",
|
|
180
|
+
"count_scan_candidates",
|
|
161
181
|
"index_available",
|
|
162
182
|
"resolve_backend",
|
|
163
183
|
"scan_repo",
|
{cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/tests/test_doctor.py
RENAMED
|
@@ -223,6 +223,82 @@ def test_path_security_probe_detects_ungated_read(monkeypatch):
|
|
|
223
223
|
assert status == "fail"
|
|
224
224
|
|
|
225
225
|
|
|
226
|
+
def test_healthy_install_ok_and_exit_zero(monkeypatch):
|
|
227
|
+
monkeypatch.setattr(
|
|
228
|
+
"cluxion_agentplugin_supercoder.doctor.probes.shutil.which",
|
|
229
|
+
lambda name: "/usr/bin/hermes" if name == "hermes" else None,
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
def fake_run(cmd, **_kwargs):
|
|
233
|
+
joined = " ".join(cmd)
|
|
234
|
+
if "--version" in joined:
|
|
235
|
+
return subprocess.CompletedProcess(cmd, 0, "Hermes Agent v1.0.0", "")
|
|
236
|
+
if "--help" in joined:
|
|
237
|
+
return subprocess.CompletedProcess(cmd, 0, "-z --oneshot", "")
|
|
238
|
+
if "tools" in joined and "list" in joined:
|
|
239
|
+
return subprocess.CompletedProcess(cmd, 0, "supercoder", "")
|
|
240
|
+
return subprocess.CompletedProcess(cmd, 0, "", "")
|
|
241
|
+
|
|
242
|
+
monkeypatch.setattr(
|
|
243
|
+
"cluxion_agentplugin_supercoder.doctor.framework.subprocess.run",
|
|
244
|
+
fake_run,
|
|
245
|
+
)
|
|
246
|
+
cat = _catalog_path()
|
|
247
|
+
result = run_doctor(
|
|
248
|
+
cwd=Path.cwd(),
|
|
249
|
+
catalog_path=cat,
|
|
250
|
+
probes=PROBES,
|
|
251
|
+
plugin="supercoder",
|
|
252
|
+
version="0.2.4",
|
|
253
|
+
)
|
|
254
|
+
statuses = {c.check_id: c.status for c in result.checks}
|
|
255
|
+
assert statuses["hermes_contract_tool_registration"] == "pass"
|
|
256
|
+
assert result.ok is True
|
|
257
|
+
assert result.summary == "ok"
|
|
258
|
+
payload = json.loads(render_json(result))
|
|
259
|
+
assert payload["ok"] is True
|
|
260
|
+
|
|
261
|
+
from cluxion_agentplugin_supercoder.cli import main
|
|
262
|
+
|
|
263
|
+
assert main(["doctor"]) == 0
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def test_genuine_failure_still_degraded_exit_one(monkeypatch):
|
|
267
|
+
monkeypatch.setattr(
|
|
268
|
+
"cluxion_agentplugin_supercoder.doctor.probes.shutil.which",
|
|
269
|
+
lambda name: "/usr/bin/hermes" if name == "hermes" else None,
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
def fake_run(cmd, **_kwargs):
|
|
273
|
+
joined = " ".join(cmd)
|
|
274
|
+
if "--version" in joined:
|
|
275
|
+
return subprocess.CompletedProcess(cmd, 0, "Hermes Agent v1.0.0", "")
|
|
276
|
+
if "--help" in joined:
|
|
277
|
+
return subprocess.CompletedProcess(cmd, 0, "-z --oneshot", "")
|
|
278
|
+
if "tools" in joined and "list" in joined:
|
|
279
|
+
return subprocess.CompletedProcess(cmd, 1, "", "tools unavailable")
|
|
280
|
+
return subprocess.CompletedProcess(cmd, 0, "", "")
|
|
281
|
+
|
|
282
|
+
monkeypatch.setattr(
|
|
283
|
+
"cluxion_agentplugin_supercoder.doctor.framework.subprocess.run",
|
|
284
|
+
fake_run,
|
|
285
|
+
)
|
|
286
|
+
result = run_doctor(
|
|
287
|
+
cwd=Path.cwd(),
|
|
288
|
+
catalog_path=_catalog_path(),
|
|
289
|
+
probes=PROBES,
|
|
290
|
+
plugin="supercoder",
|
|
291
|
+
version="0.2.4",
|
|
292
|
+
)
|
|
293
|
+
statuses = {c.check_id: c.status for c in result.checks}
|
|
294
|
+
assert statuses["toolset_valid"] == "fail"
|
|
295
|
+
assert result.ok is False
|
|
296
|
+
|
|
297
|
+
from cluxion_agentplugin_supercoder.cli import main
|
|
298
|
+
|
|
299
|
+
assert main(["doctor"]) == 1
|
|
300
|
+
|
|
301
|
+
|
|
226
302
|
def test_hermes_workspace_probe_detects_ungated_read(monkeypatch):
|
|
227
303
|
from cluxion_agentplugin_supercoder.core.safety import SafetyDecision
|
|
228
304
|
from cluxion_agentplugin_supercoder.doctor.probes import hermes_context_workspace_root
|
|
@@ -32,3 +32,16 @@ def test_is_coding_task_korean_and_english() -> None:
|
|
|
32
32
|
assert is_coding_task("fix the login bug")
|
|
33
33
|
assert is_coding_task("이 버그 수정해줘")
|
|
34
34
|
assert not is_coding_task("오늘 날씨 어때?")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def test_is_coding_task_word_boundaries_avoid_false_positives() -> None:
|
|
38
|
+
assert not is_coding_task("what is the latest news")
|
|
39
|
+
assert not is_coding_task("add a prefix to each line")
|
|
40
|
+
assert not is_coding_task("who won the contest yesterday")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_is_coding_task_true_positives_with_word_boundaries() -> None:
|
|
44
|
+
assert is_coding_task("fix the bug in main.py")
|
|
45
|
+
assert is_coding_task("add a unit test for login")
|
|
46
|
+
assert is_coding_task("refactor the auth module")
|
|
47
|
+
assert is_coding_task("debug the timeout issue")
|
|
@@ -82,6 +82,17 @@ def test_rust_outline_in_tree_sitter_tiers_fails_open_in_python(backend: str, sa
|
|
|
82
82
|
assert ("method", "run") in pairs
|
|
83
83
|
|
|
84
84
|
|
|
85
|
+
def test_max_files_cap_is_surfaced_honestly(backend: str, tmp_path: Path) -> None:
|
|
86
|
+
for index in range(6):
|
|
87
|
+
(tmp_path / f"mod_{index}.py").write_text(f"def fn_{index}():\n pass\n", encoding="utf-8")
|
|
88
|
+
result = repo_map.build_repo_map(tmp_path, max_files=3, budget_chars=8000)
|
|
89
|
+
assert result["truncated"] is True
|
|
90
|
+
assert result["files_omitted"] > 0
|
|
91
|
+
assert result["files_mapped"] + result["files_omitted"] == result["files_scanned"] == 6
|
|
92
|
+
assert result["files_omitted"] == 3
|
|
93
|
+
assert result["files_mapped"] == 3
|
|
94
|
+
|
|
95
|
+
|
|
85
96
|
def test_budget_omits_files_honestly(backend: str, sample_repo: Path) -> None:
|
|
86
97
|
# budget_chars clamps to a 200-char floor, so overflow it with real files.
|
|
87
98
|
for index in range(8):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/ARCHITECTURE.md
RENAMED
|
File without changes
|
{cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/Docs/README.md
RENAMED
|
File without changes
|
|
File without changes
|
{cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/Docs/architecture.md
RENAMED
|
File without changes
|
{cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/Docs/capabilities.md
RENAMED
|
File without changes
|
{cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/Docs/design.md
RENAMED
|
File without changes
|
{cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/Docs/installation.md
RENAMED
|
File without changes
|
|
File without changes
|
{cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/Docs/tools.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/tests/test_cursor.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/tests/test_plugin.py
RENAMED
|
File without changes
|
{cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/tests/test_queue.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cluxion_agentplugin_supercoder-0.2.8 → cluxion_agentplugin_supercoder-0.2.10}/tests/test_safety.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|