cluxion-agentplugin-preprocessing 0.3.8__tar.gz → 0.3.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.
Files changed (90) hide show
  1. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/PKG-INFO +1 -1
  2. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/pyproject.toml +1 -1
  3. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_agentplugin_preprocessing/__init__.py +1 -1
  4. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_agentplugin_preprocessing/plugin.py +3 -1
  5. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/core/clarification.py +17 -5
  6. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/core/dispatch_store.py +1 -1
  7. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/core/harness.py +3 -3
  8. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/resources/guard_bridge.py +3 -2
  9. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/tests/runtime/test_clarification.py +25 -0
  10. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/tests/runtime/test_dispatch_store.py +9 -0
  11. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/tests/runtime/test_guard.py +10 -0
  12. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/tests/test_plugin.py +6 -0
  13. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/.github/profile/README.md +0 -0
  14. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/.gitignore +0 -0
  15. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/Docs/README.md +0 -0
  16. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/LICENSE +0 -0
  17. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/README.md +0 -0
  18. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/adapters/claude/.claude-plugin/plugin.json +0 -0
  19. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/adapters/claude/skills/preprocess/SKILL.md +0 -0
  20. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/adapters/codex/config-snippet.toml +0 -0
  21. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/cluxion-Docs/README.md +0 -0
  22. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/cluxion-Docs/architecture.md +0 -0
  23. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/cluxion-Docs/harness-logic.md +0 -0
  24. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/cluxion-Docs/honesty-preprocessing.md +0 -0
  25. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/cluxion-Docs/install-and-operations.md +0 -0
  26. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/cluxion-Docs/security.md +0 -0
  27. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/rust/cluxion_queue/Cargo.lock +0 -0
  28. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/rust/cluxion_queue/Cargo.toml +0 -0
  29. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/rust/cluxion_queue/pyproject.toml +0 -0
  30. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/rust/cluxion_queue/src/context.rs +0 -0
  31. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/rust/cluxion_queue/src/dispatch.rs +0 -0
  32. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/rust/cluxion_queue/src/guard.rs +0 -0
  33. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/rust/cluxion_queue/src/lib.rs +0 -0
  34. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/rust/cluxion_queue/src/main.rs +0 -0
  35. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/rust/cluxion_queue/src/queue.rs +0 -0
  36. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/rust/cluxion_queue/src/types.rs +0 -0
  37. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_agentplugin_preprocessing/cli.py +0 -0
  38. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_agentplugin_preprocessing/doctor/__init__.py +0 -0
  39. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_agentplugin_preprocessing/doctor/catalog.json +0 -0
  40. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_agentplugin_preprocessing/doctor/framework.py +0 -0
  41. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_agentplugin_preprocessing/doctor/probes.py +0 -0
  42. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_agentplugin_preprocessing/guard_watch.py +0 -0
  43. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_agentplugin_preprocessing/hermes_config.py +0 -0
  44. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_agentplugin_preprocessing/plugin.yaml +0 -0
  45. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_agentplugin_preprocessing/runner.py +0 -0
  46. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_agentplugin_preprocessing/schemas.py +0 -0
  47. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/__init__.py +0 -0
  48. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/__main__.py +0 -0
  49. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/adapters/__init__.py +0 -0
  50. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/adapters/contract.py +0 -0
  51. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/adapters/grok_build.py +0 -0
  52. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/adapters/hermes.py +0 -0
  53. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/adapters/spec.py +0 -0
  54. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/bootstrap.py +0 -0
  55. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/cli.py +0 -0
  56. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/core/__init__.py +0 -0
  57. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/core/context_compress.py +0 -0
  58. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/core/intent.py +0 -0
  59. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/core/ledger.py +0 -0
  60. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/core/ledger_codec.py +0 -0
  61. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/core/plan_codec.py +0 -0
  62. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/core/preprocess.py +0 -0
  63. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/core/types.py +0 -0
  64. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/core/work_queue.py +0 -0
  65. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/guard_daemon_host.py +0 -0
  66. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/models/__init__.py +0 -0
  67. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/models/supervisor.py +0 -0
  68. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/models/vllm_mlx.py +0 -0
  69. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/resources/__init__.py +0 -0
  70. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/resources/py_queue.py +0 -0
  71. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/resources/queue_bridge.py +0 -0
  72. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/resources/rust_bridge.py +0 -0
  73. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/web/__init__.py +0 -0
  74. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/src/cluxion_runtime/web/browser_bridge.py +0 -0
  75. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/tests/runtime/test_browser_bridge.py +0 -0
  76. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/tests/runtime/test_cluxion_runtime_spine.py +0 -0
  77. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/tests/runtime/test_context_compress.py +0 -0
  78. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/tests/runtime/test_contract.py +0 -0
  79. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/tests/runtime/test_ledger.py +0 -0
  80. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/tests/runtime/test_py_queue_concurrency.py +0 -0
  81. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/tests/runtime/test_queue_backends.py +0 -0
  82. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/tests/runtime/test_runtime_adapter_cli.py +0 -0
  83. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/tests/runtime/test_rust_queue.py +0 -0
  84. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/tests/runtime/test_supervisor.py +0 -0
  85. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/tests/test_bootstrap.py +0 -0
  86. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/tests/test_doctor.py +0 -0
  87. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/tests/test_guard_watch.py +0 -0
  88. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/tests/test_hermes_config.py +0 -0
  89. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/tests/test_packaging_policy.py +0 -0
  90. {cluxion_agentplugin_preprocessing-0.3.8 → cluxion_agentplugin_preprocessing-0.3.10}/tests/test_runner.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cluxion-agentplugin-preprocessing
3
- Version: 0.3.8
3
+ Version: 0.3.10
4
4
  Summary: Universal agent plugin for Cluxion preprocessing, honesty contracts, clarification, Rust work queue, and resource-aware harness handoff.
5
5
  Project-URL: Homepage, https://github.com/cluxion/cluxion-Agentplugin-preprocessing
6
6
  Project-URL: Repository, https://github.com/cluxion/cluxion-Agentplugin-preprocessing
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "cluxion-agentplugin-preprocessing"
7
- version = "0.3.8"
7
+ version = "0.3.10"
8
8
  description = "Universal agent plugin for Cluxion preprocessing, honesty contracts, clarification, Rust work queue, and resource-aware harness handoff."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -2,6 +2,6 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- __version__ = "0.3.8"
5
+ __version__ = "0.3.10"
6
6
 
7
7
  __all__ = ["__version__"]
@@ -183,7 +183,9 @@ def _check_runtime_available() -> bool:
183
183
 
184
184
 
185
185
  def _check_browser_tool_available() -> bool:
186
- return True
186
+ import importlib.util
187
+
188
+ return importlib.util.find_spec("playwright") is not None
187
189
 
188
190
 
189
191
  def _handle_plan(args: dict[str, object], **_: object) -> str:
@@ -9,6 +9,7 @@ mixed-language on purpose — they classify user input, they are not output.
9
9
  from __future__ import annotations
10
10
 
11
11
  import os
12
+ import re
12
13
  from dataclasses import dataclass
13
14
 
14
15
  from cluxion_runtime.core.types import WorkIntent, WorkItem
@@ -125,11 +126,10 @@ def _question(question_id: str, locale: str) -> ClarificationQuestion:
125
126
  return ClarificationQuestion(question_id, prompt, why)
126
127
 
127
128
 
128
- _AMBIGUOUS_KEYWORDS = (
129
+ # PHRASES: multi-word or longer markers — use plain substring match
130
+ _AMBIGUOUS_PHRASES = (
129
131
  "maybe",
130
132
  "perhaps",
131
- "either",
132
- "or",
133
133
  "not sure",
134
134
  "unsure",
135
135
  "아마",
@@ -139,6 +139,18 @@ _AMBIGUOUS_KEYWORDS = (
139
139
  "헷갈",
140
140
  "애매",
141
141
  )
142
+ # WORDS: short standalone tokens — match on whole-word boundaries only
143
+ _AMBIGUOUS_WORDS = ("or", "either")
144
+
145
+
146
+ def _has_ambiguous(text: str) -> bool:
147
+ """Return True if text contains ambiguous phrasing or choice words."""
148
+ t = text.lower()
149
+ if any(p in t for p in _AMBIGUOUS_PHRASES):
150
+ return True
151
+ return any(re.search(r"\b" + re.escape(w) + r"\b", t) for w in _AMBIGUOUS_WORDS)
152
+
153
+
142
154
  _SCOPE_KEYWORDS = ("all", "everything", "전부", "전체", "모든")
143
155
  _TARGET_MISSING_KEYWORDS = ("fix", "implement", "refactor", "patch", "수정", "구현", "리팩터", "패치")
144
156
  _LOW_CONFIDENCE_THRESHOLD = 0.62
@@ -155,7 +167,7 @@ def assess_clarification(item: WorkItem, intent: WorkIntent) -> ClarificationRes
155
167
  reasons.append("low_intent_confidence")
156
168
  questions.append(_question("intent_direction", locale))
157
169
 
158
- if _has_any(text, _AMBIGUOUS_KEYWORDS):
170
+ if _has_ambiguous(text):
159
171
  reasons.append("ambiguous_language")
160
172
  questions.append(_question("disambiguate_choice", locale))
161
173
 
@@ -204,7 +216,7 @@ def assess_clarification(item: WorkItem, intent: WorkIntent) -> ClarificationRes
204
216
  def _needs_direction_confirmation(text: str, intent: WorkIntent) -> bool:
205
217
  if intent.category == "general" and len(text) < 240:
206
218
  return False
207
- if _has_any(text, _AMBIGUOUS_KEYWORDS):
219
+ if _has_ambiguous(text):
208
220
  return True
209
221
  if intent.category in {"engineering", "security", "documentation", "local_model"}:
210
222
  return True
@@ -58,7 +58,7 @@ def persist_dispatch_bundle(plan: HarnessPlan, *, dispatch_dir: Path | None = No
58
58
  return None
59
59
  bundle = _bundle_from_plan(plan)
60
60
  target_dir = default_dispatch_dir() if dispatch_dir is None else dispatch_dir
61
- if plan.queue_backend == "rust" and dispatch_dir is None and not _custom_dispatch_dir_configured():
61
+ if plan.queue_backend in ("native", "subprocess") and dispatch_dir is None and not _custom_dispatch_dir_configured():
62
62
  try:
63
63
  from cluxion_runtime.resources.queue_bridge import default_store_dir
64
64
  from cluxion_runtime.resources.queue_bridge import persist_dispatch_bundle as rust_persist
@@ -18,7 +18,7 @@ from cluxion_runtime.core.types import (
18
18
  WorkItem,
19
19
  )
20
20
  from cluxion_runtime.models.vllm_mlx import select_mac_local_profile
21
- from cluxion_runtime.resources.queue_bridge import queue_available
21
+ from cluxion_runtime.resources.queue_bridge import resolve_backend
22
22
  from cluxion_runtime.resources.rust_bridge import capacity_decision, collect_resource_snapshot
23
23
 
24
24
 
@@ -49,7 +49,7 @@ def build_harness_plan(
49
49
  queue_position=queue_position,
50
50
  clarification_required=True,
51
51
  clarification_questions=tuple(question.prompt for question in clarification.questions),
52
- queue_backend="rust" if queue_available() else "python",
52
+ queue_backend=resolve_backend(),
53
53
  )
54
54
  work_kind = _work_kind_for(item, intent_category=intent.category)
55
55
  preprocessed = preprocess_work(
@@ -72,7 +72,7 @@ def build_harness_plan(
72
72
  execution=_host_execution_plan_for(item, preprocessed, runtime),
73
73
  queue_position=queue_position,
74
74
  clarification_required=False,
75
- queue_backend="rust" if queue_available() else "python",
75
+ queue_backend=resolve_backend(),
76
76
  )
77
77
 
78
78
 
@@ -396,10 +396,11 @@ def _which(binary: str) -> bool:
396
396
 
397
397
 
398
398
  def _python_sample(body: Mapping[str, Any]) -> dict[str, Any]:
399
- interval_ms = max(100, int(body.get("cpu_sample_ms", 100)))
399
+ cpu_sample_ms = int(body.get("cpu_sample_ms", 100))
400
+ interval = None if cpu_sample_ms <= 0 else cpu_sample_ms / 1000.0
400
401
  memory = psutil.virtual_memory()
401
402
  swap = psutil.swap_memory()
402
- cpu = psutil.cpu_percent(interval=interval_ms / 1000.0)
403
+ cpu = psutil.cpu_percent(interval=interval)
403
404
  zombie_pids: list[int] = []
404
405
  count = 0
405
406
  for proc in psutil.process_iter(["status"]):
@@ -68,3 +68,28 @@ def test_resolve_locale_fallbacks() -> None:
68
68
  assert clarification.resolve_locale("한국어 텍스트") == "ko"
69
69
  assert clarification.resolve_locale("plain", explicit="ko-KR") == "ko"
70
70
  assert clarification.resolve_locale("plain", explicit="fr") == "en"
71
+
72
+
73
+ # Regression tests for word-boundary fix on 'or'/'either'
74
+ def test_clear_prompts_no_false_positive_clarification() -> None:
75
+ clear_prompts = [
76
+ "Generate a sales report",
77
+ "Optimize the code base",
78
+ "sort a list of numbers",
79
+ "What is the hex code for the color blue?",
80
+ ]
81
+ for prompt in clear_prompts:
82
+ item = WorkItem(f"w-clear-{prompt[:10]}", prompt)
83
+ plan = build_harness_plan(item)
84
+ assert plan.clarification_required is False, f"False positive on: {prompt}"
85
+
86
+
87
+ def test_real_or_choice_still_requires_clarification() -> None:
88
+ or_prompts = [
89
+ "Should I use X or Y?",
90
+ "do A or B?",
91
+ ]
92
+ for prompt in or_prompts:
93
+ item = WorkItem(f"w-or-{prompt[:10]}", prompt)
94
+ plan = build_harness_plan(item)
95
+ assert plan.clarification_required is True, f"Missed ambiguity on: {prompt}"
@@ -204,3 +204,12 @@ def test_work_id_traversal_is_neutralized(tmp_path: Path) -> None:
204
204
  def test_work_id_with_no_safe_chars_is_rejected(tmp_path: Path) -> None:
205
205
  with pytest.raises(DispatchStoreError, match="empty"):
206
206
  load_dispatch_bundle("../..", dispatch_dir=tmp_path)
207
+
208
+ from cluxion_runtime.core.types import ResourceSnapshot
209
+ from cluxion_runtime.resources.queue_bridge import resolve_backend
210
+
211
+
212
+ def test_queue_backend_label_matches_resolve_backend():
213
+ item = WorkItem("w-test", "short prompt", surface=AgentSurface.HERMES)
214
+ plan = build_harness_plan(item)
215
+ assert plan.queue_backend == resolve_backend()
@@ -344,3 +344,13 @@ def test_snapshot_prefers_fresh_daemon_state(tmp_path: Path, monkeypatch) -> Non
344
344
  (tmp_path / guard_bridge.STATE_FILE_NAME).write_text(json.dumps(state), encoding="utf-8")
345
345
  fallback = rust_bridge.collect_resource_snapshot()
346
346
  assert fallback.total_ram_mb != 4096 or fallback.available_ram_mb != 2048
347
+
348
+
349
+ def test_guard_python_sample_with_cpu_sample_ms_0_is_nonblocking(monkeypatch):
350
+ import cluxion_runtime.resources.guard_bridge as gb
351
+ t0 = time.time()
352
+ res = gb._python_sample({"cpu_sample_ms": 0})
353
+ dt = time.time() - t0
354
+ assert dt < 0.05, "should be fast non-blocking"
355
+ assert "cpu_percent" in res
356
+ assert res["ok"]
@@ -95,3 +95,9 @@ def test_directory_plugin_wrapper_exports_register() -> None:
95
95
  sys.path[:] = old_path
96
96
 
97
97
  assert module.register is plugin.register
98
+
99
+ def test_browser_check_fn_returns_false_when_playwright_missing(monkeypatch):
100
+ import importlib.util
101
+ monkeypatch.setattr(importlib.util, "find_spec", lambda name: None if name == "playwright" else object())
102
+ from cluxion_agentplugin_preprocessing.plugin import _check_browser_tool_available
103
+ assert _check_browser_tool_available() is False